diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..59ea9b2 --- /dev/null +++ b/.clang-format @@ -0,0 +1,156 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 90 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^' + Priority: 2 + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + CanonicalDelimiter: '' + BasedOnStyle: google +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Auto +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseTab: Never +... + diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e9a90c4 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,31 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "OpenOCD-Debug", + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "executable": "build/ch.elf", + "configFiles": [ + "interface/stlink.cfg", + "target/stm32f0x.cfg" + ], + "cwd": "${workspaceRoot}", + "svdFile": "STM32F0x2.svd", + "device": "stm32f0x", + "preLaunchTask": "build", + }, + { + "name": "STLink-Debug", + "type": "cortex-debug", + "request": "launch", + "servertype": "stutil", + "executable": "build/ch.elf", + "cwd": "${workspaceRoot}", + "svdFile": "STM32F0x2.svd", + "device": "stm32f0x", + "preLaunchTask": "build", + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 691a8f6..ee6833d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "C_Cpp.errorSquiggles": "Disabled" + "C_Cpp.errorSquiggles": "Disabled", + "cpplint.filters": ["-build/include_subdir", "-build/include_order", "-readability/casting", "-whitespace/comments"] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index dc6b6f8..d5aad65 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,19 +2,19 @@ "version": "2.0.0", "tasks": [ { - "label": "make", + "label": "build", "type": "shell", "command": "make", - "group": "build" + "group": { + "kind": "build", + "isDefault": true + } }, { "label": "flash", "type": "shell", "command": "make dfu flash", - "group": { - "kind": "build", - "isDefault": true - } + "group": "build" } ] } \ No newline at end of file diff --git a/Font5x7.c b/Font5x7.c index 63f66bd..26a0a87 100644 --- a/Font5x7.c +++ b/Font5x7.c @@ -1,2438 +1,2442 @@ -/* - * Font size 5x7 pixels - * most font glyph have width 5 pixels - */ - -#include - -/* - * Check 1 byte of char bitmap data for get width - */ - -#define FONT_GET_DATA(ch) (&x5x7_bits[ch*7]) -#define FONT_GET_WIDTH(ch) (7-x5x7_bits[ch*7]&3) -#define FONT_GET_HEIGHT 7 - -#define CHAR5x7_WIDTH_MASK 0x03 -#define CHAR5x7_WIDTH_4px 0x03 -#define CHAR5x7_WIDTH_5px 0x02 -#define CHAR5x7_WIDTH_6px 0x01 -#define CHAR5x7_WIDTH_7px 0x00 - -/* Font character bitmap data. */ -const uint8_t x5x7_bits[127*7] = -{ - - /* Character (0x00): - width=5 - +--------+ - |**** | - |**** | - |**** | - |**** | - |**** | - |**** | - | | - +--------+ */ - 0b11110000|CHAR5x7_WIDTH_5px, - 0b11110000, - 0b11110000, - 0b11110000, - 0b11110000, - 0b11110000, - 0b00000000, - - /* Character (0x01): - width=5 - +--------+ - | | - | * | - | *** | - |***** | - | *** | - | * | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00100000, - 0b01110000, - 0b11111000, - 0b01110000, - 0b00100000, - 0b00000000, - - /* Character (0x02): - width=5 - +--------+ - | * * | - |* * * | - | * * | - |* * * | - | * * | - |* * * | - | * * | - +--------+ */ - 0b01010000|CHAR5x7_WIDTH_5px, - 0b10101000, - 0b01010000, - 0b10101000, - 0b01010000, - 0b10101000, - 0b01010000, - - /* Character (0x03): - width=5 - +--------+ - |* * | - |*** | - |* * | - |* * | - | *** | - | * | - | * | - +--------+ */ - 0b10100000|CHAR5x7_WIDTH_5px, - 0b11100000, - 0b10100000, - 0b10100000, - 0b01110000, - 0b00100000, - 0b00100000, - - /* Character (0x04): - width=7 - +--------+ - | | - | ** | - | ** | - | * * | - | * * | - |* * | - |****** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_7px, - 0b00110000, - 0b00110000, - 0b01001000, - 0b01001000, - 0b10000100, - 0b11111100, - - /* Character (0x05): - width=5 - +--------+ - |** | - |* | - |** | - | ** | - | * * | - | ** | - | * * | - +--------+ */ - 0b11000000|CHAR5x7_WIDTH_5px, - 0b10000000, - 0b11000000, - 0b01100000, - 0b01010000, - 0b01100000, - 0b01010000, - - /* Character (0x06): - width=5 - +--------+ - |* | - |* | - |** | - | ** | - | * | - | ** | - | * | - +--------+ */ - 0b10000000|CHAR5x7_WIDTH_5px, - 0b10000000, - 0b11000000, - 0b00110000, - 0b00100000, - 0b00110000, - 0b00100000, - - /* Character (0x07): - width=5 - +--------+ - | * | - | * * | - | * | - | | - | | - | | - | | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_5px, - 0b01010000, - 0b00100000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x08): - width=5 - +--------+ - | | - | * | - | *** | - | * | - | | - | *** | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00100000, - 0b01110000, - 0b00100000, - 0b00000000, - 0b01110000, - 0b00000000, - - /* Character (0x09): - width=5 - +--------+ - |* * | - |** * | - |* ** | - |* * | - | * | - | * | - | ** | - +--------+ */ - 0b10010000|CHAR5x7_WIDTH_5px, - 0b11010000, - 0b10110000, - 0b10010000, - 0b00100000, - 0b00100000, - 0b00110000, - - /* Character (0x0a): - width=5 - +--------+ - |* * | - |* * | - |* * | - | * | - | *** | - | * | - | * | - +--------+ */ - 0b10100000|CHAR5x7_WIDTH_5px, - 0b10100000, - 0b10100000, - 0b01000000, - 0b01110000, - 0b00100000, - 0b00100000, - - /* Character (0x0b): - width=5 - +--------+ - | * | - | * | - | * | - |*** | - | | - | | - | | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_5px, - 0b00100000, - 0b00100000, - 0b11100000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x0c): - width=5 - +--------+ - | | - | | - | | - |*** | - | * | - | * | - | * | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b00000000, - 0b11100000, - 0b00100000, - 0b00100000, - 0b00100000, - - /* Character (0x0d): - width=5 - +--------+ - | | - | | - | | - | *** | - | * | - | * | - | * | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b00000000, - 0b00111000, - 0b00100000, - 0b00100000, - 0b00100000, - - /* Character (0x0e): - width=5 - +--------+ - | * | - | * | - | * | - | *** | - | | - | | - | | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_5px, - 0b00100000, - 0b00100000, - 0b00111000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x0f): - width=5 - +--------+ - | * | - | * | - | * | - |***** | - | * | - | * | - | * | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_5px, - 0b00100000, - 0b00100000, - 0b11111000, - 0b00100000, - 0b00100000, - 0b00100000, - - /* Character (0x10): - width=5 - +--------+ - | | - |***** | - | | - | | - | | - | | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b11111000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x11): - width=5 - +--------+ - | | - | | - |***** | - | | - | | - | | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b11111000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x12): - width=5 - +--------+ - | | - | | - | | - |***** | - | | - | | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b00000000, - 0b11111000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x13): - width=5 - +--------+ - | | - | | - | | - | | - |***** | - | | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b00000000, - 0b00000000, - 0b11111000, - 0b00000000, - 0b00000000, - - /* Character (0x14): - width=5 - +--------+ - | | - | | - | | - | | - | | - |***** | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b11111000, - 0b00000000, - - /* Character (0x15): - width=5 - +--------+ - | * | - | * | - | * | - | *** | - | * | - | * | - | * | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_5px, - 0b00100000, - 0b00100000, - 0b00111000, - 0b00100000, - 0b00100000, - 0b00100000, - - /* Character (0x16): - width=5 - +--------+ - | ** | - | *** | - | *** | - | *** | - | *** | - | *** | - | ** | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_5px, - 0b00100000, - 0b00100000, - 0b11100000, - 0b00100000, - 0b00100000, - 0b00100000, - - /* Character (0x17): - width=6 - +--------+ - | | - |** | - |**** | - |****** | - |**** | - |** | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_6px, - 0b11000000, - 0b11110000, - 0b00011100, - 0b11110000, - 0b11000000, - 0b00000000, - - /* Character (0x18): - width=5 - +--------+ - |* | - |** | - |*** | - |**** | - |*** | - |** | - |* | - +--------+ */ - 0b10000000|CHAR5x7_WIDTH_5px, - 0b11000000, - 0b11100000, - 0b11110000, - 0b11100000, - 0b11000000, - 0b10000000, - - /* Character (0x19): - width=7 - +--------+ - | | - | ** ** | - |* ** * | - |* * * | - |* ** * | - | ** ** | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_7px, - 0b01101100, - 0b10110010, - 0b10010010, - 0b10011010, - 0b01101100, - 0b00000000, - - /* Character (0x1a): - width=6 - +--------+ - | | - | * | - | * | - |***** | - | * | - | * | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_6px, - 0b00100000, - 0b01000000, - 0b11111000, - 0b01000000, - 0b00100000, - 0b00000000, - - /* Character (0x1b): - width=6 - +--------+ - | | - | * | - | * | - |***** | - | * | - | * | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_6px, - 0b00100000, - 0b00010000, - 0b11111000, - 0b00010000, - 0b00100000, - 0b00000000, - - /* Character (0x1c): - width=6 - +--------+ - | | - |***** | - | * * | - | * * | - | * * | - | * * | - |* ** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_6px, - 0b11111000, - 0b01010000, - 0b01010000, - 0b01010000, - 0b01010000, - 0b10011000, - - /* Character (0x1d): - width=7 - +--------+ - | | - | | - | * * | - | * * | - | ** ** | - | * * * | - |* | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_7px, - 0b00000000, - 0b01000100, - 0b01000100, - 0b01101100, - 0b01010100, - 0b10000000, - - /* Character (0x1e): - width=6 - +--------+ - | | - | *** | - |* * | - |* * | - |* * | - | * * | - |** ** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_6px, - 0b01110000, - 0b10001000, - 0b10001000, - 0b10001000, - 0b01010000, - 0b11011000, - - /* Character (0x1f): - width=5 - +--------+ - | ** | - |* * | - |* * | - | ** | - | | - | | - | | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b01100000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x20): ' ' - width=4 - +--------+ - | | - | | - | | - | | - | | - | | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_4px, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x21): '!' - width=4 - +--------+ - | * | - | * | - | * | - | * | - | * | - | | - | * | - +--------+ */ - 0b01000000|CHAR5x7_WIDTH_4px, - 0b01000000, - 0b01000000, - 0b01000000, - 0b01000000, - 0b00000000, - 0b01000000, - - /* Character (0x22): '"' - width=5 - +--------+ - | * * | - | * * | - | * * | - | | - | | - | | - | | - +--------+ */ - 0b01010000, - 0b01010000, - 0b01010000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x23): '#' - width=5 - +--------+ - | * * | - | * * | - |***** | - | * * | - |***** | - | * * | - | * * | - +--------+ */ - 0b01010000|CHAR5x7_WIDTH_6px, - 0b01010000, - 0b11111000, - 0b01010000, - 0b11111000, - 0b01010000, - 0b01010000, - - /* Character (0x24): '$' - width=5 - +--------+ - | * | - | **** | - |* * | - | *** | - | * * | - |**** | - | * | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_6px, - 0b01111000, - 0b10100000, - 0b01110000, - 0b00101000, - 0b11110000, - 0b00100000, - - /* Character (0x25): '%' - width=6 - +--------+ - |** | - |** * | - | * | - | * | - | * | - |* ** | - | ** | - +--------+ */ - 0b11000000|CHAR5x7_WIDTH_6px, - 0b11001000, - 0b00010000, - 0b00100000, - 0b01000000, - 0b10011000, - 0b00011000, - - /* Character (0x26): '&' - width=5 - +--------+ - | | - | * | - | * * | - | ** | - |* * * | - |* * | - | ** * | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_6px, - 0b00100000, - 0b01010000, - 0b01100000, - 0b10101000, - 0b10010000, - 0b01101000, - - /* Character (0x27): ''' - width=4 - +--------+ - | ** | - | * | - |* | - | | - | | - | | - | | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_4px, - 0b01000000, - 0b10000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x28): '(' - width=4 - +--------+ - | * | - | * | - |* | - |* | - |* | - | * | - | * | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_4px, - 0b01000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b01000000, - 0b00100000, - - /* Character (0x29): ')' - width=5 - +--------+ - |* | - | * | - | * | - | * | - | * | - | * | - |* | - +--------+ */ - 0b10000000|CHAR5x7_WIDTH_4px, - 0b01000000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b01000000, - 0b10000000, - - /* Character (0x2a): '*' - width=6 - +--------+ - | | - | * | - |* * * | - | *** | - |* * * | - | * | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_6px, - 0b00100000, - 0b10101000, - 0b01110000, - 0b10101000, - 0b00100000, - 0b00000000, - - /* Character (0x2b): '+' - width=6 - +--------+ - | | - | * | - | * | - |***** | - | * | - | * | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_6px, - 0b00100000, - 0b00100000, - 0b11111000, - 0b00100000, - 0b00100000, - 0b00000000, - - /* Character (0x2c): ',' - width=4 - +--------+ - | | - | | - | | - | | - |** | - | * | - |* | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_4px, - 0b00000000, - 0b00000000, - 0b00000000, - 0b11000000, - 0b01000000, - 0b10000000, - - /* Character (0x2d): '-' - width=5 - +--------+ - | | - | | - | | - |**** | - | | - | | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b00000000, - 0b11110000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x2e): '.' - width=3 - +--------+ - | | - | | - | | - | | - | | - |** | - |** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_4px, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b11000000, - 0b11000000, - - /* Character (0x2f): '/' - width=4 - +--------+ - | * | - | * | - | * | - | * | - | * | - |* | - |* | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_4px, - 0b00100000, - 0b01000000, - 0b01000000, - 0b01000000, - 0b10000000, - 0b10000000, - - /* Character (0x30): '0' - width=5 - +--------+ - | ** | - |* * | - |* ** | - |** * | - |* * | - |* * | - | ** | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10110000, - 0b11010000, - 0b10010000, - 0b10010000, - 0b01100000, - - /* Character (0x31): '1' - width=5 - +--------+ - | * | - | ** | - | * | - | * | - | * | - | * | - | *** | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_5px, - 0b01100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b01110000, - - /* Character (0x32): '2' - width=5 - +--------+ - | ** | - |* * | - | * | - | * | - | * | - |* | - |**** | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b00010000, - 0b00100000, - 0b01000000, - 0b10000000, - 0b11110000, - - /* Character (0x33): '3' - width=5 - +--------+ - | ** | - |* * | - | * | - | ** | - | * | - |* * | - | ** | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b00010000, - 0b01100000, - 0b00010000, - 0b10010000, - 0b01100000, - - /* Character (0x34): '4' - width=5 - +--------+ - |* * | - |* * | - |* * | - |* * | - |**** | - | * | - | * | - +--------+ */ - 0b10010000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b10010000, - 0b11110000, - 0b00010000, - 0b00010000, - - /* Character (0x35): '5' - width=5 - +--------+ - |**** | - |* | - |*** | - | * | - | * | - |* * | - | ** | - +--------+ */ - 0b11110000|CHAR5x7_WIDTH_5px, - 0b10000000, - 0b11100000, - 0b00010000, - 0b00010000, - 0b10010000, - 0b01100000, - - /* Character (0x36): '6' - width=5 - +--------+ - | ** | - |* * | - |* | - |*** | - |* * | - |* * | - | ** | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10000000, - 0b11100000, - 0b10010000, - 0b10010000, - 0b01100000, - - /* Character (0x37): '7' - width=5 - +--------+ - |**** | - | * | - | * | - | * | - | * | - | * | - | * | - +--------+ */ - 0b11110000|CHAR5x7_WIDTH_5px, - 0b00010000, - 0b00100000, - 0b00100000, - 0b01000000, - 0b01000000, - 0b01000000, - - /* Character (0x38): '8' - width=5 - +--------+ - | ** | - |* * | - |* * | - | ** | - |* * | - |* * | - | ** | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b01100000, - 0b10010000, - 0b10010000, - 0b01100000, - - /* Character (0x39): '9' - width=5 - +--------+ - | ** | - |* * | - |* * | - | *** | - | * | - |* * | - | ** | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b01110000, - 0b00010000, - 0b10010000, - 0b01100000, - - /* Character (0x3a): ':' - width=3 - +--------+ - | | - |** | - |** | - | | - |** | - |** | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_4px, - 0b11000000, - 0b11000000, - 0b00000000, - 0b11000000, - 0b11000000, - 0b00000000, - - /* Character (0x3b): ';' - width=4 - +--------+ - | | - | ** | - | ** | - | | - | ** | - | * | - |* | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_4px, - 0b01100000, - 0b01100000, - 0b00000000, - 0b01100000, - 0b01000000, - 0b10000000, - - /* Character (0x3c): '<' - width=5 - +--------+ - | | - | * | - | * | - |* | - | * | - | * | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00100000, - 0b01000000, - 0b10000000, - 0b01000000, - 0b00100000, - 0b00000000, - - /* Character (0x3d): '=' - width=5 - +--------+ - | | - | | - |**** | - | | - |**** | - | | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b11110000, - 0b00000000, - 0b11110000, - 0b00000000, - 0b00000000, - - /* Character (0x3e): '>' - width=5 - +--------+ - | | - |* | - | * | - | * | - | * | - |* | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b10000000, - 0b01000000, - 0b00100000, - 0b01000000, - 0b10000000, - 0b00000000, - - /* Character (0x3f): '?' - width=5 - +--------+ - | ** | - |* * | - | * | - | * | - | * | - | | - | * | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b00010000, - 0b00100000, - 0b01000000, - 0b00000000, - 0b01000000, - - /* Character (0x40): '@' - width=5 - +--------+ - | ** | - |* * | - |* ** | - |* ** | - |* | - |* | - | *** | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10110000, - 0b10110000, - 0b10000000, - 0b10000000, - 0b01110000, - - /* Character (0x41): 'A' - width=5 - +--------+ - | ** | - |* * | - |* * | - |* * | - |**** | - |* * | - |* * | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b10010000, - 0b11110000, - 0b10010000, - 0b10010000, - - /* Character (0x42): 'B' - width=5 - +--------+ - |*** | - |* * | - |* * | - |*** | - |* * | - |* * | - |*** | - +--------+ */ - 0b11100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b11100000, - 0b10010000, - 0b10010000, - 0b11100000, - - /* Character (0x43): 'C' - width=5 - +--------+ - | ** | - |* * | - |* | - |* | - |* | - |* * | - | ** | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10010000, - 0b01100000, - - /* Character (0x44): 'D' - width=5 - +--------+ - |*** | - |* * | - |* * | - |* * | - |* * | - |* * | - |*** | - +--------+ */ - 0b11100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b10010000, - 0b10010000, - 0b10010000, - 0b11100000, - - /* Character (0x45): 'E' - width=5 - +--------+ - |**** | - |* | - |* | - |*** | - |* | - |* | - |**** | - +--------+ */ - 0b11110000|CHAR5x7_WIDTH_5px, - 0b10000000, - 0b10000000, - 0b11100000, - 0b10000000, - 0b10000000, - 0b11110000, - - /* Character (0x46): 'F' - width=5 - +--------+ - |**** | - |* | - |* | - |*** | - |* | - |* | - |* | - +--------+ */ - 0b11110000|CHAR5x7_WIDTH_5px, - 0b10000000, - 0b10000000, - 0b11100000, - 0b10000000, - 0b10000000, - 0b10000000, - - /* Character (0x47): 'G' - width=5 - +--------+ - | ** | - |* * | - |* | - |* ** | - |* * | - |* * | - | *** | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10000000, - 0b10110000, - 0b10010000, - 0b10010000, - 0b01110000, - - /* Character (0x48): 'H' - width=5 - +--------+ - |* * | - |* * | - |* * | - |**** | - |* * | - |* * | - |* * | - +--------+ */ - 0b10010000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b11110000, - 0b10010000, - 0b10010000, - 0b10010000, - - /* Character (0x49): 'I' - width=4 - +--------+ - |*** | - | * | - | * | - | * | - | * | - | * | - |*** | - +--------+ */ - 0b11100000|CHAR5x7_WIDTH_4px, - 0b01000000, - 0b01000000, - 0b01000000, - 0b01000000, - 0b01000000, - 0b11100000, - - /* Character (0x4a): 'J' - width=5 - +--------+ - | *** | - | * | - | * | - | * | - | * | - |* * | - | ** | - +--------+ */ - 0b01110000|CHAR5x7_WIDTH_5px, - 0b00010000, - 0b00010000, - 0b00010000, - 0b00010000, - 0b10010000, - 0b01100000, - - /* Character (0x4b): 'K' - width=5 - +--------+ - |* * | - |* * | - |* * | - |** | - |* * | - |* * | - |* * | - +--------+ */ - 0b10010000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b11100000, - 0b10010000, - 0b10010000, - 0b10010000, - - /* Character (0x4c): 'L' - width=5 - +--------+ - |* | - |* | - |* | - |* | - |* | - |* | - |**** | - +--------+ */ - 0b10000000|CHAR5x7_WIDTH_5px, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b11110000, - - /* Character (0x4d): 'M' - width=6 - +--------+ - |* * | - |** ** | - |* * * | - |* * * | - |* * | - |* * | - |* * | - +--------+ */ - 0b10001000|CHAR5x7_WIDTH_6px, - 0b11011000, - 0b10101000, - 0b10101000, - 0b10001000, - 0b10001000, - 0b10001000, - - /* Character (0x4e): 'N' - width=5 - +--------+ - |* * | - |* * | - |** * | - |* ** | - |* * | - |* * | - |* * | - +--------+ */ - 0b10010000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b11010000, - 0b10110000, - 0b10010000, - 0b10010000, - 0b10010000, - - /* Character (0x4f): 'O' - width=5 - +--------+ - | ** | - |* * | - |* * | - |* * | - |* * | - |* * | - | ** | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b10010000, - 0b10010000, - 0b10010000, - 0b01100000, - - /* Character (0x50): 'P' - width=5 - +--------+ - |*** | - |* * | - |* * | - |*** | - |* | - |* | - |* | - +--------+ */ - 0b11100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b11100000, - 0b10000000, - 0b10000000, - 0b10000000, - - /* Character (0x51): 'Q' - width=5 - +--------+ - | ** | - |* * | - |* * | - |* * | - |* * | - |* * | - | * * | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b10010000, - 0b10010000, - 0b10100000, - 0b01010000, - - /* Character (0x52): 'R' - width=5 - +--------+ - |*** | - |* * | - |* * | - |*** | - |* * | - |* * | - |* * | - +--------+ */ - 0b11100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b11100000, - 0b10010000, - 0b10010000, - 0b10010000, - - /* Character (0x53): 'S' - width=5 - +--------+ - | ** | - |* * | - |* | - | ** | - | * | - |* * | - | ** | - +--------+ */ - 0b01100000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10000000, - 0b01100000, - 0b00010000, - 0b10010000, - 0b01100000, - - /* Character (0x54): 'T' - width=6 - +--------+ - |***** | - | * | - | * | - | * | - | * | - | * | - | * | - +--------+ */ - 0b11111000|CHAR5x7_WIDTH_6px, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - - /* Character (0x55): 'U' - width=5 - +--------+ - |* * | - |* * | - |* * | - |* * | - |* * | - |* * | - | *** | - +--------+ */ - 0b10010000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b10010000, - 0b10010000, - 0b10010000, - 0b01110000, - - /* Character (0x56): 'V' - width=5 - +--------+ - |* * | - |* * | - |* * | - |* * | - |* * | - | ** | - | ** | - +--------+ */ - 0b10010000|CHAR5x7_WIDTH_5px, - 0b10010000, - 0b10010000, - 0b10010000, - 0b10010000, - 0b01100000, - 0b01100000, - - /* Character (0x57): 'W' - width=6 - +--------+ - |* * | - |* * | - |* * | - |* * * | - |* * * | - |* * * | - | * * | - +--------+ */ - 0b10001000|CHAR5x7_WIDTH_6px, - 0b10001000, - 0b10001000, - 0b10101000, - 0b10101000, - 0b10101000, - 0b01010000, - - /* Character (0x58): 'X' - width=6 - +--------+ - |* * | - |* * | - | * * | - | * | - | * * | - |* * | - |* * | - +--------+ */ - 0b10001000|CHAR5x7_WIDTH_6px, - 0b10001000, - 0b01010000, - 0b00100000, - 0b01010000, - 0b10001000, - 0b10001000, - - /* Character (0x59): 'Y' - width=6 - +--------+ - |* * | - |* * | - |* * | - | * * | - | * | - | * | - | * | - +--------+ */ - 0b10001000|CHAR5x7_WIDTH_6px, - 0b10001000, - 0b10001000, - 0b01010000, - 0b00100000, - 0b00100000, - 0b00100000, - - /* Character (0x5a): 'Z' - width=5 - +--------+ - |**** | - | * | - | * | - | * | - |* | - |* | - |**** | - +--------+ */ - 0b11110000|CHAR5x7_WIDTH_5px, - 0b00010000, - 0b00100000, - 0b01000000, - 0b10000000, - 0b10000000, - 0b11110000, - - /* Character (0x5b): '[' - width=4 - +--------+ - |*** | - |* | - |* | - |* | - |* | - |* | - |*** | - +--------+ */ - 0b11100000|CHAR5x7_WIDTH_4px, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b11100000, - - /* Character (0x5c): '\' - width=4 - +--------+ - |* | - |* | - | * | - | * | - | * | - | * | - | * | - +--------+ */ - 0b10000000|CHAR5x7_WIDTH_4px, - 0b10000000, - 0b01000000, - 0b01000000, - 0b01000000, - 0b00100000, - 0b00100000, - - /* Character (0x5d): ']' - width=4 - +--------+ - |*** | - | * | - | * | - | * | - | * | - | * | - |*** | - +--------+ */ - 0b11100000|CHAR5x7_WIDTH_4px, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b11100000, - - /* Character (0x5e): '^' - width=4 - +--------+ - | * | - |* * | - | | - | | - | | - | | - | | - +--------+ */ - 0b01000000|CHAR5x7_WIDTH_4px, - 0b10100000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x5f): '_' - width=5 - +--------+ - | | - | | - | | - | | - | | - | | - |***** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b11111000, - - /* Character (0x60): '`' - width=4 - +--------+ - |** | - | * | - | * | - | | - | | - | | - | | - +--------+ */ - 0b11000000|CHAR5x7_WIDTH_4px, - 0b01000000, - 0b00100000, - 0b00000000, - 0b00000000, - 0b00000000, - 0b00000000, - - /* Character (0x61): 'a' - width=5 - +--------+ - | | - | | - | *** | - |* * | - |* * | - |* ** | - | * * | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b01110000, - 0b10010000, - 0b10010000, - 0b10110000, - 0b01010000, - - /* Character (0x62): 'b' - width=5 - +--------+ - |* | - |* | - |* * | - |** * | - |* * | - |* * | - |*** | - +--------+ */ - 0b10000000|CHAR5x7_WIDTH_5px, - 0b10000000, - 0b10100000, - 0b11010000, - 0b10010000, - 0b10010000, - 0b11100000, - - /* Character (0x63): 'c' - width=5 - +--------+ - | | - | | - | *** | - |* | - |* | - |* | - | *** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b01110000, - 0b10000000, - 0b10000000, - 0b10000000, - 0b01110000, - - /* Character (0x64): 'd' - width=5 - +--------+ - | * | - | * | - | * * | - |* ** | - |* * | - |* * | - | *** | - +--------+ */ - 0b00010000|CHAR5x7_WIDTH_5px, - 0b00010000, - 0b01010000, - 0b10110000, - 0b10010000, - 0b10010000, - 0b01110000, - - /* Character (0x65): 'e' - width=5 - +--------+ - | | - | | - | ** | - |* * | - |**** | - |* | - | *** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b01100000, - 0b10010000, - 0b11110000, - 0b10000000, - 0b01110000, - - /* Character (0x66): 'f' - width=5 - +--------+ - | * | - | * * | - | * | - |*** | - | * | - | * | - | * | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_5px, - 0b01010000, - 0b01000000, - 0b11100000, - 0b01000000, - 0b01000000, - 0b01000000, - - /* Character (0x67): 'g' - width=5 - +--------+ - | | - | | - | *** | - |* * | - | *** | - | * | - | ** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b01110000, - 0b10010000, - 0b01110000, - 0b00010000, - 0b01100000, - - /* Character (0x68): 'h' - width=5 - +--------+ - |* | - |* | - |* * | - |** * | - |* * | - |* * | - |* * | - +--------+ */ - 0b10000000|CHAR5x7_WIDTH_5px, - 0b10000000, - 0b10100000, - 0b11010000, - 0b10010000, - 0b10010000, - 0b10010000, - - /* Character (0x69): 'i' - width=4 - +--------+ - | * | - | | - |** | - | * | - | * | - | * | - |*** | - +--------+ */ - 0b01000000|CHAR5x7_WIDTH_4px, - 0b00000000, - 0b11000000, - 0b01000000, - 0b01000000, - 0b01000000, - 0b11100000, - - /* Character (0x6a): - width=4 - +--------+ - | * | - | | - | * | - | * | - | * | - |* * | - | * | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_4px, - 0b00000000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b10100000, - 0b01000000, - - /* Character (0x6b): 'k' - width=5 - +--------+ - |* | - |* | - |* * | - |* * | - |** | - |* * | - |* * | - +--------+ */ - 0b10000000|CHAR5x7_WIDTH_5px, - 0b10000000, - 0b10010000, - 0b10100000, - 0b11000000, - 0b10100000, - 0b10010000, - - /* Character (0x6c): 'l' - width=4 - +--------+ - |** | - | * | - | * | - | * | - | * | - | * | - |*** | - +--------+ */ - 0b11000000|CHAR5x7_WIDTH_4px, - 0b01000000, - 0b01000000, - 0b01000000, - 0b01000000, - 0b01000000, - 0b11100000, - - /* Character (0x6d): 'm' - width=6 - +--------+ - | | - | | - |**** | - |* * * | - |* * * | - |* * * | - |* * * | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_6px, - 0b00000000, - 0b11110000, - 0b10101000, - 0b10101000, - 0b10101000, - 0b10101000, - - /* Character (0x6e): 'n' - width=5 - +--------+ - | | - | | - |* * | - |** * | - |* * | - |* * | - |* * | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b10100000, - 0b11010000, - 0b10010000, - 0b10010000, - 0b10010000, - - /* Character (0x6f): 'o' - width=5 - +--------+ - | | - | | - | ** | - |* * | - |* * | - |* * | - | ** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b01100000, - 0b10010000, - 0b10010000, - 0b10010000, - 0b01100000, - - /* Character (0x70): 'p' - width=5 - +--------+ - | | - | | - |*** | - |* * | - |* * | - |*** | - |* | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b11100000, - 0b10010000, - 0b10010000, - 0b11100000, - 0b10000000, - - /* Character (0x71): 'q' - width=5 - +--------+ - | | - | | - | *** | - |* * | - |* * | - | *** | - | * | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b01110000, - 0b10010000, - 0b10010000, - 0b01110000, - 0b00010000, - - /* Character (0x72): 'r' - width=5 - +--------+ - | | - | | - |* * | - |** * | - |* | - |* | - |* | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b10100000, - 0b11010000, - 0b10000000, - 0b10000000, - 0b10000000, - - /* Character (0x73): 's' - width=5 - +--------+ - | | - | | - | *** | - |* | - | ** | - | * | - |*** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b01110000, - 0b10000000, - 0b01100000, - 0b00010000, - 0b11100000, - - /* Character (0x74): 't' - width=5 - +--------+ - | * | - | * | - |*** | - | * | - | * | - | * | - | ** | - +--------+ */ - 0b01000000|CHAR5x7_WIDTH_5px, - 0b01000000, - 0b11100000, - 0b01000000, - 0b01000000, - 0b01000000, - 0b00110000, - - /* Character (0x75): 'u' - width=5 - +--------+ - | | - | | - |* * | - |* * | - |* * | - |* ** | - | * * | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b10010000, - 0b10010000, - 0b10010000, - 0b10110000, - 0b01010000, - - /* Character (0x76): 'v' - width=5 - +--------+ - | | - | | - |* * | - |* * | - |* * | - | ** | - | ** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b10010000, - 0b10010000, - 0b10010000, - 0b01100000, - 0b01100000, - - /* Character (0x77): 'w' - width=6 - +--------+ - | | - | | - |* * | - |* * | - |* * * | - |* * * | - | * * | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_6px, - 0b00000000, - 0b10001000, - 0b10001000, - 0b10101000, - 0b10101000, - 0b01010000, - - /* Character (0x78): 'x' - width=5 - +--------+ - | | - | | - |* * | - |* * | - | ** | - |* * | - |* * | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b10010000, - 0b10010000, - 0b01100000, - 0b10010000, - 0b10010000, - - /* Character (0x79): 'y' - width=5 - +--------+ - | | - | | - |* * | - |* * | - | *** | - | * | - |*** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b10010000, - 0b10010000, - 0b01110000, - 0b00010000, - 0b11100000, - - /* Character (0x7a): 'z' - width=5 - +--------+ - | | - | | - |**** | - | * | - | * | - |* | - |**** | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b11110000, - 0b00100000, - 0b01000000, - 0b10000000, - 0b11110000, - - /* Character (0x7b): '{' - width=5 - +--------+ - | * | - | * | - | * | - |* | - | * | - | * | - | * | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_4px, - 0b01000000, - 0b01000000, - 0b10000000, - 0b01000000, - 0b01000000, - 0b00100000, - - /* Character (0x7c): '|' - width=5 - +--------+ - | * | - | * | - | * | - | * | - | * | - | * | - | * | - +--------+ */ - 0b00100000|CHAR5x7_WIDTH_4px, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - 0b00100000, - - /* Character (0x7d): '}' - width=5 - +--------+ - |* | - | * | - | * | - | * | - | * | - | * | - |* | - +--------+ */ - 0b10000000|CHAR5x7_WIDTH_4px, - 0b01000000, - 0b01000000, - 0b00100000, - 0b01000000, - 0b01000000, - 0b10000000, - - /* Character (0x7e): '~' - width=5 - +--------+ - | | - | | - | * * | - |* * | - | | - | | - | | - +--------+ */ - 0b00000000|CHAR5x7_WIDTH_5px, - 0b00000000, - 0b01010000, - 0b10100000, - 0b00000000, - 0b00000000, - 0b00000000, -}; +/* + * Font size 5x7 pixels + * most font glyph have width 5 pixels + */ + +#include + +/* + * Check 1 byte of char bitmap data for get width + */ + +#define FONT_GET_DATA(ch) (&x5x7_bits[ch*7]) +#define FONT_GET_WIDTH(ch) (8-x5x7_bits[ch*7]&7) +#define FONT_MAX_WIDTH 7 +#define FONT_GET_HEIGHT 7 + +#define CHAR5x7_WIDTH_1px 0x07 +#define CHAR5x7_WIDTH_2px 0x06 +#define CHAR5x7_WIDTH_3px 0x05 +#define CHAR5x7_WIDTH_4px 0x04 +#define CHAR5x7_WIDTH_5px 0x03 +#define CHAR5x7_WIDTH_6px 0x02 +#define CHAR5x7_WIDTH_7px 0x01 +#define CHAR5x7_WIDTH_8px 0x00 + +/* Font character bitmap data. */ +const uint8_t x5x7_bits[127*7] = +{ + + /* Character (0x00): + width=5 + +--------+ + |**** | + |**** | + |**** | + |**** | + |**** | + |**** | + | | + +--------+ */ + 0b11110000|CHAR5x7_WIDTH_5px, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b00000000, + + /* Character (0x01): + width=5 + +--------+ + | | + | * | + | *** | + |***** | + | *** | + | * | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00100000, + 0b01110000, + 0b11111000, + 0b01110000, + 0b00100000, + 0b00000000, + + /* Character (0x02): + width=5 + +--------+ + | * * | + |* * * | + | * * | + |* * * | + | * * | + |* * * | + | * * | + +--------+ */ + 0b01010000|CHAR5x7_WIDTH_5px, + 0b10101000, + 0b01010000, + 0b10101000, + 0b01010000, + 0b10101000, + 0b01010000, + + /* Character (0x03): + width=5 + +--------+ + |* * | + |*** | + |* * | + |* * | + | *** | + | * | + | * | + +--------+ */ + 0b10100000|CHAR5x7_WIDTH_5px, + 0b11100000, + 0b10100000, + 0b10100000, + 0b01110000, + 0b00100000, + 0b00100000, + + /* Character (0x04): + width=6 + +--------+ + | | + | * | + | * | + | * * | + | * * | + |* * | + |***** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b00100000, + 0b00100000, + 0b01010000, + 0b01010000, + 0b10001000, + 0b11111000, + + /* Character (0x05): + width=5 + +--------+ + |** | + |* | + |** | + | ** | + | * * | + | ** | + | * * | + +--------+ */ + 0b11000000|CHAR5x7_WIDTH_5px, + 0b10000000, + 0b11000000, + 0b01100000, + 0b01010000, + 0b01100000, + 0b01010000, + + /* Character (0x06): + width=5 + +--------+ + |* | + |* | + |** | + | ** | + | * | + | ** | + | * | + +--------+ */ + 0b10000000|CHAR5x7_WIDTH_5px, + 0b10000000, + 0b11000000, + 0b00110000, + 0b00100000, + 0b00110000, + 0b00100000, + + /* Character (0x07): + width=5 + +--------+ + | * | + | * * | + | * | + | | + | | + | | + | | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_5px, + 0b01010000, + 0b00100000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x08): + width=5 + +--------+ + | | + | * | + | *** | + | * | + | | + | *** | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00100000, + 0b01110000, + 0b00100000, + 0b00000000, + 0b01110000, + 0b00000000, + + /* Character (0x09): + width=5 + +--------+ + |* * | + |** * | + |* ** | + |* * | + | * | + | * | + | ** | + +--------+ */ + 0b10010000|CHAR5x7_WIDTH_5px, + 0b11010000, + 0b10110000, + 0b10010000, + 0b00100000, + 0b00100000, + 0b00110000, + + /* Character (0x0a): + width=5 + +--------+ + |* * | + |* * | + |* * | + | * | + | *** | + | * | + | * | + +--------+ */ + 0b10100000|CHAR5x7_WIDTH_5px, + 0b10100000, + 0b10100000, + 0b01000000, + 0b01110000, + 0b00100000, + 0b00100000, + + /* Character (0x0b): + width=5 + +--------+ + | * | + | * | + | * | + |*** | + | | + | | + | | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_5px, + 0b00100000, + 0b00100000, + 0b11100000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x0c): + width=5 + +--------+ + | | + | | + | | + |*** | + | * | + | * | + | * | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b00000000, + 0b11100000, + 0b00100000, + 0b00100000, + 0b00100000, + + /* Character (0x0d): + width=5 + +--------+ + | | + | | + | | + | *** | + | * | + | * | + | * | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b00000000, + 0b00111000, + 0b00100000, + 0b00100000, + 0b00100000, + + /* Character (0x0e): + width=5 + +--------+ + | * | + | * | + | * | + | *** | + | | + | | + | | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_5px, + 0b00100000, + 0b00100000, + 0b00111000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x0f): + width=5 + +--------+ + | * | + | * | + | * | + |***** | + | * | + | * | + | * | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_5px, + 0b00100000, + 0b00100000, + 0b11111000, + 0b00100000, + 0b00100000, + 0b00100000, + + /* Character (0x10): + width=5 + +--------+ + | | + |***** | + | | + | | + | | + | | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b11111000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x11): + width=5 + +--------+ + | | + | | + |***** | + | | + | | + | | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b11111000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x12): + width=5 + +--------+ + | | + | | + | | + |***** | + | | + | | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b00000000, + 0b11111000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x13): + width=5 + +--------+ + | | + | | + | | + | | + |***** | + | | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111000, + 0b00000000, + 0b00000000, + + /* Character (0x14): + width=5 + +--------+ + | | + | | + | | + | | + | | + |***** | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111000, + 0b00000000, + + /* Character (0x15): + width=5 + +--------+ + | * | + | * | + | * | + | *** | + | * | + | * | + | * | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_5px, + 0b00100000, + 0b00100000, + 0b00111000, + 0b00100000, + 0b00100000, + 0b00100000, + + /* Character (0x16): + width=5 + +--------+ + | ** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ** | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_5px, + 0b00100000, + 0b00100000, + 0b11100000, + 0b00100000, + 0b00100000, + 0b00100000, + + /* Character (0x17): + width=6 + +--------+ + | | + |** | + |**** | + |****** | + |**** | + |** | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b11000000, + 0b11110000, + 0b00011100, + 0b11110000, + 0b11000000, + 0b00000000, + + /* Character (0x18): + width=5 + +--------+ + |* | + |** | + |*** | + |**** | + |*** | + |** | + |* | + +--------+ */ + 0b10000000|CHAR5x7_WIDTH_4px, + 0b11000000, + 0b11100000, + 0b11110000, + 0b11100000, + 0b11000000, + 0b10000000, + + /* Character (0x19): + width=7 + +--------+ + | | + | ** ** | + |* ** * | + |* * * | + |* ** * | + | ** ** | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_7px, + 0b01101100, + 0b10110010, + 0b10010010, + 0b10011010, + 0b01101100, + 0b00000000, + + /* Character (0x1a): + width=6 + +--------+ + | | + | * | + | * | + |***** | + | * | + | * | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b00100000, + 0b01000000, + 0b11111000, + 0b01000000, + 0b00100000, + 0b00000000, + + /* Character (0x1b): + width=6 + +--------+ + | | + | * | + | * | + |***** | + | * | + | * | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b00100000, + 0b00010000, + 0b11111000, + 0b00010000, + 0b00100000, + 0b00000000, + + /* Character (0x1c): + width=6 + +--------+ + | | + |***** | + | * * | + | * * | + | * * | + | * * | + |* ** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b11111000, + 0b01010000, + 0b01010000, + 0b01010000, + 0b01010000, + 0b10011000, + + /* Character (0x1d): + width=6 + +--------+ + | | + | | + |* * | + |* * | + |** ** | + |* * * | + |* | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b00000000, + 0b10001000, + 0b10001000, + 0b11011000, + 0b10101000, + 0b10000000, + + /* Character (0x1e): + width=6 + +--------+ + | | + | *** | + |* * | + |* * | + |* * | + | * * | + |** ** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b01110000, + 0b10001000, + 0b10001000, + 0b10001000, + 0b01010000, + 0b11011000, + + /* Character (0x1f): + width=5 + +--------+ + | ** | + |* * | + |* * | + | ** | + | | + | | + | | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b01100000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x20): ' ' + width=3 + +--------+ + | | + | | + | | + | | + | | + | | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_4px, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x21): '!' + width=3 + +--------+ + | * | + | * | + | * | + | * | + | * | + | | + | * | + +--------+ */ + 0b01000000|CHAR5x7_WIDTH_3px, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b00000000, + 0b01000000, + + /* Character (0x22): '"' + width=5 + +--------+ + | * * | + | * * | + | * * | + | | + | | + | | + | | + +--------+ */ + 0b01010000, + 0b01010000, + 0b01010000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x23): '#' + width=5 + +--------+ + | * * | + | * * | + |***** | + | * * | + |***** | + | * * | + | * * | + +--------+ */ + 0b01010000|CHAR5x7_WIDTH_6px, + 0b01010000, + 0b11111000, + 0b01010000, + 0b11111000, + 0b01010000, + 0b01010000, + + /* Character (0x24): '$' + width=5 + +--------+ + | * | + | **** | + |* * | + | *** | + | * * | + |**** | + | * | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_6px, + 0b01111000, + 0b10100000, + 0b01110000, + 0b00101000, + 0b11110000, + 0b00100000, + + /* Character (0x25): '%' + width=6 + +--------+ + |** | + |** * | + | * | + | * | + | * | + |* ** | + | ** | + +--------+ */ + 0b11000000|CHAR5x7_WIDTH_6px, + 0b11001000, + 0b00010000, + 0b00100000, + 0b01000000, + 0b10011000, + 0b00011000, + + /* Character (0x26): '&' + width=5 + +--------+ + | | + | * | + | * * | + | ** | + |* * * | + |* * | + | ** * | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b00100000, + 0b01010000, + 0b01100000, + 0b10101000, + 0b10010000, + 0b01101000, + + /* Character (0x27): ''' + width=4 + +--------+ + | ** | + | * | + |* | + | | + | | + | | + | | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_4px, + 0b01000000, + 0b10000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x28): '(' + width=4 + +--------+ + | * | + | * | + |* | + |* | + |* | + | * | + | * | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_4px, + 0b01000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b01000000, + 0b00100000, + + /* Character (0x29): ')' + width=5 + +--------+ + |* | + | * | + | * | + | * | + | * | + | * | + |* | + +--------+ */ + 0b10000000|CHAR5x7_WIDTH_4px, + 0b01000000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b01000000, + 0b10000000, + + /* Character (0x2a): '*' + width=6 + +--------+ + | | + | * | + |* * * | + | *** | + |* * * | + | * | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b00100000, + 0b10101000, + 0b01110000, + 0b10101000, + 0b00100000, + 0b00000000, + + /* Character (0x2b): '+' + width=6 + +--------+ + | | + | * | + | * | + |***** | + | * | + | * | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b00100000, + 0b00100000, + 0b11111000, + 0b00100000, + 0b00100000, + 0b00000000, + + /* Character (0x2c): ',' + width=4 + +--------+ + | | + | | + | | + | | + |** | + | * | + |* | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_3px, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11000000, + 0b01000000, + 0b10000000, + + /* Character (0x2d): '-' + width=5 + +--------+ + | | + | | + | | + |**** | + | | + | | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b00000000, + 0b11110000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x2e): '.' + width=3 + +--------+ + | | + | | + | | + | | + | | + |** | + |** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_3px, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11000000, + 0b11000000, + + /* Character (0x2f): '/' + width=4 + +--------+ + | * | + | * | + | * | + | * | + | * | + |* | + |* | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_4px, + 0b00100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b10000000, + 0b10000000, + + /* Character (0x30): '0' + width=5 + +--------+ + | ** | + |* * | + |* ** | + |** * | + |* * | + |* * | + | ** | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10110000, + 0b11010000, + 0b10010000, + 0b10010000, + 0b01100000, + + /* Character (0x31): '1' + width=5 + +--------+ + | * | + | ** | + | * | + | * | + | * | + | * | + | *** | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_5px, + 0b01100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b01110000, + + /* Character (0x32): '2' + width=5 + +--------+ + | ** | + |* * | + | * | + | * | + | * | + |* | + |**** | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b00010000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b11110000, + + /* Character (0x33): '3' + width=5 + +--------+ + | ** | + |* * | + | * | + | ** | + | * | + |* * | + | ** | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b00010000, + 0b01100000, + 0b00010000, + 0b10010000, + 0b01100000, + + /* Character (0x34): '4' + width=5 + +--------+ + |* * | + |* * | + |* * | + |* * | + |**** | + | * | + | * | + +--------+ */ + 0b10010000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b10010000, + 0b11110000, + 0b00010000, + 0b00010000, + + /* Character (0x35): '5' + width=5 + +--------+ + |**** | + |* | + |*** | + | * | + | * | + |* * | + | ** | + +--------+ */ + 0b11110000|CHAR5x7_WIDTH_5px, + 0b10000000, + 0b11100000, + 0b00010000, + 0b00010000, + 0b10010000, + 0b01100000, + + /* Character (0x36): '6' + width=5 + +--------+ + | ** | + |* * | + |* | + |*** | + |* * | + |* * | + | ** | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10000000, + 0b11100000, + 0b10010000, + 0b10010000, + 0b01100000, + + /* Character (0x37): '7' + width=5 + +--------+ + |**** | + | * | + | * | + | * | + | * | + | * | + | * | + +--------+ */ + 0b11110000|CHAR5x7_WIDTH_5px, + 0b00010000, + 0b00100000, + 0b00100000, + 0b01000000, + 0b01000000, + 0b01000000, + + /* Character (0x38): '8' + width=5 + +--------+ + | ** | + |* * | + |* * | + | ** | + |* * | + |* * | + | ** | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b01100000, + 0b10010000, + 0b10010000, + 0b01100000, + + /* Character (0x39): '9' + width=5 + +--------+ + | ** | + |* * | + |* * | + | *** | + | * | + |* * | + | ** | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b01110000, + 0b00010000, + 0b10010000, + 0b01100000, + + /* Character (0x3a): ':' + width=3 + +--------+ + | | + |** | + |** | + | | + |** | + |** | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_4px, + 0b11000000, + 0b11000000, + 0b00000000, + 0b11000000, + 0b11000000, + 0b00000000, + + /* Character (0x3b): ';' + width=4 + +--------+ + | | + | ** | + | ** | + | | + | ** | + | * | + |* | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_4px, + 0b01100000, + 0b01100000, + 0b00000000, + 0b01100000, + 0b01000000, + 0b10000000, + + /* Character (0x3c): '<' + width=5 + +--------+ + | | + | * | + | * | + |* | + | * | + | * | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00100000, + 0b01000000, + 0b10000000, + 0b01000000, + 0b00100000, + 0b00000000, + + /* Character (0x3d): '=' + width=5 + +--------+ + | | + | | + |**** | + | | + |**** | + | | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b11110000, + 0b00000000, + 0b11110000, + 0b00000000, + 0b00000000, + + /* Character (0x3e): '>' + width=5 + +--------+ + | | + |* | + | * | + | * | + | * | + |* | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b10000000, + 0b01000000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b00000000, + + /* Character (0x3f): '?' + width=5 + +--------+ + | ** | + |* * | + | * | + | * | + | * | + | | + | * | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b00010000, + 0b00100000, + 0b01000000, + 0b00000000, + 0b01000000, + + /* Character (0x40): '@' + width=5 + +--------+ + | ** | + |* * | + |* ** | + |* ** | + |* | + |* | + | *** | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10110000, + 0b10110000, + 0b10000000, + 0b10000000, + 0b01110000, + + /* Character (0x41): 'A' + width=5 + +--------+ + | ** | + |* * | + |* * | + |* * | + |**** | + |* * | + |* * | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b10010000, + 0b11110000, + 0b10010000, + 0b10010000, + + /* Character (0x42): 'B' + width=5 + +--------+ + |*** | + |* * | + |* * | + |*** | + |* * | + |* * | + |*** | + +--------+ */ + 0b11100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b11100000, + 0b10010000, + 0b10010000, + 0b11100000, + + /* Character (0x43): 'C' + width=5 + +--------+ + | ** | + |* * | + |* | + |* | + |* | + |* * | + | ** | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10010000, + 0b01100000, + + /* Character (0x44): 'D' + width=5 + +--------+ + |*** | + |* * | + |* * | + |* * | + |* * | + |* * | + |*** | + +--------+ */ + 0b11100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b11100000, + + /* Character (0x45): 'E' + width=5 + +--------+ + |**** | + |* | + |* | + |*** | + |* | + |* | + |**** | + +--------+ */ + 0b11110000|CHAR5x7_WIDTH_5px, + 0b10000000, + 0b10000000, + 0b11100000, + 0b10000000, + 0b10000000, + 0b11110000, + + /* Character (0x46): 'F' + width=5 + +--------+ + |**** | + |* | + |* | + |*** | + |* | + |* | + |* | + +--------+ */ + 0b11110000|CHAR5x7_WIDTH_5px, + 0b10000000, + 0b10000000, + 0b11100000, + 0b10000000, + 0b10000000, + 0b10000000, + + /* Character (0x47): 'G' + width=5 + +--------+ + | ** | + |* * | + |* | + |* ** | + |* * | + |* * | + | *** | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10000000, + 0b10110000, + 0b10010000, + 0b10010000, + 0b01110000, + + /* Character (0x48): 'H' + width=5 + +--------+ + |* * | + |* * | + |* * | + |**** | + |* * | + |* * | + |* * | + +--------+ */ + 0b10010000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b11110000, + 0b10010000, + 0b10010000, + 0b10010000, + + /* Character (0x49): 'I' + width=4 + +--------+ + |*** | + | * | + | * | + | * | + | * | + | * | + |*** | + +--------+ */ + 0b11100000|CHAR5x7_WIDTH_4px, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b11100000, + + /* Character (0x4a): 'J' + width=5 + +--------+ + | *** | + | * | + | * | + | * | + | * | + |* * | + | ** | + +--------+ */ + 0b01110000|CHAR5x7_WIDTH_5px, + 0b00010000, + 0b00010000, + 0b00010000, + 0b00010000, + 0b10010000, + 0b01100000, + + /* Character (0x4b): 'K' + width=5 + +--------+ + |* * | + |* * | + |* * | + |** | + |* * | + |* * | + |* * | + +--------+ */ + 0b10010000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b11100000, + 0b10010000, + 0b10010000, + 0b10010000, + + /* Character (0x4c): 'L' + width=5 + +--------+ + |* | + |* | + |* | + |* | + |* | + |* | + |**** | + +--------+ */ + 0b10000000|CHAR5x7_WIDTH_5px, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b11110000, + + /* Character (0x4d): 'M' + width=6 + +--------+ + |* * | + |** ** | + |* * * | + |* * * | + |* * | + |* * | + |* * | + +--------+ */ + 0b10001000|CHAR5x7_WIDTH_6px, + 0b11011000, + 0b10101000, + 0b10101000, + 0b10001000, + 0b10001000, + 0b10001000, + + /* Character (0x4e): 'N' + width=5 + +--------+ + |* * | + |* * | + |** * | + |* ** | + |* * | + |* * | + |* * | + +--------+ */ + 0b10010000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b11010000, + 0b10110000, + 0b10010000, + 0b10010000, + 0b10010000, + + /* Character (0x4f): 'O' + width=5 + +--------+ + | ** | + |* * | + |* * | + |* * | + |* * | + |* * | + | ** | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b01100000, + + /* Character (0x50): 'P' + width=5 + +--------+ + |*** | + |* * | + |* * | + |*** | + |* | + |* | + |* | + +--------+ */ + 0b11100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b11100000, + 0b10000000, + 0b10000000, + 0b10000000, + + /* Character (0x51): 'Q' + width=5 + +--------+ + | ** | + |* * | + |* * | + |* * | + |* * | + |* * | + | * * | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b10100000, + 0b01010000, + + /* Character (0x52): 'R' + width=5 + +--------+ + |*** | + |* * | + |* * | + |*** | + |* * | + |* * | + |* * | + +--------+ */ + 0b11100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b11100000, + 0b10010000, + 0b10010000, + 0b10010000, + + /* Character (0x53): 'S' + width=5 + +--------+ + | ** | + |* * | + |* | + | ** | + | * | + |* * | + | ** | + +--------+ */ + 0b01100000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10000000, + 0b01100000, + 0b00010000, + 0b10010000, + 0b01100000, + + /* Character (0x54): 'T' + width=6 + +--------+ + |***** | + | * | + | * | + | * | + | * | + | * | + | * | + +--------+ */ + 0b11111000|CHAR5x7_WIDTH_6px, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + + /* Character (0x55): 'U' + width=5 + +--------+ + |* * | + |* * | + |* * | + |* * | + |* * | + |* * | + | *** | + +--------+ */ + 0b10010000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b01110000, + + /* Character (0x56): 'V' + width=5 + +--------+ + |* * | + |* * | + |* * | + |* * | + |* * | + | ** | + | ** | + +--------+ */ + 0b10010000|CHAR5x7_WIDTH_5px, + 0b10010000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b01100000, + 0b01100000, + + /* Character (0x57): 'W' + width=6 + +--------+ + |* * | + |* * | + |* * | + |* * * | + |* * * | + |* * * | + | * * | + +--------+ */ + 0b10001000|CHAR5x7_WIDTH_6px, + 0b10001000, + 0b10001000, + 0b10101000, + 0b10101000, + 0b10101000, + 0b01010000, + + /* Character (0x58): 'X' + width=6 + +--------+ + |* * | + |* * | + | * * | + | * | + | * * | + |* * | + |* * | + +--------+ */ + 0b10001000|CHAR5x7_WIDTH_6px, + 0b10001000, + 0b01010000, + 0b00100000, + 0b01010000, + 0b10001000, + 0b10001000, + + /* Character (0x59): 'Y' + width=6 + +--------+ + |* * | + |* * | + |* * | + | * * | + | * | + | * | + | * | + +--------+ */ + 0b10001000|CHAR5x7_WIDTH_6px, + 0b10001000, + 0b10001000, + 0b01010000, + 0b00100000, + 0b00100000, + 0b00100000, + + /* Character (0x5a): 'Z' + width=5 + +--------+ + |**** | + | * | + | * | + | * | + |* | + |* | + |**** | + +--------+ */ + 0b11110000|CHAR5x7_WIDTH_5px, + 0b00010000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b10000000, + 0b11110000, + + /* Character (0x5b): '[' + width=4 + +--------+ + |*** | + |* | + |* | + |* | + |* | + |* | + |*** | + +--------+ */ + 0b11100000|CHAR5x7_WIDTH_4px, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b11100000, + + /* Character (0x5c): '\' + width=4 + +--------+ + |* | + |* | + | * | + | * | + | * | + | * | + | * | + +--------+ */ + 0b10000000|CHAR5x7_WIDTH_4px, + 0b10000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b00100000, + 0b00100000, + + /* Character (0x5d): ']' + width=4 + +--------+ + |*** | + | * | + | * | + | * | + | * | + | * | + |*** | + +--------+ */ + 0b11100000|CHAR5x7_WIDTH_4px, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b11100000, + + /* Character (0x5e): '^' + width=4 + +--------+ + | * | + |* * | + | | + | | + | | + | | + | | + +--------+ */ + 0b01000000|CHAR5x7_WIDTH_4px, + 0b10100000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x5f): '_' + width=5 + +--------+ + | | + | | + | | + | | + | | + | | + |***** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111000, + + /* Character (0x60): '`' + width=4 + +--------+ + |** | + | * | + | * | + | | + | | + | | + | | + +--------+ */ + 0b11000000|CHAR5x7_WIDTH_4px, + 0b01000000, + 0b00100000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + + /* Character (0x61): 'a' + width=5 + +--------+ + | | + | | + | *** | + |* * | + |* * | + |* ** | + | * * | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b01110000, + 0b10010000, + 0b10010000, + 0b10110000, + 0b01010000, + + /* Character (0x62): 'b' + width=5 + +--------+ + |* | + |* | + |* * | + |** * | + |* * | + |* * | + |*** | + +--------+ */ + 0b10000000|CHAR5x7_WIDTH_5px, + 0b10000000, + 0b10100000, + 0b11010000, + 0b10010000, + 0b10010000, + 0b11100000, + + /* Character (0x63): 'c' + width=5 + +--------+ + | | + | | + | *** | + |* | + |* | + |* | + | *** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b01110000, + 0b10000000, + 0b10000000, + 0b10000000, + 0b01110000, + + /* Character (0x64): 'd' + width=5 + +--------+ + | * | + | * | + | * * | + |* ** | + |* * | + |* * | + | *** | + +--------+ */ + 0b00010000|CHAR5x7_WIDTH_5px, + 0b00010000, + 0b01010000, + 0b10110000, + 0b10010000, + 0b10010000, + 0b01110000, + + /* Character (0x65): 'e' + width=5 + +--------+ + | | + | | + | ** | + |* * | + |**** | + |* | + | *** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b01100000, + 0b10010000, + 0b11110000, + 0b10000000, + 0b01110000, + + /* Character (0x66): 'f' + width=5 + +--------+ + | * | + | * * | + | * | + |*** | + | * | + | * | + | * | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_5px, + 0b01010000, + 0b01000000, + 0b11100000, + 0b01000000, + 0b01000000, + 0b01000000, + + /* Character (0x67): 'g' + width=5 + +--------+ + | | + | | + | *** | + |* * | + | *** | + | * | + | ** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b01110000, + 0b10010000, + 0b01110000, + 0b00010000, + 0b01100000, + + /* Character (0x68): 'h' + width=5 + +--------+ + |* | + |* | + |* * | + |** * | + |* * | + |* * | + |* * | + +--------+ */ + 0b10000000|CHAR5x7_WIDTH_5px, + 0b10000000, + 0b10100000, + 0b11010000, + 0b10010000, + 0b10010000, + 0b10010000, + + /* Character (0x69): 'i' + width=4 + +--------+ + | * | + | | + |** | + | * | + | * | + | * | + |*** | + +--------+ */ + 0b01000000|CHAR5x7_WIDTH_4px, + 0b00000000, + 0b11000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b11100000, + + /* Character (0x6a): + width=4 + +--------+ + | * | + | | + | * | + | * | + | * | + |* * | + | * | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_4px, + 0b00000000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b10100000, + 0b01000000, + + /* Character (0x6b): 'k' + width=5 + +--------+ + |* | + |* | + |* * | + |* * | + |** | + |* * | + |* * | + +--------+ */ + 0b10000000|CHAR5x7_WIDTH_5px, + 0b10000000, + 0b10010000, + 0b10100000, + 0b11000000, + 0b10100000, + 0b10010000, + + /* Character (0x6c): 'l' + width=4 + +--------+ + |** | + | * | + | * | + | * | + | * | + | * | + |*** | + +--------+ */ + 0b11000000|CHAR5x7_WIDTH_4px, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b11100000, + + /* Character (0x6d): 'm' + width=6 + +--------+ + | | + | | + |**** | + |* * * | + |* * * | + |* * * | + |* * * | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b00000000, + 0b11110000, + 0b10101000, + 0b10101000, + 0b10101000, + 0b10101000, + + /* Character (0x6e): 'n' + width=5 + +--------+ + | | + | | + |* * | + |** * | + |* * | + |* * | + |* * | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b10100000, + 0b11010000, + 0b10010000, + 0b10010000, + 0b10010000, + + /* Character (0x6f): 'o' + width=5 + +--------+ + | | + | | + | ** | + |* * | + |* * | + |* * | + | ** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b01100000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b01100000, + + /* Character (0x70): 'p' + width=5 + +--------+ + | | + | | + |*** | + |* * | + |* * | + |*** | + |* | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b11100000, + 0b10010000, + 0b10010000, + 0b11100000, + 0b10000000, + + /* Character (0x71): 'q' + width=5 + +--------+ + | | + | | + | *** | + |* * | + |* * | + | *** | + | * | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b01110000, + 0b10010000, + 0b10010000, + 0b01110000, + 0b00010000, + + /* Character (0x72): 'r' + width=5 + +--------+ + | | + | | + |* * | + |** * | + |* | + |* | + |* | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b10100000, + 0b11010000, + 0b10000000, + 0b10000000, + 0b10000000, + + /* Character (0x73): 's' + width=5 + +--------+ + | | + | | + | *** | + |* | + | ** | + | * | + |*** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b01110000, + 0b10000000, + 0b01100000, + 0b00010000, + 0b11100000, + + /* Character (0x74): 't' + width=5 + +--------+ + | * | + | * | + |*** | + | * | + | * | + | * | + | ** | + +--------+ */ + 0b01000000|CHAR5x7_WIDTH_5px, + 0b01000000, + 0b11100000, + 0b01000000, + 0b01000000, + 0b01000000, + 0b00110000, + + /* Character (0x75): 'u' + width=5 + +--------+ + | | + | | + |* * | + |* * | + |* * | + |* ** | + | * * | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b10110000, + 0b01010000, + + /* Character (0x76): 'v' + width=5 + +--------+ + | | + | | + |* * | + |* * | + |* * | + | ** | + | ** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b10010000, + 0b10010000, + 0b10010000, + 0b01100000, + 0b01100000, + + /* Character (0x77): 'w' + width=6 + +--------+ + | | + | | + |* * | + |* * | + |* * * | + |* * * | + | * * | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_6px, + 0b00000000, + 0b10001000, + 0b10001000, + 0b10101000, + 0b10101000, + 0b01010000, + + /* Character (0x78): 'x' + width=5 + +--------+ + | | + | | + |* * | + |* * | + | ** | + |* * | + |* * | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b10010000, + 0b10010000, + 0b01100000, + 0b10010000, + 0b10010000, + + /* Character (0x79): 'y' + width=5 + +--------+ + | | + | | + |* * | + |* * | + | *** | + | * | + |*** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b10010000, + 0b10010000, + 0b01110000, + 0b00010000, + 0b11100000, + + /* Character (0x7a): 'z' + width=5 + +--------+ + | | + | | + |**** | + | * | + | * | + |* | + |**** | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b11110000, + 0b00100000, + 0b01000000, + 0b10000000, + 0b11110000, + + /* Character (0x7b): '{' + width=5 + +--------+ + | * | + | * | + | * | + |* | + | * | + | * | + | * | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_4px, + 0b01000000, + 0b01000000, + 0b10000000, + 0b01000000, + 0b01000000, + 0b00100000, + + /* Character (0x7c): '|' + width=5 + +--------+ + | * | + | * | + | * | + | * | + | * | + | * | + | * | + +--------+ */ + 0b00100000|CHAR5x7_WIDTH_4px, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + 0b00100000, + + /* Character (0x7d): '}' + width=5 + +--------+ + |* | + | * | + | * | + | * | + | * | + | * | + |* | + +--------+ */ + 0b10000000|CHAR5x7_WIDTH_4px, + 0b01000000, + 0b01000000, + 0b00100000, + 0b01000000, + 0b01000000, + 0b10000000, + + /* Character (0x7e): '~' + width=5 + +--------+ + | | + | | + | * * | + |* * | + | | + | | + | | + +--------+ */ + 0b00000000|CHAR5x7_WIDTH_5px, + 0b00000000, + 0b01010000, + 0b10100000, + 0b00000000, + 0b00000000, + 0b00000000, +}; diff --git a/Makefile b/Makefile index 73ebbd9..bec51b8 100644 --- a/Makefile +++ b/Makefile @@ -100,9 +100,9 @@ include $(CHIBIOS)/os/hal/osal/rt/osal.mk include $(CHIBIOS)/os/rt/rt.mk include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk # Other files (optional). -include $(CHIBIOS)/test/rt/test.mk +#include $(CHIBIOS)/test/rt/test.mk include $(CHIBIOS)/os/hal/lib/streams/streams.mk -include $(CHIBIOS)/os/various/shell/shell.mk +#include $(CHIBIOS)/os/various/shell/shell.mk # Define linker script file here #LDSCRIPT= $(STARTUPLD)/STM32F072xB.ld @@ -118,12 +118,9 @@ CSRC = $(STARTUPSRC) \ $(PLATFORMSRC) \ $(BOARDSRC) \ $(STREAMSSRC) \ - $(SHELLSRC) \ usbcfg.c \ main.c si5351.c tlv320aic3204.c dsp.c plot.c ui.c ili9341.c numfont20x22.c Font5x7.c flash.c adc.c -# $(TESTSRC) \ - # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. CPPSRC = @@ -153,8 +150,7 @@ ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM) INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) \ - $(STREAMSINC) $(SHELLINC) -# $(TESTINC) + $(STREAMSINC) # # Project, sources and paths @@ -176,7 +172,7 @@ CPPC = $(TRGT)g++ LD = $(TRGT)gcc #LD = $(TRGT)g++ CP = $(TRGT)objcopy -AS = $(TRGT)gcc -x assembler-with-cpp +AS = $(TRGT)gcc -x assembler-with-cpp -ggdb AR = $(TRGT)ar OD = $(TRGT)objdump SZ = $(TRGT)size @@ -231,7 +227,4 @@ flash: build/ch.bin dfu: -@printf "reset dfu\r" >/dev/cu.usbmodem401 -TAGS: Makefile - @etags *.[ch] NANOVNA_STM32_F072/*.[ch] $(shell find ChibiOS/os/hal/ports/STM32/STM32F0xx ChibiOS/os -name \*.\[ch\] -print) - @ls -l TAGS diff --git a/NANOVNA_STM32_F072/board.h b/NANOVNA_STM32_F072/board.h index 7ab4c29..c64cf75 100644 --- a/NANOVNA_STM32_F072/board.h +++ b/NANOVNA_STM32_F072/board.h @@ -17,10 +17,6 @@ #ifndef _BOARD_H_ #define _BOARD_H_ -/* - * Setup for the Strawberry Linux STbee - */ - /* * Board identifier. */ @@ -130,8 +126,8 @@ PIN_MODE_ALTERNATE(GPIOA_MCO) | \ PIN_MODE_INPUT(9U) | \ PIN_MODE_OUTPUT(GPIOA_USB_DISC) | \ - PIN_MODE_INPUT(GPIOA_USB_DM) | \ - PIN_MODE_INPUT(GPIOA_USB_DP) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \ PIN_MODE_ALTERNATE(GPIOA_JTMS) | \ PIN_MODE_ALTERNATE(GPIOA_JTCK) | \ PIN_MODE_OUTPUT(GPIOA_LCD_RESET)) @@ -161,7 +157,7 @@ PIN_OSPEED_2M(7) | \ PIN_OSPEED_100M(GPIOA_MCO) | \ PIN_OSPEED_100M(9) | \ - PIN_OSPEED_100M(10) | \ + PIN_OSPEED_100M(GPIOA_USB_DISC) | \ PIN_OSPEED_100M(GPIOA_USB_DM) | \ PIN_OSPEED_100M(GPIOA_USB_DP) | \ PIN_OSPEED_100M(GPIOA_JTMS) | \ @@ -177,7 +173,7 @@ PIN_PUPDR_FLOATING(7) | \ PIN_PUPDR_PULLUP(GPIOA_MCO) | \ PIN_PUPDR_PULLUP(9) | \ - PIN_PUPDR_PULLUP(GPIOA_USB_DISC) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DISC) | \ PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \ PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \ PIN_PUPDR_PULLDOWN(GPIOA_JTMS) | \ diff --git a/adc.c b/adc.c index 1da498d..53ede93 100644 --- a/adc.c +++ b/adc.c @@ -28,80 +28,82 @@ #define ADC_SMPR_SMP_239P5 7U /**< @brief 252 cycles conversion time. */ #define ADC_CFGR1_RES_12BIT (0U << 3U) +#define VNA_ADC ADC1 + void adc_init(void) { rccEnableADC1(FALSE); /* Ensure flag states */ - ADC1->IER = 0; + VNA_ADC->IER = 0; /* Calibration procedure.*/ ADC->CCR = 0; - if (ADC1->CR & ADC_CR_ADEN) { - ADC1->CR |= ~ADC_CR_ADDIS; /* Disable ADC */ + if (VNA_ADC->CR & ADC_CR_ADEN) { + VNA_ADC->CR |= ~ADC_CR_ADDIS; /* Disable ADC */ } - while (ADC1->CR & ADC_CR_ADEN) + while (VNA_ADC->CR & ADC_CR_ADEN) ; - ADC1->CFGR1 &= ~ADC_CFGR1_DMAEN; - ADC1->CR |= ADC_CR_ADCAL; - while (ADC1->CR & ADC_CR_ADCAL) + VNA_ADC->CFGR1 &= ~ADC_CFGR1_DMAEN; + VNA_ADC->CR |= ADC_CR_ADCAL; + while (VNA_ADC->CR & ADC_CR_ADCAL) ; - if (ADC1->ISR & ADC_ISR_ADRDY) { - ADC1->ISR |= ADC_ISR_ADRDY; /* clear ADRDY */ + if (VNA_ADC->ISR & ADC_ISR_ADRDY) { + VNA_ADC->ISR |= ADC_ISR_ADRDY; /* clear ADRDY */ } /* Enable ADC */ - ADC1->CR |= ADC_CR_ADEN; - while (!(ADC1->ISR & ADC_ISR_ADRDY)) + VNA_ADC->CR |= ADC_CR_ADEN; + while (!(VNA_ADC->ISR & ADC_ISR_ADRDY)) ; } -uint16_t adc_single_read(ADC_TypeDef *adc, uint32_t chsel) +uint16_t adc_single_read(uint32_t chsel) { /* ADC setup */ - adc->ISR = adc->ISR; - adc->IER = 0; - adc->TR = ADC_TR(0, 0); - adc->SMPR = ADC_SMPR_SMP_239P5; - adc->CFGR1 = ADC_CFGR1_RES_12BIT; - adc->CHSELR = chsel; + VNA_ADC->ISR = VNA_ADC->ISR; + VNA_ADC->IER = 0; + VNA_ADC->TR = ADC_TR(0, 0); + VNA_ADC->SMPR = ADC_SMPR_SMP_239P5; + VNA_ADC->CFGR1 = ADC_CFGR1_RES_12BIT; + VNA_ADC->CHSELR = chsel; /* ADC conversion start.*/ - adc->CR |= ADC_CR_ADSTART; + VNA_ADC->CR |= ADC_CR_ADSTART; - while (adc->CR & ADC_CR_ADSTART) + while (VNA_ADC->CR & ADC_CR_ADSTART) ; - return adc->DR; + return VNA_ADC->DR; } -int16_t adc_vbat_read(ADC_TypeDef *adc) +int16_t adc_vbat_read(void) { +// 13.9 Temperature sensor and internal reference voltage +// VREFINT_CAL calibrated on 3.3V, need get value in mV #define ADC_FULL_SCALE 3300 -#define VBAT_DIODE_VF 500 #define VREFINT_CAL (*((uint16_t*)0x1FFFF7BA)) - float vbat = 0; - float vrefint = 0; - - ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_VBATEN; - // VREFINT == ADC_IN17 - vrefint = adc_single_read(adc, ADC_CHSELR_CHSEL17); - // VBAT == ADC_IN18 - // VBATEN enables resiter devider circuit. It consume vbat power. - vbat = adc_single_read(adc, ADC_CHSELR_CHSEL18); - ADC->CCR &= ~(ADC_CCR_VREFEN | ADC_CCR_VBATEN); - - uint16_t vbat_raw = (ADC_FULL_SCALE * VREFINT_CAL * vbat * 2 / (vrefint * ((1<<12)-1))); - if (vbat_raw < 100) { - // maybe D2 is not installed - return -1; - } - - return vbat_raw + VBAT_DIODE_VF; - + adc_stop(); + ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_VBATEN; + // VREFINT == ADC_IN17 + uint32_t vrefint = adc_single_read(ADC_CHSELR_CHSEL17); + // VBAT == ADC_IN18 + // VBATEN enables resiter devider circuit. It consume vbat power. + uint32_t vbat = adc_single_read(ADC_CHSELR_CHSEL18); + ADC->CCR &= ~(ADC_CCR_VREFEN | ADC_CCR_VBATEN); + touch_start_watchdog(); + // vbat_raw = (3300 * 2 * vbat / 4095) * (VREFINT_CAL / vrefint) + // uint16_t vbat_raw = (ADC_FULL_SCALE * VREFINT_CAL * (float)vbat * 2 / (vrefint * ((1<<12)-1))); + // For speed divide not on 4095, divide on 4096, get little error, but no matter + uint16_t vbat_raw = ((ADC_FULL_SCALE * 2 * vbat)>>12) * VREFINT_CAL / vrefint; + if (vbat_raw < 100) { + // maybe D2 is not installed + return -1; + } + return vbat_raw + config.vbat_offset; } -void adc_start_analog_watchdogd(ADC_TypeDef *adc, uint32_t chsel) +void adc_start_analog_watchdogd(uint32_t chsel) { uint32_t cfgr1; @@ -111,38 +113,38 @@ void adc_start_analog_watchdogd(ADC_TypeDef *adc, uint32_t chsel) /* ADC setup, if it is defined a callback for the analog watch dog then it is enabled.*/ - adc->ISR = adc->ISR; - adc->IER = ADC_IER_AWDIE; - adc->TR = ADC_TR(0, TOUCH_THRESHOLD); - adc->SMPR = ADC_SMPR_SMP_1P5; - adc->CHSELR = chsel; + VNA_ADC->ISR = VNA_ADC->ISR; + VNA_ADC->IER = ADC_IER_AWDIE; + VNA_ADC->TR = ADC_TR(0, TOUCH_THRESHOLD); + VNA_ADC->SMPR = ADC_SMPR_SMP_1P5; + VNA_ADC->CHSELR = chsel; /* ADC configuration and start.*/ - adc->CFGR1 = cfgr1; + VNA_ADC->CFGR1 = cfgr1; /* ADC conversion start.*/ - adc->CR |= ADC_CR_ADSTART; + VNA_ADC->CR |= ADC_CR_ADSTART; } -void adc_stop(ADC_TypeDef *adc) +void adc_stop(void) { - if (adc->CR & ADC_CR_ADEN) { - if (adc->CR & ADC_CR_ADSTART) { - adc->CR |= ADC_CR_ADSTP; - while (adc->CR & ADC_CR_ADSTP) + if (VNA_ADC->CR & ADC_CR_ADEN) { + if (VNA_ADC->CR & ADC_CR_ADSTART) { + VNA_ADC->CR |= ADC_CR_ADSTP; + while (VNA_ADC->CR & ADC_CR_ADSTP) ; } - /* adc->CR |= ADC_CR_ADDIS; - while (adc->CR & ADC_CR_ADDIS) + /* VNA_ADC->CR |= ADC_CR_ADDIS; + while (VNA_ADC->CR & ADC_CR_ADDIS) ;*/ } } -void adc_interrupt(ADC_TypeDef *adc) +void adc_interrupt(void) { - uint32_t isr = adc->ISR; - adc->ISR = isr; + uint32_t isr = VNA_ADC->ISR; + VNA_ADC->ISR = isr; if (isr & ADC_ISR_OVR) { /* ADC overflow condition, this could happen only if the DMA is unable @@ -159,7 +161,7 @@ OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER) { OSAL_IRQ_PROLOGUE(); - adc_interrupt(ADC1); + adc_interrupt(); OSAL_IRQ_EPILOGUE(); } diff --git a/chconf.h b/chconf.h index 34e6afe..fd54b74 100644 --- a/chconf.h +++ b/chconf.h @@ -156,7 +156,7 @@ * * @note The default is @p TRUE. */ -#define CH_CFG_USE_WAITEXIT TRUE +#define CH_CFG_USE_WAITEXIT FALSE /** * @brief Semaphores APIs. @@ -183,7 +183,7 @@ * * @note The default is @p TRUE. */ -#define CH_CFG_USE_MUTEXES TRUE +#define CH_CFG_USE_MUTEXES FALSE /** * @brief Enables recursive behavior on mutexes. @@ -193,7 +193,7 @@ * @note The default is @p FALSE. * @note Requires @p CH_CFG_USE_MUTEXES. */ -#define CH_CFG_USE_MUTEXES_RECURSIVE TRUE +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE /** * @brief Conditional Variables APIs. @@ -221,7 +221,7 @@ * * @note The default is @p TRUE. */ -#define CH_CFG_USE_EVENTS TRUE +#define CH_CFG_USE_EVENTS FALSE /** * @brief Events Flags APIs with timeout. @@ -231,7 +231,7 @@ * @note The default is @p TRUE. * @note Requires @p CH_CFG_USE_EVENTS. */ -#define CH_CFG_USE_EVENTS_TIMEOUT TRUE +#define CH_CFG_USE_EVENTS_TIMEOUT FALSE /** * @brief Synchronous Messages APIs. diff --git a/chprintf.c b/chprintf.c new file mode 100644 index 0000000..fbfd1cd --- /dev/null +++ b/chprintf.c @@ -0,0 +1,594 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* + Concepts and parts of this file have been contributed by Fabio Utzig, + chvprintf() added by Brent Roman. + */ + +/** + * @file chprintf.c + * @brief Mini printf-like functionality. + * + * @addtogroup chprintf + * @{ + */ + +#include "hal.h" +#include "chprintf.h" +//#include "memstreams.h" +#include + +// Enable [flags], support: +// ' ' Prepends a space for positive signed-numeric types. positive = ' ', negative = '-'. This flag is ignored if the + flag exists. +//#define CHPRINTF_USE_SPACE_FLAG + +// Force putting trailing zeros on float value +#define CHPRINTF_FORCE_TRAILING_ZEROS + +#define MAX_FILLER 11 +#define FLOAT_PRECISION 9 + +#pragma pack(push, 2) + +static const uint32_t pow10[FLOAT_PRECISION+1] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 +}; +// Prefixes for values bigger then 1000.0 +// 1 1e3, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24 +static char bigPrefix[] = {' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 0}; +// Prefixes for values less then 1.0 +// 1e-3, 1e-6, 1e-9, 1e-12, 1e-15, 1e-18, 1e-21, 1e-24 +static char smallPrefix[] = {'m', 0x1d, 'n', 'p', 'f', 'a', 'z', 'y', 0}; + +#pragma pack(pop) + +static char *long_to_string_with_divisor(char *p, + uint32_t num, + uint32_t radix, + uint32_t precision) { + char *q = p + MAX_FILLER; + char *b = q; + // convert to string from end buffer to begin + do { + uint8_t c = num % radix; + num /= radix; + *--q = c + ((c > 9) ? ('A'-10) : '0'); + }while((precision && --precision) || num); + // copy string at begin + int i = (int)(b - q); + do + *p++ = *q++; + while (--i); + return p; +} + +// default prescision = 13 +// g.mmm kkk hhh +#define MAX_FREQ_PRESCISION 13 +#define FREQ_PSET 1 +#define FREQ_NO_SPACE 2 +#define FREQ_PREFIX_SPACE 4 + +static char * +ulong_freq(char *p, uint32_t freq, uint32_t precision) +{ + uint8_t flag = FREQ_PSET; + if (precision == 0) + flag|=FREQ_PREFIX_SPACE; + if (precision == 0 || precision > MAX_FREQ_PRESCISION) + precision = MAX_FREQ_PRESCISION; + char *q = p + MAX_FREQ_PRESCISION; + char *b = q; + // Prefix counter + uint32_t s = 0; + // Set format (every 3 digits add ' ' up to GHz) + uint32_t format = 0b00100100100; + do { +#if 0 + uint8_t c = freq % 10; + freq/= 10; +#else + // Fast and compact division uint32_t on 10, using shifts, result: + // c = freq % 10 + // freq = freq / 10; + uint32_t c = freq; + freq >>= 1; + freq += freq >> 1; + freq += freq >> 4; + freq += freq >> 8; + freq += freq >> 16; // freq = 858993459*freq/1073741824 = freq * + // 0,799999999813735485076904296875 + freq >>= 3; // freq/=8; freq = freq * 0,09999999997671693563461303710938 + c -= freq * 10; // freq*10 = (freq*4+freq)*2 = ((freq<<2)+freq)<<1 + while (c >= 10) { + freq++; + c -= 10; + } +#endif + *--q = c + '0'; + if (freq == 0) break; + // Add spaces, calculate prefix + if (format & 1) { + *--q = ' '; + s++; + } + format >>= 1; + } while (1); + s = bigPrefix[s]; + + // Get string size + uint32_t i = (b - q); + // Limit string size, max size is - precision + if (precision && i > precision) { + i = precision; + flag |= FREQ_NO_SPACE; + } + // copy string + // Replace first ' ' by '.', remove ' ' if size too big + do { + char c = *q++; + // replace first ' ' on '.' + if (c == ' ') { + if (flag & FREQ_PSET) { + c = '.'; + flag &= ~FREQ_PSET; + } else if (flag & FREQ_NO_SPACE) + c = *q++; + } + *p++ = c; + } while (--i); + // Put pref (amd space before it if need) + if (flag & FREQ_PREFIX_SPACE && s != ' ') + *p++ = ' '; + *p++ = s; + return p; +} + +#if CHPRINTF_USE_FLOAT +static char *ftoa(char *p, float num, uint32_t precision) { + // Check precision limit + if (precision > FLOAT_PRECISION) + precision = FLOAT_PRECISION; + uint32_t multi = pow10[precision]; + uint32_t l = num; + // Round value + uint32_t k = ((num-l)*multi+0.5); + // Fix rounding error if get + if (k>=multi){k-=multi;l++;} + p = long_to_string_with_divisor(p, l, 10, 0); + if (precision) { + *p++ = '.'; + p=long_to_string_with_divisor(p, k, 10, precision); +#ifndef CHPRINTF_FORCE_TRAILING_ZEROS + // remove zeros at end + while (p[-1]=='0') p--; + if (p[-1]=='.') p--; +#endif + } + return p; +} + +static char *ftoaS(char *p, float num, uint32_t precision) { + char prefix=0; + char *ptr; + if (num > 1000.0){ + for (ptr = bigPrefix+1; *ptr && num > 1000.0; num/=1000, ptr++) + ; + prefix = ptr[-1]; + } + else if (num < 1){ + for (ptr = smallPrefix; *ptr && num < 1.0; num*=1000, ptr++) + ; + prefix = num > 1e-3 ? ptr[-1] : 0; + } + // Auto set prescision + uint32_t l = num; + if (l < 10) + precision+=2; + else if (l < 100) + precision+=1; + p=ftoa(p, num, precision); + if (prefix) + *p++ = prefix; + return p; +} +#endif + +/** + * @brief System formatted output function. + * @details This function implements a minimal @p vprintf()-like functionality + * with output on a @p BaseSequentialStream. + * The general parameters format is: %[-][width|*][.precision|*][l|L]p. + * The following parameter types (p) are supported: + * - x hexadecimal integer. + * - X hexadecimal long. + * - o octal integer. + * - O octal long. + * - d decimal signed integer. + * - D decimal signed long. + * - u decimal unsigned integer. + * - U decimal unsigned long. + * - c character. + * - s string. + * . + * + * @param[in] chp pointer to a @p BaseSequentialStream implementing object + * @param[in] fmt formatting string + * @param[in] ap list of parameters + * @return The number of bytes that would have been + * written to @p chp if no stream error occurs + * + * @api + */ +#define IS_LONG 1 +#define LEFT_ALIGN 2 +#define POSITIVE 4 +#define NEGATIVE 8 +#define PAD_ZERO 16 +#define PLUS_SPACE 32 +#define DEFAULT_PRESCISION 64 + +int chvprintf(BaseSequentialStream *chp, const char *fmt, va_list ap) { + char *p, *s, c, filler=' '; + int precision, width; + int n = 0; + uint32_t state; + union { + uint32_t u; + int32_t l; + float f; + }value; +#if CHPRINTF_USE_FLOAT + char tmpbuf[2*MAX_FILLER + 1]; +#else + char tmpbuf[MAX_FREQ_PRESCISION + 1]; +#endif + + while (true) { + c = *fmt++; + if (c == 0) + return n; + if (c != '%') { + streamPut(chp, (uint8_t)c); + n++; + continue; + } + // Parse %[flags][width][.precision][length]type + p = tmpbuf; + s = tmpbuf; + state = 0; + width = 0; + precision = 0; + + // Get [flags], support: + // '-' Left-align the output of this placeholder. (The default is to right-align the output.) + // '+' Prepends a plus for positive signed-numeric types. positive = '+', negative = '-'. + // ' ' Prepends a space for positive signed-numeric types. positive = ' ', negative = '-'. This flag is ignored if the + flag exists. + // '0' When the 'width' option is specified, prepends zeros for numeric types. (The default prepends spaces.) + while (true){ + if (*fmt == '-') + state|=LEFT_ALIGN; + else if (*fmt == '+') + state|=POSITIVE; + else if (*fmt == '0') + state|=PAD_ZERO; +#ifdef CHPRINTF_USE_SPACE_FLAG + else if (*fmt == ' ') + state|=PLUS_SPACE; +#endif + else + break; + fmt++; + } + // Get [width] - The Width field specifies a minimum number of characters to output + // if set *, get width as argument + while (true) { + c = *fmt++; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c == '*') + c = va_arg(ap, int); + else + break; + width = width * 10 + c; + } + // Get [.precision] + if (c == '.') { + while (true) { + c = *fmt++; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c == '*') + c = va_arg(ap, int); + else + break; + precision = precision * 10 + c; + } + } + else + state|=DEFAULT_PRESCISION; + //Get [length] + /* + if (c == 'l' || c == 'L') { + state|=IS_LONG; + if (*fmt) + c = *fmt++; + } + else if ((c >= 'A') && (c <= 'Z')) + state|=IS_LONG; + */ + // Parse type + switch (c) { + case 'c': + state&=~PAD_ZERO; + *p++ = va_arg(ap, int); + break; + case 's': + state&=~PAD_ZERO; + if ((s = va_arg(ap, char *)) == 0) + s = "(null)"; + if (state&DEFAULT_PRESCISION) + precision = 32767; + for (p = s; *p && (--precision >= 0); p++) + ; + break; + case 'D': + case 'd': + case 'I': + case 'i':/* + if (state & IS_LONG) + value.l = va_arg(ap, long); + else*/ + value.l = va_arg(ap, uint32_t); + if (value.l < 0) { + state|=NEGATIVE; + *p++ = '-'; + value.l = -value.l; + } + else if (state & POSITIVE) + *p++ = '+'; +#ifdef CHPRINTF_USE_SPACE_FLAG + else if (state & PLUS_SPACE) + *p++ = ' '; +#endif + p = long_to_string_with_divisor(p, value.l, 10, 0); + break; + case 'q': + value.u = va_arg(ap, uint32_t); + p=ulong_freq(p, value.u, precision); + break; +#if CHPRINTF_USE_FLOAT + case 'F': + case 'f': + value.f = va_arg(ap, double); + if (value.f < 0) { + state|=NEGATIVE; + *p++ = '-'; + value.f = -value.f; + } + else if (state & POSITIVE) + *p++ = '+'; +#ifdef CHPRINTF_USE_SPACE_FLAG + else if (state & PLUS_SPACE) + *p++ = ' '; +#endif + if (value.f == INFINITY){ + *p++ = 0x19; + break; + } + p = (c=='F') ? ftoaS(p, value.f, precision) : ftoa(p, value.f, state&DEFAULT_PRESCISION ? FLOAT_PRECISION : precision); + break; +#endif + case 'X': + case 'x': + c = 16; + goto unsigned_common; + case 'U': + case 'u': + c = 10; + goto unsigned_common; + case 'O': + case 'o': + c = 8; +unsigned_common:/* + if (state & IS_LONG) + value.u = va_arg(ap, unsigned long); + else*/ + value.u = va_arg(ap, uint32_t); + p = long_to_string_with_divisor(p, value.u, c, 0); + break; + default: + *p++ = c; + break; + } + // Now need print buffer s[{sign}XXXXXXXXXXXX]p and align it on width + // Check filler width (if buffer less then width) and prepare filler if need fill + if ((width -=(int)(p - s)) < 0) + width = 0; + else + filler = (state&PAD_ZERO) ? '0' : ' '; + // if left align, put sign digit, and fill + // [{sign}ffffffXXXXXXXXXXXX] + if (!(state&LEFT_ALIGN)) { + // Put '+' or '-' or ' ' first if need + if ((state&(NEGATIVE|POSITIVE|PLUS_SPACE)) && (state&PAD_ZERO)) { + streamPut(chp, (uint8_t)*s++); + n++; + } + // fill from left + while (width){ + streamPut(chp, (uint8_t)filler); + n++; + width--; + } + } + // put data + while (s < p) { + streamPut(chp, (uint8_t)*s++); + n++; + } + // Put filler from right (if need) + while (width) { + streamPut(chp, (uint8_t)filler); + n++; + width--; + } + } +} + +/** + * @brief System formatted output function. + * @details This function implements a minimal @p printf() like functionality + * with output on a @p BaseSequentialStream. + * The general parameters format is: %[-][width|*][.precision|*][l|L]p. + * The following parameter types (p) are supported: + * - x hexadecimal integer. + * - X hexadecimal long. + * - o octal integer. + * - O octal long. + * - d decimal signed integer. + * - D decimal signed long. + * - u decimal unsigned integer. + * - U decimal unsigned long. + * - c character. + * - s string. + * . + * + * @param[in] chp pointer to a @p BaseSequentialStream implementing object + * @param[in] fmt formatting string + * + * @api + */ +#if 0 +int chprintf(BaseSequentialStream *chp, const char *fmt, ...) { + va_list ap; + int formatted_bytes; + + va_start(ap, fmt); + formatted_bytes = chvprintf(chp, fmt, ap); + va_end(ap); + + return formatted_bytes; +} +#endif +/** + * @brief System formatted output function. + * @details This function implements a minimal @p vprintf()-like functionality + * with output on a @p BaseSequentialStream. + * The general parameters format is: %[-][width|*][.precision|*][l|L]p. + * The following parameter types (p) are supported: + * - x hexadecimal integer. + * - X hexadecimal long. + * - o octal integer. + * - O octal long. + * - d decimal signed integer. + * - D decimal signed long. + * - u decimal unsigned integer. + * - U decimal unsigned long. + * - c character. + * - s string. + * . + * @post @p str is NUL-terminated, unless @p size is 0. + * + * @param[in] str pointer to a buffer + * @param[in] size maximum size of the buffer + * @param[in] fmt formatting string + * @return The number of characters (excluding the + * terminating NUL byte) that would have been + * stored in @p str if there was room. + * + * @api + */ +#if 0 +int chsnprintf(char *str, size_t size, const char *fmt, ...) { + va_list ap; + MemoryStream ms; + BaseSequentialStream *chp; + size_t size_wo_nul; + int retval; + + if (size > 0) + size_wo_nul = size - 1; + else + size_wo_nul = 0; + + /* Memory stream object to be used as a string writer, reserving one + byte for the final zero.*/ + msObjectInit(&ms, (uint8_t *)str, size_wo_nul, 0); + + /* Performing the print operation using the common code.*/ + chp = (BaseSequentialStream *)(void *)&ms; + va_start(ap, fmt); + retval = chvprintf(chp, fmt, ap); + va_end(ap); + + /* Terminate with a zero, unless size==0.*/ + if (ms.eos < size) + str[ms.eos] = 0; + + /* Return number of bytes that would have been written.*/ + return retval; +} +#endif + +// +// Small memory stream object, only put function +// +struct printStreamVMT { + _base_sequential_stream_methods +}; + +typedef struct { + const struct printStreamVMT *vmt; + uint8_t *buffer; + uint16_t size; +} printStream; + +static msg_t put(void *ip, uint8_t b) { + printStream *ps = ip; + if (ps->size > 1){ + *(ps->buffer++) = b; + ps->size--; + } + return MSG_OK; +} + +static const struct printStreamVMT vmt = {NULL, NULL, put, NULL}; +void printObjectInit(printStream *ps, int size, uint8_t *buffer){ + ps->vmt = &vmt; + ps->buffer = buffer; + ps->size = size; +} +// Simple print in buffer function +int plot_printf(char *str, int size, const char *fmt, ...) { + va_list ap; + printStream ps; + int retval; + if (size <= 0) return 0; + // Init small memory stream for print + printObjectInit(&ps, size, (uint8_t *)str); + // Performing the print operation using the common code. + va_start(ap, fmt); + retval = chvprintf((BaseSequentialStream *)(void *)&ps, fmt, ap); + va_end(ap); + *(ps.buffer)=0; + if (retval > size-1) retval = size-1; + // Return number of bytes that would have been written. + return retval; +} + +/** @} */ diff --git a/fft.h b/fft.h index 0c367b7..dbaa32f 100644 --- a/fft.h +++ b/fft.h @@ -68,8 +68,8 @@ static void fft256(float array[][2], const uint8_t dir) { uint16_t j, k; for (j = i, k = 0; j < i + halfsize; j++, k += tablestep) { uint16_t l = j + halfsize; - float tpre = array[l][real] * cos(2 * M_PI * k / 256) + array[l][imag] * sin(2 * M_PI * k / 256); - float tpim = -array[l][real] * sin(2 * M_PI * k / 256) + array[l][imag] * cos(2 * M_PI * k / 256); + float tpre = array[l][real] * cos(2 * VNA_PI * k / 256) + array[l][imag] * sin(2 * VNA_PI * k / 256); + float tpim = -array[l][real] * sin(2 * VNA_PI * k / 256) + array[l][imag] * cos(2 * VNA_PI * k / 256); array[l][real] = array[j][real] - tpre; array[l][imag] = array[j][imag] - tpim; array[j][real] += tpre; diff --git a/flash.c b/flash.c index 01f58f1..a66315d 100644 --- a/flash.c +++ b/flash.c @@ -32,12 +32,12 @@ static int flash_wait_for_last_operation(void) static void flash_erase_page0(uint32_t page_address) { - flash_wait_for_last_operation(); - FLASH->CR |= FLASH_CR_PER; - FLASH->AR = page_address; - FLASH->CR |= FLASH_CR_STRT; - flash_wait_for_last_operation(); - FLASH->CR &= ~FLASH_CR_PER; + flash_wait_for_last_operation(); + FLASH->CR |= FLASH_CR_PER; + FLASH->AR = page_address; + FLASH->CR |= FLASH_CR_STRT; + flash_wait_for_last_operation(); + FLASH->CR &= ~FLASH_CR_PER; } int flash_erase_page(uint32_t page_address) @@ -50,11 +50,11 @@ int flash_erase_page(uint32_t page_address) void flash_program_half_word(uint32_t address, uint16_t data) { - flash_wait_for_last_operation(); - FLASH->CR |= FLASH_CR_PG; - *(__IO uint16_t*)address = data; - flash_wait_for_last_operation(); - FLASH->CR &= ~FLASH_CR_PG; + flash_wait_for_last_operation(); + FLASH->CR |= FLASH_CR_PG; + *(__IO uint16_t*)address = data; + flash_wait_for_last_operation(); + FLASH->CR &= ~FLASH_CR_PG; } void flash_unlock(void) @@ -64,7 +64,6 @@ void flash_unlock(void) FLASH->KEYR = 0xCDEF89AB; } - static uint32_t checksum(const void *start, size_t len) { @@ -72,14 +71,14 @@ checksum(const void *start, size_t len) uint32_t *tail = (uint32_t*)(start + len); uint32_t value = 0; while (p < tail) - value ^= *p++; + value = __ROR(value, 31) + *p++; return value; } #define FLASH_PAGESIZE 0x800 -const uint32_t save_config_area = 0x08018000; +const uint32_t save_config_area = SAVE_CONFIG_ADDR; int config_save(void) @@ -89,8 +88,7 @@ config_save(void) int count = sizeof(config_t) / sizeof(uint16_t); config.magic = CONFIG_MAGIC; - config.checksum = 0; - config.checksum = checksum(&config, sizeof config); + config.checksum = checksum(&config, sizeof config - sizeof config.checksum); flash_unlock(); @@ -98,7 +96,7 @@ config_save(void) flash_erase_page((uint32_t)dst); /* write to flahs */ - while(count-- > 0) { + while (count-- > 0) { flash_program_half_word((uint32_t)dst, *src++); dst++; } @@ -114,7 +112,7 @@ config_recall(void) if (src->magic != CONFIG_MAGIC) return -1; - if (checksum(src, sizeof(config_t)) != 0) + if (checksum(src, sizeof *src - sizeof src->checksum) != src->checksum) return -1; /* duplicated saved data onto sram to be able to modify marker/trace */ @@ -122,14 +120,15 @@ config_recall(void) return 0; } -#define SAVEAREA_MAX 5 - -const uint32_t saveareas[] = - { 0x08018800, 0x0801a000, 0x0801b800, 0x0801d000, 0x0801e800 }; +const uint32_t saveareas[SAVEAREA_MAX] = { + SAVE_PROP_CONFIG_0_ADDR, + SAVE_PROP_CONFIG_1_ADDR, + SAVE_PROP_CONFIG_2_ADDR, + SAVE_PROP_CONFIG_3_ADDR, + SAVE_PROP_CONFIG_4_ADDR }; int16_t lastsaveid = 0; - int caldata_save(int id) { @@ -142,8 +141,8 @@ caldata_save(int id) dst = (uint16_t*)saveareas[id]; current_props.magic = CONFIG_MAGIC; - current_props.checksum = 0; - current_props.checksum = checksum(¤t_props, sizeof current_props); + current_props.checksum = checksum( + ¤t_props, sizeof current_props - sizeof current_props.checksum); flash_unlock(); @@ -156,7 +155,7 @@ caldata_save(int id) } /* write to flahs */ - while(count-- > 0) { + while (count-- > 0) { flash_program_half_word((uint32_t)dst, *src++); dst++; } @@ -175,15 +174,15 @@ caldata_recall(int id) void *dst = ¤t_props; if (id < 0 || id >= SAVEAREA_MAX) - return -1; + goto load_default; // point to saved area on the flash memory src = (properties_t*)saveareas[id]; if (src->magic != CONFIG_MAGIC) - return -1; - if (checksum(src, sizeof(properties_t)) != 0) - return -1; + goto load_default; + if (checksum(src, sizeof *src - sizeof src->checksum) != src->checksum) + goto load_default; /* active configuration points to save data on flash memory */ active_props = src; @@ -191,8 +190,10 @@ caldata_recall(int id) /* duplicated saved data onto sram to be able to modify marker/trace */ memcpy(dst, src, sizeof(properties_t)); - return 0; +load_default: + load_default_properties(); + return -1; } const properties_t * @@ -205,12 +206,12 @@ caldata_ref(int id) if (src->magic != CONFIG_MAGIC) return NULL; - if (checksum(src, sizeof(properties_t)) != 0) + if (checksum(src, sizeof *src - sizeof src->checksum) != src->checksum) return NULL; return src; } -const uint32_t save_config_prop_area_size = 0x8000; +const uint32_t save_config_prop_area_size = SAVE_CONFIG_AREA_SIZE; void clear_all_config_prop_data(void) diff --git a/halconf.h b/halconf.h index 9a44c8b..38341a0 100644 --- a/halconf.h +++ b/halconf.h @@ -118,7 +118,7 @@ * @brief Enables the RTC subsystem. */ #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) -#define HAL_USE_RTC TRUE +#define HAL_USE_RTC FALSE #endif /** diff --git a/ili9341.c b/ili9341.c index 12edc9c..f1e4674 100644 --- a/ili9341.c +++ b/ili9341.c @@ -21,99 +21,99 @@ #include "hal.h" #include "nanovna.h" -uint16_t spi_buffer[1024]; +uint16_t spi_buffer[SPI_BUFFER_SIZE]; // Default foreground & background colors -uint16_t foreground_color=DEFAULT_FG_COLOR; -uint16_t background_color=DEFAULT_BG_COLOR; +uint16_t foreground_color = 0; +uint16_t background_color = 0; // Display width and height definition -#define ILI9341_WIDTH 320 -#define ILI9341_HEIGHT 240 +#define ILI9341_WIDTH 320 +#define ILI9341_HEIGHT 240 // Display commands list -#define ILI9341_NOP 0x00 -#define ILI9341_SOFTWARE_RESET 0x01 -#define ILI9341_READ_IDENTIFICATION 0x04 -#define ILI9341_READ_STATUS 0x09 -#define ILI9341_READ_POWER_MODE 0x0A -#define ILI9341_READ_MADCTL 0x0B -#define ILI9341_READ_PIXEL_FORMAT 0x0C -#define ILI9341_READ_IMAGE_FORMAT 0x0D -#define ILI9341_READ_SIGNAL_MODE 0x0E -#define ILI9341_READ_SELF_DIAGNOSTIC 0x0F -#define ILI9341_SLEEP_IN 0x10 -#define ILI9341_SLEEP_OUT 0x11 -#define ILI9341_PARTIAL_MODE_ON 0x12 -#define ILI9341_NORMAL_DISPLAY_MODE_ON 0x13 -#define ILI9341_INVERSION_OFF 0x20 -#define ILI9341_INVERSION_ON 0x21 -#define ILI9341_GAMMA_SET 0x26 -#define ILI9341_DISPLAY_OFF 0x28 -#define ILI9341_DISPLAY_ON 0x29 -#define ILI9341_COLUMN_ADDRESS_SET 0x2A -#define ILI9341_PAGE_ADDRESS_SET 0x2B -#define ILI9341_MEMORY_WRITE 0x2C -#define ILI9341_COLOR_SET 0x2D -#define ILI9341_MEMORY_READ 0x2E -#define ILI9341_PARTIAL_AREA 0x30 -#define ILI9341_VERTICAL_SCROLLING_DEF 0x33 -#define ILI9341_TEARING_LINE_OFF 0x34 -#define ILI9341_TEARING_LINE_ON 0x35 -#define ILI9341_MEMORY_ACCESS_CONTROL 0x36 -#define ILI9341_VERTICAL_SCROLLING 0x37 -#define ILI9341_IDLE_MODE_OFF 0x38 -#define ILI9341_IDLE_MODE_ON 0x39 -#define ILI9341_PIXEL_FORMAT_SET 0x3A -#define ILI9341_WRITE_MEMORY_CONTINUE 0x3C -#define ILI9341_READ_MEMORY_CONTINUE 0x3E -#define ILI9341_SET_TEAR_SCANLINE 0x44 -#define ILI9341_GET_SCANLINE 0x45 -#define ILI9341_WRITE_BRIGHTNESS 0x51 -#define ILI9341_READ_BRIGHTNESS 0x52 -#define ILI9341_WRITE_CTRL_DISPLAY 0x53 -#define ILI9341_READ_CTRL_DISPLAY 0x54 -#define ILI9341_WRITE_CA_BRIGHTNESS 0x55 -#define ILI9341_READ_CA_BRIGHTNESS 0x56 -#define ILI9341_WRITE_CA_MIN_BRIGHTNESS 0x5E -#define ILI9341_READ_CA_MIN_BRIGHTNESS 0x5F -#define ILI9341_READ_ID1 0xDA -#define ILI9341_READ_ID2 0xDB -#define ILI9341_READ_ID3 0xDC -#define ILI9341_RGB_INTERFACE_CONTROL 0xB0 -#define ILI9341_FRAME_RATE_CONTROL_1 0xB1 -#define ILI9341_FRAME_RATE_CONTROL_2 0xB2 -#define ILI9341_FRAME_RATE_CONTROL_3 0xB3 -#define ILI9341_DISPLAY_INVERSION_CONTROL 0xB4 -#define ILI9341_BLANKING_PORCH_CONTROL 0xB5 -#define ILI9341_DISPLAY_FUNCTION_CONTROL 0xB6 -#define ILI9341_ENTRY_MODE_SET 0xB7 -#define ILI9341_BACKLIGHT_CONTROL_1 0xB8 -#define ILI9341_BACKLIGHT_CONTROL_2 0xB9 -#define ILI9341_BACKLIGHT_CONTROL_3 0xBA -#define ILI9341_BACKLIGHT_CONTROL_4 0xBB -#define ILI9341_BACKLIGHT_CONTROL_5 0xBC -#define ILI9341_BACKLIGHT_CONTROL_7 0xBE -#define ILI9341_BACKLIGHT_CONTROL_8 0xBF -#define ILI9341_POWER_CONTROL_1 0xC0 -#define ILI9341_POWER_CONTROL_2 0xC1 -#define ILI9341_VCOM_CONTROL_1 0xC5 -#define ILI9341_VCOM_CONTROL_2 0xC7 -#define ILI9341_POWERA 0xCB -#define ILI9341_POWERB 0xCF -#define ILI9341_NV_MEMORY_WRITE 0xD0 -#define ILI9341_NV_PROTECTION_KEY 0xD1 -#define ILI9341_NV_STATUS_READ 0xD2 -#define ILI9341_READ_ID4 0xD3 -#define ILI9341_POSITIVE_GAMMA_CORRECTION 0xE0 -#define ILI9341_NEGATIVE_GAMMA_CORRECTION 0xE1 -#define ILI9341_DIGITAL_GAMMA_CONTROL_1 0xE2 -#define ILI9341_DIGITAL_GAMMA_CONTROL_2 0xE3 -#define ILI9341_DTCA 0xE8 -#define ILI9341_DTCB 0xEA -#define ILI9341_POWER_SEQ 0xED -#define ILI9341_3GAMMA_EN 0xF2 -#define ILI9341_INTERFACE_CONTROL 0xF6 -#define ILI9341_PUMP_RATIO_CONTROL 0xF7 +#define ILI9341_NOP 0x00 +#define ILI9341_SOFTWARE_RESET 0x01 +#define ILI9341_READ_IDENTIFICATION 0x04 +#define ILI9341_READ_STATUS 0x09 +#define ILI9341_READ_POWER_MODE 0x0A +#define ILI9341_READ_MADCTL 0x0B +#define ILI9341_READ_PIXEL_FORMAT 0x0C +#define ILI9341_READ_IMAGE_FORMAT 0x0D +#define ILI9341_READ_SIGNAL_MODE 0x0E +#define ILI9341_READ_SELF_DIAGNOSTIC 0x0F +#define ILI9341_SLEEP_IN 0x10 +#define ILI9341_SLEEP_OUT 0x11 +#define ILI9341_PARTIAL_MODE_ON 0x12 +#define ILI9341_NORMAL_DISPLAY_MODE_ON 0x13 +#define ILI9341_INVERSION_OFF 0x20 +#define ILI9341_INVERSION_ON 0x21 +#define ILI9341_GAMMA_SET 0x26 +#define ILI9341_DISPLAY_OFF 0x28 +#define ILI9341_DISPLAY_ON 0x29 +#define ILI9341_COLUMN_ADDRESS_SET 0x2A +#define ILI9341_PAGE_ADDRESS_SET 0x2B +#define ILI9341_MEMORY_WRITE 0x2C +#define ILI9341_COLOR_SET 0x2D +#define ILI9341_MEMORY_READ 0x2E +#define ILI9341_PARTIAL_AREA 0x30 +#define ILI9341_VERTICAL_SCROLLING_DEF 0x33 +#define ILI9341_TEARING_LINE_OFF 0x34 +#define ILI9341_TEARING_LINE_ON 0x35 +#define ILI9341_MEMORY_ACCESS_CONTROL 0x36 +#define ILI9341_VERTICAL_SCROLLING 0x37 +#define ILI9341_IDLE_MODE_OFF 0x38 +#define ILI9341_IDLE_MODE_ON 0x39 +#define ILI9341_PIXEL_FORMAT_SET 0x3A +#define ILI9341_WRITE_MEMORY_CONTINUE 0x3C +#define ILI9341_READ_MEMORY_CONTINUE 0x3E +#define ILI9341_SET_TEAR_SCANLINE 0x44 +#define ILI9341_GET_SCANLINE 0x45 +#define ILI9341_WRITE_BRIGHTNESS 0x51 +#define ILI9341_READ_BRIGHTNESS 0x52 +#define ILI9341_WRITE_CTRL_DISPLAY 0x53 +#define ILI9341_READ_CTRL_DISPLAY 0x54 +#define ILI9341_WRITE_CA_BRIGHTNESS 0x55 +#define ILI9341_READ_CA_BRIGHTNESS 0x56 +#define ILI9341_WRITE_CA_MIN_BRIGHTNESS 0x5E +#define ILI9341_READ_CA_MIN_BRIGHTNESS 0x5F +#define ILI9341_READ_ID1 0xDA +#define ILI9341_READ_ID2 0xDB +#define ILI9341_READ_ID3 0xDC +#define ILI9341_RGB_INTERFACE_CONTROL 0xB0 +#define ILI9341_FRAME_RATE_CONTROL_1 0xB1 +#define ILI9341_FRAME_RATE_CONTROL_2 0xB2 +#define ILI9341_FRAME_RATE_CONTROL_3 0xB3 +#define ILI9341_DISPLAY_INVERSION_CONTROL 0xB4 +#define ILI9341_BLANKING_PORCH_CONTROL 0xB5 +#define ILI9341_DISPLAY_FUNCTION_CONTROL 0xB6 +#define ILI9341_ENTRY_MODE_SET 0xB7 +#define ILI9341_BACKLIGHT_CONTROL_1 0xB8 +#define ILI9341_BACKLIGHT_CONTROL_2 0xB9 +#define ILI9341_BACKLIGHT_CONTROL_3 0xBA +#define ILI9341_BACKLIGHT_CONTROL_4 0xBB +#define ILI9341_BACKLIGHT_CONTROL_5 0xBC +#define ILI9341_BACKLIGHT_CONTROL_7 0xBE +#define ILI9341_BACKLIGHT_CONTROL_8 0xBF +#define ILI9341_POWER_CONTROL_1 0xC0 +#define ILI9341_POWER_CONTROL_2 0xC1 +#define ILI9341_VCOM_CONTROL_1 0xC5 +#define ILI9341_VCOM_CONTROL_2 0xC7 +#define ILI9341_POWERA 0xCB +#define ILI9341_POWERB 0xCF +#define ILI9341_NV_MEMORY_WRITE 0xD0 +#define ILI9341_NV_PROTECTION_KEY 0xD1 +#define ILI9341_NV_STATUS_READ 0xD2 +#define ILI9341_READ_ID4 0xD3 +#define ILI9341_POSITIVE_GAMMA_CORRECTION 0xE0 +#define ILI9341_NEGATIVE_GAMMA_CORRECTION 0xE1 +#define ILI9341_DIGITAL_GAMMA_CONTROL_1 0xE2 +#define ILI9341_DIGITAL_GAMMA_CONTROL_2 0xE3 +#define ILI9341_DTCA 0xE8 +#define ILI9341_DTCB 0xEA +#define ILI9341_POWER_SEQ 0xED +#define ILI9341_3GAMMA_EN 0xF2 +#define ILI9341_INTERFACE_CONTROL 0xF6 +#define ILI9341_PUMP_RATIO_CONTROL 0xF7 // // ILI9341_MEMORY_ACCESS_CONTROL registers @@ -126,20 +126,21 @@ uint16_t background_color=DEFAULT_BG_COLOR; #define ILI9341_MADCTL_MH 0x04 #define ILI9341_MADCTL_RGB 0x00 -#define DISPLAY_ROTATION_270 (ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR) -#define DISPLAY_ROTATION_90 (ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR) -#define DISPLAY_ROTATION_0 (ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR) -#define DISPLAY_ROTATION_180 (ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR) +#define DISPLAY_ROTATION_270 (ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR) +#define DISPLAY_ROTATION_90 (ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR) +#define DISPLAY_ROTATION_0 (ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR) +#define DISPLAY_ROTATION_180 (ILI9341_MADCTL_MX | ILI9341_MADCTL_MY \ + | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR) // // Pin macros // -#define RESET_ASSERT palClearPad(GPIOA, 15) -#define RESET_NEGATE palSetPad(GPIOA, 15) -#define CS_LOW palClearPad(GPIOB, 6) -#define CS_HIGH palSetPad(GPIOB, 6) -#define DC_CMD palClearPad(GPIOB, 7) -#define DC_DATA palSetPad(GPIOB, 7) +#define RESET_ASSERT palClearPad(GPIOA, 15) +#define RESET_NEGATE palSetPad(GPIOA, 15) +#define CS_LOW palClearPad(GPIOB, 6) +#define CS_HIGH palSetPad(GPIOB, 6) +#define DC_CMD palClearPad(GPIOB, 7) +#define DC_DATA palSetPad(GPIOB, 7) //***************************************************************************** //********************************** SPI bus ********************************** @@ -159,17 +160,17 @@ uint16_t background_color=DEFAULT_BG_COLOR; // The RXNE flag is set depending on the FRXTH bit value in the SPIx_CR2 register: // • If FRXTH is set, RXNE goes high and stays high until the RXFIFO level is greater or equal to 1/4 (8-bit). -#define SPI_RX_IS_NOT_EMPTY (SPI1->SR&SPI_SR_RXNE) +#define SPI_RX_IS_NOT_EMPTY (SPI1->SR&SPI_SR_RXNE) #define SPI_RX_IS_EMPTY (((SPI1->SR&SPI_SR_RXNE) == 0)) // The TXE flag is set when transmission TXFIFO has enough space to store data to send. // 0: Tx buffer not empty, bit is cleared automatically when the TXFIFO level becomes greater than 1/2 // 1: Tx buffer empty, flag goes high and stays high until the TXFIFO level is lower or equal to 1/2 of the FIFO depth -#define SPI_TX_IS_NOT_EMPTY (((SPI1->SR&(SPI_SR_TXE)) == 0)) +#define SPI_TX_IS_NOT_EMPTY (((SPI1->SR&(SPI_SR_TXE)) == 0)) #define SPI_TX_IS_EMPTY (SPI1->SR&SPI_SR_TXE) // When BSY is set, it indicates that a data transfer is in progress on the SPI (the SPI bus is busy). -#define SPI_IS_BUSY (SPI1->SR & SPI_SR_BSY) +#define SPI_IS_BUSY (SPI1->SR & SPI_SR_BSY) // SPI send data macros #define SPI_WRITE_8BIT(data) *(__IO uint8_t*)(&SPI1->DR) = (uint8_t) data @@ -179,40 +180,45 @@ uint16_t background_color=DEFAULT_BG_COLOR; #define SPI_READ_DATA SPI1->DR #ifdef __USE_DISPLAY_DMA__ -static const stm32_dma_stream_t *dmatx = STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM); -static uint32_t txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) // Select SPI1 Tx DMA - | STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) // Set priority - | STM32_DMA_CR_DIR_M2P // Memory to Spi - | STM32_DMA_CR_DMEIE // - | STM32_DMA_CR_TEIE; - -static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { +static const stm32_dma_stream_t *dmatx = + STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM); +static uint32_t txdmamode = + STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) // Select SPI1 Tx DMA + | STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) // Set priority + | STM32_DMA_CR_DIR_M2P // Memory to Spi + | STM32_DMA_CR_DMEIE // + | STM32_DMA_CR_TEIE; + +static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) +{ (void)spip; (void)flags; } static const stm32_dma_stream_t *dmarx = STM32_DMA_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM); static uint32_t rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_CHANNEL) - | STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) - | STM32_DMA_CR_DIR_P2M - | STM32_DMA_CR_TCIE - | STM32_DMA_CR_DMEIE - | STM32_DMA_CR_TEIE; + | STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) + | STM32_DMA_CR_DIR_P2M + | STM32_DMA_CR_TCIE + | STM32_DMA_CR_DMEIE + | STM32_DMA_CR_TEIE; -static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { +static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) +{ (void)spip; (void)flags; } -static void dmaStreamFlush(uint32_t len){ - while (len){ - // DMA data transfer limited by 65535 - uint16_t tx_size = len > 65535 ? 65535 : len; - dmaStreamSetTransactionSize(dmatx, tx_size); - dmaStreamEnable(dmatx); - len -= tx_size; - dmaWaitCompletion(dmatx); - } +static void dmaStreamFlush(uint32_t len) +{ + while (len) { + // DMA data transfer limited by 65535 + uint16_t tx_size = len > 65535 ? 65535 : len; + dmaStreamSetTransactionSize(dmatx, tx_size); + dmaStreamEnable(dmatx); + len -= tx_size; + dmaWaitCompletion(dmatx); + } } #endif @@ -221,13 +227,13 @@ static void spi_init(void) rccEnableSPI1(FALSE); SPI1->CR1 = 0; SPI1->CR1 = SPI_CR1_MSTR // SPI is MASTER - | SPI_CR1_SSM // Software slave management (The external NSS pin is free for other application uses) - | SPI_CR1_SSI; // Internal slave select (This bit has an effect only when the SSM bit is set. Allow use NSS pin as I/O) - // | SPI_CR1_BR_1; // Baud rate control + | SPI_CR1_SSM // Software slave management (The external NSS pin is free for other application uses) + | SPI_CR1_SSI; // Internal slave select (This bit has an effect only when the SSM bit is set. Allow use NSS pin as I/O) +// | SPI_CR1_BR_1; // Baud rate control SPI1->CR2 = SPI_CR2_8BIT // SPI data size, set to 8 bit - | SPI_CR2_FRXTH; // SPI_SR_RXNE generated every 8 bit data -// | SPI_CR2_SSOE; // + | SPI_CR2_FRXTH; // SPI_SR_RXNE generated every 8 bit data +// | SPI_CR2_SSOE; // #ifdef __USE_DISPLAY_DMA__ // Tx DMA init @@ -238,7 +244,7 @@ static void spi_init(void) dmaStreamSetPeripheral(dmarx, &SPI1->DR); // Enable DMA on SPI SPI1->CR2|= SPI_CR2_TXDMAEN // Tx DMA enable - | SPI_CR2_RXDMAEN; // Rx DMA enable + | SPI_CR2_RXDMAEN; // Rx DMA enable #endif SPI1->CR1|= SPI_CR1_SPE; //SPI enable } @@ -246,166 +252,170 @@ static void spi_init(void) // Disable inline for this function static void __attribute__ ((noinline)) send_command(uint8_t cmd, uint8_t len, const uint8_t *data) { - CS_LOW; - // while (SPI_TX_IS_NOT_EMPTY); - DC_CMD; - SPI_WRITE_8BIT(cmd); - // Need wait transfer complete and set data bit - while (SPI_IS_BUSY); - // Send command data (if need) - DC_DATA; - while (len-- > 0) { - while (SPI_TX_IS_NOT_EMPTY); - SPI_WRITE_8BIT(*data++); - } - //CS_HIGH; + CS_LOW; + //while (SPI_TX_IS_NOT_EMPTY); + DC_CMD; + SPI_WRITE_8BIT(cmd); + // Need wait transfer complete and set data bit + while (SPI_IS_BUSY) + ; + // Send command data (if need) + DC_DATA; + while (len-- > 0) { + while (SPI_TX_IS_NOT_EMPTY) + ; + SPI_WRITE_8BIT(*data++); + } + //CS_HIGH; } static const uint8_t ili9341_init_seq[] = { - // cmd, len, data..., - // SW reset - ILI9341_SOFTWARE_RESET, 0, - // display off - ILI9341_DISPLAY_OFF, 0, - // Power control B - ILI9341_POWERB, 3, 0x00, 0x83, 0x30, - // Power on sequence control - ILI9341_POWER_SEQ, 4, 0x64, 0x03, 0x12, 0x81, - //ILI9341_POWER_SEQ, 4, 0x55, 0x01, 0x23, 0x01, - // Driver timing control A - ILI9341_DTCA, 3, 0x85, 0x01, 0x79, - //ILI9341_DTCA, 3, 0x84, 0x11, 0x7a, - // Power control A - ILI9341_POWERA, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, - // Pump ratio control - ILI9341_PUMP_RATIO_CONTROL, 1, 0x20, - // Driver timing control B - ILI9341_DTCB, 2, 0x00, 0x00, - // POWER_CONTROL_1 - ILI9341_POWER_CONTROL_1, 1, 0x26, - // POWER_CONTROL_2 - ILI9341_POWER_CONTROL_2, 1, 0x11, - // VCOM_CONTROL_1 - ILI9341_VCOM_CONTROL_1, 2, 0x35, 0x3E, - // VCOM_CONTROL_2 - ILI9341_VCOM_CONTROL_2, 1, 0xBE, - // MEMORY_ACCESS_CONTROL - //ILI9341_MEMORY_ACCESS_CONTROL, 1, 0x48, // portlait - ILI9341_MEMORY_ACCESS_CONTROL, 1, DISPLAY_ROTATION_0, // landscape - // COLMOD_PIXEL_FORMAT_SET : 16 bit pixel - ILI9341_PIXEL_FORMAT_SET, 1, 0x55, - // Frame Rate - ILI9341_FRAME_RATE_CONTROL_1, 2, 0x00, 0x1B, - // Gamma Function Disable - ILI9341_3GAMMA_EN, 1, 0x08, - // gamma set for curve 01/2/04/08 - ILI9341_GAMMA_SET, 1, 0x01, - // positive gamma correction -// ILI9341_POSITIVE_GAMMA_CORRECTION, 15, 0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0x87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00, - // negativ gamma correction -// ILI9341_NEGATIVE_GAMMA_CORRECTION, 15, 0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F, - // Column Address Set -// ILI9341_COLUMN_ADDRESS_SET, 4, 0x00, 0x00, 0x01, 0x3f, // width 320 - // Page Address Set -// ILI9341_PAGE_ADDRESS_SET, 4, 0x00, 0x00, 0x00, 0xef, // height 240 - // entry mode - ILI9341_ENTRY_MODE_SET, 1, 0x06, - // display function control - ILI9341_DISPLAY_FUNCTION_CONTROL, 4, 0x0A, 0x82, 0x27, 0x00, - // Interface Control (set WEMODE=0) - ILI9341_INTERFACE_CONTROL, 3, 0x00, 0x00, 0x00, - // control display - //ILI9341_WRITE_CTRL_DISPLAY, 1, 0x0c, - // diaplay brightness - //ILI9341_WRITE_BRIGHTNESS, 1, 0xff, - // sleep out - ILI9341_SLEEP_OUT, 0, - // display on - ILI9341_DISPLAY_ON, 0, - 0 // sentinel + // cmd, len, data..., + // SW reset + ILI9341_SOFTWARE_RESET, 0, + // display off + ILI9341_DISPLAY_OFF, 0, + // Power control B + ILI9341_POWERB, 3, 0x00, 0x83, 0x30, + // Power on sequence control + ILI9341_POWER_SEQ, 4, 0x64, 0x03, 0x12, 0x81, + //ILI9341_POWER_SEQ, 4, 0x55, 0x01, 0x23, 0x01, + // Driver timing control A + ILI9341_DTCA, 3, 0x85, 0x01, 0x79, + //ILI9341_DTCA, 3, 0x84, 0x11, 0x7a, + // Power control A + ILI9341_POWERA, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, + // Pump ratio control + ILI9341_PUMP_RATIO_CONTROL, 1, 0x20, + // Driver timing control B + ILI9341_DTCB, 2, 0x00, 0x00, + // POWER_CONTROL_1 + ILI9341_POWER_CONTROL_1, 1, 0x26, + // POWER_CONTROL_2 + ILI9341_POWER_CONTROL_2, 1, 0x11, + // VCOM_CONTROL_1 + ILI9341_VCOM_CONTROL_1, 2, 0x35, 0x3E, + // VCOM_CONTROL_2 + ILI9341_VCOM_CONTROL_2, 1, 0xBE, + // MEMORY_ACCESS_CONTROL + //ILI9341_MEMORY_ACCESS_CONTROL, 1, 0x48, // portlait + ILI9341_MEMORY_ACCESS_CONTROL, 1, DISPLAY_ROTATION_0, // landscape + // COLMOD_PIXEL_FORMAT_SET : 16 bit pixel + ILI9341_PIXEL_FORMAT_SET, 1, 0x55, + // Frame Rate + ILI9341_FRAME_RATE_CONTROL_1, 2, 0x00, 0x1B, + // Gamma Function Disable + ILI9341_3GAMMA_EN, 1, 0x08, + // gamma set for curve 01/2/04/08 + ILI9341_GAMMA_SET, 1, 0x01, + // positive gamma correction +//ILI9341_POSITIVE_GAMMA_CORRECTION, 15, 0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0x87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00, + // negativ gamma correction +//ILI9341_NEGATIVE_GAMMA_CORRECTION, 15, 0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F, + // Column Address Set +//ILI9341_COLUMN_ADDRESS_SET, 4, 0x00, 0x00, 0x01, 0x3f, // width 320 + // Page Address Set +//ILI9341_PAGE_ADDRESS_SET, 4, 0x00, 0x00, 0x00, 0xef, // height 240 + // entry mode + ILI9341_ENTRY_MODE_SET, 1, 0x06, + // display function control + ILI9341_DISPLAY_FUNCTION_CONTROL, 4, 0x0A, 0x82, 0x27, 0x00, + // Interface Control (set WEMODE=0) + ILI9341_INTERFACE_CONTROL, 3, 0x00, 0x00, 0x00, + // control display + //ILI9341_WRITE_CTRL_DISPLAY, 1, 0x0c, + // diaplay brightness + //ILI9341_WRITE_BRIGHTNESS, 1, 0xff, + // sleep out + ILI9341_SLEEP_OUT, 0, + // display on + ILI9341_DISPLAY_ON, 0, + 0 // sentinel }; void ili9341_init(void) { - spi_init(); - DC_DATA; - RESET_ASSERT; - chThdSleepMilliseconds(10); - RESET_NEGATE; - const uint8_t *p; - for (p = ili9341_init_seq; *p; ) { - send_command(p[0], p[1], &p[2]); - p += 2 + p[1]; - chThdSleepMilliseconds(5); - } + spi_init(); + DC_DATA; + RESET_ASSERT; + chThdSleepMilliseconds(10); + RESET_NEGATE; + const uint8_t *p; + for (p = ili9341_init_seq; *p; ) { + send_command(p[0], p[1], &p[2]); + p += 2 + p[1]; + chThdSleepMilliseconds(5); + } } #ifndef __USE_DISPLAY_DMA__ void ili9341_fill(int x, int y, int w, int h, int color) { -// uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) }; -// uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) }; - uint32_t xx = __REV16(x|((x+w-1)<<16)); - uint32_t yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - send_command(ILI9341_MEMORY_WRITE, 0, NULL); - int32_t len = w * h; - while (len-- > 0){ - while (SPI_TX_IS_NOT_EMPTY); - SPI_WRITE_16BIT(color); - } +//uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) }; +//uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) }; + uint32_t xx = __REV16(x | ((x + w - 1) << 16)); + uint32_t yy = __REV16(y | ((y + h - 1) << 16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); + send_command(ILI9341_MEMORY_WRITE, 0, NULL); + int32_t len = w * h; + while (len-- > 0) { + while (SPI_TX_IS_NOT_EMPTY) + ; + SPI_WRITE_16BIT(color); + } } void ili9341_bulk(int x, int y, int w, int h) { -// uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) }; -// uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) }; - uint16_t *buf = spi_buffer; - uint32_t xx = __REV16(x|((x+w-1)<<16)); - uint32_t yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - send_command(ILI9341_MEMORY_WRITE, 0, NULL); - int32_t len = w * h; - while (len-- > 0){ - while (SPI_TX_IS_NOT_EMPTY); - SPI_WRITE_16BIT(*buf++); - } + // uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) }; + // uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) }; + uint16_t *buf = spi_buffer; + uint32_t xx = __REV16(x | ((x + w - 1) << 16)); + uint32_t yy = __REV16(y | ((y + h - 1) << 16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); + send_command(ILI9341_MEMORY_WRITE, 0, NULL); + int32_t len = w * h; + while (len-- > 0) { + while (SPI_TX_IS_NOT_EMPTY) + ; + SPI_WRITE_16BIT(*buf++); + } } static uint8_t ssp_sendrecvdata(void) { - // Start RX clock (by sending data) - SPI_WRITE_8BIT(0); - while(SPI_RX_IS_EMPTY && SPI_IS_BUSY) - ; - return SPI_READ_DATA; + // Start RX clock (by sending data) + SPI_WRITE_8BIT(0); + while (SPI_RX_IS_EMPTY && SPI_IS_BUSY) + ; + return SPI_READ_DATA; } void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out) { -// uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) }; -// uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) }; - uint32_t xx = __REV16(x|((x+w-1)<<16)); - uint32_t yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - send_command(ILI9341_MEMORY_READ, 0, NULL); - - // Skip data from rx buffer - while (SPI_RX_IS_NOT_EMPTY) - (void) SPI_READ_DATA; - // require 8bit dummy clock - ssp_sendrecvdata(); - while (len-- > 0) { - // read data is always 18bit - uint8_t r = ssp_sendrecvdata(); - uint8_t g = ssp_sendrecvdata(); - uint8_t b = ssp_sendrecvdata(); - *out++ = RGB565(r,g,b); - } - CS_HIGH; + // uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) }; + // uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) }; + uint32_t xx = __REV16(x | ((x + w - 1) << 16)); + uint32_t yy = __REV16(y | ((y + h - 1) << 16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); + send_command(ILI9341_MEMORY_READ, 0, NULL); + + // Skip data from rx buffer + while (SPI_RX_IS_NOT_EMPTY) + (void) SPI_READ_DATA; + // require 8bit dummy clock + ssp_sendrecvdata(); + while (len-- > 0) { + // read data is always 18bit + uint8_t r = ssp_sendrecvdata(); + uint8_t g = ssp_sendrecvdata(); + uint8_t b = ssp_sendrecvdata(); + *out++ = RGB565(r, g, b); + } + CS_HIGH; } #else // @@ -415,257 +425,309 @@ void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out) // Fill region by some color void ili9341_fill(int x, int y, int w, int h, int color) { - uint32_t xx = __REV16(x|((x+w-1)<<16)); - uint32_t yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - send_command(ILI9341_MEMORY_WRITE, 0, NULL); - - dmaStreamSetMemory0(dmatx, &color); - dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD); - dmaStreamFlush(w * h); + uint32_t xx = __REV16(x | ((x + w - 1) << 16)); + uint32_t yy = __REV16(y | ((y + h - 1) << 16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t *)&yy); + send_command(ILI9341_MEMORY_WRITE, 0, NULL); + + dmaStreamSetMemory0(dmatx, &color); + dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD); + dmaStreamFlush(w * h); } + +void ili9341_bulk_8bit(int x, int y, int w, int h, uint16_t *palette) +{ + uint32_t xx = __REV16(x | ((x + w - 1) << 16)); + uint32_t yy = __REV16(y | ((y + h - 1) << 16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t *)&yy); + send_command(ILI9341_MEMORY_WRITE, 0, NULL); + + uint8_t *buf = (uint8_t *)spi_buffer; + int32_t len = w * h; + while (len-- > 0) { + uint16_t color = palette[*buf++]; + while (SPI_TX_IS_NOT_EMPTY) + ; + SPI_WRITE_16BIT(color); + } +} + // Copy spi_buffer to region void ili9341_bulk(int x, int y, int w, int h) { - uint32_t xx = __REV16(x|((x+w-1)<<16)); - uint32_t yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - send_command(ILI9341_MEMORY_WRITE, 0, NULL); - - // Init Tx DMA mem->spi, set size, mode (spi and mem data size is 16 bit) - dmaStreamSetMemory0(dmatx, spi_buffer); - dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_MINC); - dmaStreamFlush(w * h); + uint32_t xx = __REV16(x | ((x + w - 1) << 16)); + uint32_t yy = __REV16(y | ((y + h - 1) << 16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t *)&yy); + send_command(ILI9341_MEMORY_WRITE, 0, NULL); + + // Init Tx DMA mem->spi, set size, mode (spi and mem data size is 16 bit) + dmaStreamSetMemory0(dmatx, spi_buffer); + dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | + STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_MINC); + dmaStreamFlush(w * h); } // Copy screen data to buffer // Warning!!! buffer size must be greater then 3*len + 1 bytes void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out) { - uint8_t dummy_tx = 0; - uint8_t *rgbbuf=(uint8_t *)out; - uint16_t data_size = len * 3 + 1; - uint32_t xx = __REV16(x|((x+w-1)<<16)); - uint32_t yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - send_command(ILI9341_MEMORY_READ, 0, NULL); - // Skip SPI rx buffer - while (SPI_RX_IS_NOT_EMPTY) - (void) SPI_READ_DATA; - // Init Rx DMA buffer, size, mode (spi and mem data size is 8 bit) - dmaStreamSetMemory0(dmarx, rgbbuf); - dmaStreamSetTransactionSize(dmarx, data_size); - dmaStreamSetMode(dmarx, rxdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_MINC); - // Init dummy Tx DMA (for rx clock), size, mode (spi and mem data size is 8 bit) - dmaStreamSetMemory0(dmatx, &dummy_tx); - dmaStreamSetTransactionSize(dmatx, data_size); - dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE); - - // Start DMA exchange - dmaStreamEnable(dmatx); - dmaStreamEnable(dmarx); - // Wait DMA completion - dmaWaitCompletion(dmatx); - dmaWaitCompletion(dmarx); - CS_HIGH; - - // Parce recived data - // Skip dummy 8-bit read - rgbbuf++; - while (len-- > 0) { - uint8_t r, g, b; - // read data is always 18bit - r = rgbbuf[0]; - g = rgbbuf[1]; - b = rgbbuf[2]; - *out++ = RGB565(r,g,b); - rgbbuf+=3; - } + uint8_t dummy_tx = 0; + uint8_t *rgbbuf = (uint8_t *)out; + uint16_t data_size = len * 3 + 1; + uint32_t xx = __REV16(x | ((x + w - 1) << 16)); + uint32_t yy = __REV16(y | ((y + h - 1) << 16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t *)&yy); + send_command(ILI9341_MEMORY_READ, 0, NULL); + // Skip SPI rx buffer + while (SPI_RX_IS_NOT_EMPTY) (void)SPI_READ_DATA; + // Init Rx DMA buffer, size, mode (spi and mem data size is 8 bit) + dmaStreamSetMemory0(dmarx, rgbbuf); + dmaStreamSetTransactionSize(dmarx, data_size); + dmaStreamSetMode(dmarx, rxdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC); + // Init dummy Tx DMA (for rx clock), size, mode (spi and mem data size is 8 bit) + dmaStreamSetMemory0(dmatx, &dummy_tx); + dmaStreamSetTransactionSize(dmatx, data_size); + dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE); + + // Start DMA exchange + dmaStreamEnable(dmatx); + dmaStreamEnable(dmarx); + // Wait DMA completion + dmaWaitCompletion(dmatx); + dmaWaitCompletion(dmarx); + CS_HIGH; + + // Parce recived data + // Skip dummy 8-bit read + rgbbuf++; + while (len-- > 0) { + uint8_t r, g, b; + // read data is always 18bit + r = rgbbuf[0]; + g = rgbbuf[1]; + b = rgbbuf[2]; + *out++ = RGB565(r, g, b); + rgbbuf += 3; + } } #endif -void setForegroundColor(uint16_t fg) {foreground_color = fg;} -void setBackgroundColor(uint16_t bg) {background_color = bg;} +void ili9341_clear_screen(void) +{ + ili9341_fill(0, 0, ILI9341_WIDTH, ILI9341_HEIGHT, background_color); +} -void ili9341_setRotation(uint8_t r) { -// static const uint8_t rotation_const[]={DISPLAY_ROTATION_0, DISPLAY_ROTATION_90, DISPLAY_ROTATION_180, DISPLAY_ROTATION_270}; - send_command(ILI9341_MEMORY_ACCESS_CONTROL, 1, &r); +void ili9341_set_foreground(uint16_t fg) +{ + foreground_color = fg; } -void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *bitmap){ - uint16_t *buf = spi_buffer; - for(uint16_t c = 0; c < height; c++) { - uint8_t bits = *bitmap++; - for (uint16_t r = 0; r < width; r++) { - *buf++ = (0x80 & bits) ? foreground_color : background_color; - bits <<= 1; - } +void ili9341_set_background(uint16_t bg) +{ + background_color = bg; +} + +void ili9341_set_rotation(uint8_t r) +{ + // static const uint8_t rotation_const[]={DISPLAY_ROTATION_0, DISPLAY_ROTATION_90, + // DISPLAY_ROTATION_180, DISPLAY_ROTATION_270}; + send_command(ILI9341_MEMORY_ACCESS_CONTROL, 1, &r); +} + +void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, + const uint8_t *bitmap) +{ + uint16_t *buf = spi_buffer; + for (uint16_t c = 0; c < height; c++) { + uint8_t bits = *bitmap++; + for (uint16_t r = 0; r < width; r++) { + *buf++ = (0x80 & bits) ? foreground_color : background_color; + bits <<= 1; } - ili9341_bulk(x, y, width, height); + } + ili9341_bulk(x, y, width, height); } -void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *bitmap){ - uint16_t *buf = spi_buffer; - for(uint16_t c = 0; c < height; c++) { - uint16_t bits = *bitmap++; - for (uint16_t r = 0; r < width; r++) { - *buf++ = (0x8000 & bits) ? foreground_color : background_color; - bits <<= 1; - } +static void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, + const uint16_t *bitmap) +{ + uint16_t *buf = spi_buffer; + for (uint16_t c = 0; c < height; c++) { + uint16_t bits = *bitmap++; + for (uint16_t r = 0; r < width; r++) { + *buf++ = (0x8000 & bits) ? foreground_color : background_color; + bits <<= 1; } - ili9341_bulk(x, y, width, height); + } + ili9341_bulk(x, y, width, height); } void ili9341_drawchar(uint8_t ch, int x, int y) { - blit8BitWidthBitmap(x, y, FONT_GET_WIDTH(ch), FONT_GET_HEIGHT, FONT_GET_DATA(ch)); + blit8BitWidthBitmap(x, y, FONT_GET_WIDTH(ch), FONT_GET_HEIGHT, FONT_GET_DATA(ch)); } void ili9341_drawstring(const char *str, int x, int y) { - while (*str) { - uint8_t ch = *str++; - const uint8_t *char_buf = FONT_GET_DATA(ch); - uint16_t w = FONT_GET_WIDTH(ch); - blit8BitWidthBitmap(x, y, w, FONT_GET_HEIGHT, char_buf); - x+=w; - } + while (*str) { + uint8_t ch = *str++; + const uint8_t *char_buf = FONT_GET_DATA(ch); + uint16_t w = FONT_GET_WIDTH(ch); + blit8BitWidthBitmap(x, y, w, FONT_GET_HEIGHT, char_buf); + x += w; + } } -void ili9341_drawstringV(const char *str, int x, int y){ - ili9341_setRotation(DISPLAY_ROTATION_270); - ili9341_drawstring(str, ILI9341_HEIGHT-y, x); - ili9341_setRotation(DISPLAY_ROTATION_0); +void ili9341_drawstringV(const char *str, int x, int y) +{ + ili9341_set_rotation(DISPLAY_ROTATION_270); + ili9341_drawstring(str, ILI9341_HEIGHT-y, x); + ili9341_set_rotation(DISPLAY_ROTATION_0); } int ili9341_drawchar_size(uint8_t ch, int x, int y, uint8_t size) { - uint16_t *buf = spi_buffer; - const uint8_t *char_buf = FONT_GET_DATA(ch); - uint16_t w=FONT_GET_WIDTH(ch); - for(int c = 0; c < FONT_GET_HEIGHT; c++, char_buf++){ - for (int i=0;i dy ? dx : -dy) / 2; + while (1) { + ili9341_pixel(x0, y0, DEFAULT_FG_COLOR); + if (x0 == x1 && y0 == y1) + break; + int e2 = err; + if (e2 > -dx) { err -= dy; x0 += sx; } + if (e2 < dy) { err += dx; y0 += sy; } + } +#endif - if (x0 > x1) { - SWAP(x0, x1); - SWAP(y0, y1); - } - - while (x0 <= x1) { - int dx = x1 - x0 + 1; - int dy = y1 - y0; - if (dy >= 0) { - dy++; - if (dy > dx) { - dy /= dx; dx = 1; - } else { - dx /= dy; dy = 1; - } - } else { - dy--; - if (-dy > dx) { - dy /= dx; dx = 1; - } else { - dx /= -dy;dy = -1; - } - } - if (dy > 0) - ili9341_fill(x0, y0, dx, dy, foreground_color); - else - ili9341_fill(x0, y0+dy, dx, -dy, foreground_color); - x0 += dx; - y0 += dy; + if (x0 > x1) { + SWAP(x0, x1); + SWAP(y0, y1); + } + + while (x0 <= x1) { + int dx = x1 - x0 + 1; + int dy = y1 - y0; + if (dy >= 0) { + dy++; + if (dy > dx) { + dy /= dx; dx = 1; + } else { + dx /= dy; dy = 1; + } + } else { + dy--; + if (-dy > dx) { + dy /= dx; dx = 1; + } else { + dx /= -dy;dy = -1; + } } + if (dy > 0) + ili9341_fill(x0, y0, dx, dy, foreground_color); + else + ili9341_fill(x0, y0+dy, dx, -dy, foreground_color); + x0 += dx; + y0 += dy; + } } #if 0 static const uint16_t colormap[] = { - RGBHEX(0x00ff00), RGBHEX(0x0000ff), RGBHEX(0xff0000), - RGBHEX(0x00ffff), RGBHEX(0xff00ff), RGBHEX(0xffff00) + RGBHEX(0x00ff00), RGBHEX(0x0000ff), RGBHEX(0xff0000), + RGBHEX(0x00ffff), RGBHEX(0xff00ff), RGBHEX(0xffff00) }; -static void ili9341_pixel(int x, int y, int color) -{ - uint8_t xx[4] = { x >> 8, x, (x+1) >> 8, (x+1) }; - uint8_t yy[4] = { y >> 8, y, (y+1) >> 8, (y+1) }; - uint8_t cc[2] = { color >> 8, color }; - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, yy); - send_command(ILI9341_MEMORY_WRITE, 2, cc); - //send_command16(ILI9341_MEMORY_WRITE, color); -} - void ili9341_test(int mode) { - chMtxLock(&mutex_ili9341); - int x, y; - int i; - switch (mode) { - default: + int x, y; + int i; + switch (mode) { + default: #if 1 - ili9341_fill(0, 0, 320, 240, 0); - for (y = 0; y < 240; y++) { - ili9341_fill(0, y, 320, 1, RGB(240-y, y, (y + 120) % 256)); - } - break; - case 1: - ili9341_fill(0, 0, 320, 240, 0); - for (y = 0; y < 240; y++) { - for (x = 0; x < 320; x++) { - ili9341_pixel(x, y, (y<<8)|x); - } - } - break; - case 2: - //send_command16(0x55, 0xff00); - ili9341_pixel(64, 64, 0xaa55); - break; + ili9341_fill(0, 0, 320, 240, 0); + for (y = 0; y < 240; y++) { + ili9341_fill(0, y, 320, 1, RGB(240-y, y, (y + 120) % 256)); + } + break; + case 1: + ili9341_fill(0, 0, 320, 240, 0); + for (y = 0; y < 240; y++) { + for (x = 0; x < 320; x++) { + ili9341_pixel(x, y, (y<<8)|x); + } + } + break; + case 2: + //send_command16(0x55, 0xff00); + ili9341_pixel(64, 64, 0xaa55); + break; #endif #if 1 - case 3: - for (i = 0; i < 10; i++) - ili9341_drawfont(i, i*20, 120); - break; + case 3: + for (i = 0; i < 10; i++) + ili9341_drawfont(i, i*20, 120); + break; #endif #if 0 - case 4: - draw_grid(10, 8, 29, 29, 15, 0, 0xffff, 0); - break; + case 4: + draw_grid(10, 8, 29, 29, 15, 0, 0xffff, 0); + break; #endif - case 4: - ili9341_line(0, 0, 15, 100); - ili9341_line(0, 0, 100, 100); - ili9341_line(0, 15, 100, 0); - ili9341_line(0, 100, 100, 0); - break; - } - chMtxUnlock(&mutex_ili9341); + case 4: + ili9341_line(0, 0, 15, 100); + ili9341_line(0, 0, 100, 100); + ili9341_line(0, 15, 100, 0); + ili9341_line(0, 100, 100, 0); + break; + } } #endif diff --git a/main.c b/main.c index caf2f60..fff210d 100644 --- a/main.c +++ b/main.c @@ -26,132 +26,174 @@ #include "fft.h" #include -#include -#include #include -#include #include +/* + * Shell settings + */ +// If need run shell as thread (use more amount of memory fore stack), after +// enable this need reduce spi_buffer size, by default shell run in main thread +// #define VNA_SHELL_THREAD + +static BaseSequentialStream *shell_stream = (BaseSequentialStream *)&SDU1; + +// Shell new line +#define VNA_SHELL_NEWLINE_STR "\r\n" +// Shell command promt +#define VNA_SHELL_PROMPT_STR "ch> " +// Shell max arguments +#define VNA_SHELL_MAX_ARGUMENTS 4 +// Shell max command line size +#define VNA_SHELL_MAX_LENGTH 48 + +// Shell command functions prototypes +typedef void (*vna_shellcmd_t)(int argc, char *argv[]); +#define VNA_SHELL_FUNCTION(command_name) \ + static void command_name(int argc, char *argv[]) + +// Shell command line buffer, args, nargs, and function ptr +static char shell_line[VNA_SHELL_MAX_LENGTH]; +static char *shell_args[VNA_SHELL_MAX_ARGUMENTS + 1]; +static uint16_t shell_nargs; +static volatile vna_shellcmd_t shell_function = 0; + //#define ENABLED_DUMP +// Allow get threads debug info +//#define ENABLE_THREADS_COMMAND +// RTC time not used +//#define ENABLE_TIME_COMMAND +// Enable vbat_offset command, allow change battery voltage correction in config +#define ENABLE_VBAT_OFFSET_COMMAND +// Info about NanoVNA, need fore soft +#define ENABLE_INFO_COMMAND +// Enable color command, allow change config color for traces, grid, menu +#define ENABLE_COLOR_COMMAND static void apply_error_term_at(int i); static void apply_edelay_at(int i); static void cal_interpolate(int s); -void update_frequencies(void); -void set_frequencies(uint32_t start, uint32_t stop, int16_t points); - -bool sweep(bool break_on_operation); - -static MUTEX_DECL(mutex); +static void update_frequencies(void); +static void set_frequencies(uint32_t start, uint32_t stop, uint16_t points); +static bool sweep(bool break_on_operation); +static void transform_domain(void); #define DRIVE_STRENGTH_AUTO (-1) #define FREQ_HARMONICS (config.harmonic_freq_threshold) #define IS_HARMONIC_MODE(f) ((f) > FREQ_HARMONICS) - -int32_t frequency_offset = 5000; -uint32_t frequency = 10000000; -int8_t drive_strength = DRIVE_STRENGTH_AUTO; -int8_t sweep_enabled = TRUE; -int8_t sweep_once = FALSE; -int8_t cal_auto_interpolate = TRUE; -uint16_t redraw_request = 0; // contains REDRAW_XXX flags -int16_t vbat = 0; - +// Obsolete, always use interpolate +#define cal_auto_interpolate TRUE + +static int8_t drive_strength = DRIVE_STRENGTH_AUTO; +int8_t sweep_mode = SWEEP_ENABLE; +volatile uint8_t redraw_request = 0; // contains REDRAW_XXX flags + +// Version text, displayed in Config->Version menu, also send by info command +const char *info_about[]={ + BOARD_NAME, + "2016-2020 Copyright @edy555", + "Licensed under GPL. See: https://github.com/ttrftech/NanoVNA", + "Version: " VERSION, + "Build Time: " __DATE__ " - " __TIME__, + "Kernel: " CH_KERNEL_VERSION, + "Compiler: " PORT_COMPILER_NAME, + "Architecture: " PORT_ARCHITECTURE_NAME " Core Variant: " PORT_CORE_VARIANT_NAME, + "Port Info: " PORT_INFO, + "Platform: " PLATFORM_NAME, + 0 // sentinel +}; static THD_WORKING_AREA(waThread1, 640); static THD_FUNCTION(Thread1, arg) { - (void)arg; - chRegSetThreadName("sweep"); + (void)arg; + chRegSetThreadName("sweep"); - while (1) { - bool completed = false; - if (sweep_enabled || sweep_once) { - chMtxLock(&mutex); - completed = sweep(true); - sweep_once = FALSE; - chMtxUnlock(&mutex); - } else { - __WFI(); - } - - chMtxLock(&mutex); - ui_process(); - - if (sweep_enabled) { - if (vbat != -1) { - adc_stop(ADC1); - vbat = adc_vbat_read(ADC1); - touch_start_watchdog(); - draw_battery_status(); - } - - /* calculate trace coordinates and plot only if scan completed */ - if (completed) { - plot_into_index(measured); - redraw_request |= REDRAW_CELLS; - - if (marker_tracking) { - int i = marker_search(); - if (i != -1 && active_marker != -1) { - markers[active_marker].index = i; - redraw_request |= REDRAW_MARKER; - } - } + while (1) { + bool completed = false; + if (sweep_mode&(SWEEP_ENABLE|SWEEP_ONCE)) { + completed = sweep(true); + sweep_mode&=~SWEEP_ONCE; + } else { + __WFI(); + } + // Run Shell command in sweep thread + if (shell_function) { + shell_function(shell_nargs - 1, &shell_args[1]); + shell_function = 0; + osalThreadSleepMilliseconds(10); + continue; + } + // Process UI inputs + ui_process(); + // Process collected data, calculate trace coordinates and plot only if scan + // completed + if (sweep_mode & SWEEP_ENABLE && completed) { + if ((domain_mode & DOMAIN_MODE) == DOMAIN_TIME) transform_domain(); + // Prepare draw graphics, cache all lines, mark screen cells for redraw + plot_into_index(measured); + redraw_request |= REDRAW_CELLS | REDRAW_BATTERY; + + if (uistat.marker_tracking) { + int i = marker_search(); + if (i != -1 && active_marker != -1) { + markers[active_marker].index = i; + redraw_request |= REDRAW_MARKER; } } - - /* plot trace and other indications as raster */ - draw_all(completed); // flush markmap only if scan completed to prevent remaining traces - chMtxUnlock(&mutex); } + // plot trace and other indications as raster + draw_all(completed); // flush markmap only if scan completed to prevent + // remaining traces + } } -void +static inline void pause_sweep(void) { - sweep_enabled = FALSE; + sweep_mode &= ~SWEEP_ENABLE; } -void +static inline void resume_sweep(void) { - sweep_enabled = TRUE; + sweep_mode |= SWEEP_ENABLE; } void toggle_sweep(void) { - sweep_enabled = !sweep_enabled; + sweep_mode ^= SWEEP_ENABLE; } -float bessel0(float x) { - const float eps = 0.0001; - - float ret = 0; - float term = 1; - float m = 0; +static float +bessel0(float x) +{ + const float eps = 0.0001; - while (term > eps * ret) { - ret += term; - ++m; - term *= (x*x) / (4*m*m); - } + float ret = 0; + float term = 1; + float m = 0; - return ret; + while (term > eps * ret) { + ret += term; + ++m; + term *= (x*x) / (4*m*m); + } + return ret; } -float kaiser_window(float k, float n, float beta) { - if (beta == 0.0) return 1.0; - float r = (2 * k) / (n - 1) - 1; - return bessel0(beta * sqrt(1 - r * r)) / bessel0(beta); +static float +kaiser_window(float k, float n, float beta) +{ + if (beta == 0.0) return 1.0; + float r = (2 * k) / (n - 1) - 1; + return bessel0(beta * sqrt(1 - r * r)) / bessel0(beta); } -static -void +static void transform_domain(void) { - if ((domain_mode & DOMAIN_MODE) != DOMAIN_TIME) return; // nothing to do for freq domain // use spi_buffer as temporary buffer // and calculate ifft for time domain float* tmp = (float*)spi_buffer; @@ -159,113 +201,119 @@ transform_domain(void) uint8_t window_size = POINTS_COUNT, offset = 0; uint8_t is_lowpass = FALSE; switch (domain_mode & TD_FUNC) { - case TD_FUNC_BANDPASS: - offset = 0; - window_size = POINTS_COUNT; - break; - case TD_FUNC_LOWPASS_IMPULSE: - case TD_FUNC_LOWPASS_STEP: - is_lowpass = TRUE; - offset = POINTS_COUNT; - window_size = POINTS_COUNT*2; - break; + case TD_FUNC_BANDPASS: + offset = 0; + window_size = POINTS_COUNT; + break; + case TD_FUNC_LOWPASS_IMPULSE: + case TD_FUNC_LOWPASS_STEP: + is_lowpass = TRUE; + offset = POINTS_COUNT; + window_size = POINTS_COUNT * 2; + break; } float beta = 0.0; switch (domain_mode & TD_WINDOW) { - case TD_WINDOW_MINIMUM: - beta = 0.0; // this is rectangular - break; - case TD_WINDOW_NORMAL: - beta = 6.0; - break; - case TD_WINDOW_MAXIMUM: - beta = 13; - break; + case TD_WINDOW_MINIMUM: + beta = 0.0; // this is rectangular + break; + case TD_WINDOW_NORMAL: + beta = 6.0; + break; + case TD_WINDOW_MAXIMUM: + beta = 13; + break; } - for (int ch = 0; ch < 2; ch++) { - memcpy(tmp, measured[ch], sizeof(measured[0])); - for (int i = 0; i < POINTS_COUNT; i++) { - float w = kaiser_window(i+offset, window_size, beta); - tmp[i*2+0] *= w; - tmp[i*2+1] *= w; - } - for (int i = POINTS_COUNT; i < FFT_SIZE; i++) { - tmp[i*2+0] = 0.0; - tmp[i*2+1] = 0.0; - } - if (is_lowpass) { - for (int i = 1; i < POINTS_COUNT; i++) { - tmp[(FFT_SIZE-i)*2+0] = tmp[i*2+0]; - tmp[(FFT_SIZE-i)*2+1] = -tmp[i*2+1]; - } + memcpy(tmp, measured[ch], sizeof(measured[0])); + for (int i = 0; i < POINTS_COUNT; i++) { + float w = kaiser_window(i + offset, window_size, beta); + tmp[i * 2 + 0] *= w; + tmp[i * 2 + 1] *= w; + } + for (int i = POINTS_COUNT; i < FFT_SIZE; i++) { + tmp[i * 2 + 0] = 0.0; + tmp[i * 2 + 1] = 0.0; + } + if (is_lowpass) { + for (int i = 1; i < POINTS_COUNT; i++) { + tmp[(FFT_SIZE - i) * 2 + 0] = tmp[i * 2 + 0]; + tmp[(FFT_SIZE - i) * 2 + 1] = -tmp[i * 2 + 1]; } + } - fft256_inverse((float(*)[2])tmp); - memcpy(measured[ch], tmp, sizeof(measured[0])); - for (int i = 0; i < POINTS_COUNT; i++) { - measured[ch][i][0] /= (float)FFT_SIZE; - if (is_lowpass) { - measured[ch][i][1] = 0.0; - } else { - measured[ch][i][1] /= (float)FFT_SIZE; - } + fft256_inverse((float(*)[2])tmp); + memcpy(measured[ch], tmp, sizeof(measured[0])); + for (int i = 0; i < POINTS_COUNT; i++) { + measured[ch][i][0] /= (float)FFT_SIZE; + if (is_lowpass) { + measured[ch][i][1] = 0.0; + } else { + measured[ch][i][1] /= (float)FFT_SIZE; } - if ( (domain_mode & TD_FUNC) == TD_FUNC_LOWPASS_STEP ) { - for (int i = 1; i < POINTS_COUNT; i++) { - measured[ch][i][0] += measured[ch][i-1][0]; - } + } + if ((domain_mode & TD_FUNC) == TD_FUNC_LOWPASS_STEP) { + for (int i = 1; i < POINTS_COUNT; i++) { + measured[ch][i][0] += measured[ch][i - 1][0]; } + } } } -static void cmd_pause(BaseSequentialStream *chp, int argc, char *argv[]) +// Shell commands output +static int shell_printf(const char *fmt, ...) { - (void)chp; - (void)argc; - (void)argv; - pause_sweep(); + va_list ap; + int formatted_bytes; + va_start(ap, fmt); + formatted_bytes = chvprintf(shell_stream, fmt, ap); + va_end(ap); + return formatted_bytes; } -static void cmd_resume(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_pause) { - (void)chp; - (void)argc; - (void)argv; + (void)argc; + (void)argv; + pause_sweep(); +} - // restore frequencies array and cal - update_frequencies(); - if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY)) - cal_interpolate(lastsaveid); +VNA_SHELL_FUNCTION(cmd_resume) +{ + (void)argc; + (void)argv; - resume_sweep(); + // restore frequencies array and cal + update_frequencies(); + if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY)) + cal_interpolate(lastsaveid); + + resume_sweep(); } -static void cmd_reset(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_reset) { - (void)argc; - (void)argv; + (void)argc; + (void)argv; - if (argc == 1) { - if (strcmp(argv[0], "dfu") == 0) { - chprintf(chp, "Performing reset to DFU mode\r\n"); - enter_dfu(); - return; - } + if (argc == 1) { + if (strcmp(argv[0], "dfu") == 0) { + shell_printf("Performing reset to DFU mode\r\n"); + enter_dfu(); + return; } + } + shell_printf("Performing reset\r\n"); - chprintf(chp, "Performing reset\r\n"); - - rccEnableWWDG(FALSE); - - WWDG->CFR = 0x60; - WWDG->CR = 0xff; + rccEnableWWDG(FALSE); + WWDG->CFR = 0x60; + WWDG->CR = 0xff; - /* wait forever */ - while (1) - ; + /* wait forever */ + while (1) + ; } const int8_t gain_table[] = { @@ -280,126 +328,241 @@ const int8_t gain_table[] = { 95 // 2400MHz ~ }; -#define DELAY_GAIN_CHANGE 10 +#define DELAY_GAIN_CHANGE 2 static int -adjust_gain(int newfreq) +adjust_gain(uint32_t newfreq) { - int delay = 0; int new_order = newfreq / FREQ_HARMONICS; - int old_order = frequency / FREQ_HARMONICS; + int old_order = si5351_get_frequency() / FREQ_HARMONICS; if (new_order != old_order) { tlv320aic3204_set_gain(gain_table[new_order], gain_table[new_order]); - delay += DELAY_GAIN_CHANGE; + return DELAY_GAIN_CHANGE; } - return delay; + return 0; } int set_frequency(uint32_t freq) { - int delay = adjust_gain(freq); - int8_t ds = drive_strength; - if (ds == DRIVE_STRENGTH_AUTO) { - ds = freq > FREQ_HARMONICS ? SI5351_CLK_DRIVE_STRENGTH_8MA : SI5351_CLK_DRIVE_STRENGTH_2MA; - } - delay += si5351_set_frequency_with_offset(freq, frequency_offset, ds); + int delay = adjust_gain(freq); + int8_t ds = drive_strength; + if (ds == DRIVE_STRENGTH_AUTO) { + ds = freq > FREQ_HARMONICS ? SI5351_CLK_DRIVE_STRENGTH_8MA : SI5351_CLK_DRIVE_STRENGTH_2MA; + } + delay += si5351_set_frequency(freq, ds); + return delay; +} - frequency = freq; - return delay; +// Use macro, std isdigit more big +#define _isdigit(c) (c >= '0' && c <= '9') +// Rewrite universal standart str to value functions to more compact +// +// Convert string to int32 +static int32_t my_atoi(const char *p) +{ + int32_t value = 0; + uint32_t c; + bool neg = false; + + if (*p == '-') {neg = true; p++;} + if (*p == '+') p++; + while ((c = *p++ - '0') < 10) + value = value * 10 + c; + return neg ? -value : value; +} + +// Convert string to uint32 +// 0x - for hex radix +// 0o - for oct radix +// 0b - for bin radix +// default dec radix +uint32_t my_atoui(const char *p) +{ + uint32_t value = 0, radix = 10, c; + if (*p == '+') p++; + if (*p == '0') { + switch (p[1]) { + case 'x': radix = 16; break; + case 'o': radix = 8; break; + case 'b': radix = 2; break; + default: goto calculate; + } + p+=2; + } +calculate: + while (1) { + c = *p++ - '0'; + // c = to_upper(*p) - 'A' + 10 + if (c >= 'A' - '0') c = (c&(~0x20)) - ('A' - '0') + 10; + if (c >= radix) return value; + value = value * radix + c; + } } -static void cmd_offset(BaseSequentialStream *chp, int argc, char *argv[]) +double +my_atof(const char *p) { - if (argc != 1) { - chprintf(chp, "usage: offset {frequency offset(Hz)}\r\n"); - return; + int neg = FALSE; + if (*p == '-') + neg = TRUE; + if (*p == '-' || *p == '+') + p++; + double x = my_atoi(p); + while (_isdigit((int)*p)) + p++; + if (*p == '.') { + double d = 1.0f; + p++; + while (_isdigit((int)*p)) { + d /= 10; + x += d * (*p - '0'); + p++; } - frequency_offset = atoi(argv[0]); - set_frequency(frequency); + } + if (*p == 'e' || *p == 'E') { + p++; + int exp = my_atoi(p); + while (exp > 0) { + x *= 10; + exp--; + } + while (exp < 0) { + x /= 10; + exp++; + } + } + if (neg) + x = -x; + return x; } -static void cmd_freq(BaseSequentialStream *chp, int argc, char *argv[]) +// +// Function used for search substring v in list +// Example need search parameter "center" in "start|stop|center|span|cw" getStringIndex return 2 +// If not found return -1 +// Used for easy parse command arguments +static int get_str_index(char *v, const char *list) { - int freq; - if (argc != 1) { - chprintf(chp, "usage: freq {frequency(Hz)}\r\n"); - return; + int i = 0; + while (1) { + char *p = v; + while (1) { + char c = *list; + if (c == '|') c = 0; + if (c == *p++) { + // Found, return index + if (c == 0) return i; + list++; // Compare next symbol + continue; + } + break; // Not equal, break } - pause_sweep(); - chMtxLock(&mutex); - freq = atoi(argv[0]); - set_frequency(freq); - chMtxUnlock(&mutex); + // Set new substring ptr + while (1) { + // End of string, not found + if (*list == 0) return -1; + if (*list++ == '|') break; + } + i++; + } + return -1; } -static void cmd_power(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_offset) { - if (argc != 1) { - chprintf(chp, "usage: power {0-3|-1}\r\n"); - return; - } - drive_strength = atoi(argv[0]); - set_frequency(frequency); + if (argc != 1) { + shell_printf("usage: offset {frequency offset(Hz)}\r\n"); + return; + } + si5351_set_frequency_offset(my_atoi(argv[0])); } -static void cmd_time(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_freq) { - RTCDateTime timespec; - (void)argc; - (void)argv; - rtcGetTime(&RTCD1, ×pec); - chprintf(chp, "%d/%d/%d %d\r\n", timespec.year+1980, timespec.month, timespec.day, timespec.millisecond); + if (argc != 1) { + goto usage; + } + uint32_t freq = my_atoui(argv[0]); + + pause_sweep(); + set_frequency(freq); + return; +usage: + shell_printf("usage: freq {frequency(Hz)}\r\n"); } +VNA_SHELL_FUNCTION(cmd_power) +{ + if (argc != 1) { + shell_printf("usage: power {0-3|-1}\r\n"); + return; + } + drive_strength = my_atoi(argv[0]); +// set_frequency(frequency); +} -static void cmd_dac(BaseSequentialStream *chp, int argc, char *argv[]) +#ifdef ENABLE_TIME_COMMAND +#if HAL_USE_RTC == FALSE +#error "Error cmd_time require define HAL_USE_RTC = TRUE in halconf.h" +#endif +VNA_SHELL_FUNCTION(cmd_time) { - int value; - if (argc != 1) { - chprintf(chp, "usage: dac {value(0-4095)}\r\n"); - chprintf(chp, "current value: %d\r\n", config.dac_value); - return; - } - value = atoi(argv[0]); - config.dac_value = value; - dacPutChannelX(&DACD2, 0, value); + RTCDateTime timespec; + (void)argc; + (void)argv; + rtcGetTime(&RTCD1, ×pec); + shell_printf("%d/%d/%d %d\r\n", timespec.year+1980, timespec.month, timespec.day, timespec.millisecond); } +#endif -static void cmd_threshold(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_dac) { - int value; - if (argc != 1) { - chprintf(chp, "usage: threshold {frequency in harmonic mode}\r\n"); - chprintf(chp, "current: %d\r\n", config.harmonic_freq_threshold); - return; - } - value = atoi(argv[0]); - config.harmonic_freq_threshold = value; + int value; + if (argc != 1) { + shell_printf("usage: dac {value(0-4095)}\r\n"\ + "current value: %d\r\n", config.dac_value); + return; + } + value = my_atoui(argv[0]); + config.dac_value = value; + dacPutChannelX(&DACD2, 0, value); +} + +VNA_SHELL_FUNCTION(cmd_threshold) +{ + uint32_t value; + if (argc != 1) { + shell_printf("usage: threshold {frequency in harmonic mode}\r\n"\ + "current: %d\r\n", config.harmonic_freq_threshold); + return; + } + value = my_atoui(argv[0]); + config.harmonic_freq_threshold = value; } -static void cmd_saveconfig(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_saveconfig) { (void)argc; (void)argv; config_save(); - chprintf(chp, "Config saved.\r\n"); + shell_printf("Config saved.\r\n"); } -static void cmd_clearconfig(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_clearconfig) { if (argc != 1) { - chprintf(chp, "usage: clearconfig {protection key}\r\n"); + shell_printf("usage: clearconfig {protection key}\r\n"); return; } if (strcmp(argv[0], "1234") != 0) { - chprintf(chp, "Key unmatched.\r\n"); + shell_printf("Key unmatched.\r\n"); return; } clear_all_config_prop_data(); - chprintf(chp, "Config and all cal data cleared.\r\n"); - chprintf(chp, "Do reset manually to take effect. Then do touch cal and save.\r\n"); + shell_printf("Config and all cal data cleared.\r\n"\ + "Do reset manually to take effect. Then do touch cal and save.\r\n"); } static struct { @@ -425,15 +588,6 @@ volatile int16_t wait_count = 0; float measured[2][POINTS_COUNT][2]; -static void -wait_dsp(int count) -{ - wait_count = count; - //reset_dsp_accumerator(); - while (wait_count) - __WFI(); -} - #ifdef ENABLED_DUMP static void duplicate_buffer_to_dump(int16_t *p) @@ -484,40 +638,35 @@ static const I2SConfig i2sconfig = { 2 // i2spr }; -static void cmd_data(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_data) { int i; int sel = 0; - + float (*array)[2]; if (argc == 1) - sel = atoi(argv[0]); - if (sel == 0 || sel == 1) { - chMtxLock(&mutex); - for (i = 0; i < sweep_points; i++) { - if (frequencies[i] != 0) - chprintf(chp, "%f %f\r\n", measured[sel][i][0], measured[sel][i][1]); - } - chMtxUnlock(&mutex); - } else if (sel >= 2 && sel < 7) { - chMtxLock(&mutex); - for (i = 0; i < sweep_points; i++) { - if (frequencies[i] != 0) - chprintf(chp, "%f %f\r\n", cal_data[sel-2][i][0], cal_data[sel-2][i][1]); - } - chMtxUnlock(&mutex); - } else { - chprintf(chp, "usage: data [array]\r\n"); - } + sel = my_atoi(argv[0]); + + if (sel == 0 || sel == 1) + array = measured[sel]; + else if (sel >= 2 && sel < 7) + array = cal_data[sel-2]; + else + goto usage; + for (i = 0; i < sweep_points; i++) + shell_printf("%f %f\r\n", array[i][0], array[i][1]); + return; +usage: + shell_printf("usage: data [array]\r\n"); } #ifdef ENABLED_DUMP -static void cmd_dump(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_dump) { int i, j; int len; if (argc == 1) - dump_selection = atoi(argv[0]); + dump_selection = my_atoi(argv[0]); wait_dsp(3); @@ -526,37 +675,35 @@ static void cmd_dump(BaseSequentialStream *chp, int argc, char *argv[]) len /= 2; for (i = 0; i < len; ) { for (j = 0; j < 16; j++, i++) { - chprintf(chp, "%04x ", 0xffff & (int)dump_buffer[i]); + shell_printf("%04x ", 0xffff & (int)dump_buffer[i]); } - chprintf(chp, "\r\n"); + shell_printf("\r\n"); } } #endif -static void cmd_capture(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_capture) { // read pixel count at one time (PART*2 bytes required for read buffer) - (void)argc; - (void)argv; - - chMtxLock(&mutex); - - // read 2 row pixel time (read buffer limit by 2/3 + 1 from spi_buffer size) - for (int y=0; y < 240; y+=2) - { - // use uint16_t spi_buffer[1024] (defined in ili9341) for read buffer - uint8_t *buf = (uint8_t *)spi_buffer; - ili9341_read_memory(0, y, 320, 2, 2*320, spi_buffer); - for (int i = 0; i < 4*320; i++) { - streamPut(chp, *buf++); - } + (void)argc; + (void)argv; + int i, y; +#if SPI_BUFFER_SIZE < (3*320 + 1) +#error "Low size of spi_buffer for cmd_capture" +#endif + // read 2 row pixel time (read buffer limit by 2/3 + 1 from spi_buffer size) + for (y = 0; y < 240; y += 2) { + // use uint16_t spi_buffer[2048] (defined in ili9341) for read buffer + uint8_t *buf = (uint8_t *)spi_buffer; + ili9341_read_memory(0, y, 320, 2, 2 * 320, spi_buffer); + for (i = 0; i < 4 * 320; i++) { + streamPut(shell_stream, *buf++); } - - chMtxUnlock(&mutex); + } } #if 0 -static void cmd_gamma(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_gamma) { float gamma[2]; (void)argc; @@ -568,27 +715,32 @@ static void cmd_gamma(BaseSequentialStream *chp, int argc, char *argv[]) calculate_gamma(gamma); chMtxUnlock(&mutex); - chprintf(chp, "%d %d\r\n", gamma[0], gamma[1]); + shell_printf("%d %d\r\n", gamma[0], gamma[1]); } #endif static void (*sample_func)(float *gamma) = calculate_gamma; -static void cmd_sample(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_sample) { - if (argc == 1) { - if (strcmp(argv[0], "ref") == 0) { - sample_func = fetch_amplitude_ref; + if (argc != 1) goto usage; + // 0 1 2 + static const char cmd_sample_list[] = "gamma|ampl|ref"; + switch (get_str_index(argv[0], cmd_sample_list)) { + case 0: + sample_func = calculate_gamma; return; - } else if (strcmp(argv[0], "ampl") == 0) { + case 1: sample_func = fetch_amplitude; return; - } else if (strcmp(argv[0], "gamma") == 0) { - sample_func = calculate_gamma; + case 2: + sample_func = fetch_amplitude_ref; return; - } + default: + break; } - chprintf(chp, "usage: sample {gamma|ampl|ref}\r\n"); +usage: + shell_printf("usage: sample {%s}\r\n", cmd_sample_list); } config_t config = { @@ -600,29 +752,50 @@ config_t config = { .trace_color = { DEFAULT_TRACE_1_COLOR, DEFAULT_TRACE_2_COLOR, DEFAULT_TRACE_3_COLOR, DEFAULT_TRACE_4_COLOR }, // .touch_cal = { 693, 605, 124, 171 }, // 2.4 inch LCD panel .touch_cal = { 338, 522, 153, 192 }, // 2.8 inch LCD panel - .default_loadcal = 0, - .harmonic_freq_threshold = 300000000 + .freq_mode = FREQ_MODE_START_STOP, + .harmonic_freq_threshold = 300000000, + .vbat_offset = 500 }; -properties_t current_props = { - .magic = CONFIG_MAGIC, - ._frequency0 = 50000, // start = 50kHz - ._frequency1 = 900000000, // end = 900MHz - ._sweep_points = POINTS_COUNT, - ._trace = {/*enable, type, channel, polar, scale, refpos*/ - { 1, TRC_LOGMAG, 0, 0, 1.0, 9.0 }, - { 1, TRC_LOGMAG, 1, 0, 1.0, 9.0 }, - { 1, TRC_SMITH, 0, 1, 1.0, 0.0 }, - { 1, TRC_PHASE, 1, 0, 1.0, 5.0 } - }, - ._markers = { - { 1, 30, 0 }, { 0, 40, 0 }, { 0, 60, 0 }, { 0, 80, 0 } - }, - ._velocity_factor = 0.7, - ._marker_smith_format = MS_RLC -}; +properties_t current_props; properties_t *active_props = ¤t_props; +// NanoVNA Default settings +static const trace_t def_trace[TRACES_MAX] = {//enable, type, channel, reserved, scale, refpos + { 1, TRC_LOGMAG, 0, 0, 10.0, NGRIDY-1 }, + { 1, TRC_LOGMAG, 1, 0, 10.0, NGRIDY-1 }, + { 1, TRC_SMITH, 0, 0, 1.0, 0 }, + { 1, TRC_PHASE, 1, 0, 90.0, NGRIDY/2 } +}; + +static const marker_t def_markers[MARKERS_MAX] = { + { 1, 30, 0 }, { 0, 40, 0 }, { 0, 60, 0 }, { 0, 80, 0 } +}; + +// Load propeties default settings +void load_default_properties(void) +{ +//Magic add on caldata_save +//current_props.magic = CONFIG_MAGIC; + current_props._frequency0 = 50000; // start = 50kHz + current_props._frequency1 = 900000000; // end = 900MHz + current_props._sweep_points = POINTS_COUNT; + current_props._cal_status = 0; +//This data not loaded by default +//current_props._frequencies[POINTS_COUNT]; +//current_props._cal_data[5][POINTS_COUNT][2]; +//============================================= + current_props._electrical_delay = 0.0; + memcpy(current_props._trace, def_trace, sizeof(def_trace)); + memcpy(current_props._markers, def_markers, sizeof(def_markers)); + current_props._velocity_factor = 0.7; + current_props._active_marker = 0; + current_props._domain_mode = 0; + current_props._marker_smith_format = MS_RLC; +//Checksum add on caldata_save +//current_props.checksum = 0; +} + void ensure_edit_config(void) { @@ -635,33 +808,39 @@ ensure_edit_config(void) cal_status = 0; } -#define DELAY_CHANNEL_CHANGE 3 +#define DSP_START(delay) wait_count = delay; +#define DSP_WAIT_READY while (wait_count) __WFI(); + +#define DELAY_CHANNEL_CHANGE 2 // main loop for measurement bool sweep(bool break_on_operation) { - int i; - - for (i = 0; i < sweep_points; i++) { - int delay = set_frequency(frequencies[i]); - tlv320aic3204_select(0); // CH0:REFLECT - wait_dsp(delay); - - // blink LED while scanning - palClearPad(GPIOC, GPIOC_LED); - - /* calculate reflection coeficient */ - (*sample_func)(measured[0][i]); - - tlv320aic3204_select(1); // CH1:TRANSMISSION - wait_dsp(DELAY_CHANNEL_CHANGE); - - /* calculate transmission coeficient */ - (*sample_func)(measured[1][i]); - - // blink LED while scanning - palSetPad(GPIOC, GPIOC_LED); - + int i, delay; + // blink LED while scanning + palClearPad(GPIOC, GPIOC_LED); + // Power stabilization after LED off, also align timings on i == 0 + for (i = 0; i < sweep_points; i++) { // 5300 + if (frequencies[i] == 0) break; + delay = set_frequency(frequencies[i]); // 700 + tlv320aic3204_select(0); // 60 CH0:REFLECT, reset and begin measure + DSP_START(delay + ((i == 0) ? 1 : 0)); // 1900 + //================================================ + // Place some code thats need execute while delay + //================================================ + DSP_WAIT_READY; + // calculate reflection coefficient + (*sample_func)(measured[0][i]); // 60 + + tlv320aic3204_select(1); // 60 CH1:TRANSMISSION, reset and begin measure + DSP_START(DELAY_CHANNEL_CHANGE); // 1700 + //================================================ + // Place some code thats need execute while delay + //================================================ + DSP_WAIT_READY; + // calculate transmission coefficient + (*sample_func)(measured[1][i]); // 60 + // ======== 170 =========== if (cal_status & CALSTAT_APPLY) apply_error_term_at(i); @@ -672,47 +851,52 @@ bool sweep(bool break_on_operation) if (operation_requested && break_on_operation) return false; } - - transform_domain(); + // blink LED while scanning + palSetPad(GPIOC, GPIOC_LED); return true; } -static void cmd_scan(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_scan) { - int32_t start, stop; + uint32_t start, stop; int16_t points = sweep_points; - - if (argc != 2 && argc != 3) { - chprintf(chp, "usage: sweep {start(Hz)} {stop(Hz)} [points]\r\n"); + int i; + if (argc < 2 || argc > 4) { + shell_printf("usage: scan {start(Hz)} {stop(Hz)} [points] [outmask]\r\n"); return; } - start = atoi(argv[0]); - stop = atoi(argv[1]); + start = my_atoui(argv[0]); + stop = my_atoui(argv[1]); if (start == 0 || stop == 0 || start > stop) { - chprintf(chp, "frequency range is invalid\r\n"); + shell_printf("frequency range is invalid\r\n"); return; } - if (argc == 3) { - points = atoi(argv[2]); - if (points <= 0 || points > sweep_points) { - chprintf(chp, "sweep points exceeds range\r\n"); + if (argc >= 3) { + points = my_atoi(argv[2]); + if (points <= 0 || points > POINTS_COUNT) { + shell_printf("sweep points exceeds range "define_to_STR(POINTS_COUNT)"\r\n"); return; } } - pause_sweep(); - chMtxLock(&mutex); set_frequencies(start, stop, points); if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY)) cal_interpolate(lastsaveid); - - sweep_once = TRUE; - chMtxUnlock(&mutex); - - // wait finishing sweep - while (sweep_once) - chThdSleepMilliseconds(10); + pause_sweep(); + sweep(false); + // Output data after if set (faster data recive) + if (argc == 4) { + uint16_t mask = my_atoui(argv[3]); + if (mask) { + for (i = 0; i < points; i++) { + if (mask & 1) shell_printf("%u ", frequencies[i]); + if (mask & 2) shell_printf("%f %f ", measured[0][i][0], measured[0][i][1]); + if (mask & 4) shell_printf("%f %f ", measured[1][i][0], measured[1][i][1]); + shell_printf("\r\n"); + } + } + } } static void @@ -720,25 +904,22 @@ update_marker_index(void) { int m; int i; - for (m = 0; m < 4; m++) { + for (m = 0; m < MARKERS_MAX; m++) { if (!markers[m].enabled) continue; uint32_t f = markers[m].frequency; - if (f < frequencies[0]) { + uint32_t fstart = get_sweep_frequency(ST_START); + uint32_t fstop = get_sweep_frequency(ST_STOP); + if (f < fstart) { markers[m].index = 0; - markers[m].frequency = frequencies[0]; - } else if (f >= frequencies[sweep_points-1]) { + markers[m].frequency = fstart; + } else if (f >= fstop) { markers[m].index = sweep_points-1; - markers[m].frequency = frequencies[sweep_points-1]; + markers[m].frequency = fstop; } else { for (i = 0; i < sweep_points-1; i++) { if (frequencies[i] <= f && f < frequencies[i+1]) { - uint32_t mid = (frequencies[i] + frequencies[i+1])/2; - if (f < mid) { - markers[m].index = i; - } else { - markers[m].index = i + 1; - } + markers[m].index = f < (frequencies[i] / 2 + frequencies[i + 1] / 2) ? i : i + 1; break; } } @@ -746,159 +927,111 @@ update_marker_index(void) } } -void -set_frequencies(uint32_t start, uint32_t stop, int16_t points) -{ - int i; - float span = stop - start; - for (i = 0; i < points; i++) { - float offset = i * span / (float)(points - 1); - frequencies[i] = start + (uint32_t)offset; +static void +set_frequencies(uint32_t start, uint32_t stop, uint16_t points) +{ + uint32_t i; + uint32_t step = (points - 1); + uint32_t span = stop - start; + uint32_t delta = span / step; + uint32_t error = span % step; + uint32_t f = start, df = step>>1; + for (i = 0; i <= step; i++, f+=delta) { + frequencies[i] = f; + df+=error; + if (df >=step) { + f++; + df -= step; + } } // disable at out of sweep range - for (; i < sweep_points; i++) + for (; i < POINTS_COUNT; i++) frequencies[i] = 0; } -void +static void update_frequencies(void) { uint32_t start, stop; - if (frequency0 < frequency1) { - start = frequency0; - stop = frequency1; - } else { - start = frequency1; - stop = frequency0; - } + start = get_sweep_frequency(ST_START); + stop = get_sweep_frequency(ST_STOP); set_frequencies(start, stop, sweep_points); - operation_requested = OP_FREQCHANGE; - + // operation_requested|= OP_FREQCHANGE; + update_marker_index(); - + // set grid layout update_grid(); } -void -freq_mode_startstop(void) -{ - if (frequency0 > frequency1) { - ensure_edit_config(); - uint32_t f = frequency1; - frequency1 = frequency0; - frequency0 = f; - } -} - -void -freq_mode_centerspan(void) -{ - if (frequency0 <= frequency1) { - ensure_edit_config(); - uint32_t f = frequency1; - frequency1 = frequency0; - frequency0 = f; - } -} - - -#define START_MIN 50000 -#define STOP_MAX 2700000000U - void set_sweep_frequency(int type, uint32_t freq) { int cal_applied = cal_status & CALSTAT_APPLY; -/* // negative value indicate overflow, do nothing - if (freq < 0) - return;*/ + + // Check frequency for out of bounds (minimum SPAN can be any value) + if (type != ST_SPAN && freq < START_MIN) + freq = START_MIN; + if (freq > STOP_MAX) + freq = STOP_MAX; + + ensure_edit_config(); switch (type) { - case ST_START: - freq_mode_startstop(); - if (freq < START_MIN) - freq = START_MIN; - if (freq > STOP_MAX) - freq = STOP_MAX; - if (frequency0 != freq) { - ensure_edit_config(); - frequency0 = freq; - // if start > stop then make start = stop - if (frequency1 < freq) - frequency1 = freq; - update_frequencies(); - } - break; - case ST_STOP: - freq_mode_startstop(); - if (freq > STOP_MAX) - freq = STOP_MAX; - if (freq < START_MIN) - freq = START_MIN; - if (frequency1 != freq) { - ensure_edit_config(); - frequency1 = freq; - // if start > stop then make start = stop - if (frequency0 > freq) + case ST_START: + config.freq_mode &= ~FREQ_MODE_CENTER_SPAN; + if (frequency0 != freq) { frequency0 = freq; - update_frequencies(); - } - break; - case ST_CENTER: - if (freq < START_MIN) - freq = START_MIN; - if (freq > STOP_MAX) - freq = STOP_MAX; - freq_mode_centerspan(); - uint32_t center = frequency0/2 + frequency1/2; - if (center != freq) { - uint32_t span = frequency0 - frequency1; - ensure_edit_config(); - if (freq < START_MIN + span/2) { - span = (freq - START_MIN) * 2; + // if start > stop then make start = stop + if (frequency1 < freq) frequency1 = freq; } - if (freq > STOP_MAX - span/2) { - span = (STOP_MAX - freq) * 2; + break; + case ST_STOP: + config.freq_mode &= ~FREQ_MODE_CENTER_SPAN; + if (frequency1 != freq) { + frequency1 = freq; + // if start > stop then make start = stop + if (frequency0 > freq) frequency0 = freq; } - frequency0 = freq + span/2; - frequency1 = freq - span/2; - update_frequencies(); - } - break; - case ST_SPAN: - if (freq > STOP_MAX) - freq = STOP_MAX; - freq_mode_centerspan(); - if (frequency0 - frequency1 != freq) { - ensure_edit_config(); - uint32_t center = frequency0/2 + frequency1/2; - if (center < START_MIN + freq/2) { - center = START_MIN + freq/2; + break; + case ST_CENTER: + config.freq_mode |= FREQ_MODE_CENTER_SPAN; + uint32_t center = frequency0 / 2 + frequency1 / 2; + if (center != freq) { + uint32_t span = frequency1 - frequency0; + if (freq < START_MIN + span / 2) { + span = (freq - START_MIN) * 2; + } + if (freq > STOP_MAX - span / 2) { + span = (STOP_MAX - freq) * 2; + } + frequency0 = freq - span / 2; + frequency1 = freq + span / 2; } - if (center > STOP_MAX - freq/2) { - center = STOP_MAX - freq/2; + break; + case ST_SPAN: + config.freq_mode |= FREQ_MODE_CENTER_SPAN; + if (frequency1 - frequency0 != freq) { + uint32_t center = frequency0 / 2 + frequency1 / 2; + if (center < START_MIN + freq / 2) { + center = START_MIN + freq / 2; + } + if (center > STOP_MAX - freq / 2) { + center = STOP_MAX - freq / 2; + } + frequency0 = center - freq / 2; + frequency1 = center + freq / 2; } - frequency1 = center - freq/2; - frequency0 = center + freq/2; - update_frequencies(); - } - break; - case ST_CW: - if (freq < START_MIN) - freq = START_MIN; - if (freq > STOP_MAX) - freq = STOP_MAX; - freq_mode_centerspan(); - if (frequency0 != freq || frequency1 != freq) { - ensure_edit_config(); - frequency0 = freq; - frequency1 = freq; - update_frequencies(); - } - break; + break; + case ST_CW: + config.freq_mode |= FREQ_MODE_CENTER_SPAN; + if (frequency0 != freq || frequency1 != freq) { + frequency0 = freq; + frequency1 = freq; + } + break; } - + update_frequencies(); if (cal_auto_interpolate && cal_applied) cal_interpolate(lastsaveid); } @@ -906,73 +1039,56 @@ set_sweep_frequency(int type, uint32_t freq) uint32_t get_sweep_frequency(int type) { - if (frequency0 <= frequency1) { - switch (type) { - case ST_START: return frequency0; - case ST_STOP: return frequency1; - case ST_CENTER: return frequency0/2 + frequency1/2; - case ST_SPAN: return frequency1 - frequency0; - case ST_CW: return frequency0/2 + frequency1/2; - } - } else { - switch (type) { - case ST_START: return frequency1; - case ST_STOP: return frequency0; + // Obsolete, ensure correct start/stop, start always must be < stop + if (frequency0 > frequency1) { + uint32_t t = frequency0; + frequency0 = frequency1; + frequency1 = t; + } + switch (type) { + case ST_START: return frequency0; + case ST_STOP: return frequency1; case ST_CENTER: return frequency0/2 + frequency1/2; - case ST_SPAN: return frequency0 - frequency1; - case ST_CW: return frequency0/2 + frequency1/2; - } + case ST_SPAN: return frequency1 - frequency0; + case ST_CW: return frequency0; } return 0; } - -static void cmd_sweep(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_sweep) { if (argc == 0) { - chprintf(chp, "%d %d %d\r\n", frequency0, frequency1, sweep_points); + shell_printf("%d %d %d\r\n", get_sweep_frequency(ST_START), get_sweep_frequency(ST_STOP), sweep_points); return; } else if (argc > 3) { goto usage; } - if (argc >= 2) { - if (strcmp(argv[0], "start") == 0) { - int32_t value = atoi(argv[1]); - set_sweep_frequency(ST_START, value); - return; - } else if (strcmp(argv[0], "stop") == 0) { - int32_t value = atoi(argv[1]); - set_sweep_frequency(ST_STOP, value); - return; - } else if (strcmp(argv[0], "center") == 0) { - int32_t value = atoi(argv[1]); - set_sweep_frequency(ST_CENTER, value); - return; - } else if (strcmp(argv[0], "span") == 0) { - int32_t value = atoi(argv[1]); - set_sweep_frequency(ST_SPAN, value); - return; - } else if (strcmp(argv[0], "cw") == 0) { - int32_t value = atoi(argv[1]); - set_sweep_frequency(ST_CW, value); - return; - } - } - - if (argc >= 1) { - int32_t value = atoi(argv[0]); - if (value == 0) + uint32_t value0 = 0; + uint32_t value1 = 0; + if (argc >= 1) value0 = my_atoui(argv[0]); + if (argc >= 2) value1 = my_atoui(argv[1]); +#if MAX_FREQ_TYPE != 5 +#error "Sweep mode possibly changed, check cmd_sweep function" +#endif + // Parse sweep {start|stop|center|span|cw} {freq(Hz)} + // get enum ST_START, ST_STOP, ST_CENTER, ST_SPAN, ST_CW + static const char sweep_cmd[] = "start|stop|center|span|cw"; + if (argc == 2 && value0 == 0) { + int type = get_str_index(argv[0], sweep_cmd); + if (type == -1) goto usage; - set_sweep_frequency(ST_START, value); - } - if (argc >= 2) { - int32_t value = atoi(argv[1]); - set_sweep_frequency(ST_STOP, value); + set_sweep_frequency(type, value1); + return; } + // Parse sweep {start(Hz)} [stop(Hz)] + if (value0) + set_sweep_frequency(ST_START, value0); + if (value1) + set_sweep_frequency(ST_STOP, value1); return; usage: - chprintf(chp, "usage: sweep {start(Hz)} [stop(Hz)]\r\n"); - chprintf(chp, "\tsweep {start|stop|center|span|cw} {freq(Hz)}\r\n"); + shell_printf("usage: sweep {start(Hz)} [stop(Hz)]\r\n"\ + "\tsweep {%s} {freq(Hz)}\r\n", sweep_cmd); } @@ -992,13 +1108,14 @@ eterm_copy(int dst, int src) memcpy(cal_data[dst], cal_data[src], sizeof cal_data[dst]); } - +#if 0 const struct open_model { float c0; float c1; float c2; float c3; } open_model = { 50, 0, -300, 27 }; +#endif #if 0 static void @@ -1011,7 +1128,7 @@ adjust_ed(void) // prepare 1/s11ao to avoid dividing complex float c = 1000e-15; float z0 = 50; - //float z = 6.2832 * frequencies[i] * c * z0; + //float z = 2 * VNA_PI * frequencies[i] * c * z0; float z = 0.02; cal_data[ETERM_ED][i][0] += z; } @@ -1029,7 +1146,7 @@ eterm_calc_es(void) float c = 50e-15; //float c = 1.707e-12; float z0 = 50; - float z = 6.2832 * frequencies[i] * c * z0; + float z = 2 * VNA_PI * frequencies[i] * c * z0; float sq = 1 + z*z; float s11aor = (1 - z*z) / sq; float s11aoi = 2*z / sq; @@ -1134,7 +1251,7 @@ void apply_error_term(void) } #endif -void apply_error_term_at(int i) +static void apply_error_term_at(int i) { // S11m' = S11m - Ed // S11a = S11m' / (Er + Es S11m') @@ -1165,7 +1282,7 @@ void apply_error_term_at(int i) static void apply_edelay_at(int i) { - float w = 2 * M_PI * electrical_delay * frequencies[i] * 1E-12; + float w = 2 * VNA_PI * electrical_delay * frequencies[i] * 1E-12; float s = sin(w); float c = cos(w); float real = measured[0][i][0]; @@ -1182,37 +1299,20 @@ void cal_collect(int type) { ensure_edit_config(); - chMtxLock(&mutex); - + int dst, src; switch (type) { - case CAL_LOAD: - cal_status |= CALSTAT_LOAD; - memcpy(cal_data[CAL_LOAD], measured[0], sizeof measured[0]); - break; - - case CAL_OPEN: - cal_status |= CALSTAT_OPEN; - cal_status &= ~(CALSTAT_ES|CALSTAT_APPLY); - memcpy(cal_data[CAL_OPEN], measured[0], sizeof measured[0]); - break; - - case CAL_SHORT: - cal_status |= CALSTAT_SHORT; - cal_status &= ~(CALSTAT_ER|CALSTAT_APPLY); - memcpy(cal_data[CAL_SHORT], measured[0], sizeof measured[0]); - break; - - case CAL_THRU: - cal_status |= CALSTAT_THRU; - memcpy(cal_data[CAL_THRU], measured[1], sizeof measured[0]); - break; - - case CAL_ISOLN: - cal_status |= CALSTAT_ISOLN; - memcpy(cal_data[CAL_ISOLN], measured[1], sizeof measured[0]); - break; + case CAL_LOAD: cal_status|= CALSTAT_LOAD; dst = CAL_LOAD; src = 0; break; + case CAL_OPEN: cal_status|= CALSTAT_OPEN; dst = CAL_OPEN; src = 0; cal_status&= ~(CALSTAT_ES|CALSTAT_APPLY); break; + case CAL_SHORT: cal_status|= CALSTAT_SHORT; dst = CAL_SHORT; src = 0; cal_status&= ~(CALSTAT_ER|CALSTAT_APPLY); break; + case CAL_THRU: cal_status|= CALSTAT_THRU; dst = CAL_THRU; src = 1; break; + case CAL_ISOLN: cal_status|= CALSTAT_ISOLN; dst = CAL_ISOLN; src = 1; break; + default: + return; } - chMtxUnlock(&mutex); + // Run sweep for collect data + sweep(false); + // Copy calibration data + memcpy(cal_data[dst], measured[src], sizeof measured[0]); redraw_request |= REDRAW_CAL_STATUS; } @@ -1251,7 +1351,7 @@ cal_done(void) redraw_request |= REDRAW_CAL_STATUS; } -void +static void cal_interpolate(int s) { const properties_t *src = caldata_ref(s); @@ -1277,13 +1377,13 @@ cal_interpolate(int s) j = 0; for (; i < sweep_points; i++) { uint32_t f = frequencies[i]; - - for (; j < sweep_points-1; j++) { + if (f == 0) goto interpolate_finish; + for (; j < src->_sweep_points-1; j++) { if (src->_frequencies[j] <= f && f < src->_frequencies[j+1]) { // found f between freqs at j and j+1 float k1 = (float)(f - src->_frequencies[j]) / (src->_frequencies[j+1] - src->_frequencies[j]); - + // avoid glitch between freqs in different harmonics mode if (IS_HARMONIC_MODE(src->_frequencies[j]) != IS_HARMONIC_MODE(src->_frequencies[j+1])) { // assume f[j] < f[j+1] @@ -1298,91 +1398,89 @@ cal_interpolate(int s) break; } } - if (j == sweep_points-1) + if (j == src->_sweep_points-1) break; } - + // upper than end freq of src range for (; i < sweep_points; i++) { // fill cal_data at tail of src for (eterm = 0; eterm < 5; eterm++) { - cal_data[eterm][i][0] = src->_cal_data[eterm][sweep_points-1][0]; - cal_data[eterm][i][1] = src->_cal_data[eterm][sweep_points-1][1]; + cal_data[eterm][i][0] = src->_cal_data[eterm][src->_sweep_points-1][0]; + cal_data[eterm][i][1] = src->_cal_data[eterm][src->_sweep_points-1][1]; } } - +interpolate_finish: cal_status |= src->_cal_status | CALSTAT_APPLY | CALSTAT_INTERPOLATED; redraw_request |= REDRAW_CAL_STATUS; } -static void cmd_cal(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_cal) { - const char *items[] = { "load", "open", "short", "thru", "isoln", "Es", "Er", "Et", "cal'ed" }; + static const char *items[] = { "load", "open", "short", "thru", "isoln", "Es", "Er", "Et", "cal'ed" }; if (argc == 0) { int i; for (i = 0; i < 9; i++) { if (cal_status & (1< 1) - s = atoi(argv[1]); - cal_interpolate(s); - redraw_request |= REDRAW_CAL_STATUS; - return; - } else { - chprintf(chp, "usage: cal [load|open|short|thru|isoln|done|reset|on|off|in]\r\n"); - return; + redraw_request|=REDRAW_CAL_STATUS; + // 0 1 2 3 4 5 6 7 8 9 10 + static const char cmd_cal_list[] = "load|open|short|thru|isoln|done|on|off|reset|data|in"; + switch (get_str_index(argv[0], cmd_cal_list)) { + case 0: + cal_collect(CAL_LOAD); + return; + case 1: + cal_collect(CAL_OPEN); + return; + case 2: + cal_collect(CAL_SHORT); + return; + case 3: + cal_collect(CAL_THRU); + return; + case 4: + cal_collect(CAL_ISOLN); + return; + case 5: + cal_done(); + return; + case 6: + cal_status |= CALSTAT_APPLY; + return; + case 7: + cal_status &= ~CALSTAT_APPLY; + return; + case 8: + cal_status = 0; + return; + case 9: + shell_printf("%f %f\r\n", cal_data[CAL_LOAD][0][0], cal_data[CAL_LOAD][0][1]); + shell_printf("%f %f\r\n", cal_data[CAL_OPEN][0][0], cal_data[CAL_OPEN][0][1]); + shell_printf("%f %f\r\n", cal_data[CAL_SHORT][0][0], cal_data[CAL_SHORT][0][1]); + shell_printf("%f %f\r\n", cal_data[CAL_THRU][0][0], cal_data[CAL_THRU][0][1]); + shell_printf("%f %f\r\n", cal_data[CAL_ISOLN][0][0], cal_data[CAL_ISOLN][0][1]); + return; + case 10: + cal_interpolate((argc > 1) ? my_atoi(argv[1]) : 0); + return; + default: + break; } + shell_printf("usage: cal [%s]\r\n", cmd_cal_list); } -static void cmd_save(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_save) { - (void)chp; - if (argc != 1) goto usage; - int id = atoi(argv[0]); + int id = my_atoi(argv[0]); if (id < 0 || id >= SAVEAREA_MAX) goto usage; caldata_save(id); @@ -1390,82 +1488,71 @@ static void cmd_save(BaseSequentialStream *chp, int argc, char *argv[]) return; usage: - chprintf(chp, "save {id}\r\n"); + shell_printf("save {id}\r\n"); } -static void cmd_recall(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_recall) { - (void)chp; if (argc != 1) goto usage; - int id = atoi(argv[0]); + int id = my_atoi(argv[0]); if (id < 0 || id >= SAVEAREA_MAX) goto usage; - - pause_sweep(); - chMtxLock(&mutex); - if (caldata_recall(id) == 0) { - // success - update_frequencies(); - redraw_request |= REDRAW_CAL_STATUS; - } - chMtxUnlock(&mutex); - resume_sweep(); + // Check for success + if (caldata_recall(id) == -1) + shell_printf("Err, default load\r\n"); + update_frequencies(); + redraw_request |= REDRAW_CAL_STATUS; return; - usage: - chprintf(chp, "recall {id}\r\n"); + shell_printf("recall {id}\r\n"); } -const struct { +static const struct { const char *name; uint16_t refpos; float scale_unit; } trace_info[] = { - { "LOGMAG", 9, 10 }, - { "PHASE", 5, 90 }, - { "DELAY", 5, 1e-9 }, - { "SMITH", 0, 1 }, - { "POLAR", 0, 1 }, - { "LINEAR", 0, 0.125 }, - { "SWR", 0, 1 }, - { "REAL", 5, 0.25 }, - { "IMAG", 5, 0.25 }, - { "R", 0, 100 }, - { "X", 5, 100 } + { "LOGMAG", NGRIDY-1, 10.0 }, + { "PHASE", NGRIDY/2, 90.0 }, + { "DELAY", NGRIDY/2, 1e-9 }, + { "SMITH", 0, 1.00 }, + { "POLAR", 0, 1.00 }, + { "LINEAR", 0, 0.125}, + { "SWR", 0, 0.25 }, + { "REAL", NGRIDY/2, 0.25 }, + { "IMAG", NGRIDY/2, 0.25 }, + { "R", NGRIDY/2, 100.0 }, + { "X", NGRIDY/2, 100.0 } }; -const char * const trc_channel_name[] = { +static const char * const trc_channel_name[] = { "CH0", "CH1" }; -const char * -get_trace_typename(int t) +const char *get_trace_typename(int t) { return trace_info[trace[t].type].name; } void set_trace_type(int t, int type) { - int polar = type == TRC_SMITH || type == TRC_POLAR; int enabled = type != TRC_OFF; int force = FALSE; - if (trace[t].polar != polar) { - trace[t].polar = polar; - force = TRUE; - } if (trace[t].enabled != enabled) { trace[t].enabled = enabled; force = TRUE; } if (trace[t].type != type) { trace[t].type = type; + // Set default trace refpos trace[t].refpos = trace_info[type].refpos; - if (polar) - force = TRUE; - } + // Set default trace scale + trace[t].scale = trace_info[type].scale_unit; + force = TRUE; + } if (force) { plot_into_index(measured); force_set_markmap(); @@ -1482,7 +1569,6 @@ void set_trace_channel(int t, int channel) void set_trace_scale(int t, float scale) { - scale /= trace_info[trace[t].type].scale_unit; if (trace[t].scale != scale) { trace[t].scale = scale; force_set_markmap(); @@ -1491,7 +1577,7 @@ void set_trace_scale(int t, float scale) float get_trace_scale(int t) { - return trace[t].scale * trace_info[trace[t].type].scale_unit; + return trace[t].scale; } void set_trace_refpos(int t, float refpos) @@ -1507,128 +1593,76 @@ float get_trace_refpos(int t) return trace[t].refpos; } -float -my_atof(const char *p) -{ - int neg = FALSE; - if (*p == '-') - neg = TRUE; - if (*p == '-' || *p == '+') - p++; - float x = atoi(p); - while (isdigit((int)*p)) - p++; - if (*p == '.') { - float d = 1.0f; - p++; - while (isdigit((int)*p)) { - d /= 10; - x += d * (*p - '0'); - p++; - } - } - if (*p == 'e' || *p == 'E') { - p++; - int exp = atoi(p); - while (exp > 0) { - x *= 10; - exp--; - } - while (exp < 0) { - x /= 10; - exp++; - } - } - if (neg) - x = -x; - return x; -} - -typedef struct { - char *tracename; - uint8_t type; -} type_list; - -static void cmd_trace(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_trace) { int t; if (argc == 0) { - for (t = 0; t < 4; t++) { + for (t = 0; t < TRACES_MAX; t++) { if (trace[t].enabled) { - const char *type = trace_info[trace[t].type].name; + const char *type = get_trace_typename(t); const char *channel = trc_channel_name[trace[t].channel]; float scale = get_trace_scale(t); float refpos = get_trace_refpos(t); - chprintf(chp, "%d %s %s %f %f\r\n", t, type, channel, scale, refpos); + shell_printf("%d %s %s %f %f\r\n", t, type, channel, scale, refpos); } } return; - } + } if (strcmp(argv[0], "all") == 0 && argc > 1 && strcmp(argv[1], "off") == 0) { - set_trace_type(0, TRC_OFF); - set_trace_type(1, TRC_OFF); - set_trace_type(2, TRC_OFF); - set_trace_type(3, TRC_OFF); + for (t = 0; t < TRACES_MAX; t++) + set_trace_type(t, TRC_OFF); goto exit; } - t = atoi(argv[0]); - if (t < 0 || t >= 4) + t = my_atoi(argv[0]); + if (t < 0 || t >= TRACES_MAX) goto usage; if (argc == 1) { const char *type = get_trace_typename(t); const char *channel = trc_channel_name[trace[t].channel]; - chprintf(chp, "%d %s %s\r\n", t, type, channel); + shell_printf("%d %s %s\r\n", t, type, channel); return; } - - if (argc > 1) { - static const type_list t_list[] = { - {"logmag", TRC_LOGMAG}, - {"phase", TRC_PHASE}, - {"polar", TRC_POLAR}, - {"smith", TRC_SMITH}, - {"delay", TRC_DELAY}, - {"linear", TRC_LINEAR}, - {"swr", TRC_SWR}, - {"real", TRC_REAL}, - {"imag", TRC_IMAG}, - {"r", TRC_R}, - {"x", TRC_X}, - {"off", TRC_OFF}, - }; - for (uint16_t i=0; i= 3) { - //trace[t].scale = my_atof(argv[2]); - set_trace_scale(t, my_atof(argv[2])); - goto exit; - } else if (strcmp(argv[1], "refpos") == 0 && argc >= 3) { - //trace[t].refpos = my_atof(argv[2]); - set_trace_refpos(t, my_atof(argv[2])); - goto exit; - } else { - goto usage; +#if MAX_TRACE_TYPE != 12 +#error "Trace type enum possibly changed, check cmd_trace function" +#endif + // enum TRC_LOGMAG, TRC_PHASE, TRC_DELAY, TRC_SMITH, TRC_POLAR, TRC_LINEAR, TRC_SWR, TRC_REAL, TRC_IMAG, TRC_R, TRC_X, TRC_OFF + static const char cmd_type_list[] = "logmag|phase|delay|smith|polar|linear|swr|real|imag|r|x|off"; + int type = get_str_index(argv[1], cmd_type_list); + if (type >= 0) { + set_trace_type(t, type); + goto check_ch_num; + } + // 0 1 + static const char cmd_scale_ref_list[] = "scale|refpos"; + if (argc >= 3) { + switch (get_str_index(argv[1], cmd_scale_ref_list)) { + case 0: + //trace[t].scale = my_atof(argv[2]); + set_trace_scale(t, my_atof(argv[2])); + goto exit; + case 1: + //trace[t].refpos = my_atof(argv[2]); + set_trace_refpos(t, my_atof(argv[2])); + goto exit; + default: + goto usage; } } - check_ch_num: +check_ch_num: if (argc > 2) { - int src = atoi(argv[2]); + int src = my_atoi(argv[2]); if (src != 0 && src != 1) goto usage; trace[t].channel = src; } - exit: +exit: return; - usage: - chprintf(chp, "trace {0|1|2|3|all} [logmag|phase|polar|smith|linear|delay|swr|real|imag|r|x|off] [src]\r\n"); - chprintf(chp, "trace {0|1|2|3} {scale|refpos} {value}\r\n"); +usage: + shell_printf("trace {0|1|2|3|all} [%s] [src]\r\n"\ + "trace {0|1|2|3} {%s} {value}\r\n", cmd_type_list, cmd_scale_ref_list); } @@ -1638,6 +1672,7 @@ void set_electrical_delay(float picoseconds) electrical_delay = picoseconds; force_set_markmap(); } + redraw_request |= REDRAW_MARKER; } float get_electrical_delay(void) @@ -1645,10 +1680,10 @@ float get_electrical_delay(void) return electrical_delay; } -static void cmd_edelay(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_edelay) { if (argc == 0) { - chprintf(chp, "%f\r\n", electrical_delay); + shell_printf("%f\r\n", electrical_delay); return; } if (argc > 0) { @@ -1657,103 +1692,86 @@ static void cmd_edelay(BaseSequentialStream *chp, int argc, char *argv[]) } -static void cmd_marker(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_marker) { int t; if (argc == 0) { - for (t = 0; t < 4; t++) { + for (t = 0; t < MARKERS_MAX; t++) { if (markers[t].enabled) { - chprintf(chp, "%d %d %d\r\n", t+1, markers[t].index, markers[t].frequency); + shell_printf("%d %d %d\r\n", t+1, markers[t].index, markers[t].frequency); } } return; - } + } + redraw_request |= REDRAW_MARKER; if (strcmp(argv[0], "off") == 0) { active_marker = -1; - for (t = 0; t < 4; t++) + for (t = 0; t < MARKERS_MAX; t++) markers[t].enabled = FALSE; - redraw_request |= REDRAW_MARKER; return; } - - t = atoi(argv[0])-1; - if (t < 0 || t >= 4) + t = my_atoi(argv[0])-1; + if (t < 0 || t >= MARKERS_MAX) goto usage; if (argc == 1) { - chprintf(chp, "%d %d %d\r\n", t+1, markers[t].index, frequency); + shell_printf("%d %d %d\r\n", t+1, markers[t].index, markers[t].frequency); active_marker = t; // select active marker markers[t].enabled = TRUE; - redraw_request |= REDRAW_MARKER; return; } - if (argc > 1) { - if (strcmp(argv[1], "off") == 0) { - markers[t].enabled = FALSE; - if (active_marker == t) - active_marker = -1; - redraw_request |= REDRAW_MARKER; - } else if (strcmp(argv[1], "on") == 0) { - markers[t].enabled = TRUE; - active_marker = t; - redraw_request |= REDRAW_MARKER; - } else { + static const char cmd_marker_list[] = "on|off"; + switch (get_str_index(argv[1], cmd_marker_list)) { + case 0: markers[t].enabled = TRUE; active_marker = t; return; + case 1: markers[t].enabled =FALSE; if (active_marker == t) active_marker = -1; return; + default: // select active marker and move to index markers[t].enabled = TRUE; - int index = atoi(argv[1]); + int index = my_atoi(argv[1]); markers[t].index = index; markers[t].frequency = frequencies[index]; active_marker = t; - redraw_request |= REDRAW_MARKER; - } + return; } - return; usage: - chprintf(chp, "marker [n] [off|{index}]\r\n"); + shell_printf("marker [n] [%s|{index}]\r\n", cmd_marker_list); } -static void cmd_touchcal(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_touchcal) { (void)argc; (void)argv; //extern int16_t touch_cal[4]; int i; - chMtxLock(&mutex); - chprintf(chp, "first touch upper left, then lower right..."); + shell_printf("first touch upper left, then lower right..."); touch_cal_exec(); - chprintf(chp, "done\r\n"); + shell_printf("done\r\n"); - chprintf(chp, "touch cal params: "); + shell_printf("touch cal params: "); for (i = 0; i < 4; i++) { - chprintf(chp, "%d ", config.touch_cal[i]); + shell_printf("%d ", config.touch_cal[i]); } - chprintf(chp, "\r\n"); - chMtxUnlock(&mutex); + shell_printf("\r\n"); } -static void cmd_touchtest(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_touchtest) { - (void)chp; (void)argc; (void)argv; - chMtxLock(&mutex); do { touch_draw_test(); - } while(argc); - chMtxUnlock(&mutex); - + } while (argc); } -static void cmd_frequencies(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_frequencies) { int i; - (void)chp; (void)argc; (void)argv; for (i = 0; i < sweep_points; i++) { if (frequencies[i] != 0) - chprintf(chp, "%d\r\n", frequencies[i]); + shell_printf("%u\r\n", frequencies[i]); } } @@ -1779,44 +1797,51 @@ set_timedomain_window(int func) // accept TD_WINDOW_MINIMUM/TD_WINDOW_NORMAL/TD_ domain_mode = (domain_mode & ~TD_WINDOW) | (func & TD_WINDOW); } -static void cmd_transform(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_transform) { int i; if (argc == 0) { goto usage; } - + // 0 1 2 3 4 5 6 7 + static const char cmd_transform_list[] = "on|off|impulse|step|bandpass|minimum|normal|maximum"; for (i = 0; i < argc; i++) { - char *cmd = argv[i]; - if (strcmp(cmd, "on") == 0) { - set_domain_mode(DOMAIN_TIME); - } else if (strcmp(cmd, "off") == 0) { - set_domain_mode(DOMAIN_FREQ); - } else if (strcmp(cmd, "impulse") == 0) { - set_timedomain_func(TD_FUNC_LOWPASS_IMPULSE); - } else if (strcmp(cmd, "step") == 0) { - set_timedomain_func(TD_FUNC_LOWPASS_STEP); - } else if (strcmp(cmd, "bandpass") == 0) { - set_timedomain_func(TD_FUNC_BANDPASS); - } else if (strcmp(cmd, "minimum") == 0) { - set_timedomain_window(TD_WINDOW_MINIMUM); - } else if (strcmp(cmd, "normal") == 0) { - set_timedomain_window(TD_WINDOW_NORMAL); - } else if (strcmp(cmd, "maximum") == 0) { - set_timedomain_window(TD_WINDOW_MAXIMUM); - } else { - goto usage; + switch (get_str_index(argv[i], cmd_transform_list)) { + case 0: + set_domain_mode(DOMAIN_TIME); + return; + case 1: + set_domain_mode(DOMAIN_FREQ); + return; + case 2: + set_timedomain_func(TD_FUNC_LOWPASS_IMPULSE); + return; + case 3: + set_timedomain_func(TD_FUNC_LOWPASS_STEP); + return; + case 4: + set_timedomain_func(TD_FUNC_BANDPASS); + return; + case 5: + set_timedomain_window(TD_WINDOW_MINIMUM); + return; + case 6: + set_timedomain_window(TD_WINDOW_NORMAL); + return; + case 7: + set_timedomain_window(TD_WINDOW_MAXIMUM); + return; + default: + goto usage; } } return; - usage: - chprintf(chp, "usage: transform {on|off|impulse|step|bandpass|minimum|normal|maximum} [...]\r\n"); + shell_printf("usage: transform {%s} [...]\r\n", cmd_transform_list); } -static void cmd_test(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_test) { - (void)chp; (void)argc; (void)argv; @@ -1839,7 +1864,7 @@ static void cmd_test(BaseSequentialStream *chp, int argc, char *argv[]) int i; int mode = 0; if (argc >= 1) - mode = atoi(argv[0]); + mode = my_atoi(argv[0]); for (i = 0; i < 20; i++) { palClearPad(GPIOC, GPIOC_LED); @@ -1851,52 +1876,52 @@ static void cmd_test(BaseSequentialStream *chp, int argc, char *argv[]) #if 0 //extern adcsample_t adc_samples[2]; - //chprintf(chp, "adc: %d %d\r\n", adc_samples[0], adc_samples[1]); + //shell_printf("adc: %d %d\r\n", adc_samples[0], adc_samples[1]); int i; int x, y; for (i = 0; i < 50; i++) { test_touch(&x, &y); - chprintf(chp, "adc: %d %d\r\n", x, y); + shell_printf("adc: %d %d\r\n", x, y); chThdSleepMilliseconds(200); } //extern int touch_x, touch_y; - //chprintf(chp, "adc: %d %d\r\n", touch_x, touch_y); + //shell_printf("adc: %d %d\r\n", touch_x, touch_y); #endif while (argc > 1) { int x, y; touch_position(&x, &y); - chprintf(chp, "touch: %d %d\r\n", x, y); + shell_printf("touch: %d %d\r\n", x, y); chThdSleepMilliseconds(200); } } -static void cmd_gain(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_gain) { int rvalue; int lvalue = 0; if (argc != 1 && argc != 2) { - chprintf(chp, "usage: gain {lgain(0-95)} [rgain(0-95)]\r\n"); + shell_printf("usage: gain {lgain(0-95)} [rgain(0-95)]\r\n"); return; } - rvalue = atoi(argv[0]); + rvalue = my_atoi(argv[0]); if (argc == 2) - lvalue = atoi(argv[1]); + lvalue = my_atoi(argv[1]); tlv320aic3204_set_gain(lvalue, rvalue); } -static void cmd_port(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_port) { int port; if (argc != 1) { - chprintf(chp, "usage: port {0:TX 1:RX}\r\n"); + shell_printf("usage: port {0:TX 1:RX}\r\n"); return; } - port = atoi(argv[0]); + port = my_atoi(argv[0]); tlv320aic3204_select(port); } -static void cmd_stat(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_stat) { int16_t *p = &rx_buffer[0]; int32_t acc0, acc1; @@ -1922,90 +1947,354 @@ static void cmd_stat(BaseSequentialStream *chp, int argc, char *argv[]) stat.ave[0] = ave0; stat.ave[1] = ave1; - chprintf(chp, "average: %d %d\r\n", stat.ave[0], stat.ave[1]); - chprintf(chp, "rms: %d %d\r\n", stat.rms[0], stat.rms[1]); - chprintf(chp, "callback count: %d\r\n", stat.callback_count); - //chprintf(chp, "interval cycle: %d\r\n", stat.interval_cycles); - //chprintf(chp, "busy cycle: %d\r\n", stat.busy_cycles); - //chprintf(chp, "load: %d\r\n", stat.busy_cycles * 100 / stat.interval_cycles); - extern int awd_count; - chprintf(chp, "awd: %d\r\n", awd_count); + shell_printf("average: %d %d\r\n", stat.ave[0], stat.ave[1]); + shell_printf("rms: %d %d\r\n", stat.rms[0], stat.rms[1]); + shell_printf("callback count: %d\r\n", stat.callback_count); + //shell_printf("interval cycle: %d\r\n", stat.interval_cycles); + //shell_printf("busy cycle: %d\r\n", stat.busy_cycles); + //shell_printf("load: %d\r\n", stat.busy_cycles * 100 / stat.interval_cycles); +// extern int awd_count; +// shell_printf("awd: %d\r\n", awd_count); } - #ifndef VERSION #define VERSION "unknown" #endif const char NANOVNA_VERSION[] = VERSION; -static void cmd_version(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_version) { (void)argc; (void)argv; - chprintf(chp, "%s\r\n", NANOVNA_VERSION); + shell_printf("%s\r\n", NANOVNA_VERSION); } -static void cmd_vbat(BaseSequentialStream *chp, int argc, char *argv[]) +VNA_SHELL_FUNCTION(cmd_vbat) { (void)argc; (void)argv; - chprintf(chp, "%d mV\r\n", vbat); + shell_printf("%d mV\r\n", adc_vbat_read()); } -static THD_WORKING_AREA(waThread2, /* cmd_* max stack size + alpha */442); +#ifdef ENABLE_VBAT_OFFSET_COMMAND +VNA_SHELL_FUNCTION(cmd_vbat_offset) +{ + if (argc != 1) { + shell_printf("%d\r\n", config.vbat_offset); + return; + } + config.vbat_offset = (int16_t)my_atoi(argv[0]); +} +#endif + +#ifdef ENABLE_INFO_COMMAND +VNA_SHELL_FUNCTION(cmd_info) +{ + (void)argc; + (void)argv; + int i = 0; + while (info_about[i]) + shell_printf("%s\r\n", info_about[i++]); +} +#endif -static const ShellCommand commands[] = -{ - { "version", cmd_version }, - { "reset", cmd_reset }, - { "freq", cmd_freq }, - { "offset", cmd_offset }, - { "time", cmd_time }, - { "dac", cmd_dac }, - { "saveconfig", cmd_saveconfig }, - { "clearconfig", cmd_clearconfig }, - { "data", cmd_data }, +#ifdef ENABLE_COLOR_COMMAND +VNA_SHELL_FUNCTION(cmd_color) +{ + uint32_t color; + int i; + if (argc != 2) { + shell_printf("usage: color {id} {rgb24}\r\n"); + for (i=-3; i < TRACES_MAX; i++) { +#if 0 + switch(i) { + case -3: color = config.grid_color; break; + case -2: color = config.menu_normal_color; break; + case -1: color = config.menu_active_color; break; + default: color = config.trace_color[i];break; + } +#else + // WARNING!!! Dirty hack for size, depend from config struct + color = config.trace_color[i]; +#endif + color = ((color >> 3) & 0x001c00) | + ((color >> 5) & 0x0000f8) | + ((color << 16) & 0xf80000) | + ((color << 13) & 0x00e000); +// color = (color>>8)|(color<<8); +// color = ((color<<8)&0xF80000)|((color<<5)&0x00FC00)|((color<<3)&0x0000F8); + shell_printf(" %d: 0x%06x\r\n", i, color); + } + return; + } + i = my_atoi(argv[0]); + if (i < -3 && i >= TRACES_MAX) + return; + color = RGBHEX(my_atoui(argv[1])); +#if 0 + switch(i) { + case -3: config.grid_color = color; break; + case -2: config.menu_normal_color = color; break; + case -1: config.menu_active_color = color; break; + default: config.trace_color[i] = color;break; + } +#else + // WARNING!!! Dirty hack for size, depend from config struct + config.trace_color[i] = color; +#endif + // Redraw all + redraw_request|= REDRAW_AREA; +} +#endif + +#ifdef ENABLE_THREADS_COMMAND +#if CH_CFG_USE_REGISTRY == FALSE +#error "Threads Requite enabled CH_CFG_USE_REGISTRY in chconf.h" +#endif +VNA_SHELL_FUNCTION(cmd_threads) +{ + static const char *states[] = {CH_STATE_NAMES}; + thread_t *tp; + (void)argc; + (void)argv; + shell_printf("stklimit| stack|stk free| addr|refs|prio| state| name"VNA_SHELL_NEWLINE_STR); + tp = chRegFirstThread(); + do { + uint32_t max_stack_use = 0U; +#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) + uint32_t stklimit = (uint32_t)tp->wabase; +#if CH_DBG_FILL_THREADS == TRUE + uint8_t *p = (uint8_t *)tp->wabase; while(p[max_stack_use]==CH_DBG_STACK_FILL_VALUE) max_stack_use++; +#endif +#else + uint32_t stklimit = 0U; +#endif + shell_printf("%08x|%08x|%08x|%08x|%4u|%4u|%9s|%12s"VNA_SHELL_NEWLINE_STR, + stklimit, (uint32_t)tp->ctx.sp, max_stack_use, (uint32_t)tp, + (uint32_t)tp->refs - 1, (uint32_t)tp->prio, states[tp->state], + tp->name == NULL ? "" : tp->name); + tp = chRegNextThread(tp); + } while (tp != NULL); +} +#endif + +//============================================================================= +VNA_SHELL_FUNCTION(cmd_help); + +#pragma pack(push, 2) +typedef struct { + const char *sc_name; + vna_shellcmd_t sc_function; + uint16_t flags; +} VNAShellCommand; +#pragma pack(pop) + +// Some commands can executed only in sweep thread, not in main cycle +#define CMD_WAIT_MUTEX 1 +static const VNAShellCommand commands[] = +{ + {"version" , cmd_version , 0}, + {"reset" , cmd_reset , 0}, + {"freq" , cmd_freq , CMD_WAIT_MUTEX}, + {"offset" , cmd_offset , 0}, +#ifdef ENABLE_TIME_COMMAND + {"time" , cmd_time , 0}, +#endif + {"dac" , cmd_dac , 0}, + {"saveconfig" , cmd_saveconfig , 0}, + {"clearconfig" , cmd_clearconfig , 0}, + {"data" , cmd_data , CMD_WAIT_MUTEX}, #ifdef ENABLED_DUMP - { "dump", cmd_dump }, + {"dump" , cmd_dump , 0}, #endif - { "frequencies", cmd_frequencies }, - { "port", cmd_port }, - { "stat", cmd_stat }, - { "gain", cmd_gain }, - { "power", cmd_power }, - { "sample", cmd_sample }, - //{ "gamma", cmd_gamma }, - { "scan", cmd_scan }, - { "sweep", cmd_sweep }, - { "test", cmd_test }, - { "touchcal", cmd_touchcal }, - { "touchtest", cmd_touchtest }, - { "pause", cmd_pause }, - { "resume", cmd_resume }, - { "cal", cmd_cal }, - { "save", cmd_save }, - { "recall", cmd_recall }, - { "trace", cmd_trace }, - { "marker", cmd_marker }, - { "edelay", cmd_edelay }, - { "capture", cmd_capture }, - { "vbat", cmd_vbat }, - { "transform", cmd_transform }, - { "threshold", cmd_threshold }, - { NULL, NULL } + {"frequencies" , cmd_frequencies , 0}, + {"port" , cmd_port , 0}, + {"stat" , cmd_stat , 0}, + {"gain" , cmd_gain , 0}, + {"power" , cmd_power , 0}, + {"sample" , cmd_sample , 0}, +// {"gamma" , cmd_gamma , 0}, + {"scan" , cmd_scan , CMD_WAIT_MUTEX}, + {"sweep" , cmd_sweep , 0}, + {"test" , cmd_test , 0}, + {"touchcal" , cmd_touchcal , CMD_WAIT_MUTEX}, + {"touchtest" , cmd_touchtest , CMD_WAIT_MUTEX}, + {"pause" , cmd_pause , 0}, + {"resume" , cmd_resume , 0}, + {"cal" , cmd_cal , CMD_WAIT_MUTEX}, + {"save" , cmd_save , 0}, + {"recall" , cmd_recall , CMD_WAIT_MUTEX}, + {"trace" , cmd_trace , 0}, + {"marker" , cmd_marker , 0}, + {"edelay" , cmd_edelay , 0}, + {"capture" , cmd_capture , CMD_WAIT_MUTEX}, + {"vbat" , cmd_vbat , 0}, +#ifdef ENABLE_VBAT_OFFSET_COMMAND + {"vbat_offset" , cmd_vbat_offset , 0}, +#endif + {"transform" , cmd_transform , 0}, + {"threshold" , cmd_threshold , 0}, + {"help" , cmd_help , 0}, +#ifdef ENABLE_INFO_COMMAND + {"info" , cmd_info , 0}, +#endif +#ifdef ENABLE_COLOR_COMMAND + {"color" , cmd_color , 0}, +#endif +#ifdef ENABLE_THREADS_COMMAND + {"threads" , cmd_threads , 0}, +#endif + {NULL , NULL , 0} }; -static const ShellConfig shell_cfg1 = +VNA_SHELL_FUNCTION(cmd_help) { - (BaseSequentialStream *)&SDU1, - commands -}; + (void)argc; + (void)argv; + const VNAShellCommand *scp = commands; + shell_printf("Commands:"); + while (scp->sc_name != NULL) { + shell_printf(" %s", scp->sc_name); + scp++; + } + shell_printf(VNA_SHELL_NEWLINE_STR); + return; +} + +/* + * VNA shell functions + */ + +// +// Read command line from shell_stream +// +static int VNAShell_readLine(char *line, int max_size) +{ + // Read line from input stream + uint8_t c; + char *ptr = line; + while (1) { + // Return 0 only if stream not active + if (streamRead(shell_stream, &c, 1) == 0) + return 0; + // Backspace or Delete + if (c == 8 || c == 0x7f) { + if (ptr != line) { + static const char backspace[] = {0x08, 0x20, 0x08, 0x00}; + shell_printf(backspace); + ptr--; + } + continue; + } + // New line (Enter) + if (c == '\r') { + shell_printf(VNA_SHELL_NEWLINE_STR); + *ptr = 0; + return 1; + } + // Others (skip) + if (c < 0x20) + continue; + // Store + if (ptr < line + max_size - 1) { + streamPut(shell_stream, c); // Echo + *ptr++ = (char)c; + } + } + return 0; +} + +// +// Parse and run command line +// +static void VNAShell_executeLine(char *line) +{ + // Parse and execute line + char *lp = line, *ep; + shell_nargs = 0; + while (*lp != 0) { + // Skipping white space and tabs at string begin. + while (*lp == ' ' || *lp == '\t') lp++; + // If an argument starts with a double quote then its delimiter is another quote, else + // delimiter is white space. + ep = (*lp == '"') ? strpbrk(++lp, "\"") : strpbrk(lp, " \t"); + // Store in args string + shell_args[shell_nargs++] = lp; + // Stop, end of input string + if ((lp = ep) == NULL) break; + // Argument limits check + if (shell_nargs > VNA_SHELL_MAX_ARGUMENTS) { + shell_printf("too many arguments, max " define_to_STR( + VNA_SHELL_MAX_ARGUMENTS) "" VNA_SHELL_NEWLINE_STR); + return; + } + // Set zero at the end of string and continue check + *lp++ = 0; + } + if (shell_nargs == 0) return; + // Execute line + const VNAShellCommand *scp; + for (scp = commands; scp->sc_name != NULL; scp++) { + if (strcmp(scp->sc_name, shell_args[0]) == 0) { + if (scp->flags & CMD_WAIT_MUTEX) { + shell_function = scp->sc_function; + // Wait execute command in sweep thread + do { + osalThreadSleepMilliseconds(100); + } while (shell_function); + } else { + scp->sc_function(shell_nargs - 1, &shell_args[1]); + } + return; + } + } + shell_printf("%s?" VNA_SHELL_NEWLINE_STR, shell_args[0]); +} + +#ifdef VNA_SHELL_THREAD +static THD_WORKING_AREA(waThread2, /* cmd_* max stack size + alpha */442); +THD_FUNCTION(myshellThread, p) +{ + (void)p; + chRegSetThreadName("shell"); + shell_printf(VNA_SHELL_NEWLINE_STR"NanoVNA Shell"VNA_SHELL_NEWLINE_STR); + while (true) { + shell_printf(VNA_SHELL_PROMPT_STR); + if (VNAShell_readLine(shell_line, VNA_SHELL_MAX_LENGTH)) + VNAShell_executeLine(shell_line); + else // Putting a delay in order to avoid an endless loop trying to read an unavailable stream. + osalThreadSleepMilliseconds(100); + } +} +#endif +// I2C clock bus setting: depend from STM32_I2C1SW in mcuconf.h static const I2CConfig i2ccfg = { - 0x00300506, //voodoo magic 400kHz @ HSI 8MHz - 0, - 0 + .timingr = // TIMINGR register initialization. (use I2C timing configuration tool for STM32F3xx and STM32F0xx microcontrollers (AN4235)) +#if STM32_I2C1SW == STM32_I2C1SW_HSI + // STM32_I2C1SW == STM32_I2C1SW_HSI (HSI=8MHz) + // 400kHz @ HSI 8MHz (Use 26.4.10 I2C_TIMINGR register configuration examples from STM32 RM0091 Reference manual) + STM32_TIMINGR_PRESC(0U) | + STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(1U) | + STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U), + // Old values voodoo magic 400kHz @ HSI 8MHz + //0x00300506, +#elif STM32_I2C1SW == STM32_I2C1SW_SYSCLK + // STM32_I2C1SW == STM32_I2C1SW_SYSCLK (SYSCLK = 48MHz) + // 400kHz @ SYSCLK 48MHz (Use 26.4.10 I2C_TIMINGR register configuration examples from STM32 RM0091 Reference manual) + STM32_TIMINGR_PRESC(5U) | + STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) | + STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U), + // 600kHz @ SYSCLK 48MHz, manually get values, x1.5 I2C speed, but need calc timings +// STM32_TIMINGR_PRESC(3U) | +// STM32_TIMINGR_SCLDEL(2U) | STM32_TIMINGR_SDADEL(2U) | +// STM32_TIMINGR_SCLH(4U) | STM32_TIMINGR_SCLL(4U), +#else +#error "Need Define STM32_I2C1SW and set correct TIMINGR settings" +#endif + .cr1 = 0, // CR1 register initialization. + .cr2 = 0 // CR2 register initialization. }; static DACConfig dac1cfg1 = { @@ -2014,68 +2303,61 @@ static DACConfig dac1cfg1 = { datamode: DAC_DHRM_12BIT_RIGHT }; + +// Main thread stack size defined in makefile USE_PROCESS_STACKSIZE = 0x200 +// Profile stack usage (enable threads command by def ENABLE_THREADS_COMMAND) show: +// Stack maximum usage = 472 bytes (need test more and run all commands), free stack = 40 bytes +// int main(void) { - halInit(); - chSysInit(); - - chMtxObjectInit(&mutex); - - //palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN); - //palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN); - i2cStart(&I2CD1, &i2ccfg); - si5351_init(); - - // MCO on PA8 - //palSetPadMode(GPIOA, 8, PAL_MODE_ALTERNATE(0)); - /* - * Initializes a serial-over-USB CDC driver. - */ - sduObjectInit(&SDU1); - sduStart(&SDU1, &serusbcfg); - - /* - * Activates the USB driver and then the USB bus pull-up on D+. - * Note, a delay is inserted in order to not have to disconnect the cable - * after a reset. - */ - usbDisconnectBus(serusbcfg.usbp); - chThdSleepMilliseconds(100); - usbStart(serusbcfg.usbp, &usbcfg); - usbConnectBus(serusbcfg.usbp); - - /* - * SPI LCD Initialize - */ - ili9341_init(); + halInit(); + chSysInit(); - /* - * Initialize graph plotting - */ - plot_init(); + //palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN); + //palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN); + i2cStart(&I2CD1, &i2ccfg); + si5351_init(); + + // MCO on PA8 + //palSetPadMode(GPIOA, 8, PAL_MODE_ALTERNATE(0)); +/* + * Initializes a serial-over-USB CDC driver. + */ + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); +/* + * Activates the USB driver and then the USB bus pull-up on D+. + * Note, a delay is inserted in order to not have to disconnect the cable + * after a reset. + */ + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(100); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + +/* + * SPI LCD Initialize + */ + ili9341_init(); - /* restore config */ +/* restore config */ config_recall(); +/* restore frequencies and calibration 0 slot properties from flash memory */ + caldata_recall(0); dac1cfg1.init = config.dac_value; - /* - * Starting DAC1 driver, setting up the output pin as analog as suggested - * by the Reference Manual. - */ +/* + * Starting DAC1 driver, setting up the output pin as analog as suggested + * by the Reference Manual. + */ dacStart(&DACD2, &dac1cfg1); - /* initial frequencies */ +/* initial frequencies */ update_frequencies(); - /* restore frequencies and calibration properties from flash memory */ - if (config.default_loadcal >= 0) - caldata_recall(config.default_loadcal); - - redraw_frame(); - - /* - * I2S Initialize - */ +/* + * I2S Initialize + */ tlv320aic3204_init(); i2sInit(); i2sObjectInit(&I2SD2); @@ -2083,42 +2365,53 @@ int main(void) i2sStartExchange(&I2SD2); ui_init(); + //Initialize graph plotting + plot_init(); + redraw_frame(); + chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO-1, Thread1, NULL); - /* - * Shell manager initialization. - */ - shellInit(); - - chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); - - while (1) { - if (SDU1.config->usbp->state == USB_ACTIVE) { - thread_t *shelltp = chThdCreateStatic(waThread2, sizeof(waThread2), - NORMALPRIO + 1, - shellThread, (void *)&shell_cfg1); - chThdWait(shelltp); /* Waiting termination. */ - } - - chThdSleepMilliseconds(1000); + while (1) { + if (SDU1.config->usbp->state == USB_ACTIVE) { +#ifdef VNA_SHELL_THREAD +#if CH_CFG_USE_WAITEXIT == FALSE +#error "VNA_SHELL_THREAD use chThdWait, need enable CH_CFG_USE_WAITEXIT in chconf.h" +#endif + thread_t *shelltp = chThdCreateStatic(waThread2, sizeof(waThread2), + NORMALPRIO + 1, + myshellThread, NULL); + chThdWait(shelltp); +#else + shell_printf(VNA_SHELL_NEWLINE_STR"NanoVNA Shell"VNA_SHELL_NEWLINE_STR); + do { + shell_printf(VNA_SHELL_PROMPT_STR); + if (VNAShell_readLine(shell_line, VNA_SHELL_MAX_LENGTH)) + VNAShell_executeLine(shell_line); + else + chThdSleepMilliseconds(200); + } while (SDU1.config->usbp->state == USB_ACTIVE); +#endif } + chThdSleepMilliseconds(1000); + } } /* The prototype shows it is a naked function - in effect this is just an assembly function. */ -void HardFault_Handler( void ); +void HardFault_Handler(void); -void hard_fault_handler_c(uint32_t *sp) __attribute__( ( naked ) );; +void hard_fault_handler_c(uint32_t *sp) __attribute__((naked)); void HardFault_Handler(void) { - uint32_t* sp; + uint32_t *sp; //__asm volatile ("mrs %0, msp \n\t": "=r" (sp) ); - __asm volatile ("mrs %0, psp \n\t": "=r" (sp) ); + __asm volatile("mrs %0, psp \n\t" : "=r"(sp)); hard_fault_handler_c(sp); } -void hard_fault_handler_c(uint32_t* sp) +void hard_fault_handler_c(uint32_t *sp) { (void)sp; - while (true) {} + while (true) { + } } diff --git a/mcuconf.h b/mcuconf.h index 3db6404..a1da287 100644 --- a/mcuconf.h +++ b/mcuconf.h @@ -58,7 +58,8 @@ #define STM32_ADCSW STM32_ADCSW_HSI14 #define STM32_USBSW STM32_USBSW_HSI48 #define STM32_CECSW STM32_CECSW_HSI -#define STM32_I2C1SW STM32_I2C1SW_HSI +//#define STM32_I2C1SW STM32_I2C1SW_HSI +#define STM32_I2C1SW STM32_I2C1SW_SYSCLK #define STM32_USART1SW STM32_USART1SW_PCLK #define STM32_RTCSEL STM32_RTCSEL_LSI @@ -95,7 +96,7 @@ #define STM32_EXT_EXTI17_IRQ_PRIORITY 3 #define STM32_EXT_EXTI21_22_IRQ_PRIORITY 3 -#define STM32_DISABLE_EXTI2122_HANDLER TRUE +#define STM32_DISABLE_EXTI2122_HANDLER TRUE /* * GPT driver system settings. diff --git a/nanovna.h b/nanovna.h index 800b4e1..d553f38 100644 --- a/nanovna.h +++ b/nanovna.h @@ -26,6 +26,17 @@ * main.c */ +// Minimum frequency set +#define START_MIN 50000 +// Maximum frequency set +#define STOP_MAX 2700000000U +// Frequency offset (sin_cos table in dsp.c generated for this offset, if change need create new table) +#define FREQUENCY_OFFSET 5000 +// Speed of light const +#define SPEED_OF_LIGHT 299792458 +// pi const +#define VNA_PI 3.14159265358979323846 + #define POINTS_COUNT 101 extern float measured[2][POINTS_COUNT][2]; @@ -71,27 +82,23 @@ extern float measured[2][POINTS_COUNT][2]; void cal_collect(int type); void cal_done(void); -enum { - ST_START, ST_STOP, ST_CENTER, ST_SPAN, ST_CW +#define MAX_FREQ_TYPE 5 +enum stimulus_type { + ST_START=0, ST_STOP, ST_CENTER, ST_SPAN, ST_CW }; void set_sweep_frequency(int type, uint32_t frequency); uint32_t get_sweep_frequency(int type); -float my_atof(const char *p); +double my_atof(const char *p); void toggle_sweep(void); +void load_default_properties(void); -extern int8_t sweep_enabled; - -/* - * ui.c - */ -extern void ui_init(void); -extern void ui_process(void); - -enum { OP_NONE = 0, OP_LEVER, OP_TOUCH, OP_FREQCHANGE }; -extern uint8_t operation_requested; +#define SWEEP_ENABLE 0x01 +#define SWEEP_ONCE 0x02 +extern int8_t sweep_mode; +extern const char *info_about[]; /* * dsp.c @@ -115,9 +122,6 @@ void calculate_gamma(float *gamma); void fetch_amplitude(float *gamma); void fetch_amplitude_ref(float *gamma); -int si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength); - - /* * tlv320aic3204.c */ @@ -126,39 +130,54 @@ extern void tlv320aic3204_init(void); extern void tlv320aic3204_set_gain(int lgain, int rgain); extern void tlv320aic3204_select(int channel); - /* * plot.c */ -#define OFFSETX 15 -#define OFFSETY 0 -#define WIDTH 291 -#define HEIGHT 230 -// Smith/polar chart -#define P_CENTER_X 145 -#define P_CENTER_Y 115 -#define P_RADIUS 115 +// Offset of plot area +#define OFFSETX 10 +#define OFFSETY 0 + +// WIDTH better be n*(POINTS_COUNT-1) +#define WIDTH 300 +// HEIGHT = 8*GRIDY +#define HEIGHT 232 + +//#define NGRIDY 10 +#define NGRIDY 8 + +#define FREQUENCIES_XPOS1 OFFSETX +#define FREQUENCIES_XPOS2 200 +#define FREQUENCIES_YPOS (240-7) + +// GRIDX calculated depends from frequency span +//#define GRIDY 29 +#define GRIDY (HEIGHT / NGRIDY) +// #define CELLOFFSETX 5 -#define AREA_WIDTH_NORMAL (WIDTH + CELLOFFSETX*2) +#define AREA_WIDTH_NORMAL (CELLOFFSETX + WIDTH + 1 + 4) +#define AREA_HEIGHT_NORMAL ( HEIGHT + 1) + +// Smith/polar chart +#define P_CENTER_X (CELLOFFSETX + WIDTH/2) +#define P_CENTER_Y (HEIGHT/2) +#define P_RADIUS (HEIGHT/2) extern int16_t area_width; extern int16_t area_height; -#define GRIDY 23 - // font - extern const uint8_t x5x7_bits []; -#define FONT_GET_DATA(ch) (&x5x7_bits[ch*7]) -#define FONT_GET_WIDTH(ch) (7-(x5x7_bits[ch*7]&3)) -#define FONT_GET_HEIGHT 7 +#define FONT_GET_DATA(ch) (&x5x7_bits[ch*7]) +#define FONT_GET_WIDTH(ch) (8-(x5x7_bits[ch*7]&7)) +#define FONT_MAX_WIDTH 7 +#define FONT_GET_HEIGHT 7 extern const uint16_t numfont16x22[]; -#define NUM_FONT_GET_DATA(ch) (&numfont16x22[ch*22]) -#define NUM_FONT_GET_WIDTH 16 -#define NUM_FONT_GET_HEIGHT 22 +#define NUM_FONT_GET_DATA(ch) (&numfont16x22[ch*22]) +#define NUM_FONT_GET_WIDTH 16 +#define NUM_FONT_GET_HEIGHT 22 #define S_DELTA "\004" #define S_DEGREE "\037" @@ -173,9 +192,12 @@ extern const uint16_t numfont16x22[]; #define TRACES_MAX 4 -enum { - TRC_LOGMAG, TRC_PHASE, TRC_DELAY, TRC_SMITH, TRC_POLAR, TRC_LINEAR, TRC_SWR, TRC_REAL, TRC_IMAG, TRC_R, TRC_X, TRC_OFF +#define MAX_TRACE_TYPE 12 +enum trace_type { + TRC_LOGMAG=0, TRC_PHASE, TRC_DELAY, TRC_SMITH, TRC_POLAR, TRC_LINEAR, TRC_SWR, TRC_REAL, TRC_IMAG, TRC_R, TRC_X, TRC_OFF }; +// Mask for define rectangular plot +#define RECTANGULAR_GRID_MASK ((1<>5) ) #define RGBHEX(hex) ( (((hex)&0x001c00)<<3) | (((hex)&0x0000f8)<<5) | (((hex)&0xf80000)>>16) | (((hex)&0x00e000)>>13) ) -#define DEFAULT_FG_COLOR RGB565(255,255,255) -#define DEFAULT_BG_COLOR RGB565( 0, 0, 0) -#define DEFAULT_GRID_COLOR RGB565(128,128,128) -#define DEFAULT_MENU_COLOR RGB565(255,255,255) -#define DEFAULT_MENU_TEXT_COLOR RGB565( 0, 0, 0) -#define DEFAULT_MENU_ACTIVE_COLOR RGB565(180,255,180) -#define DEFAULT_TRACE_1_COLOR RGB565(255,255, 0) -#define DEFAULT_TRACE_2_COLOR RGB565( 0,255,255) -#define DEFAULT_TRACE_3_COLOR RGB565( 0,255, 0) -#define DEFAULT_TRACE_4_COLOR RGB565(255, 0,255) -#define DEFAULT_NORMAL_BAT_COLOR RGB565( 31,227, 0) -#define DEFAULT_LOW_BAT_COLOR RGB565(255, 0, 0) -#define DEFAULT_SPEC_INPUT_COLOR RGB565(128,255,128); +// Define size of screen buffer in pixels (one pixel 16bit size) +#define SPI_BUFFER_SIZE 2048 + +#define DEFAULT_FG_COLOR RGB565(255,255,255) +#define DEFAULT_BG_COLOR RGB565( 0, 0, 0) +#define DEFAULT_GRID_COLOR RGB565(128,128,128) +#define DEFAULT_MENU_COLOR RGB565(255,255,255) +#define DEFAULT_MENU_TEXT_COLOR RGB565( 0, 0, 0) +#define DEFAULT_MENU_ACTIVE_COLOR RGB565(180,255,180) +#define DEFAULT_TRACE_1_COLOR RGB565(255,255, 0) +#define DEFAULT_TRACE_2_COLOR RGB565( 0,255,255) +#define DEFAULT_TRACE_3_COLOR RGB565( 0,255, 0) +#define DEFAULT_TRACE_4_COLOR RGB565(255, 0,255) +#define DEFAULT_NORMAL_BAT_COLOR RGB565( 31,227, 0) +#define DEFAULT_LOW_BAT_COLOR RGB565(255, 0, 0) +#define DEFAULT_SPEC_INPUT_COLOR RGB565(128,255,128); extern uint16_t foreground_color; extern uint16_t background_color; -extern uint16_t spi_buffer[1024]; +extern uint16_t spi_buffer[SPI_BUFFER_SIZE]; void ili9341_init(void); -//void ili9341_setRotation(uint8_t r); void ili9341_test(int mode); void ili9341_bulk(int x, int y, int w, int h); void ili9341_fill(int x, int y, int w, int h, int color); -void setForegroundColor(uint16_t fg); -void setBackgroundColor(uint16_t fg); +void ili9341_set_foreground(uint16_t fg); +void ili9341_set_background(uint16_t fg); +void ili9341_clear_screen(void); void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *bitmap); -void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *bitmap); void ili9341_drawchar(uint8_t ch, int x, int y); void ili9341_drawstring(const char *str, int x, int y); void ili9341_drawstringV(const char *str, int x, int y); @@ -325,12 +350,22 @@ void show_logo(void); * flash.c */ #define SAVEAREA_MAX 5 - -typedef struct { +// Begin addr 0x08018000 +#define SAVE_CONFIG_AREA_SIZE 0x00008000 +// config save area +#define SAVE_CONFIG_ADDR 0x08018000 +// properties_t save area +#define SAVE_PROP_CONFIG_0_ADDR 0x08018800 +#define SAVE_PROP_CONFIG_1_ADDR 0x0801a000 +#define SAVE_PROP_CONFIG_2_ADDR 0x0801b800 +#define SAVE_PROP_CONFIG_3_ADDR 0x0801d000 +#define SAVE_PROP_CONFIG_4_ADDR 0x0801e800 + +typedef struct properties { uint32_t magic; uint32_t _frequency0; uint32_t _frequency1; - int16_t _sweep_points; + uint16_t _sweep_points; uint16_t _cal_status; uint32_t _frequencies[POINTS_COUNT]; @@ -345,7 +380,7 @@ typedef struct { uint8_t _domain_mode; /* 0bxxxxxffm : where ff: TD_FUNC m: DOMAIN_MODE */ uint8_t _marker_smith_format; uint8_t _reserved[50]; - int32_t checksum; + uint32_t checksum; } properties_t; //sizeof(properties_t) == 0x1200 @@ -371,6 +406,10 @@ extern properties_t current_props; #define velocity_factor current_props._velocity_factor #define marker_smith_format current_props._marker_smith_format +#define FREQ_IS_STARTSTOP() (!(config.freq_mode&FREQ_MODE_CENTER_SPAN)) +#define FREQ_IS_CENTERSPAN() (config.freq_mode&FREQ_MODE_CENTER_SPAN) +#define FREQ_IS_CW() (frequency0 == frequency1) + int caldata_save(int id); int caldata_recall(int id); const properties_t *caldata_ref(int id); @@ -383,29 +422,38 @@ void clear_all_config_prop_data(void); /* * ui.c */ +extern void ui_init(void); +extern void ui_process(void); + +// Irq operation process set +#define OP_NONE 0x00 +#define OP_LEVER 0x01 +#define OP_TOUCH 0x02 +//#define OP_FREQCHANGE 0x04 +extern volatile uint8_t operation_requested; // lever_mode -enum { - LM_MARKER, LM_SEARCH, LM_CENTER, LM_SPAN +enum lever_mode { + LM_MARKER, LM_SEARCH, LM_CENTER, LM_SPAN, LM_EDELAY }; // marker smith value format -enum { +enum marker_smithvalue { MS_LIN, MS_LOG, MS_REIM, MS_RX, MS_RLC }; -typedef struct { +typedef struct uistat { int8_t digit; /* 0~5 */ int8_t digit_mode; int8_t current_trace; /* 0..3 */ uint32_t value; // for editing at numeric input area - uint32_t previous_value; +// uint32_t previous_value; uint8_t lever_mode; - bool marker_delta; + uint8_t marker_delta; + uint8_t marker_tracking; } uistat_t; extern uistat_t uistat; - void ui_init(void); void ui_show(void); void ui_hide(void); @@ -425,15 +473,22 @@ void enter_dfu(void); */ void adc_init(void); -uint16_t adc_single_read(ADC_TypeDef *adc, uint32_t chsel); -void adc_start_analog_watchdogd(ADC_TypeDef *adc, uint32_t chsel); -void adc_stop(ADC_TypeDef *adc); -void adc_interrupt(ADC_TypeDef *adc); -int16_t adc_vbat_read(ADC_TypeDef *adc); +uint16_t adc_single_read(uint32_t chsel); +void adc_start_analog_watchdogd(uint32_t chsel); +void adc_stop(void); +void adc_interrupt(void); +int16_t adc_vbat_read(void); /* * misclinous */ +int plot_printf(char *str, int, const char *fmt, ...); #define PULSE do { palClearPad(GPIOC, GPIOC_LED); palSetPad(GPIOC, GPIOC_LED);} while(0) +// Speed profile definition +#define START_PROFILE systime_t time = chVTGetSystemTimeX(); +#define STOP_PROFILE {char string_buf[12];plot_printf(string_buf, sizeof string_buf, "T:%06d", chVTGetSystemTimeX() - time);ili9341_drawstringV(string_buf, 1, 60);} +// Macros for convert define value to string +#define STR1(x) #x +#define define_to_STR(x) STR1(x) /*EOF*/ diff --git a/numfont20x22.c b/numfont20x22.c index 538c674..85498ec 100644 --- a/numfont20x22.c +++ b/numfont20x22.c @@ -24,533 +24,532 @@ const uint16_t numfont16x22[] = { - 0b0000111111110000, - 0b0011111111111100, - 0b0111111111111110, - 0b0111110000111110, - 0b1111100000011111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111100000011111, - 0b0111110000111110, - 0b0111111111111110, - 0b0011111111111100, - 0b0000111111110000, + 0b0000111111110000, + 0b0011111111111100, + 0b0111111111111110, + 0b0111110000111110, + 0b1111100000011111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111100000011111, + 0b0111110000111110, + 0b0111111111111110, + 0b0011111111111100, + 0b0000111111110000, - 0b0000000011110000, - 0b0000000111110000, - 0b0000001111110000, - 0b0000011111110000, - 0b0000111111110000, - 0b0000111111110000, - 0b0000111011110000, - 0b0000110011110000, - 0b0000000011110000, - 0b0000000011110000, - 0b0000000011110000, - 0b0000000011110000, - 0b0000000011110000, - 0b0000000011110000, - 0b0000000011110000, - 0b0000000011110000, - 0b0000000011110000, - 0b0000000011110000, - 0b0000000011110000, - 0b0000001111111100, - 0b0000001111111100, - 0b0000001111111100, + 0b0000000011110000, + 0b0000000111110000, + 0b0000001111110000, + 0b0000011111110000, + 0b0000111111110000, + 0b0000111111110000, + 0b0000111011110000, + 0b0000110011110000, + 0b0000000011110000, + 0b0000000011110000, + 0b0000000011110000, + 0b0000000011110000, + 0b0000000011110000, + 0b0000000011110000, + 0b0000000011110000, + 0b0000000011110000, + 0b0000000011110000, + 0b0000000011110000, + 0b0000000011110000, + 0b0000001111111100, + 0b0000001111111100, + 0b0000001111111100, - 0b0000111111110000, - 0b0011111111111100, - 0b0111111111111110, - 0b0111110000111110, - 0b1111100000011111, - 0b1111000000001111, - 0b1111000000001111, - 0b0000000000011111, - 0b0000000000111111, - 0b0000000001111110, - 0b0000000011111100, - 0b0000000111111000, - 0b0000001111110000, - 0b0000011111100000, - 0b0000111111000000, - 0b0001111110000000, - 0b0011111100000000, - 0b0111111000000000, - 0b1111110000000000, - 0b1111111111111111, - 0b1111111111111111, - 0b1111111111111111, + 0b0000111111110000, + 0b0011111111111100, + 0b0111111111111110, + 0b0111110000111110, + 0b1111100000011111, + 0b1111000000001111, + 0b1111000000001111, + 0b0000000000011111, + 0b0000000000111111, + 0b0000000001111110, + 0b0000000011111100, + 0b0000000111111000, + 0b0000001111110000, + 0b0000011111100000, + 0b0000111111000000, + 0b0001111110000000, + 0b0011111100000000, + 0b0111111000000000, + 0b1111110000000000, + 0b1111111111111111, + 0b1111111111111111, + 0b1111111111111111, - 0b0000111111110000, - 0b0011111111111100, - 0b0111111111111110, - 0b0111110000111110, - 0b1111100000011111, - 0b1111000000011111, - 0b1111000000011111, - 0b0000000000011110, - 0b0000000000111110, - 0b0000000111111100, - 0b0000000111111000, - 0b0000000111111100, - 0b0000000001111110, - 0b0000000000011111, - 0b0000000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111100000011111, - 0b0111110000111110, - 0b0111111111111110, - 0b0011111111111100, - 0b0000111111110000, + 0b0000111111110000, + 0b0011111111111100, + 0b0111111111111110, + 0b0111110000111110, + 0b1111100000011111, + 0b1111000000001111, + 0b1111000000001111, + 0b0000000000011110, + 0b0000000000111110, + 0b0000000111111100, + 0b0000000111111000, + 0b0000000111111100, + 0b0000000001111110, + 0b0000000000011111, + 0b0000000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111100000011111, + 0b0111110000111110, + 0b0111111111111110, + 0b0011111111111100, + 0b0000111111110000, - 0b0000000111111000, - 0b0000000111111000, - 0b0000001111111000, - 0b0000001111111000, - 0b0000011111111000, - 0b0000011111111000, - 0b0000111111111000, - 0b0000111101111000, - 0b0001111101111000, - 0b0001111001111000, - 0b0011111001111000, - 0b0011110001111000, - 0b0111110001111000, - 0b0111100001111000, - 0b1111100001111000, - 0b1111111111111111, - 0b1111111111111111, - 0b1111111111111111, - 0b0000000001111000, - 0b0000000001111000, - 0b0000000001111000, - 0b0000000001111000, + 0b0000000111111000, + 0b0000000111111000, + 0b0000001111111000, + 0b0000001111111000, + 0b0000011111111000, + 0b0000011111111000, + 0b0000111111111000, + 0b0000111101111000, + 0b0001111101111000, + 0b0001111001111000, + 0b0011111001111000, + 0b0011110001111000, + 0b0111110001111000, + 0b0111100001111000, + 0b1111100001111000, + 0b1111111111111111, + 0b1111111111111111, + 0b1111111111111111, + 0b0000000001111000, + 0b0000000001111000, + 0b0000000001111000, + 0b0000000001111000, - 0b1111111111111111, - 0b1111111111111111, - 0b1111111111111111, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000000000000, - 0b1111011111110000, - 0b1111111111111100, - 0b1111111111111110, - 0b1111110000111110, - 0b1111100000011111, - 0b0000000000001111, - 0b0000000000001111, - 0b0000000000001111, - 0b0000000000001111, - 0b1111000000001111, - 0b1111100000011111, - 0b0111110000111110, - 0b0111111111111110, - 0b0011111111111100, - 0b0000111111110000, + 0b1111111111111111, + 0b1111111111111111, + 0b1111111111111111, + 0b1111000000000000, + 0b1111000000000000, + 0b1111000000000000, + 0b1111000000000000, + 0b1111011111110000, + 0b1111111111111100, + 0b1111111111111110, + 0b1111110000111110, + 0b1111100000011111, + 0b0000000000001111, + 0b0000000000001111, + 0b0000000000001111, + 0b0000000000001111, + 0b1111000000001111, + 0b1111100000011111, + 0b0111110000111110, + 0b0111111111111110, + 0b0011111111111100, + 0b0000111111110000, - 0b0000111111110000, - 0b0011111111111100, - 0b0111111111111110, - 0b0111110000111110, - 0b1111100000011111, - 0b1111000000001111, - 0b1111000000000000, - 0b1111000000000000, - 0b1111011111110000, - 0b1111111111111100, - 0b1111111111111110, - 0b1111110000111110, - 0b1111100000011111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111100000011111, - 0b0111110000111110, - 0b0111111111111110, - 0b0011111111111100, - 0b0000111111110000, + 0b0000111111110000, + 0b0011111111111100, + 0b0111111111111110, + 0b0111110000111110, + 0b1111100000011111, + 0b1111000000001111, + 0b1111000000000000, + 0b1111000000000000, + 0b1111011111110000, + 0b1111111111111100, + 0b1111111111111110, + 0b1111110000111110, + 0b1111100000011111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111100000011111, + 0b0111110000111110, + 0b0111111111111110, + 0b0011111111111100, + 0b0000111111110000, - 0b1111111111111111, - 0b1111111111111111, - 0b1111111111111111, - 0b0000000000011111, - 0b0000000000111110, - 0b0000000001111100, - 0b0000000011111000, - 0b0000000111110000, - 0b0000000111100000, - 0b0000001111100000, - 0b0000001111000000, - 0b0000011111000000, - 0b0000011110000000, - 0b0000011110000000, - 0b0000111110000000, - 0b0000111100000000, - 0b0000111100000000, - 0b0000111100000000, - 0b0000111100000000, - 0b0000111100000000, - 0b0000111100000000, - 0b0000111100000000, + 0b1111111111111111, + 0b1111111111111111, + 0b1111111111111111, + 0b0000000000011111, + 0b0000000000111110, + 0b0000000001111100, + 0b0000000011111000, + 0b0000000111110000, + 0b0000000111100000, + 0b0000001111100000, + 0b0000001111000000, + 0b0000011111000000, + 0b0000011110000000, + 0b0000011110000000, + 0b0000111110000000, + 0b0000111100000000, + 0b0000111100000000, + 0b0000111100000000, + 0b0000111100000000, + 0b0000111100000000, + 0b0000111100000000, + 0b0000111100000000, - 0b0000011111100000, - 0b0001111111111000, - 0b0011111111111100, - 0b0111110000111110, - 0b0111100000011110, - 0b0111100000011110, - 0b0111100000011110, - 0b0011110000111100, - 0b0001111111111000, - 0b0000111111110000, - 0b0011111111111100, - 0b0111110000111110, - 0b0111100000011110, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111100000011111, - 0b0111110000111110, - 0b0111111111111110, - 0b0011111111111100, - 0b0000111111110000, + 0b0000011111100000, + 0b0001111111111000, + 0b0011111111111100, + 0b0111110000111110, + 0b0111100000011110, + 0b0111100000011110, + 0b0111100000011110, + 0b0011110000111100, + 0b0001111111111000, + 0b0000111111110000, + 0b0011111111111100, + 0b0111110000111110, + 0b0111100000011110, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111100000011111, + 0b0111110000111110, + 0b0111111111111110, + 0b0011111111111100, + 0b0000111111110000, - 0b0000111111110000, - 0b0011111111111100, - 0b0111111111111110, - 0b0111110000111110, - 0b1111100000011111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111100000011111, - 0b0111110000111111, - 0b0111111111111111, - 0b0011111111111111, - 0b0000111111111111, - 0b0000000000001111, - 0b0000000000001111, - 0b1111000000001111, - 0b1111100000011111, - 0b0111110000111110, - 0b0111111111111110, - 0b0011111111111100, - 0b0000111111110000, + 0b0000111111110000, + 0b0011111111111100, + 0b0111111111111110, + 0b0111110000111110, + 0b1111100000011111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111100000011111, + 0b0111110000111111, + 0b0111111111111111, + 0b0011111111111111, + 0b0000111111111111, + 0b0000000000001111, + 0b0000000000001111, + 0b1111000000001111, + 0b1111100000011111, + 0b0111110000111110, + 0b0111111111111110, + 0b0011111111111100, + 0b0000111111110000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000011100000000, - 0b0000111110000000, - 0b0000111110000000, - 0b0000011100000000, - 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000001110000000, + 0b0000011111000000, + 0b0000011111000000, + 0b0000001110000000, + 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0011111111111100, - 0b0011111111111100, - 0b0011111111111100, - 0b0011111111111100, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0011111111111100, + 0b0011111111111100, + 0b0011111111111100, + 0b0011111111111100, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000011, - 0b0000000000000111, - 0b0000000000001111, - 0b0000000000011111, - 0b0000000000111111, - 0b0000000000111111, - 0b0000000000001111, - 0b0000000000001111, - 0b0000000000001111, - 0b0110000011001111, - 0b1111000111101111, - 0b0111101111001111, - 0b0011111110001111, - 0b0001111100001111, - 0b0001111100001111, - 0b0011111110001111, - 0b0111101111001111, - 0b1111000111101111, - 0b0110000011001111, + 0b0000000000000011, + 0b0000000000000111, + 0b0000000000001111, + 0b0000000000011111, + 0b0000000000111111, + 0b0000000001111111, + 0b0000000000001111, + 0b0000000000001111, + 0b0000000000001111, + 0b0110000011001111, + 0b1111000111101111, + 0b0111101111001111, + 0b0011111110001111, + 0b0001111100001111, + 0b0001111100001111, + 0b0011111110001111, + 0b0111101111001111, + 0b1111000111101111, + 0b0110000011001111, + 0b0000000000001111, + 0b0000000000001111, + 0b0000000000001111, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000000111110, - 0b1111000001111100, - 0b1111000011111000, - 0b1111000111110000, - 0b1111001111100000, - 0b1111011111000000, - 0b1111111110000000, - 0b1111111100000000, - 0b1111111100000000, - 0b1111111110000000, - 0b1111011111000000, - 0b1111001111100000, - 0b1111000111110000, - 0b1111000011111000, - 0b1111000001111100, - 0b1111000000111110, + 0b1111000000000000, + 0b1111000000000000, + 0b1111000000000000, + 0b1111000000000000, + 0b1111000000000000, + 0b1111000000000000, + 0b1111000000111110, + 0b1111000001111100, + 0b1111000011111000, + 0b1111000111110000, + 0b1111001111100000, + 0b1111011111000000, + 0b1111111110000000, + 0b1111111100000000, + 0b1111111100000000, + 0b1111111110000000, + 0b1111011111000000, + 0b1111001111100000, + 0b1111000111110000, + 0b1111000011111000, + 0b1111000001111100, + 0b1111000000111110, - 0b1111000000001111, - 0b1111000000001111, - 0b1111100000011111, - 0b1111100000011111, - 0b1111110000111111, - 0b1111110000111111, - 0b1111111001111111, - 0b1111111001111111, - 0b1111111111111111, - 0b1111111111111111, - 0b1111111111111111, - 0b1111111111111111, - 0b1111111111111111, - 0b1111111111111111, - 0b1111011111101111, - 0b1111011111101111, - 0b1111001111001111, - 0b1111001111001111, - 0b1111000110001111, - 0b1111000110001111, - 0b1111000000001111, - 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111100000011111, + 0b1111100000011111, + 0b1111110000111111, + 0b1111110000111111, + 0b1111111001111111, + 0b1111111001111111, + 0b1111111111111111, + 0b1111111111111111, + 0b1111111111111111, + 0b1111111111111111, + 0b1111011111101111, + 0b1111011111101111, + 0b1111001111001111, + 0b1111001111001111, + 0b1111000110001111, + 0b1111000110001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, - 0b0000111111110000, - 0b0011111111111100, - 0b0111111111111110, - 0b0111110000111110, - 0b1111100000011111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000001111111, - 0b1111000001111111, - 0b1111000001111111, - 0b1111000000001111, - 0b1111100000011111, - 0b0111110000111111, - 0b0111111111111111, - 0b0011111111110111, - 0b0000111111100111, + 0b0000111111110000, + 0b0011111111111100, + 0b0111111111111110, + 0b0111110000111110, + 0b1111100000011111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000000000, + 0b1111000000000000, + 0b1111000000000000, + 0b1111000000000000, + 0b1111000000111111, + 0b1111000000111111, + 0b1111000000111111, + 0b1111000000000111, + 0b1111000000001111, + 0b1111100000011111, + 0b0111110000111111, + 0b0111111111111111, + 0b0011111111110111, + 0b0000111111100111, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000001000000, - 0b0000000011000000, - 0b0000000111000000, - 0b0000001111000000, - 0b0000011111000000, - 0b0000111111111111, - 0b0001111111111111, - 0b0011111111111111, - 0b0111111111111111, - 0b1111111111111111, - 0b0111111111111111, - 0b0011111111111111, - 0b0001111111111111, - 0b0000111111111111, - 0b0000011111000000, - 0b0000001111000000, - 0b0000000111000000, - 0b0000000011000000, - 0b0000000001000000, - 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000001000000, + 0b0000000011000000, + 0b0000000111000000, + 0b0000001111000000, + 0b0000011111000000, + 0b0000111111111111, + 0b0001111111111111, + 0b0011111111111111, + 0b0111111111111111, + 0b1111111111111111, + 0b0111111111111111, + 0b0011111111111111, + 0b0001111111111111, + 0b0000111111111111, + 0b0000011111000000, + 0b0000001111000000, + 0b0000000111000000, + 0b0000000011000000, + 0b0000000001000000, + 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000111000111000, - 0b0001111101111100, - 0b0011111111111110, - 0b0111001111001110, - 0b1110000110000111, - 0b1110000110000111, - 0b1110000110000111, - 0b1110000110000111, - 0b1110000110000111, - 0b1110000110000111, - 0b0111001111001110, - 0b0111111111111110, - 0b0011111011111100, - 0b0001110001110000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0001111000111100, + 0b0011111101111110, + 0b0111001111100110, + 0b0110000111000011, + 0b1110000111000011, + 0b1100000110000011, + 0b1100000110000011, + 0b1100000110000011, + 0b1100000110000011, + 0b1100001110000111, + 0b1100001110000110, + 0b0110011111001110, + 0b0111111011111100, + 0b0011110001111000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000011101111100, - 0b0000011101111110, - 0b0000001101100110, - 0b0000001101100110, - 0b0000001101100110, - 0b0011101101111100, - 0b0111111101111110, - 0b1110011101100111, - 0b1100001101100011, - 0b1100001101100011, - 0b1100001101100011, - 0b1100001101100011, - 0b1110011101100111, - 0b0111111101111110, - 0b0011101101111100, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000011101111100, + 0b0000011101111110, + 0b0000001101100110, + 0b0000001101100110, + 0b0000001101100110, + 0b0000001101100110, + 0b0000001101100110, + 0b0011101101111100, + 0b0111111101111110, + 0b1110011101100111, + 0b1100001101100011, + 0b1100001101100011, + 0b1100001101100011, + 0b1100001101100011, + 0b1100001101100011, + 0b1100001101100011, + 0b1110011101100111, + 0b0111111101111110, + 0b0011101101111100, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000001110000000, - 0b0000001110000000, - 0b0000001110000000, - 0b0001111111110000, - 0b0001111111110000, - 0b0001111111110000, - 0b0000001110000000, - 0b0000001110000000, - 0b0000001110000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0001111111110000, - 0b0001111111110000, - 0b0001111111110000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000001110000000, + 0b0000001110000000, + 0b0000001110000000, + 0b0000001110000000, + 0b0011111111111000, + 0b0011111111111000, + 0b0011111111111000, + 0b0000001110000000, + 0b0000001110000000, + 0b0000001110000000, + 0b0000001110000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0011111111111000, + 0b0011111111111000, + 0b0011111111111000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, - 0b0000000000000000, - 0b0111101111011110, - 0b0111101111011110, - 0b0111101111011110, - 0b0111101111011110, - 0b0000000000000000, - 0b0111101111011110, - 0b0111101111011110, - 0b0111101111011110, - 0b0111101111011110, - 0b0000000000000000, - 0b0111101111011110, - 0b0111101111011110, - 0b0111101111011110, - 0b0111101111011110, - 0b0000000000000000, - 0b0111101111011110, - 0b0111101111011110, - 0b0111101111011110, - 0b0111101111011110, - 0b0000000000000000, - 0b0000000000000000, + 0b0000000000000000, + 0b0111101111011110, + 0b0111101111011110, + 0b0111101111011110, + 0b0111101111011110, + 0b0000000000000000, + 0b0111101111011110, + 0b0111101111011110, + 0b0111101111011110, + 0b0111101111011110, + 0b0000000000000000, + 0b0111101111011110, + 0b0111101111011110, + 0b0111101111011110, + 0b0111101111011110, + 0b0000000000000000, + 0b0111101111011110, + 0b0111101111011110, + 0b0111101111011110, + 0b0111101111011110, + 0b0000000000000000, + 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b1111000111110000, - 0b1111011111111100, - 0b1111111111111110, - 0b1111111000111110, - 0b1111110000011111, - 0b1111100000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, - 0b1111000000001111, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b1111000111110000, + 0b1111011111111100, + 0b1111111111111110, + 0b1111111000111110, + 0b1111110000011111, + 0b1111100000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, + 0b1111000000001111, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b1111001111110000, - 0b1111011111111100, - 0b1111111111111110, - 0b1111111000011111, - 0b1111110000001111, - 0b1111100000000111, - 0b1111100000000111, - 0b1111100000000111, - 0b1111110000001111, - 0b1111111000011111, - 0b1111111111111110, - 0b1111011111111100, - 0b1111001111110000, - 0b1111000000000000, - 0b1111000000000000, - 0b1111000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b0000000000000000, + 0b1111001111110000, + 0b1111011111111100, + 0b1111111111111110, + 0b1111111000011111, + 0b1111110000001111, + 0b1111100000000111, + 0b1111100000000111, + 0b1111100000000111, + 0b1111110000001111, + 0b1111111000011111, + 0b1111111111111110, + 0b1111011111111100, + 0b1111001111110000, + 0b1111000000000000, + 0b1111000000000000, + 0b1111000000000000, }; - diff --git a/plot.c b/plot.c index 14e992e..01b1e85 100644 --- a/plot.c +++ b/plot.c @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com + * All rights reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #include #include #include "ch.h" @@ -5,74 +25,68 @@ #include "chprintf.h" #include "nanovna.h" -#define SWAP(x,y) do { int z=x; x = y; y = z; } while(0) - -static void cell_draw_marker_info(int m, int n, int w, int h); -void frequency_string(char *buf, size_t len, uint32_t freq, char *prefix); -void frequency_string_short(char *buf, size_t len, int32_t freq, char prefix); -void markmap_all_markers(void); - -/* indicate dirty cells */ -uint16_t markmap[2][8]; -uint16_t current_mappage = 0; - -int16_t grid_offset; -int16_t grid_width; - -int16_t area_width = AREA_WIDTH_NORMAL; -int16_t area_height = HEIGHT+1; - -#define GRID_RECTANGULAR (1<<0) -#define GRID_SMITH (1<<1) -#define GRID_ADMIT (1<<2) -#define GRID_POLAR (1<<3) - - -#define CELLWIDTH 32 -#define CELLHEIGHT 32 - -/* - * CELL_X0[27:31] cell position - * CELL_Y0[22:26] - * CELL_N[10:21] original order - * CELL_X[5:9] position in the cell - * CELL_Y[0:4] - */ -uint32_t trace_index[TRACES_MAX][POINTS_COUNT]; +static void cell_draw_marker_info(int x0, int y0); +static void draw_battery_status(void); + +static int16_t grid_offset; +static int16_t grid_width; + +int16_t area_width = AREA_WIDTH_NORMAL; +int16_t area_height = AREA_HEIGHT_NORMAL; + +// Cell render use spi buffer +typedef uint16_t pixel_t; +pixel_t *cell_buffer = (pixel_t *)spi_buffer; +// Cell size +// Depends from spi_buffer size, CELLWIDTH*CELLHEIGHT*sizeof(pixel) <= sizeof(spi_buffer) +#define CELLWIDTH (64) +#define CELLHEIGHT (32) +// Check buffer size +#if CELLWIDTH*CELLHEIGHT > SPI_BUFFER_SIZE +#error "Too small spi_buffer size SPI_BUFFER_SIZE < CELLWIDTH*CELLHEIGH" +#endif -#define INDEX(x, y, n) \ - ((((x)&0x03e0UL)<<22) | (((y)&0x03e0UL)<<17) | (((n)&0x0fffUL)<<10) \ - | (((x)&0x1fUL)<<5) | ((y)&0x1fUL)) +// indicate dirty cells (not redraw if cell data not changed) +#define MAX_MARKMAP_X ((320+CELLWIDTH-1)/CELLWIDTH) +#define MAX_MARKMAP_Y ((240+CELLHEIGHT-1)/CELLHEIGHT) +// Define markmap mask size +#if MAX_MARKMAP_X <= 8 +typedef uint8_t map_t; +#elif MAX_MARKMAP_X <= 16 +typedef uint16_t map_t; +#elif MAX_MARKMAP_X <= 32 +typedef uint32_t map_t; +#endif -#define CELL_X(i) (int)((((i)>>5)&0x1f) | (((i)>>22)&0x03e0)) -#define CELL_Y(i) (int)(((i)&0x1f) | (((i)>>17)&0x03e0)) -#define CELL_N(i) (int)(((i)>>10)&0xfff) +map_t markmap[2][MAX_MARKMAP_Y]; +uint8_t current_mappage = 0; -#define CELL_X0(i) (int)(((i)>>22)&0x03e0) -#define CELL_Y0(i) (int)(((i)>>17)&0x03e0) +// Trace data cache, for faster redraw cells +// CELL_X[16:31] x position +// CELL_Y[ 0:15] y position +typedef uint32_t index_t; +static index_t trace_index[TRACES_MAX][POINTS_COUNT]; -#define CELL_P(i, x, y) (((((x)&0x03e0UL)<<22) | (((y)&0x03e0UL)<<17)) == ((i)&0xffc00000UL)) +#define INDEX(x, y) ((((index_t)x)<<16)|(((index_t)y))) +#define CELL_X(i) (int)(((i)>>16)) +#define CELL_Y(i) (int)(((i)&0xFFFF)) -//#define floatToInt(v) ((int)(v)) -int floatToInt(float v){ - if (v < 0) return v-0.5; - if (v > 0) return v+0.5; - return 0; +//#define float2int(v) ((int)(v)) +static int +float2int(float v) +{ + if (v < 0) return v - 0.5; + if (v > 0) return v + 0.5; + return 0; } void update_grid(void) { uint32_t gdigit = 100000000; - uint32_t fstart, fspan; + uint32_t fstart = get_sweep_frequency(ST_START); + uint32_t fspan = get_sweep_frequency(ST_SPAN); uint32_t grid; - if (frequency0 <= frequency1) { - fstart = frequency0; - fspan = frequency1 - frequency0; - } else { - fstart = frequency1; - fspan = frequency0 - frequency1; - } - + while (gdigit > 100) { grid = 5 * gdigit; if (fspan / grid >= 4) @@ -86,8 +100,8 @@ void update_grid(void) gdigit /= 10; } - grid_offset = (WIDTH-1) * ((fstart % grid) / 100) / (fspan / 100); - grid_width = (WIDTH-1) * (grid / 100) / (fspan / 1000); + grid_offset = (WIDTH) * ((fstart % grid) / 100) / (fspan / 100); + grid_width = (WIDTH) * (grid / 100) / (fspan / 1000); force_set_markmap(); redraw_request |= REDRAW_FREQUENCY; @@ -97,9 +111,9 @@ static inline int circle_inout(int x, int y, int r) { int d = x*x + y*y - r*r; - if (d <= -r) + if (d < -r) return 1; - if (d > r) + if (d > r) return -1; return 0; } @@ -119,8 +133,7 @@ polar_grid(int x, int y) if (d == 0) return 1; // vertical and horizontal axis - if (x == 0 || y == 0) - return 1; + if (x == 0 || y == 0) return 1; d = circle_inout(x, y, P_RADIUS / 5); if (d == 0) return 1; @@ -131,8 +144,7 @@ polar_grid(int x, int y) if (d > 0) return 0; // cross sloping lines - if (x == y || x == -y) - return 1; + if (x == y || x == -y) return 1; d = circle_inout(x, y, P_RADIUS * 3 / 5); if (d == 0) return 1; @@ -147,7 +159,7 @@ polar_grid(int x, int y) * Constant Resistance circle: (u - r/(r+1))^2 + v^2 = 1/(r+1)^2 * Constant Reactance circle: (u - 1)^2 + (v-1/x)^2 = 1/x^2 */ -int +static int smith_grid(int x, int y) { int d; @@ -155,57 +167,47 @@ smith_grid(int x, int y) // offset to center x -= P_CENTER_X; y -= P_CENTER_Y; - + // outer circle d = circle_inout(x, y, P_RADIUS); - if (d < 0) - return 0; - if (d == 0) - return 1; - + if (d < 0) return 0; + if (d == 0) return 1; + // horizontal axis - if (y == 0) - return 1; + if (y == 0) return 1; // shift circle center to right origin x -= P_RADIUS; // Constant Reactance Circle: 2j : R/2 = P_RADIUS/2 - if (circle_inout(x, y+P_RADIUS/2, P_RADIUS/2) == 0) - return 1; - if (circle_inout(x, y-P_RADIUS/2, P_RADIUS/2) == 0) - return 1; + if (circle_inout(x, y + P_RADIUS / 2, P_RADIUS / 2) == 0) return 1; + if (circle_inout(x, y - P_RADIUS / 2, P_RADIUS / 2) == 0) return 1; // Constant Resistance Circle: 3 : R/4 = P_RADIUS/4 - d = circle_inout(x+P_RADIUS/4, y, P_RADIUS/4); + d = circle_inout(x + P_RADIUS / 4, y, P_RADIUS / 4); if (d > 0) return 0; if (d == 0) return 1; // Constant Reactance Circle: 1j : R = P_RADIUS - if (circle_inout(x, y+P_RADIUS, P_RADIUS) == 0) - return 1; - if (circle_inout(x, y-P_RADIUS, P_RADIUS) == 0) - return 1; + if (circle_inout(x, y + P_RADIUS, P_RADIUS) == 0) return 1; + if (circle_inout(x, y - P_RADIUS, P_RADIUS) == 0) return 1; // Constant Resistance Circle: 1 : R/2 - d = circle_inout(x+P_RADIUS/2, y, P_RADIUS/2); + d = circle_inout(x + P_RADIUS / 2, y, P_RADIUS / 2); if (d > 0) return 0; if (d == 0) return 1; // Constant Reactance Circle: 1/2j : R*2 - if (circle_inout(x, y+P_RADIUS*2, P_RADIUS*2) == 0) - return 1; - if (circle_inout(x, y-P_RADIUS*2, P_RADIUS*2) == 0) - return 1; + if (circle_inout(x, y + P_RADIUS * 2, P_RADIUS * 2) == 0) return 1; + if (circle_inout(x, y - P_RADIUS * 2, P_RADIUS * 2) == 0) return 1; // Constant Resistance Circle: 1/3 : R*3/4 - if (circle_inout(x+P_RADIUS*3/4, y, P_RADIUS*3/4) == 0) - return 1; + if (circle_inout(x + P_RADIUS * 3 / 4, y, P_RADIUS * 3 / 4) == 0) return 1; return 0; } #if 0 -int +static int smith_grid2(int x, int y, float scale) { int d; @@ -213,7 +215,7 @@ smith_grid2(int x, int y, float scale) // offset to center x -= P_CENTER_X; y -= P_CENTER_Y; - + // outer circle d = circle_inout(x, y, P_RADIUS); if (d < 0) @@ -288,6 +290,7 @@ smith_grid2(int x, int y, float scale) } #endif +#if 0 const int cirs[][4] = { { 0, 58/2, 58/2, 0 }, // Constant Reactance Circle: 2j : R/2 = 58 { 29/2, 0, 29/2, 1 }, // Constant Resistance Circle: 3 : R/4 = 29 @@ -299,9 +302,9 @@ const int cirs[][4] = { { 115/2, 0, 115/2, 1 }, // Constant Resistance Circle: 0 : R { 173/2, 0, 173/2, 1 }, // Constant Resistance Circle: -1/3 : R*3/2 = 173 { 0, 0, 0, 0 } // sentinel -}; +}; -int +static int smith_grid3(int x, int y) { int d; @@ -309,7 +312,7 @@ smith_grid3(int x, int y) // offset to center x -= P_CENTER_X; y -= P_CENTER_Y; - + // outer circle d = circle_inout(x, y, P_RADIUS); if (d < 0) @@ -335,9 +338,10 @@ smith_grid3(int x, int y) } return 0; } +#endif #if 0 -int +static int rectangular_grid(int x, int y) { //#define FREQ(x) (((x) * (fspan / 1000) / (WIDTH-1)) * 1000 + fstart) @@ -359,9 +363,9 @@ rectangular_grid(int x, int y) static int rectangular_grid_x(int x) { - if (x < 0) - return 0; - if (x == 0 || x == WIDTH-1) + x -= CELLOFFSETX; + if (x < 0) return 0; + if (x == 0 || x == WIDTH) return 1; if ((((x + grid_offset) * 10) % grid_width) < 10) return 1; @@ -417,7 +421,8 @@ draw_on_strut(int v0, int d, int color) /* * calculate log10(abs(gamma)) */ -float logmag(const float *v) +static float +logmag(const float *v) { return log10f(v[0]*v[0] + v[1]*v[1]) * 10; } @@ -425,30 +430,33 @@ float logmag(const float *v) /* * calculate phase[-2:2] of coefficient */ -float phase(const float *v) +static float +phase(const float *v) { - return 2 * atan2f(v[1], v[0]) / M_PI * 90; + return 2 * atan2f(v[1], v[0]) / VNA_PI * 90; } /* * calculate groupdelay */ -float groupdelay(const float *v, const float *w, float deltaf) +static float +groupdelay(const float *v, const float *w, float deltaf) { #if 1 // atan(w)-atan(v) = atan((w-v)/(1+wv)) float r = w[0]*v[1] - w[1]*v[0]; float i = w[0]*v[0] + w[1]*v[1]; - return atan2f(r, i) / (2 * M_PI * deltaf); + return atan2f(r, i) / (2 * VNA_PI * deltaf); #else - return (atan2f(w[0], w[1]) - atan2f(v[0], v[1])) / (2 * M_PI * deltaf); + return (atan2f(w[0], w[1]) - atan2f(v[0], v[1])) / (2 * VNA_PI * deltaf); #endif } /* * calculate abs(gamma) */ -float linear(const float *v) +static float +linear(const float *v) { return - sqrtf(v[0]*v[0] + v[1]*v[1]); } @@ -456,7 +464,8 @@ float linear(const float *v) /* * calculate vswr; (1+gamma)/(1-gamma) */ -float swr(const float *v) +static float +swr(const float *v) { float x = sqrtf(v[0]*v[0] + v[1]*v[1]); if (x >= 1) @@ -464,30 +473,34 @@ float swr(const float *v) return (1 + x)/(1 - x); } -float resitance(const float *v) { +static float +resitance(const float *v) +{ float z0 = 50; float d = z0 / ((1-v[0])*(1-v[0])+v[1]*v[1]); float zr = ((1+v[0])*(1-v[0]) - v[1]*v[1]) * d; return zr; } -float reactance(const float *v) { +static float +reactance(const float *v) +{ float z0 = 50; float d = z0 / ((1-v[0])*(1-v[0])+v[1]*v[1]); float zi = 2*v[1] * d; return zi; } -void +static void cartesian_scale(float re, float im, int *xp, int *yp, float scale) { //float scale = 4e-3; - int x = floatToInt(re * P_RADIUS * scale); - int y = floatToInt(im * P_RADIUS * scale); - if (x < -P_RADIUS) x = -P_RADIUS; - if (y < -P_RADIUS) y = -P_RADIUS; - if (x > P_RADIUS) x = P_RADIUS; - if (y > P_RADIUS) y = P_RADIUS; + int x = float2int(re * P_RADIUS * scale); + int y = float2int(im * P_RADIUS * scale); + if (x < -P_RADIUS) x = -P_RADIUS; + else if (x > P_RADIUS) x = P_RADIUS; + if (y < -P_RADIUS) y = -P_RADIUS; + else if (y > P_RADIUS) y = P_RADIUS; *xp = P_CENTER_X + x; *yp = P_CENTER_Y - y; } @@ -496,121 +509,78 @@ float groupdelay_from_array(int i, float array[POINTS_COUNT][2]) { int bottom = (i == 0) ? 0 : i - 1; - int top = (i == POINTS_COUNT-1) ? POINTS_COUNT-1 : i + 1; + int top = (i == sweep_points-1) ? sweep_points-1 : i + 1; float deltaf = frequencies[top] - frequencies[bottom]; return groupdelay(array[bottom], array[top], deltaf); } -uint32_t -trace_into_index(int x, int t, int i, float array[POINTS_COUNT][2]) +static float +gamma2resistance(const float v[2]) +{ + float z0 = 50; + float d = z0 / ((1-v[0])*(1-v[0])+v[1]*v[1]); + return ((1+v[0])*(1-v[0]) - v[1]*v[1]) * d; +} + +static float +gamma2reactance(const float v[2]) +{ + float z0 = 50; + float d = z0 / ((1-v[0])*(1-v[0])+v[1]*v[1]); + return 2*v[1] * d; +} + +static index_t +trace_into_index(int t, int i, float array[POINTS_COUNT][2]) { - int y = 0; - float v = 0; + int y, x; + float *coeff = array[i]; - float refpos = 10 - get_trace_refpos(t); + float refpos = NGRIDY - get_trace_refpos(t); + float v = refpos; float scale = 1 / get_trace_scale(t); switch (trace[t].type) { case TRC_LOGMAG: - v = refpos - logmag(coeff) * scale; + v-= logmag(coeff) * scale; break; case TRC_PHASE: - v = refpos - phase(coeff) * scale; + v-= phase(coeff) * scale; break; case TRC_DELAY: - v = refpos - groupdelay_from_array(i, array) * scale; + v-= groupdelay_from_array(i, array) * scale; break; case TRC_LINEAR: - v = refpos + linear(coeff) * scale; + v+= linear(coeff) * scale; break; case TRC_SWR: - v = refpos+ (1 - swr(coeff)) * scale; + v+= (1 - swr(coeff)) * scale; break; case TRC_REAL: - v = refpos - coeff[0] * scale; + v-= coeff[0] * scale; break; case TRC_IMAG: - v = refpos - coeff[1] * scale; + v-= coeff[1] * scale; break; case TRC_R: - v = refpos - resitance(coeff) * scale; + v-= resitance(coeff) * scale; break; case TRC_X: - v = refpos - reactance(coeff) * scale; + v-= reactance(coeff) * scale; break; case TRC_SMITH: //case TRC_ADMIT: case TRC_POLAR: cartesian_scale(coeff[0], coeff[1], &x, &y, scale); - return INDEX(x +CELLOFFSETX, y, i); - break; + goto set_index; } - if (v < 0) v = 0; - if (v > 10) v = 10; - y = floatToInt(v * GRIDY); - return INDEX(x +CELLOFFSETX, y, i); + if (v < 0) v = 0; + if (v > NGRIDY) v = NGRIDY; + x = (i * (WIDTH) + (sweep_points-1)/2) / (sweep_points-1) + CELLOFFSETX; + y = float2int(v * GRIDY); +set_index: + return INDEX(x, y); } -static int -string_value_with_prefix(char *buf, int len, float val, char unit) -{ - char prefix; - int n = 0; - if (val < 0) { - val = -val; - *buf = '-'; - n++; - len--; - } - if (val == INFINITY){ - prefix = S_INFINITY[0]; - } - else { - if (val < 1e-12) { - prefix = 'f'; - val *= 1e15; - } else if (val < 1e-9) { - prefix = 'p'; - val *= 1e12; - } else if (val < 1e-6) { - prefix = 'n'; - val *= 1e9; - } else if (val < 1e-3) { - prefix = S_MICRO[0]; - val *= 1e6; - } else if (val < 1) { - prefix = 'm'; - val *= 1e3; - } else if (val < 1e3) { - prefix = 0; - } else if (val < 1e6) { - prefix = 'k'; - val /= 1e3; - } else if (val < 1e9) { - prefix = 'M'; - val /= 1e6; - } else { - prefix = 'G'; - val /= 1e9; - } - - if (val < 10) { - n += chsnprintf(&buf[n], len, "%.2f", val); - } else if (val < 100) { - n += chsnprintf(&buf[n], len, "%.1f", val); - } else { - n += chsnprintf(&buf[n], len, "%d", (int)val); - } - } - if (prefix) - buf[n++] = prefix; - if (unit) - buf[n++] = unit; - buf[n] = '\0'; - return n; -} - -#define PI2 6.283184 - static void format_smith_value(char *buf, int len, const float coeff[2], uint32_t frequency) { @@ -619,124 +589,96 @@ format_smith_value(char *buf, int len, const float coeff[2], uint32_t frequency) float d = z0 / ((1-coeff[0])*(1-coeff[0])+coeff[1]*coeff[1]); float zr = ((1+coeff[0])*(1-coeff[0]) - coeff[1]*coeff[1]) * d; float zi = 2*coeff[1] * d; - int n; - + char prefix; + float value; switch (marker_smith_format) { case MS_LIN: - chsnprintf(buf, len, "%.2f %.1f" S_DEGREE, linear(coeff), phase(coeff)); + plot_printf(buf, len, "%.2f %.1f" S_DEGREE, linear(coeff), phase(coeff)); break; case MS_LOG: { float v = logmag(coeff); if (v == -INFINITY) - chsnprintf(buf, len, "-"S_INFINITY" dB"); + plot_printf(buf, len, "-"S_INFINITY" dB"); else - chsnprintf(buf, len, "%.1fdB %.1f" S_DEGREE, v, phase(coeff)); + plot_printf(buf, len, "%.1fdB %.1f" S_DEGREE, v, phase(coeff)); } break; case MS_REIM: - n = string_value_with_prefix(buf, len, coeff[0], '\0'); - if (coeff[1] >= 0) buf[n++] = '+'; - string_value_with_prefix(buf+n, len-n, coeff[1], 'j'); - break; + plot_printf(buf, len, "%F%+Fj", coeff[0], coeff[1]); + break; case MS_RX: - n = string_value_with_prefix(buf, len, zr, S_OHM[0]); - if (zi >= 0) - buf[n++] = ' '; - string_value_with_prefix(buf+n, len-n, zi, 'j'); + plot_printf(buf, len, "%F"S_OHM"%+Fj", zr, zi); break; case MS_RLC: - n = string_value_with_prefix(buf, len, zr, S_OHM[0]); - buf[n++] = ' '; - - char prefix; - float value; - if (zi < 0){// Capacity - prefix = 'F'; - value = -1 / (PI2 * frequency * zi); - } - else { - prefix = 'H'; - value = zi / (PI2 * frequency); + if (zi < 0) {// Capacity + prefix = 'F'; + value = -1 / (2 * VNA_PI * frequency * zi); + } else { + prefix = 'H'; + value = zi / (2 * VNA_PI * frequency); } - string_value_with_prefix(buf+n, len-n, value, prefix); + plot_printf(buf, len, "%F"S_OHM" %F%c", zr, value, prefix); break; } } -static void -gamma2resistance(char *buf, int len, const float coeff[2]) -{ - float z0 = 50; - float d = z0 / ((1-coeff[0])*(1-coeff[0])+coeff[1]*coeff[1]); - float zr = ((1+coeff[0])*(1-coeff[0]) - coeff[1]*coeff[1]) * d; - string_value_with_prefix(buf, len, zr, S_OHM[0]); -} - -static void -gamma2reactance(char *buf, int len, const float coeff[2]) -{ - float z0 = 50; - float d = z0 / ((1-coeff[0])*(1-coeff[0])+coeff[1]*coeff[1]); - float zi = 2*coeff[1] * d; - string_value_with_prefix(buf, len, zi, S_OHM[0]); -} - static void trace_get_value_string(int t, char *buf, int len, float array[POINTS_COUNT][2], int i) { float *coeff = array[i]; float v; + char *format; switch (trace[t].type) { case TRC_LOGMAG: + format = "%.2fdB"; v = logmag(coeff); - if (v == -INFINITY) - chsnprintf(buf, len, "-"S_INFINITY" dB"); - else - chsnprintf(buf, len, "%.2fdB", v); break; case TRC_PHASE: + format = "%.1f"S_DEGREE; v = phase(coeff); - chsnprintf(buf, len, "%.2f" S_DEGREE, v); break; case TRC_DELAY: + format = "%.2Fs"; v = groupdelay_from_array(i, array); - string_value_with_prefix(buf, len, v, 's'); break; case TRC_LINEAR: + format = "%.4f"; v = linear(coeff); - chsnprintf(buf, len, "%.2f", v); break; case TRC_SWR: + format = "%.4f"; v = swr(coeff); - if (v == INFINITY) - chsnprintf(buf, len, S_INFINITY); - else - chsnprintf(buf, len, "%.2f", v); - break; - case TRC_SMITH: - format_smith_value(buf, len, coeff, frequencies[i]); break; case TRC_REAL: - chsnprintf(buf, len, "%.2f", coeff[0]); + format = "%.4f"; + v = coeff[0]; break; case TRC_IMAG: - chsnprintf(buf, len, "%.2fj", coeff[1]); + format = "%.4fj"; + v = coeff[1]; break; case TRC_R: - gamma2resistance(buf, len, coeff); + format = "%.2F"S_OHM; + v = gamma2resistance(coeff); break; case TRC_X: - gamma2reactance(buf, len, coeff); + format = "%.2F"S_OHM; + v = gamma2reactance(coeff); break; - //case TRC_ADMIT: + case TRC_SMITH: + format_smith_value(buf, len, coeff, frequencies[i]); + return; + //case TRC_ADMIT: case TRC_POLAR: - chsnprintf(buf, len, "%.2f %.2fj", coeff[0], coeff[1]); - break; + plot_printf(buf, len, "%.2f%+.2fj", coeff[0], coeff[1]); + default: + return; } + plot_printf(buf, len, format, v); } static void @@ -745,465 +687,373 @@ trace_get_value_string_delta(int t, char *buf, int len, float array[POINTS_COUNT float *coeff = array[index]; float *coeff_ref = array[index_ref]; float v; + char *format; switch (trace[t].type) { case TRC_LOGMAG: + format = S_DELTA"%.2fdB"; v = logmag(coeff) - logmag(coeff_ref); - if (v == -INFINITY) - chsnprintf(buf, len, S_DELTA "-"S_INFINITY" dB"); - else - chsnprintf(buf, len, S_DELTA "%.2fdB", v); break; case TRC_PHASE: + format = S_DELTA"%.2f"S_DEGREE; v = phase(coeff) - phase(coeff_ref); - chsnprintf(buf, len, S_DELTA "%.2f" S_DEGREE, v); break; case TRC_DELAY: + format = "%.2Fs"; v = groupdelay_from_array(index, array) - groupdelay_from_array(index_ref, array); - string_value_with_prefix(buf, len, v, 's'); break; case TRC_LINEAR: + format = S_DELTA"%.3f"; v = linear(coeff) - linear(coeff_ref); - chsnprintf(buf, len, S_DELTA "%.2f", v); break; case TRC_SWR: - v = swr(coeff) - swr(coeff_ref); - chsnprintf(buf, len, S_DELTA "%.2f", v); + format = S_DELTA"%.3f"; + v = swr(coeff); + if (v != INFINITY) v -= swr(coeff_ref); break; case TRC_SMITH: format_smith_value(buf, len, coeff, frequencies[index]); - break; + return; case TRC_REAL: - chsnprintf(buf, len, S_DELTA "%.2f", coeff[0] - coeff_ref[0]); + format = S_DELTA"%.3f"; + v = coeff[0] - coeff_ref[0]; break; case TRC_IMAG: - chsnprintf(buf, len, S_DELTA "%.2fj", coeff[1] - coeff_ref[1]); + format = S_DELTA"%.3fj"; + v = coeff[1] - coeff_ref[1]; break; case TRC_R: - gamma2resistance(buf, len, coeff); + format = "%.2F"S_OHM; + v = gamma2resistance(coeff); break; case TRC_X: - gamma2reactance(buf, len, coeff); + format = "%.2F"S_OHM; + v = gamma2reactance(coeff); break; //case TRC_ADMIT: case TRC_POLAR: - chsnprintf(buf, len, "%.2f %.2fj", coeff[0], coeff[1]); - break; + plot_printf(buf, len, "%.2f%+.2fj", coeff[0], coeff[1]); + return; + default: + return; } + plot_printf(buf, len, format, v); } static int trace_get_info(int t, char *buf, int len) { - strcpy(buf, get_trace_typename(t)); - int n = strlen(buf); - char *p = buf + n; - len -= n; + const char *name = get_trace_typename(t); + float scale = get_trace_scale(t); switch (trace[t].type) { case TRC_LOGMAG: - n += chsnprintf(p, len, " %ddB/", (int)get_trace_scale(t)); - break; + return plot_printf(buf, len, "%s %ddB/", name, (int)scale); case TRC_PHASE: - n += chsnprintf(p, len, " %d" S_DEGREE "/", (int)get_trace_scale(t)); - break; + return plot_printf(buf, len, "%s %d" S_DEGREE "/", name, (int)scale); case TRC_SMITH: //case TRC_ADMIT: case TRC_POLAR: - if (get_trace_scale(t) != 1.0) - n += chsnprintf(p, len, " %.1fFS", get_trace_scale(t)); - break; + if (scale != 1.0) + return plot_printf(buf, len, "%s %.1fFS", name, scale); + else + return plot_printf(buf, len, "%s ", name); default: - strcat(p, " "); - string_value_with_prefix(p+1, len-1 , get_trace_scale(t), '/'); - break; + return plot_printf(buf, len, "%s %F/", name, scale); } - return n; -} - -static float time_of_index(int idx) { - return 1.0 / (float)(frequencies[1] - frequencies[0]) / (float)FFT_SIZE * idx; -} - -static float distance_of_index(int idx) { -#define SPEED_OF_LIGHT 299792458 - float distance = ((float)idx * (float)SPEED_OF_LIGHT) / ( (float)(frequencies[1] - frequencies[0]) * (float)FFT_SIZE * 2.0); - return distance * velocity_factor; + return 0; } - -static inline void -mark_map(int x, int y) +static float time_of_index(int idx) { - if (y >= 0 && y < 8 && x >= 0 && x < 16) - markmap[current_mappage][y] |= 1<= 0 && y < MAX_MARKMAP_Y && x >= 0 && x < MAX_MARKMAP_X) + markmap[current_mappage][y] |= 1 << x; } static inline void swap_markmap(void) { - current_mappage = 1 - current_mappage; + current_mappage^= 1; } -static inline void +static void clear_markmap(void) { memset(markmap[current_mappage], 0, sizeof markmap[current_mappage]); } -inline void +void force_set_markmap(void) { memset(markmap[current_mappage], 0xff, sizeof markmap[current_mappage]); } void +invalidate_rect(int x0, int y0, int x1, int y1) +{ + x0 /= CELLWIDTH; + x1 /= CELLWIDTH; + y0 /= CELLHEIGHT; + y1 /= CELLHEIGHT; + int x, y; + for (y = y0; y <= y1; y++) + for (x = x0; x <= x1; x++) + mark_map(x, y); +} + +#define SWAP(x,y) {int t=x;x=y;y=t;} + +static void mark_cells_from_index(void) { - int t; + int t, i, j; /* mark cells between each neighber points */ + map_t *map = &markmap[current_mappage][0]; for (t = 0; t < TRACES_MAX; t++) { if (!trace[t].enabled) continue; - int x0 = CELL_X(trace_index[t][0]); - int y0 = CELL_Y(trace_index[t][0]); - int m0 = x0 >> 5; - int n0 = y0 >> 5; - int i; - mark_map(m0, n0); + index_t *index = &trace_index[t][0]; + int m0 = CELL_X(index[0]) / CELLWIDTH; + int n0 = CELL_Y(index[0]) / CELLHEIGHT; + map[n0] |= 1 << m0; for (i = 1; i < sweep_points; i++) { - int x1 = CELL_X(trace_index[t][i]); - int y1 = CELL_Y(trace_index[t][i]); - int m1 = x1 >> 5; - int n1 = y1 >> 5; - while (m0 != m1 || n0 != n1) { - if (m0 == m1) { - if (n0 < n1) n0++; else n0--; - } else if (n0 == n1) { - if (m0 < m1) m0++; else m0--; - } else { - int x = (m0 < m1) ? (m0 + 1)<<5 : m0<<5; - int y = (n0 < n1) ? (n0 + 1)<<5 : n0<<5; - int sgn = (n0 < n1) ? 1 : -1; - if (sgn*(y-y0)*(x1-x0) < sgn*(x-x0)*(y1-y0)) { - if (m0 < m1) m0++; - else m0--; - } else { - if (n0 < n1) n0++; - else n0--; - } - } - mark_map(m0, n0); - } - x0 = x1; - y0 = y1; - m0 = m1; - n0 = n1; - } - } -} - -void plot_into_index(float measured[2][POINTS_COUNT][2]) -{ - int i, t; - for (i = 0; i < sweep_points; i++) { - int x = (i * (WIDTH-1) + sweep_points/2) / (sweep_points-1); - for (t = 0; t < TRACES_MAX; t++) { - if (!trace[t].enabled) + int m1 = CELL_X(index[i]) / CELLWIDTH; + int n1 = CELL_Y(index[i]) / CELLHEIGHT; + if (m0 == m1 && n0 == n1) continue; - int n = trace[t].channel; - trace_index[t][i] = trace_into_index(x, t, i, measured[n]); + int x0 = m0; int x1 = m1; if (x0>x1) SWAP(x0, x1); m0 = m1; + int y0 = n0; int y1 = n1; if (y0>y1) SWAP(y0, y1); n0 = n1; + for (; y0 <= y1; y0++) + for (j = x0; j <= x1; j++) + map[y0] |= 1 << j; } } -#if 0 - for (t = 0; t < TRACES_MAX; t++) - if (trace[t].enabled && trace[t].polar) - quicksort(trace_index[t], 0, sweep_points); -#endif - - mark_cells_from_index(); - markmap_all_markers(); } -const uint8_t INSIDE = 0b0000; -const uint8_t LEFT = 0b0001; -const uint8_t RIGHT = 0b0010; -const uint8_t BOTTOM = 0b0100; -const uint8_t TOP = 0b1000; - -inline static uint8_t -_compute_outcode(int w, int h, int x, int y) +static inline void +markmap_upperarea(void) { - uint8_t code = 0; - if (x < 0) { - code |= LEFT; - } else - if (x > w) { - code |= RIGHT; - } - if (y < 0) { - code |= BOTTOM; - } else - if (y > h) { - code |= TOP; - } - return code; + // Hardcoded, Text info from upper area + invalidate_rect(0, 0, AREA_WIDTH_NORMAL, 31); } -static void -cell_drawline(int w, int h, int x0, int y0, int x1, int y1, int c) +// +// in most cases _compute_outcode clip calculation not give render line speedup +// +static inline void +cell_drawline(int x0, int y0, int x1, int y1, int c) { - uint8_t outcode0 = _compute_outcode(w, h, x0, y0); - uint8_t outcode1 = _compute_outcode(w, h, x1, y1); - - if (outcode0 & outcode1) { - // this line is out of requested area. early return - return; - } - - if (x0 > x1) { - SWAP(x0, x1); - SWAP(y0, y1); - } + if (x0 < 0 && x1 < 0) return; + if (y0 < 0 && y1 < 0) return; + if (x0 >= CELLWIDTH && x1 >= CELLWIDTH) return; + if (y0 >= CELLHEIGHT && y1 >= CELLHEIGHT) return; + // modifed Bresenham's line algorithm, see https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm + if (x1 < x0) { SWAP(x0, x1); SWAP(y0, y1); } int dx = x1 - x0; - int dy = y1 - y0; - int sy = dy > 0 ? 1 : -1; - int e = 0; - - dy *= sy; - - if (dx >= dy) { - e = dy * 2 - dx; - while (x0 != x1) { - if (y0 >= 0 && y0 < h && x0 >= 0 && x0 < w) spi_buffer[y0*w+x0] |= c; - x0++; - e += dy * 2; - if (e >= 0) { - e -= dx * 2; - y0 += sy; - } - } - if (y0 >= 0 && y0 < h && x0 >= 0 && x0 < w) spi_buffer[y0*w+x0] |= c; - } else { - e = dx * 2 - dy; - while (y0 != y1) { - if (y0 >= 0 && y0 < h && x0 >= 0 && x0 < w) spi_buffer[y0*w+x0] |= c; - y0 += sy; - e += dx * 2; - if (e >= 0) { - e -= dy * 2; - x0++; - } - } - if (y0 >= 0 && y0 < h && x0 >= 0 && x0 < w) spi_buffer[y0*w+x0] |= c; - } -} + int dy = y1 - y0, sy = 1; if (dy < 0) { dy = -dy; sy = -1; } + int err = (dx > dy ? dx : -dy) / 2; -int -search_index_range(int x, int y, uint32_t index[POINTS_COUNT], int *i0, int *i1) -{ - int i, j; - int head = 0; - int tail = sweep_points; - i = 0; - x &= 0x03e0; - y &= 0x03e0; - while (head < tail) { - i = (head + tail) / 2; - if (x < CELL_X0(index[i])) - tail = i+1; - else if (x > CELL_X0(index[i])) - head = i; - else if (y < CELL_Y0(index[i])) - tail = i+1; - else if (y > CELL_Y0(index[i])) - head = i; - else - break; + while (1) { + if (y0 >= 0 && y0 < CELLHEIGHT && x0 >= 0 && x0 < CELLWIDTH) + cell_buffer[y0 * CELLWIDTH + x0] |= c; + if (x0 == x1 && y0 == y1) + return; + int e2 = err; + if (e2 > -dx) { err -= dy; x0++; } + if (e2 < dy) { err += dx; y0+=sy;} } - - if (x != CELL_X0(index[i]) || y != CELL_Y0(index[i])) - return FALSE; - - j = i; - while (j > 0 && x == CELL_X0(index[j-1]) && y == CELL_Y0(index[j-1])) - j--; - *i0 = j; - j = i; - while (j < POINTS_COUNT-1 && x == CELL_X0(index[j+1]) && y == CELL_Y0(index[j+1])) - j++; - *i1 = j; - return TRUE; } +// Give a little speedup then draw rectangular plot (50 systick on all calls, all render req 700 systick) +// Write more difficult algoritm for seach indexes not give speedup static int -search_index_range_x(int x, uint32_t index[POINTS_COUNT], int *i0, int *i1) +search_index_range_x(int x1, int x2, index_t index[POINTS_COUNT], int *i0, int *i1) { int i, j; int head = 0; int tail = sweep_points; - x &= 0x03e0; - i = 0; - while (head < tail) { + int idx_x; + + // Search index point in cell + while (1) { i = (head + tail) / 2; - if (x == CELL_X0(index[i])) - break; - else if (x < CELL_X0(index[i])) { - if (tail == i+1) - break; - tail = i+1; - } else { + idx_x = CELL_X(index[i]); + if (idx_x >= x2) { // index after cell + if (tail == i) + return false; + tail = i; + } + else if (idx_x < x1) { // index before cell if (head == i) - break; + return false; head = i; } + else // index in cell (x =< idx_x < cell_end) + break; } - - if (x != CELL_X0(index[i])) - return FALSE; - j = i; - while (j > 0 && x == CELL_X0(index[j-1])) + // Search index left from point + do { j--; + } while (j > 0 && x1 <= CELL_X(index[j])); *i0 = j; - j = i; - while (j < POINTS_COUNT-1 && x == CELL_X0(index[j+1])) - j++; - *i1 = j; + // Search index right from point + do { + i++; + } while (i < sweep_points-1 && CELL_X(index[i]) < x2); + *i1 = i; + return TRUE; } -void -draw_refpos(int w, int h, int x, int y, int c) -{ - // draw triangle - int i, j; - if (y < -3 || y > 32 + 3) - return; - for (j = 0; j < 3; j++) { - int j0 = 6 - j*2; - for (i = 0; i < j0; i++) { - int x0 = x + i-5; - int y0 = y - j; - int y1 = y + j; - if (y0 >= 0 && y0 < h && x0 >= 0 && x0 < w) - spi_buffer[y0*w+x0] = c; - if (j != 0 && y1 >= 0 && y1 < h && x0 >= 0 && x0 < w) - spi_buffer[y1*w+x0] = c; +#define REFERENCE_WIDTH 6 +#define REFERENCE_HEIGHT 5 +#define REFERENCE_X_OFFSET 5 +#define REFERENCE_Y_OFFSET 2 + +// Reference bitmap +static const uint8_t reference_bitmap[]={ + 0b11000000, + 0b11110000, + 0b11111100, + 0b11110000, + 0b11000000, +}; + +static void +draw_refpos(int x, int y, int c) +{ + int y0 = y, j; + for (j = 0; j < REFERENCE_HEIGHT; j++, y0++) { + if (y0 < 0 || y0 >= CELLHEIGHT) continue; + int x0 = x; + uint8_t bits = reference_bitmap[j]; + while (bits) { + if (x0 >= 0 && x0 < CELLWIDTH) + cell_buffer[y0 * CELLWIDTH + x0] = (bits & 0x80) ? c : DEFAULT_BG_COLOR; + x0++; + bits <<= 1; } } } +#define MARKER_WIDTH 7 +#define MARKER_HEIGHT 10 +#define X_MARKER_OFFSET 3 +#define Y_MARKER_OFFSET 10 +static const uint8_t marker_bitmap[]={ + // Marker 1 + 0b11111110, + 0b11101110, + 0b11001110, + 0b11101110, + 0b11101110, + 0b11101110, + 0b11000110, + 0b01111100, + 0b00111000, + 0b00010000, + // Marker 2 + 0b11111110, + 0b11000110, + 0b10111010, + 0b11111010, + 0b11000110, + 0b10111110, + 0b10000010, + 0b01111100, + 0b00111000, + 0b00010000, + // Marker 3 + 0b11111110, + 0b11000110, + 0b10111010, + 0b11100110, + 0b11111010, + 0b10111010, + 0b11000110, + 0b01111100, + 0b00111000, + 0b00010000, + // Marker 4 + 0b11111110, + 0b11110110, + 0b11100110, + 0b11010110, + 0b10110110, + 0b10110110, + 0b10000010, + 0b01110100, + 0b00111000, + 0b00010000, +}; -void -cell_draw_refpos(int m, int n, int w, int h) +static void +draw_marker(int x, int y, int c, int ch) +{ + int y0 = y, j; + for (j = 0; j < MARKER_HEIGHT; j++, y0++) { + int x0 = x; + uint8_t bits = marker_bitmap[ch * MARKER_HEIGHT + j]; + bool force_color = false; + while (bits) { + if (bits & 0x80) force_color = true; + if (x0 >= 0 && x0 < CELLWIDTH && y0 >= 0 && y0 < CELLHEIGHT) { + if (bits & 0x80) + cell_buffer[y0 * CELLWIDTH + x0] = c; + else if (force_color) + cell_buffer[y0 * CELLWIDTH + x0] = DEFAULT_BG_COLOR; + } + x0++; + bits <<= 1; + } + } +} + +static void +markmap_marker(int marker) { - int x0 = m * CELLWIDTH; - int y0 = n * CELLHEIGHT; int t; + if (!markers[marker].enabled) + return; for (t = 0; t < TRACES_MAX; t++) { if (!trace[t].enabled) continue; - if (trace[t].type == TRC_SMITH || trace[t].type == TRC_POLAR) - continue; - int x = 0 - x0 +CELLOFFSETX; - int y = 10*GRIDY - floatToInt((get_trace_refpos(t) * GRIDY)) - y0; - if (x > -5 && x < w && y >= -3 && y < h+3) - draw_refpos(w, h, x, y, config.trace_color[t]); + index_t index = trace_index[t][markers[marker].index]; + int x = CELL_X(index) - X_MARKER_OFFSET; + int y = CELL_Y(index) - Y_MARKER_OFFSET; + invalidate_rect(x, y, x+MARKER_WIDTH-1, y+MARKER_HEIGHT-1); } } -#define MARKER_WIDTH 7 -#define MARKER_HEIGHT 10 -#define X_MARKER_OFFSET 3 -#define Y_MARKER_OFFSET 10 -static const uint8_t marker_bitmap[]={ - // Marker 1 - 0b11111110, - 0b11101110, - 0b11001110, - 0b11101110, - 0b11101110, - 0b11101110, - 0b11000110, - 0b01111100, - 0b00111000, - 0b00010000, - // Marker 2 - 0b11111110, - 0b11000110, - 0b10111010, - 0b11111010, - 0b11000110, - 0b10111110, - 0b10000010, - 0b01111100, - 0b00111000, - 0b00010000, - // Marker 3 - 0b11111110, - 0b11000110, - 0b10111010, - 0b11100110, - 0b11111010, - 0b10111010, - 0b11000110, - 0b01111100, - 0b00111000, - 0b00010000, - // Marker 4 - 0b11111110, - 0b11110110, - 0b11100110, - 0b11010110, - 0b10110110, - 0b10110110, - 0b10000010, - 0b01110100, - 0b00111000, - 0b00010000, -}; - -static void draw_marker(int w, int h, int x, int y, int c, int ch) -{ - int y0=y; - for (int j=0;j= 0 && x0 < w && y0 >= 0 && y0 < h) - { - if (bits&0x80) - spi_buffer[y0*w+x0] = c; - else if (force_color) - spi_buffer[y0*w+x0] = DEFAULT_BG_COLOR; - } - x0++; - bits<<=1; - } - } +static void +markmap_all_markers(void) +{ + int i; + for (i = 0; i < MARKERS_MAX; i++) { + if (!markers[i].enabled) + continue; + markmap_marker(i); + } + markmap_upperarea(); } void marker_position(int m, int t, int *x, int *y) { - uint32_t index = trace_index[t][markers[m].index]; + index_t index = trace_index[t][markers[m].index]; *x = CELL_X(index); *y = CELL_Y(index); } @@ -1212,7 +1062,6 @@ static int greater(int x, int y) { return x > y; } static int lesser(int x, int y) { return x < y; } static int (*compare)(int x, int y) = lesser; -int8_t marker_tracking = false; int marker_search(void) @@ -1224,8 +1073,8 @@ marker_search(void) return -1; int value = CELL_Y(trace_index[uistat.current_trace][0]); - for (i = 0; i < POINTS_COUNT; i++) { - uint32_t index = trace_index[uistat.current_trace][i]; + for (i = 0; i < sweep_points; i++) { + index_t index = trace_index[uistat.current_trace][i]; if ((*compare)(value, CELL_Y(index))) { value = CELL_Y(index); found = i; @@ -1238,10 +1087,7 @@ marker_search(void) void set_marker_search(int mode) { - if (mode == 0) - compare = greater; - else - compare = lesser; + compare = (mode == 0) ? greater : lesser; } int @@ -1255,14 +1101,14 @@ marker_search_left(int from) int value = CELL_Y(trace_index[uistat.current_trace][from]); for (i = from - 1; i >= 0; i--) { - uint32_t index = trace_index[uistat.current_trace][i]; + index_t index = trace_index[uistat.current_trace][i]; if ((*compare)(value, CELL_Y(index))) break; value = CELL_Y(index); } for (; i >= 0; i--) { - uint32_t index = trace_index[uistat.current_trace][i]; + index_t index = trace_index[uistat.current_trace][i]; if ((*compare)(CELL_Y(index), value)) { break; } @@ -1282,15 +1128,15 @@ marker_search_right(int from) return -1; int value = CELL_Y(trace_index[uistat.current_trace][from]); - for (i = from + 1; i < POINTS_COUNT; i++) { - uint32_t index = trace_index[uistat.current_trace][i]; + for (i = from + 1; i < sweep_points; i++) { + index_t index = trace_index[uistat.current_trace][i]; if ((*compare)(value, CELL_Y(index))) break; value = CELL_Y(index); } - for (; i < POINTS_COUNT; i++) { - uint32_t index = trace_index[uistat.current_trace][i]; + for (; i < sweep_points; i++) { + index_t index = trace_index[uistat.current_trace][i]; if ((*compare)(CELL_Y(index), value)) { break; } @@ -1303,230 +1149,236 @@ marker_search_right(int from) int search_nearest_index(int x, int y, int t) { - uint32_t *index = trace_index[t]; + index_t *index = trace_index[t]; int min_i = -1; int min_d = 1000; int i; for (i = 0; i < sweep_points; i++) { - int16_t dx = x - CELL_X(index[i]) - OFFSETX; - int16_t dy = y - CELL_Y(index[i]) - OFFSETY; + int16_t dx = x - CELL_X(index[i]); + int16_t dy = y - CELL_Y(index[i]); if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; if (dx > 20 || dy > 20) continue; int d = dx*dx + dy*dy; if (d < min_d) { + min_d = d; min_i = i; } } - return min_i; } void -cell_draw_markers(int m, int n, int w, int h) +plot_into_index(float measured[2][POINTS_COUNT][2]) { - int t, i; - for (i = 0; i < MARKERS_MAX; i++) { - if (!markers[i].enabled) - continue; - for (t = 0; t < TRACES_MAX; t++) { - if (!trace[t].enabled) - continue; - uint32_t index = trace_index[t][markers[i].index]; - int x = CELL_X(index) - m * CELLWIDTH - X_MARKER_OFFSET; - int y = CELL_Y(index) - n * CELLHEIGHT - Y_MARKER_OFFSET; - - if (x >=-MARKER_WIDTH && x < w + MARKER_WIDTH && y >= -MARKER_HEIGHT && y < h + MARKER_HEIGHT) - draw_marker(w, h, x, y, config.trace_color[t], i); - } - } -} - -void -markmap_marker(int marker) -{ - int t; - if (!markers[marker].enabled) - return; + int t, i; for (t = 0; t < TRACES_MAX; t++) { if (!trace[t].enabled) continue; - uint32_t index = trace_index[t][markers[marker].index]; - int x = CELL_X(index); - int y = CELL_Y(index); - int m = x>>5; - int n = y>>5; - mark_map(m, n); - if ((x&31) < 6) - mark_map(m-1, n); - if ((x&31) > 32-6) - mark_map(m+1, n); - if ((y&31) < 12) { - mark_map(m, n-1); - if ((x&31) < 6) - mark_map(m-1, n-1); - if ((x&31) > 32-6) - mark_map(m+1, n-1); - } + int ch = trace[t].channel; + index_t *index = trace_index[t]; + for (i = 0; i < sweep_points; i++) + index[i] = trace_into_index(t, i, measured[ch]); } -} +#if 0 + for (t = 0; t < TRACES_MAX; t++) + if (trace[t].enabled && trace[t].polar) + quicksort(trace_index[t], 0, sweep_points); +#endif -void -markmap_all_markers(void) -{ - int i; - for (i = 0; i < MARKERS_MAX; i++) { - if (!markers[i].enabled) - continue; - markmap_marker(i); - } - markmap_upperarea(); + mark_cells_from_index(); + markmap_all_markers(); } - static void draw_cell(int m, int n) { int x0 = m * CELLWIDTH; int y0 = n * CELLHEIGHT; - int x0off = x0 - CELLOFFSETX; int w = CELLWIDTH; int h = CELLHEIGHT; int x, y; - int i0, i1; - int i; + int i0, i1, i; int t; - - if (x0off + w > area_width) - w = area_width - x0off; + uint16_t c; + // Clip cell by area + if (x0 + w > area_width) + w = area_width - x0; if (y0 + h > area_height) h = area_height - y0; if (w <= 0 || h <= 0) return; +// PULSE; - uint16_t grid_mode = 0; - for (t = 0; t < TRACES_MAX; t++) { - if (!trace[t].enabled) - continue; - - if (trace[t].type == TRC_SMITH) - grid_mode |= GRID_SMITH; - //else if (trace[t].type == TRC_ADMIT) - // grid_mode |= GRID_ADMIT; - else if (trace[t].type == TRC_POLAR) - grid_mode |= GRID_POLAR; - else - grid_mode |= GRID_RECTANGULAR; + // Clear buffer ("0 : height" lines) +#if 0 + // use memset 350 system ticks for all screen calls + // as understand it use 8 bit set, slow down on 32 bit systems + memset(spi_buffer, DEFAULT_BG_COLOR, (h*CELLWIDTH)*sizeof(uint16_t)); +#else + // use direct set 35 system ticks for all screen calls +#if CELLWIDTH%8 != 0 +#error "CELLWIDTH % 8 should be == 0 for speed, or need rewrite cell cleanup" +#endif + // Set DEFAULT_BG_COLOR for 8 pixels in one cycle + int count = h*CELLWIDTH / (16/sizeof(pixel_t)); + uint32_t *p = (uint32_t *)cell_buffer; + while (count--) { + p[0] = DEFAULT_BG_COLOR | (DEFAULT_BG_COLOR << 16); + p[1] = DEFAULT_BG_COLOR | (DEFAULT_BG_COLOR << 16); + p[2] = DEFAULT_BG_COLOR | (DEFAULT_BG_COLOR << 16); + p[3] = DEFAULT_BG_COLOR | (DEFAULT_BG_COLOR << 16); + p += 4; } +#endif - PULSE; - memset(spi_buffer, DEFAULT_BG_COLOR, sizeof spi_buffer); - uint16_t c = config.grid_color; - /* draw grid */ - if (grid_mode & GRID_RECTANGULAR) { +// Draw grid +#if 1 + c = config.grid_color; + // Generate grid type list + uint32_t trace_type = 0; + for (t = 0; t < TRACES_MAX; t++) { + if (trace[t].enabled) { + trace_type |= (1 << trace[t].type); + } + } + // Draw rectangular plot (40 system ticks for all screen calls) + if (trace_type & RECTANGULAR_GRID_MASK) { for (x = 0; x < w; x++) { - if (rectangular_grid_x(x+x0off)){ - for (y = 0; y < h; y++) - spi_buffer[y * w + x] = c; + if (rectangular_grid_x(x + x0)) { + for (y = 0; y < h; y++) cell_buffer[y * CELLWIDTH + x] = c; } } for (y = 0; y < h; y++) { - if (rectangular_grid_y(y+y0)){ - for (x = 0; x < w; x++) - if (x+x0off >= 0 && x+x0off < WIDTH) - spi_buffer[y * w + x] = c; + if (rectangular_grid_y(y + y0)) { + for (x = 0; x < w; x++) + if (x + x0 >= CELLOFFSETX && x + x0 <= WIDTH + CELLOFFSETX) + cell_buffer[y * CELLWIDTH + x] = c; } } } - if (grid_mode & (GRID_SMITH|GRID_ADMIT|GRID_POLAR)) { - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - int n = 0; - if (grid_mode & GRID_SMITH) - n = smith_grid(x+x0off, y+y0); - else if (grid_mode & GRID_ADMIT) - n = smith_grid3(x+x0off, y+y0); - //n = smith_grid2(x+x0, y+y0, 0.5); - else if (grid_mode & GRID_POLAR) - n = polar_grid(x+x0off, y+y0); - if (n) - spi_buffer[y * w + x] = c; - } - } + // Smith greed line (1000 system ticks for all screen calls) + if (trace_type & (1 << TRC_SMITH)) { + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) + if (smith_grid(x + x0, y + y0)) cell_buffer[y * CELLWIDTH + x] = c; } - PULSE; - + // Polar greed line (800 system ticks for all screen calls) + else if (trace_type & (1 << TRC_POLAR)) { + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) + if (polar_grid(x + x0, y + y0)) cell_buffer[y * CELLWIDTH + x] = c; + } +#if 0 + else if (trace_type & (1 << TRC_ADMIT)) { + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) + if (smith_grid3(x+x0, y+y0) + // smith_grid2(x+x0, y+y0, 0.5)) + cell_buffer[y * CELLWIDTH + x] = c; + } +#endif +#endif +// PULSE; +// Draw traces (50-600 system ticks for all screen calls, depend from lines +// count and size) #if 1 - /* draw rectanglar plot */ for (t = 0; t < TRACES_MAX; t++) { if (!trace[t].enabled) continue; - if (trace[t].type == TRC_SMITH || trace[t].type == TRC_POLAR) + c = config.trace_color[t]; + // draw polar plot (check all points) + i0 = 0; + i1 = 0; + uint32_t trace_type = (1 << trace[t].type); + if (trace_type & ((1 << TRC_SMITH) | (1 << TRC_POLAR))) + i1 = sweep_points - 1; + else // draw rectangular plot (search index range in cell, save 50-70 + // system ticks for all screen calls) + search_index_range_x(x0, x0 + w, trace_index[t], &i0, &i1); + index_t *index = trace_index[t]; + for (i = i0; i < i1; i++) { + int x1 = CELL_X(index[i]) - x0; + int y1 = CELL_Y(index[i]) - y0; + int x2 = CELL_X(index[i + 1]) - x0; + int y2 = CELL_Y(index[i + 1]) - y0; + cell_drawline(x1, y1, x2, y2, c); + } + } +#else + for (x = 0; x < area_width; x += 6) + cell_drawline(x - x0, 0 - y0, area_width - x - x0, area_height - y0, + config.trace_color[0]); +#endif +// PULSE; +// draw marker symbols on each trace (<10 system ticks for all screen calls) +#if 1 + for (i = 0; i < MARKERS_MAX; i++) { + if (!markers[i].enabled) continue; - - if (search_index_range_x(x0, trace_index[t], &i0, &i1)) { - if (i0 > 0) - i0--; - if (i1 < POINTS_COUNT-1) - i1++; - for (i = i0; i < i1; i++) { - int x1 = CELL_X(trace_index[t][i]); - int x2 = CELL_X(trace_index[t][i+1]); - int y1 = CELL_Y(trace_index[t][i]); - int y2 = CELL_Y(trace_index[t][i+1]); - int c = config.trace_color[t]; - cell_drawline(w, h, x1 - x0, y1 - y0, x2 - x0, y2 - y0, c); - } + for (t = 0; t < TRACES_MAX; t++) { + if (!trace[t].enabled) + continue; + index_t index = trace_index[t][markers[i].index]; + int x = CELL_X(index) - x0 - X_MARKER_OFFSET; + int y = CELL_Y(index) - y0 - Y_MARKER_OFFSET; + // Check marker icon on cell + if (x + MARKER_WIDTH >= 0 && x - MARKER_WIDTH < CELLWIDTH && + y + MARKER_HEIGHT >= 0 && y - MARKER_HEIGHT < CELLHEIGHT) + draw_marker(x, y, config.trace_color[t], i); } } #endif +// Draw trace and marker info on the top (50 system ticks for all screen calls) #if 1 - /* draw polar plot */ + if (n == 0) + cell_draw_marker_info(x0, y0); +#endif +// PULSE; +// Draw reference position (<10 system ticks for all screen calls) for (t = 0; t < TRACES_MAX; t++) { - int c = config.trace_color[t]; if (!trace[t].enabled) continue; - if (trace[t].type != TRC_SMITH && trace[t].type != TRC_POLAR) + uint32_t trace_type = (1 << trace[t].type); + if (trace_type & ((1 << TRC_SMITH) | (1 << TRC_POLAR))) continue; - - for (i = 1; i < sweep_points; i++) { - //uint32_t index = trace_index[t][i]; - //uint32_t pindex = trace_index[t][i-1]; - //if (!CELL_P(index, x0, y0) && !CELL_P(pindex, x0, y0)) - // continue; - int x1 = CELL_X(trace_index[t][i-1]); - int x2 = CELL_X(trace_index[t][i]); - int y1 = CELL_Y(trace_index[t][i-1]); - int y2 = CELL_Y(trace_index[t][i]); - cell_drawline(w, h, x1 - x0, y1 - y0, x2 - x0, y2 - y0, c); + int x = 0 - x0 + CELLOFFSETX - REFERENCE_X_OFFSET; + if (x + REFERENCE_WIDTH >= 0 && x - REFERENCE_WIDTH < CELLWIDTH) { + int y = HEIGHT - float2int((get_trace_refpos(t) * GRIDY)) - y0 - REFERENCE_Y_OFFSET; + if (y + REFERENCE_HEIGHT >= 0 && y - REFERENCE_HEIGHT < CELLHEIGHT) + draw_refpos(x, y, config.trace_color[t]); } } +// Need right clip cell render (25 system ticks for all screen calls) +#if 1 + if (w < CELLWIDTH) { + pixel_t *src = cell_buffer + CELLWIDTH; + pixel_t *dst = cell_buffer + w; + for (y = h; --y; src += CELLWIDTH - w) + for (x = w; x--;) + *dst++ = *src++; + } #endif - - PULSE; - //draw marker symbols on each trace - cell_draw_markers(m, n, w, h); - // draw trace and marker info on the top - cell_draw_marker_info(m, n, w, h); - PULSE; - - if (m == 0) - cell_draw_refpos(m, n, w, h); - - ili9341_bulk(OFFSETX + x0off, OFFSETY + y0, w, h); + // Draw cell (500 system ticks for all screen calls) + ili9341_bulk(OFFSETX + x0, OFFSETY + y0, w, h); } -void +static void draw_all_cells(bool flush_markmap) { int m, n; +// START_PROFILE for (m = 0; m < (area_width+CELLWIDTH-1) / CELLWIDTH; m++) for (n = 0; n < (area_height+CELLHEIGHT-1) / CELLHEIGHT; n++) { - if (is_mapmarked(m, n)) + if ((markmap[0][n] | markmap[1][n]) & (1 << m)) { draw_cell(m, n); +// ili9341_fill(m*CELLWIDTH+10, n*CELLHEIGHT, 2, 2, RGB565(255,0,0)); + } +// else +// ili9341_fill(m*CELLWIDTH+10, n*CELLHEIGHT, 2, 2, RGB565(0,255,0)); } - +// STOP_PROFILE if (flush_markmap) { // keep current map for update swap_markmap(); @@ -1538,17 +1390,26 @@ draw_all_cells(bool flush_markmap) void draw_all(bool flush) { - if (redraw_request & REDRAW_CELLS) + if (redraw_request & REDRAW_AREA) + force_set_markmap(); + if (redraw_request & REDRAW_MARKER) + markmap_upperarea(); + if (redraw_request & (REDRAW_CELLS | REDRAW_MARKER | REDRAW_AREA)) draw_all_cells(flush); if (redraw_request & REDRAW_FREQUENCY) draw_frequencies(); if (redraw_request & REDRAW_CAL_STATUS) draw_cal_status(); + if (redraw_request & REDRAW_BATTERY) + draw_battery_status(); redraw_request = 0; } +// +// Call this function then need fast draw marker and marker info +// Used in ui.c for leveler move marker, drag marker and etc. void -redraw_marker(int marker, int update_info) +redraw_marker(int marker) { if (marker < 0) return; @@ -1556,304 +1417,219 @@ redraw_marker(int marker, int update_info) markmap_marker(marker); // mark cells on marker info - if (update_info) - markmap[current_mappage][0] = 0xffff; + markmap_upperarea(); draw_all_cells(TRUE); + // Force redraw all area after (disable artifacts after fast marker update area) + redraw_request|=REDRAW_AREA; } void request_to_draw_cells_behind_menu(void) { - int n, m; - for (m = 7; m <= 9; m++) - for (n = 0; n < 8; n++) - mark_map(m, n); + // Values Hardcoded from ui.c + invalidate_rect(320-70, 0, 319, 239); redraw_request |= REDRAW_CELLS; } void request_to_draw_cells_behind_numeric_input(void) { - int n, m; - for (m = 0; m <= 9; m++) - for (n = 6; n < 8; n++) - mark_map(m, n); + // Values Hardcoded from ui.c + invalidate_rect(0, 240-32, 319, 239); redraw_request |= REDRAW_CELLS; } - -int -cell_drawchar(int w, int h, uint8_t ch, int x, int y, int invert) -{ - uint8_t bits; - int c, r, ch_size; - const uint8_t *char_buf = FONT_GET_DATA(ch); - ch_size=FONT_GET_WIDTH(ch); - if (y <= -FONT_GET_HEIGHT || y >= h || x <= -ch_size || x >= w) - return ch_size; - for(c = 0; c < FONT_GET_HEIGHT; c++) { - bits = *char_buf++; - if ((y + c) < 0 || (y + c) >= h) - continue; - if (invert) - bits = ~bits; - for (r = 0; r < ch_size; r++) { - if ((x+r) >= 0 && (x+r) < w && (0x80 & bits)) - spi_buffer[(y+c)*w + (x+r)] = foreground_color; - bits <<= 1; - } - } - return ch_size; -} - -void -cell_drawstring(int w, int h, char *str, int x, int y) -{ - while (*str) { - x += cell_drawchar(w, h, *str, x, y, FALSE); - str++; +static int +cell_drawchar(uint8_t ch, int x, int y) +{ + uint8_t bits; + int c, r, ch_size; + const uint8_t *char_buf = FONT_GET_DATA(ch); + ch_size = FONT_GET_WIDTH(ch); + // if (y <= -FONT_GET_HEIGHT || y >= CELLHEIGHT || x <= -ch_size || x >= CELLWIDTH) + // return ch_size; + if (x <= -ch_size) + return ch_size; + for (c = 0; c < FONT_GET_HEIGHT; c++) { + bits = *char_buf++; + if ((y + c) < 0 || (y + c) >= CELLHEIGHT) + continue; + for (r = 0; r < ch_size; r++) { + if ((x+r) >= 0 && (x+r) < CELLWIDTH && (0x80 & bits)) + cell_buffer[(y+c)*CELLWIDTH + (x+r)] = foreground_color; + bits <<= 1; + } } + return ch_size; } -void -cell_drawstring_invert(int w, int h, char *str, int x, int y, int invert) +static void +cell_drawstring(char *str, int x, int y) { + if (y <= -FONT_GET_HEIGHT || y >= CELLHEIGHT) + return; while (*str) { - x += cell_drawchar(w, h, *str, x, y, invert); - str++; + if (x >= CELLWIDTH) + return; + x += cell_drawchar(*str++, x, y); } } static void -cell_draw_marker_info(int m, int n, int w, int h) +cell_draw_marker_info(int x0, int y0) { char buf[24]; int t; - if (n != 0) - return; if (active_marker < 0) return; int idx = markers[active_marker].index; int j = 0; - if (active_marker != -1 && previous_marker != -1 && uistat.current_trace != -1) { + if (previous_marker != -1 && uistat.current_trace != -1) { int t = uistat.current_trace; int mk; for (mk = 0; mk < MARKERS_MAX; mk++) { if (!markers[mk].enabled) continue; - int xpos = 1 + (j%2)*146; - int ypos = 1 + (j/2)*8; - xpos -= m * CELLWIDTH -CELLOFFSETX; - ypos -= n * CELLHEIGHT; - - setForegroundColor(config.trace_color[t]); - if (mk == active_marker) - cell_drawstring(w, h, S_SARROW, xpos, ypos); - xpos += 5; - chsnprintf(buf, sizeof buf, "M%d", mk+1); - cell_drawstring(w, h, buf, xpos, ypos); - - xpos += 13; + int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0; + int ypos = 1 + (j/2)*(FONT_GET_HEIGHT+1) - y0; + + ili9341_set_foreground(config.trace_color[t]); + if (mk == active_marker) + cell_drawstring(S_SARROW, xpos, ypos); + xpos += 5; + plot_printf(buf, sizeof buf, "M%d", mk+1); + cell_drawstring(buf, xpos, ypos); + xpos += 13; //trace_get_info(t, buf, sizeof buf); - int32_t freq = frequencies[markers[mk].index]; + uint32_t freq = frequencies[markers[mk].index]; if (uistat.marker_delta && mk != active_marker) { - freq -= frequencies[markers[active_marker].index]; - frequency_string_short(buf, sizeof buf, freq, S_DELTA[0]); + uint32_t freq1 = frequencies[markers[active_marker].index]; + uint32_t delta = freq > freq1 ? freq - freq1 : freq1 - freq; + plot_printf(buf, sizeof buf, S_DELTA"%.9qHz", delta); } else { - frequency_string_short(buf, sizeof buf, freq, 0); + plot_printf(buf, sizeof buf, "%.10qHz", freq); } - cell_drawstring(w, h, buf, xpos, ypos); - xpos += 64; + cell_drawstring(buf, xpos, ypos); + xpos += 67; if (uistat.marker_delta && mk != active_marker) trace_get_value_string_delta(t, buf, sizeof buf, measured[trace[t].channel], markers[mk].index, markers[active_marker].index); else trace_get_value_string(t, buf, sizeof buf, measured[trace[t].channel], markers[mk].index); - setForegroundColor(DEFAULT_FG_COLOR); - cell_drawstring(w, h, buf, xpos, ypos); + ili9341_set_foreground(DEFAULT_FG_COLOR); + cell_drawstring(buf, xpos, ypos); j++; } // draw marker delta if (!uistat.marker_delta && previous_marker >= 0 && active_marker != previous_marker && markers[previous_marker].enabled) { int idx0 = markers[previous_marker].index; - int xpos = 185; - int ypos = 1 + (j/2)*8; - xpos -= m * CELLWIDTH -CELLOFFSETX; - ypos -= n * CELLHEIGHT; - strcpy(buf, S_DELTA "1-1:"); - buf[1] += active_marker; - buf[3] += previous_marker; - setForegroundColor(DEFAULT_FG_COLOR); - cell_drawstring(w, h, buf, xpos, ypos); - xpos += 29; + int xpos = (WIDTH/2+30) + CELLOFFSETX - x0; + int ypos = 1 + (j/2)*(FONT_GET_HEIGHT+1) - y0; + + plot_printf(buf, sizeof buf, S_DELTA"%d-%d:", active_marker+1, previous_marker+1); + ili9341_set_foreground(DEFAULT_FG_COLOR); + cell_drawstring(buf, xpos, ypos); + xpos += 27; if ((domain_mode & DOMAIN_MODE) == DOMAIN_FREQ) { - frequency_string_short(buf, sizeof buf, frequencies[idx] - frequencies[idx0], 0); + uint32_t freq = frequencies[idx]; + uint32_t freq1 = frequencies[idx0]; + uint32_t delta = freq > freq1 ? freq - freq1 : freq1 - freq; + plot_printf(buf, sizeof buf, "%c%.13qHz", freq >= freq1 ? '+' : '-', delta); } else { - //chsnprintf(buf, sizeof buf, "%d ns %.1f m", (uint16_t)(time_of_index(idx) * 1e9 - time_of_index(idx0) * 1e9), - // distance_of_index(idx) - distance_of_index(idx0)); - int n = string_value_with_prefix(buf, sizeof buf, time_of_index(idx) - time_of_index(idx0), 's'); - buf[n++] = ' '; - string_value_with_prefix(&buf[n], sizeof buf - n, distance_of_index(idx) - distance_of_index(idx0), 'm'); + plot_printf(buf, sizeof buf, "%Fs (%Fm)", time_of_index(idx) - time_of_index(idx0), distance_of_index(idx) - distance_of_index(idx0)); } - cell_drawstring(w, h, buf, xpos, ypos); + cell_drawstring(buf, xpos, ypos); } } else { for (t = 0; t < TRACES_MAX; t++) { if (!trace[t].enabled) continue; - int xpos = 1 + (j%2)*146; - int ypos = 1 + (j/2)*8; - xpos -= m * CELLWIDTH -CELLOFFSETX; - ypos -= n * CELLHEIGHT; -// setForegroundColor(config.trace_color[t]); -// strcpy(buf, "CH0"); -// buf[2] += trace[t].channel; - //chsnprintf(buf, sizeof buf, "CH%d", trace[t].channel); -// cell_drawstring_invert(w, h, buf, xpos, ypos, t == uistat.current_trace); -// xpos += 20; - setForegroundColor(config.trace_color[t]); + int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0; + int ypos = 1 + (j/2)*(FONT_GET_HEIGHT+1) - y0; + + ili9341_set_foreground(config.trace_color[t]); if (t == uistat.current_trace) - cell_drawstring(w, h, S_SARROW, xpos, ypos); + cell_drawstring(S_SARROW, xpos, ypos); xpos += 5; - chsnprintf(buf, sizeof buf, "CH%d", trace[t].channel); - cell_drawstring(w, h, buf, xpos, ypos); + plot_printf(buf, sizeof buf, "CH%d", trace[t].channel); + cell_drawstring(buf, xpos, ypos); xpos += 19; - trace_get_info(t, buf, sizeof buf); - cell_drawstring(w, h, buf, xpos, ypos); - xpos += (strlen(buf) + 1) * 5; + int n = trace_get_info(t, buf, sizeof buf); + cell_drawstring(buf, xpos, ypos); + xpos += n * 5 + 2; //xpos += 60; trace_get_value_string(t, buf, sizeof buf, measured[trace[t].channel], idx); - setForegroundColor(DEFAULT_FG_COLOR); - cell_drawstring(w, h, buf, xpos, ypos); + ili9341_set_foreground(DEFAULT_FG_COLOR); + cell_drawstring(buf, xpos, ypos); j++; } // draw marker frequency - int xpos = 185; - int ypos = 1 + (j/2)*8; - xpos -= m * CELLWIDTH -CELLOFFSETX; - ypos -= n * CELLHEIGHT; - setForegroundColor(DEFAULT_FG_COLOR); -// strcpy(buf, "1:"); -// buf[0] += active_marker; -// xpos += 5; -// setForegroundColor(0xffff); -// cell_drawstring_invert(w, h, buf, xpos, ypos, uistat.lever_mode == LM_MARKER); -// xpos += 14; - setForegroundColor(DEFAULT_FG_COLOR); + int xpos = (WIDTH/2+40) + CELLOFFSETX - x0; + int ypos = 1 + (j/2)*(FONT_GET_HEIGHT+1) - y0; + + ili9341_set_foreground(DEFAULT_FG_COLOR); if (uistat.lever_mode == LM_MARKER) - cell_drawstring(w, h, S_SARROW, xpos, ypos); + cell_drawstring(S_SARROW, xpos, ypos); xpos += 5; - chsnprintf(buf, sizeof buf, "M%d:", active_marker+1); - cell_drawstring(w, h, buf, xpos, ypos); - xpos += 19; + plot_printf(buf, sizeof buf, "M%d:", active_marker+1); + cell_drawstring(buf, xpos, ypos); + xpos += 19; if ((domain_mode & DOMAIN_MODE) == DOMAIN_FREQ) { - frequency_string(buf, sizeof buf, frequencies[idx], ""); + plot_printf(buf, sizeof buf, "%qHz", frequencies[idx]); } else { - //chsnprintf(buf, sizeof buf, "%d ns %.1f m", (uint16_t)(time_of_index(idx) * 1e9), distance_of_index(idx)); - int n = string_value_with_prefix(buf, sizeof buf, time_of_index(idx), 's'); - buf[n++] = ' '; - string_value_with_prefix(&buf[n], sizeof buf-n, distance_of_index(idx), 'm'); + plot_printf(buf, sizeof buf, "%Fs (%Fm)", time_of_index(idx), distance_of_index(idx)); } - cell_drawstring(w, h, buf, xpos, ypos); + cell_drawstring(buf, xpos, ypos); } - setForegroundColor(DEFAULT_FG_COLOR); + ili9341_set_foreground(DEFAULT_FG_COLOR); if (electrical_delay != 0) { // draw electrical delay - int xpos = 21; - int ypos = 1 + ((j+1)/2)*8; - xpos -= m * CELLWIDTH -CELLOFFSETX; - ypos -= n * CELLHEIGHT; - chsnprintf(buf, sizeof buf, "Edelay"); - cell_drawstring(w, h, buf, xpos, ypos); - xpos += 7 * 5; - int n = string_value_with_prefix(buf, sizeof buf, electrical_delay * 1e-12, 's'); - cell_drawstring(w, h, buf, xpos, ypos); - xpos += n * 5 + 5; - float light_speed_ps = 299792458e-12; //(m/ps) - string_value_with_prefix(buf, sizeof buf, electrical_delay * light_speed_ps * velocity_factor, 'm'); - cell_drawstring(w, h, buf, xpos, ypos); - } -} + int xpos = 21 + CELLOFFSETX - x0; + int ypos = 1 + ((j+1)/2)*(FONT_GET_HEIGHT+1) - y0; -void -frequency_string(char *buf, size_t len, uint32_t freq, char *prefix) -{ -/* if (freq < 0) { - freq = -freq; - *buf++ = '-'; - len -= 1; - }*/ - if (freq < 1000) { - chsnprintf(buf, len, "%s%d Hz", prefix, (int)freq); - } else if (freq < 1000000U) { - chsnprintf(buf, len, "%s%d.%03d kHz", prefix, - (freq / 1000U), - (freq % 1000U)); - } else { - chsnprintf(buf, len, "%s%d.%03d %03d MHz", prefix, - (freq / 1000000U), - ((freq / 1000U) % 1000U), - (freq % 1000U)); - } -} + if (uistat.lever_mode == LM_EDELAY) + cell_drawstring(S_SARROW, xpos, ypos); + xpos += 5; -void -frequency_string_short(char *b, size_t len, int32_t freq, char prefix) -{ - char *buf = b; - if (prefix) { - *buf++ = prefix; - len -= 1; - } - if (freq < 0) { - freq = -freq; - *buf++ = '-'; - len -= 1; - } - if (freq < 1000) { - chsnprintf(buf, len, "%d Hz", (int)freq); - } else if (freq < 1000000) { - chsnprintf(buf, len, "%d.%03dkHz", - (int)(freq / 1000), - (int)(freq % 1000)); - } else { - chsnprintf(buf, len, "%d.%06d", - (int)(freq / 1000000), - (int)(freq % 1000000)); - strcpy(b+9, "MHz"); + float light_speed_ps = SPEED_OF_LIGHT*1e-12; //(m/ps) + plot_printf(buf, sizeof buf, "Edelay %Fs %Fm", electrical_delay * 1e-12, + electrical_delay * light_speed_ps * velocity_factor); + cell_drawstring(buf, xpos, ypos); } } void draw_frequencies(void) { - char buf1[24];buf1[0]=' '; - char buf2[24];buf2[0]=0; + char buf1[32]; + char buf2[32]; buf2[0] = 0; if ((domain_mode & DOMAIN_MODE) == DOMAIN_FREQ) { - if (frequency0 < frequency1) { - frequency_string(buf1+1, sizeof(buf1)-1, frequency0, "START "); - frequency_string(buf2, sizeof buf2, frequency1, "STOP "); - } else if (frequency0 > frequency1) { - frequency_string(buf1+1, sizeof(buf1)-1, frequency0/2 + frequency1/2, "CENTER "); - frequency_string(buf2, sizeof buf2, frequency0 - frequency1, "SPAN "); - } else { - frequency_string(buf1+1, sizeof(buf1)-1, frequency0, "CW "); - } + if (FREQ_IS_CW()) { + plot_printf(buf1, sizeof(buf1), " CW %qHz", get_sweep_frequency(ST_CW)); + } else if (FREQ_IS_STARTSTOP()) { + plot_printf(buf1, sizeof(buf1), " START %qHz", get_sweep_frequency(ST_START)); + plot_printf(buf2, sizeof(buf2), " STOP %qHz", get_sweep_frequency(ST_STOP)); + } else if (FREQ_IS_CENTERSPAN()) { + plot_printf(buf1, sizeof(buf1), " CENTER %qHz", get_sweep_frequency(ST_CENTER)); + plot_printf(buf2, sizeof(buf2), " SPAN %qHz", get_sweep_frequency(ST_SPAN)); + } } else { - chsnprintf(buf1+1, sizeof(buf1)-1, "START 0s"); - chsnprintf(buf2, sizeof buf2, "%s%dns (%.2fm)", "STOP ", (uint16_t)(time_of_index(POINTS_COUNT-1) * 1e9), distance_of_index(POINTS_COUNT-1)); + plot_printf(buf1, sizeof(buf1), " START 0s"); + plot_printf(buf2, sizeof(buf2), "STOP %Fs (%Fm)", time_of_index(sweep_points-1), distance_of_index(sweep_points-1)); } - setForegroundColor(DEFAULT_FG_COLOR); - setBackgroundColor(DEFAULT_BG_COLOR); - ili9341_fill(0, 232, 320, 8, DEFAULT_BG_COLOR); - if (uistat.lever_mode == LM_SPAN || uistat.lever_mode == LM_CENTER) - buf1[0] = S_SARROW[0]; - ili9341_drawstring(buf1, OFFSETX, 232); - ili9341_drawstring(buf2, 205, 232); + ili9341_set_foreground(DEFAULT_FG_COLOR); + ili9341_set_background(DEFAULT_BG_COLOR); + ili9341_fill(0, FREQUENCIES_YPOS, 320, FONT_GET_HEIGHT, DEFAULT_BG_COLOR); + if (uistat.lever_mode == LM_CENTER) + buf1[0] = S_SARROW[0]; + if (uistat.lever_mode == LM_SPAN) + buf2[0] = S_SARROW[0]; + ili9341_drawstring(buf1, FREQUENCIES_XPOS1, FREQUENCIES_YPOS); + ili9341_drawstring(buf2, FREQUENCIES_XPOS2, FREQUENCIES_YPOS); } void @@ -1861,73 +1637,62 @@ draw_cal_status(void) { int x = 0; int y = 100; -#define YSTEP 8 - setForegroundColor(DEFAULT_FG_COLOR); - setBackgroundColor(DEFAULT_BG_COLOR); - ili9341_fill(0, y, 10, 6*YSTEP, DEFAULT_BG_COLOR); + char c[3]; + ili9341_set_foreground(DEFAULT_FG_COLOR); + ili9341_set_background(DEFAULT_BG_COLOR); + ili9341_fill(0, y, OFFSETX, 6*(FONT_GET_HEIGHT+1), DEFAULT_BG_COLOR); if (cal_status & CALSTAT_APPLY) { - char c[3] = "C0"; - c[1] += lastsaveid; - if (cal_status & CALSTAT_INTERPOLATED) - c[0] = 'c'; - else if (active_props == ¤t_props) - c[1] = '*'; + c[0] = cal_status & CALSTAT_INTERPOLATED ? 'c' : 'C'; + c[1] = active_props == ¤t_props ? '*' : '0' + lastsaveid; + c[2] = 0; ili9341_drawstring(c, x, y); - y += YSTEP; - } - - if (cal_status & CALSTAT_ED) { - ili9341_drawstring("D", x, y); - y += YSTEP; - } - if (cal_status & CALSTAT_ER) { - ili9341_drawstring("R", x, y); - y += YSTEP; - } - if (cal_status & CALSTAT_ES) { - ili9341_drawstring("S", x, y); - y += YSTEP; - } - if (cal_status & CALSTAT_ET) { - ili9341_drawstring("T", x, y); - y += YSTEP; - } - if (cal_status & CALSTAT_EX) { - ili9341_drawstring("X", x, y); - y += YSTEP; + y +=FONT_GET_HEIGHT+1; } + int i; + static const struct {char text, zero, mask;} calibration_text[]={ + {'D', 0, CALSTAT_ED}, + {'R', 0, CALSTAT_ER}, + {'S', 0, CALSTAT_ES}, + {'T', 0, CALSTAT_ET}, + {'X', 0, CALSTAT_EX} + }; + for (i = 0; i < 5; i++, y+=FONT_GET_HEIGHT+1) + if (cal_status & calibration_text[i].mask) + ili9341_drawstring(&calibration_text[i].text, x, y); } // Draw battery level -#define BATTERY_TOP_LEVEL 4100 -#define BATTERY_BOTTOM_LEVEL 3100 -#define BATTERY_WARNING_LEVEL 3300 +#define BATTERY_TOP_LEVEL 4100 +#define BATTERY_BOTTOM_LEVEL 3100 +#define BATTERY_WARNING_LEVEL 3300 -void -draw_battery_status(void) -{ - uint8_t string_buf[25]; - // Set battery color - setForegroundColor(vbat < BATTERY_WARNING_LEVEL ? DEFAULT_LOW_BAT_COLOR : DEFAULT_NORMAL_BAT_COLOR); - setBackgroundColor(DEFAULT_BG_COLOR); -// chsnprintf(string_buf, sizeof string_buf, "V:%d", vbat); -// ili9341_drawstringV(string_buf, 1, 60); - // Prepare battery bitmap image - // Battery top - int x=0; - string_buf[x++] = 0b00111100; - string_buf[x++] = 0b00100100; - string_buf[x++] = 0b11111111; -// string_buf[x++] = 0b10000001; - // Fill battery status - for (int power=BATTERY_TOP_LEVEL; power > BATTERY_BOTTOM_LEVEL; power-=100) - string_buf[x++] = (power > vbat) ? 0b10000001 : // Empty line - 0b11111111; // Full line - // Battery bottom -// string_buf[x++] = 0b10000001; - string_buf[x++] = 0b11111111; - // Draw battery - blit8BitWidthBitmap(0, 1, 8, x, string_buf); +static void draw_battery_status(void) +{ + int16_t vbat = adc_vbat_read(); + if (vbat <= 0) + return; + uint8_t string_buf[16]; + // Set battery color + ili9341_set_foreground(vbat < BATTERY_WARNING_LEVEL ? DEFAULT_LOW_BAT_COLOR : DEFAULT_NORMAL_BAT_COLOR); + ili9341_set_background(DEFAULT_BG_COLOR); +// plot_printf(string_buf, sizeof string_buf, "V:%d", vbat); +// ili9341_drawstringV(string_buf, 1, 60); + // Prepare battery bitmap image + // Battery top + int x = 0; + string_buf[x++] = 0b00111100; + string_buf[x++] = 0b00100100; + string_buf[x++] = 0b11111111; +// string_buf[x++] = 0b10000001; + // Fill battery status + for (int power=BATTERY_TOP_LEVEL; power > BATTERY_BOTTOM_LEVEL; power-=100) + string_buf[x++] = (power > vbat) ? 0b10000001 : // Empty line + 0b11111111; // Full line + // Battery bottom +// string_buf[x++] = 0b10000001; + string_buf[x++] = 0b11111111; + // Draw battery + blit8BitWidthBitmap(1, 1, 8, x, string_buf); } void @@ -1940,7 +1705,8 @@ request_to_redraw_grid(void) void redraw_frame(void) { - ili9341_fill(0, 0, 320, 240, DEFAULT_BG_COLOR); + ili9341_set_background(DEFAULT_BG_COLOR); + ili9341_clear_screen(); draw_frequencies(); draw_cal_status(); } diff --git a/si5351.c b/si5351.c index 8c548a3..8f7c9c5 100644 --- a/si5351.c +++ b/si5351.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com + * Modified by DiSlord dislordlive@gmail.com * All rights reserved. * * This is free software; you can redistribute it and/or modify @@ -21,25 +22,81 @@ #include "nanovna.h" #include "si5351.h" -#define SI5351_I2C_ADDR (0x60<<1) +// Enable cache for SI5351 CLKX_CONTROL register, little speedup exchange +#define USE_CLK_CONTROL_CACHE TRUE + +// XTAL frequency on si5351 +#define XTALFREQ 26000000U +// MCLK (processor clock if set, audio codec) frequency clock +#define CLK2_FREQUENCY 8000000U + +// Fixed PLL mode multiplier (used in band 1) +#define PLL_N 32 + +// I2C address on bus (only 0x60 for Si5351A in 10-Pin MSOP) +#define SI5351_I2C_ADDR 0x60 + +static uint8_t current_band = 0; +static uint32_t current_freq = 0; +static int32_t current_offset = FREQUENCY_OFFSET; + +// Minimum value is 2, freq change apply at next dsp measure, and need skip it +#define DELAY_NORMAL 2 +// Delay for bands (depend set band 1 more fast (can change before next dsp buffer ready, need wait additional interval) +#define DELAY_BAND_1 3 +#define DELAY_BAND_2 2 +// Band changes need set delay after reset PLL +#define DELAY_BANDCHANGE_1 3 +#define DELAY_BANDCHANGE_2 3 +// Delay after set new PLL values, and send reset (on band 1 unstable if less then 900, on 4000-5000 no amplitude spike on change) +#define DELAY_RESET_PLL 5000 + +uint32_t si5351_get_frequency(void) +{ + return current_freq; +} + +void si5351_set_frequency_offset(int32_t offset) +{ + current_offset = offset; + current_freq = 0; // reset freq, for +} static void -si5351_write(uint8_t reg, uint8_t dat) +si5351_bulk_write(const uint8_t *buf, int len) { - int addr = SI5351_I2C_ADDR>>1; - uint8_t buf[] = { reg, dat }; i2cAcquireBus(&I2CD1); - (void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, 2, NULL, 0, 1000); + (void)i2cMasterTransmitTimeout(&I2CD1, SI5351_I2C_ADDR, buf, len, NULL, 0, 1000); i2cReleaseBus(&I2CD1); } -static void -si5351_bulk_write(const uint8_t *buf, int len) +#if 0 +static bool si5351_bulk_read(uint8_t reg, uint8_t* buf, int len) { - int addr = SI5351_I2C_ADDR>>1; i2cAcquireBus(&I2CD1); - (void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000); + msg_t mr = i2cMasterTransmitTimeout(&I2CD1, SI5351_I2C_ADDR, ®, 1, buf, len, 1000); i2cReleaseBus(&I2CD1); + return mr == MSG_OK; +} + +static void si5351_wait_pll_lock(void) +{ + uint8_t status; + int count = 100; + do{ + status=0xFF; + si5351_bulk_read(0, &status, 1); + if ((status & 0x60) == 0) // PLLA and PLLB locked + return; + }while (--count); +} +#endif + +static inline void +si5351_write(uint8_t reg, uint8_t dat) +{ + uint8_t buf[] = { reg, dat }; + si5351_bulk_write(buf, 2); } // register addr, length, data, ... @@ -47,14 +104,18 @@ const uint8_t si5351_configs[] = { 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff, 4, SI5351_REG_16_CLK0_CONTROL, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, 2, SI5351_REG_183_CRYSTAL_LOAD, SI5351_CRYSTAL_LOAD_8PF, +// All of this init code run late on sweep +#if 0 // setup PLL (26MHz * 32 = 832MHz, 32/2-2=14) - 9, SI5351_REG_26_PLL_A, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0, + 9, SI5351_REG_PLL_A, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0, + 9, SI5351_REG_PLL_B, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0, // RESET PLL - 2, SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B, + 2, SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B | 0x0C, // // setup multisynth (832MHz / 104 = 8MHz, 104/2-2=50) 9, SI5351_REG_58_MULTISYNTH2, /*P3*/0, 1, /*P1*/0, 50, 0, /*P2|P3*/0, 0, 0, 2, SI5351_REG_18_CLK2_CONTROL, SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_INPUT_MULTISYNTH_N | SI5351_CLK_INTEGER_MODE, - 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0, +#endif + 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, ~(SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN), 0 // sentinel }; @@ -69,230 +130,211 @@ si5351_init(void) } } -void si5351_disable_output(void) +static const uint8_t disable_output[] = { + SI5351_REG_16_CLK0_CONTROL, + SI5351_CLK_POWERDOWN, // CLK 0 + SI5351_CLK_POWERDOWN, // CLK 1 + SI5351_CLK_POWERDOWN // CLK 2 +}; + +/* Get the appropriate starting point for the PLL registers */ +static const uint8_t msreg_base[] = { + SI5351_REG_42_MULTISYNTH0, + SI5351_REG_50_MULTISYNTH1, + SI5351_REG_58_MULTISYNTH2, +}; +static const uint8_t clkctrl[] = { + SI5351_REG_16_CLK0_CONTROL, + SI5351_REG_17_CLK1_CONTROL, + SI5351_REG_18_CLK2_CONTROL +}; + +// Reset PLL need then band changes +static void si5351_reset_pll(uint8_t mask) { - uint8_t reg[4]; - si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff); - reg[0] = SI5351_REG_16_CLK0_CONTROL; - reg[1] = SI5351_CLK_POWERDOWN; - reg[2] = SI5351_CLK_POWERDOWN; - reg[3] = SI5351_CLK_POWERDOWN; - si5351_bulk_write(reg, 4); + // Writing a 1<<5 will reset PLLA, 1<<7 reset PLLB, this is a self clearing bits. + // !!! Need delay before reset PLL for apply PLL freq changes before + chThdSleepMicroseconds(DELAY_RESET_PLL); + si5351_write(SI5351_REG_177_PLL_RESET, mask | 0x0C); } -void si5351_enable_output(void) +void si5351_disable_output(void) { - si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0x00); + si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xFF); + si5351_bulk_write(disable_output, sizeof(disable_output)); + current_band = 0; } -void si5351_reset_pll(void) +void si5351_enable_output(void) { - //si5351_write(SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B); - si5351_write(SI5351_REG_177_PLL_RESET, 0xAC); + si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, ~(SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN)); +//si5351_reset_pll(SI5351_PLL_RESET_A | SI5351_PLL_RESET_B); + current_freq = 0; + current_band = 0; } -void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */ - uint8_t mult, - uint32_t num, - uint32_t denom) +// Set PLL freq = XTALFREQ * (mult + num/denom) +static void si5351_setupPLL(uint8_t pllSource, /* SI5351_REG_PLL_A or SI5351_REG_PLL_B */ + uint32_t mult, + uint32_t num, + uint32_t denom) { - /* Get the appropriate starting point for the PLL registers */ - const uint8_t pllreg_base[] = { - SI5351_REG_26_PLL_A, - SI5351_REG_34_PLL_B - }; - uint32_t P1; - uint32_t P2; - uint32_t P3; - /* Feedback Multisynth Divider Equation * where: a = mult, b = num and c = denom * P1 register is an 18-bit value using following formula: - * P1[17:0] = 128 * mult + floor(128*(num/denom)) - 512 + * P1[17:0] = 128 * mult + int((128*num)/denom) - 512 * P2 register is a 20-bit value using the following formula: - * P2[19:0] = 128 * num - denom * floor(128*(num/denom)) + * P2[19:0] = (128 * num) % denom * P3 register is a 20-bit value using the following formula: - * P3[19:0] = denom + * P3[19:0] = denom */ - /* Set the main PLL config registers */ - if (num == 0) - { - /* Integer mode */ - P1 = 128 * mult - 512; - P2 = 0; - P3 = 1; - } - else - { - /* Fractional mode */ - //P1 = (uint32_t)(128 * mult + floor(128 * ((float)num/(float)denom)) - 512); - P1 = 128 * mult + ((128 * num) / denom) - 512; - //P2 = (uint32_t)(128 * num - denom * floor(128 * ((float)num/(float)denom))); - P2 = 128 * num - denom * ((128 * num) / denom); + mult <<= 7; + num <<= 7; + uint32_t P1 = mult - 512; // Integer mode + uint32_t P2 = 0; + uint32_t P3 = 1; + if (num) { // Fractional mode + P1+= num / denom; + P2 = num % denom; P3 = denom; } - - /* The datasheet is a nightmare of typos and inconsistencies here! */ + // Pll MSN(A|B) registers Datasheet uint8_t reg[9]; - reg[0] = pllreg_base[pll]; - reg[1] = (P3 & 0x0000FF00) >> 8; - reg[2] = (P3 & 0x000000FF); - reg[3] = (P1 & 0x00030000) >> 16; - reg[4] = (P1 & 0x0000FF00) >> 8; - reg[5] = (P1 & 0x000000FF); - reg[6] = ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16); - reg[7] = (P2 & 0x0000FF00) >> 8; - reg[8] = (P2 & 0x000000FF); + reg[0] = pllSource; // SI5351_REG_PLL_A or SI5351_REG_PLL_B + reg[1] = (P3 & 0x0FF00) >> 8; // MSN_P3[15: 8] + reg[2] = (P3 & 0x000FF); // MSN_P3[ 7: 0] + reg[3] = (P1 & 0x30000) >> 16; // MSN_P1[17:16] + reg[4] = (P1 & 0x0FF00) >> 8; // MSN_P1[15: 8] + reg[5] = (P1 & 0x000FF); // MSN_P1[ 7: 0] + reg[6] = ((P3 & 0xF0000) >> 12) | ((P2 & 0xF0000) >> 16); // MSN_P3[19:16] | MSN_P2[19:16] + reg[7] = (P2 & 0x0FF00) >> 8; // MSN_P2[15: 8] + reg[8] = (P2 & 0x000FF); // MSN_P2[ 7: 0] si5351_bulk_write(reg, 9); } -void -si5351_setupMultisynth(uint8_t output, - uint8_t pllSource, - uint32_t div, // 4,6,8, 8+ ~ 900 - uint32_t num, - uint32_t denom, - uint32_t rdiv, // SI5351_R_DIV_1~128 - uint8_t drive_strength) +// Set Multisynth divider = (div + num/denom) * rdiv +static void +si5351_setupMultisynth(uint8_t channel, + uint32_t div, // 4,6,8, 8+ ~ 900 + uint32_t num, + uint32_t denom, + uint32_t rdiv, // SI5351_R_DIV_1~128 + uint8_t chctrl) // SI5351_REG_16_CLKX_CONTROL settings { - /* Get the appropriate starting point for the PLL registers */ - const uint8_t msreg_base[] = { - SI5351_REG_42_MULTISYNTH0, - SI5351_REG_50_MULTISYNTH1, - SI5351_REG_58_MULTISYNTH2, - }; - const uint8_t clkctrl[] = { - SI5351_REG_16_CLK0_CONTROL, - SI5351_REG_17_CLK1_CONTROL, - SI5351_REG_18_CLK2_CONTROL - }; - uint8_t dat; - - uint32_t P1; - uint32_t P2; - uint32_t P3; - uint32_t div4 = 0; - /* Output Multisynth Divider Equations * where: a = div, b = num and c = denom * P1 register is an 18-bit value using following formula: - * P1[17:0] = 128 * a + floor(128*(b/c)) - 512 + * P1[17:0] = 128 * a + int((128*b)/c) - 512 * P2 register is a 20-bit value using the following formula: - * P2[19:0] = 128 * b - c * floor(128*(b/c)) + * P2[19:0] = (128 * b) % c * P3 register is a 20-bit value using the following formula: - * P3[19:0] = c + * P3[19:0] = c */ /* Set the main PLL config registers */ - if (div == 4) { - div4 = SI5351_DIVBY4; - P1 = P2 = 0; - P3 = 1; - } else if (num == 0) { - /* Integer mode */ - P1 = 128 * div - 512; - P2 = 0; - P3 = 1; - } else { - /* Fractional mode */ - P1 = 128 * div + ((128 * num) / denom) - 512; - P2 = 128 * num - denom * ((128 * num) / denom); - P3 = denom; + uint32_t P1 = 0; + uint32_t P2 = 0; + uint32_t P3 = 1; + if (div == 4) + rdiv|= SI5351_DIVBY4; + else { + num<<=7; + div<<=7; + P1 = div - 512; // Integer mode + if (num) { // Fractional mode + P1+= num / denom; + P2 = num % denom; + P3 = denom; + } } - /* Set the MSx config registers */ uint8_t reg[9]; - reg[0] = msreg_base[output]; - reg[1] = (P3 & 0x0000FF00) >> 8; - reg[2] = (P3 & 0x000000FF); - reg[3] = ((P1 & 0x00030000) >> 16) | div4 | rdiv; - reg[4] = (P1 & 0x0000FF00) >> 8; - reg[5] = (P1 & 0x000000FF); - reg[6] = ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16); - reg[7] = (P2 & 0x0000FF00) >> 8; - reg[8] = (P2 & 0x000000FF); + reg[0] = msreg_base[channel]; // SI5351_REG_42_MULTISYNTH0, SI5351_REG_50_MULTISYNTH1, SI5351_REG_58_MULTISYNTH2 + reg[1] = (P3 & 0x0FF00)>>8; // MSx_P3[15: 8] + reg[2] = (P3 & 0x000FF); // MSx_P3[ 7: 0] + reg[3] = ((P1 & 0x30000)>>16)| rdiv; // Rx_DIV[2:0] | MSx_DIVBY4[1:0] | MSx_P1[17:16] + reg[4] = (P1 & 0x0FF00)>> 8; // MSx_P1[15: 8] + reg[5] = (P1 & 0x000FF); // MSx_P1[ 7: 0] + reg[6] = ((P3 & 0xF0000)>>12)|((P2 & 0xF0000)>>16); // MSx_P3[19:16] | MSx_P2[19:16] + reg[7] = (P2 & 0x0FF00)>>8; // MSx_P2[15: 8] + reg[8] = (P2 & 0x000FF); // MSx_P2[ 7: 0] si5351_bulk_write(reg, 9); /* Configure the clk control and enable the output */ - dat = drive_strength | SI5351_CLK_INPUT_MULTISYNTH_N; - if (pllSource == SI5351_PLL_B) - dat |= SI5351_CLK_PLL_SELECT_B; + uint8_t dat = chctrl | SI5351_CLK_INPUT_MULTISYNTH_N; if (num == 0) dat |= SI5351_CLK_INTEGER_MODE; - si5351_write(clkctrl[output], dat); -} -#define XTALFREQ 26000000L -#define PLL_N 32 -#define PLLFREQ (XTALFREQ * PLL_N) +#if USE_CLK_CONTROL_CACHE == TRUE + // Use cache for this reg, not update if not change + static uint8_t clk_cache[3]; + if (clk_cache[channel]!=dat) { + si5351_write(clkctrl[channel], dat); + clk_cache[channel]=dat; + } +#else + si5351_write(clkctrl[channel], dat); +#endif +} -void -si5351_set_frequency_fixedpll(int channel, int pll, uint32_t pllfreq, uint32_t freq, - int rdiv, uint8_t drive_strength, int mul) +// Find better approximate values for n/d +#define MAX_DENOMINATOR ((1 << 20) - 1) +static inline void approximate_fraction(uint32_t *n, uint32_t *d) { - int denom = freq; - int div = (pllfreq * mul) / denom; // range: 8 ~ 1800 - int num = (pllfreq * mul) - denom * div; - - // cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227 - int max_denominator = (1 << 20) - 1; - if (denom > max_denominator) { - int p0 = 0, q0 = 1, p1 = 1, q1 = 0; - while (denom != 0) { - int a = num / denom; - int q2 = q0 + a*q1; - if (q2 > max_denominator) - break; - int p2 = p0 + a*p1; - p0 = p1; q0 = q1; p1 = p2; q1 = q2; - int new_denom = num - a * denom; - num = denom; denom = new_denom; - } - num = p1; - denom = q1; + // cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227 + uint32_t denom = *d; + if (denom > MAX_DENOMINATOR) { + uint32_t num = *n; + uint32_t p0 = 0, q0 = 1, p1 = 1, q1 = 0; + while (denom != 0) { + uint32_t a = num / denom; + uint32_t b = num % denom; + uint32_t q2 = q0 + a*q1; + if (q2 > MAX_DENOMINATOR) + break; + uint32_t p2 = p0 + a*p1; + p0 = p1; q0 = q1; p1 = p2; q1 = q2; + num = denom; denom = b; } - - si5351_setupMultisynth(channel, pll, div, num, denom, rdiv, drive_strength); + *n = p1; + *d = q1; + } } -void -si5351_set_frequency_fixeddiv(int channel, int pll, uint32_t freq, int div, - uint8_t drive_strength, int mul) +// Setup Multisynth divider for get correct output freq if fixed PLL = pllfreq +static void +si5351_set_frequency_fixedpll(uint8_t channel, uint64_t pllfreq, uint32_t freq, uint32_t rdiv, uint8_t chctrl) { - int denom = XTALFREQ * mul; - int64_t pllfreq = (int64_t)freq * div; - int multi = pllfreq / denom; - int num = pllfreq - denom * multi; + uint32_t denom = freq; + uint32_t div = pllfreq / denom; // range: 8 ~ 1800 + uint32_t num = pllfreq % denom; + approximate_fraction(&num, &denom); + si5351_setupMultisynth(channel, div, num, denom, rdiv, chctrl); +} - // cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227 - int max_denominator = (1 << 20) - 1; - if (denom > max_denominator) { - int p0 = 0, q0 = 1, p1 = 1, q1 = 0; - while (denom != 0) { - int a = num / denom; - int q2 = q0 + a*q1; - if (q2 > max_denominator) - break; - int p2 = p0 + a*p1; - p0 = p1; q0 = q1; p1 = p2; q1 = q2; - int new_denom = num - a * denom; - num = denom; denom = new_denom; - } - num = p1; - denom = q1; - } +// Setup PLL freq if Multisynth divider fixed = div (need get output = freq/mul) +static void +si5351_setupPLL_freq(uint32_t pllSource, uint32_t freq, uint32_t div, uint32_t mul) +{ + uint32_t denom = XTALFREQ * mul; + uint64_t pllfreq = (uint64_t)freq * div; + uint32_t multi = pllfreq / denom; + uint32_t num = pllfreq % denom; + approximate_fraction(&num, &denom); + si5351_setupPLL(pllSource, multi, num, denom); +} - si5351_setupPLL(pll, multi, num, denom); - si5351_setupMultisynth(channel, pll, div, 0, 1, SI5351_R_DIV_1, drive_strength); +#if 0 +static void +si5351_set_frequency_fixeddiv(uint8_t channel, uint32_t pll, uint32_t freq, uint32_t div, + uint8_t chctrl, uint32_t mul) +{ + si5351_setupPLL_freq(pll, freq, div, mul); + si5351_setupMultisynth(channel, div, 0, 1, SI5351_R_DIV_1, chctrl); } -/* - * 1~100MHz fixed PLL 900MHz, fractional divider - * 100~150MHz fractional PLL 600-900MHz, fixed divider 6 - * 150~200MHz fractional PLL 600-900MHz, fixed divider 4 - */ void -si5351_set_frequency(int channel, int freq, uint8_t drive_strength) +si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength) { if (freq <= 100000000) { si5351_setupPLL(SI5351_PLL_B, 32, 0, 1); @@ -303,119 +345,129 @@ si5351_set_frequency(int channel, int freq, uint8_t drive_strength) si5351_set_frequency_fixeddiv(channel, SI5351_PLL_B, freq, 4, drive_strength, 1); } } +#endif - -int current_band = -1; - -#define DELAY_NORMAL 3 -#define DELAY_BANDCHANGE 1 -#define DELAY_LOWBAND 1 +/* + * Frequency generation divide on 3 band + * Band 1 + * 1~100MHz fixed PLL = XTALFREQ * PLL_N, fractional divider + * Band 2 + * 100~150MHz fractional PLL = 600- 900MHz, fixed divider 'fdiv = 6' + * Band 3 + * 150~300MHz fractional PLL = 600-1200MHz, fixed divider 'fdiv = 4' + * + * For FREQ_HARMONICS = 300MHz - band range is: + * +-----------------------------------------------------------------------------------------------------------------------+ + * | Band 1 | Band 2 | Band 3 | Band 2 | Band 3 | + * +-----------------------------------------------------------------------------------------------------------------------+ + * | Direct mode x1 : x1 | x3 : x5 | x5-x7 | x7-x9 | x9-x11 | + * +-----------------------------------------------------------------------------------------------------------------------+ + * | 50kHz - 100MHz | 100 - 150MHz | 150 - 300MHz | 300-450MHz | 450-900MHz | 900-1500MHz | 1500-2100MHz | 2100-2700MHz | + * +-----------------------------------------------------------------------------------------------------------------------+ + * | f = 50kHz-300MHz | f=100-150 | f=150-300 | f=150-300 | f=214-300 | f=233-300 | + * | of = 50kHz-300MHz |of= 60- 90 |of= 90-180 |of=128-215 |of=166-234 |of=190-246 | + * +-----------------------------------------------------------------------------------------------------------------------+ + */ +static inline uint8_t +si5351_get_band(uint32_t freq) +{ + if (freq < 100000000U) return 1; + if (freq < 150000000U) return 2; + return 3; +} /* + * Maximum supported frequency = FREQ_HARMONICS * 9U * configure output as follows: * CLK0: frequency + offset * CLK1: frequency * CLK2: fixed 8MHz */ -#define CLK2_FREQUENCY 8000000L int -si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength) +si5351_set_frequency(uint32_t freq, uint8_t drive_strength) { - int band; + uint8_t band; int delay = DELAY_NORMAL; - uint32_t ofreq = freq + offset; + if (freq == current_freq) + return delay; + else if (current_freq > freq) // Reset band on sweep begin (if set range 150-600, fix error then 600 MHz band 2 or 3 go back) + current_band = 0; + current_freq = freq; + uint32_t ofreq = freq + current_offset; uint32_t mul = 1, omul = 1; uint32_t rdiv = SI5351_R_DIV_1; + uint32_t fdiv; + // Fix possible incorrect input + drive_strength&=SI5351_CLK_DRIVE_STRENGTH_MASK; + if (freq >= config.harmonic_freq_threshold * 7U) { - mul = 9; + mul = 9; omul = 11; } else if (freq >= config.harmonic_freq_threshold * 5U) { - mul = 7; + mul = 7; omul = 9; } else if (freq >= config.harmonic_freq_threshold * 3U) { - mul = 5; + mul = 5; omul = 7; } else if (freq >= config.harmonic_freq_threshold) { - mul = 3; + mul = 3; omul = 5; - } - if ((freq / mul) < 100000000U) { - band = 0; - } else if ((freq / mul) < 150000000U) { - band = 1; - } else { - band = 2; - } - if (freq <= 500000U) { + } else if (freq <= 500000U) { rdiv = SI5351_R_DIV_64; + freq<<= 6; + ofreq<<= 6; } else if (freq <= 4000000U) { rdiv = SI5351_R_DIV_8; + freq<<= 3; + ofreq<<= 3; } - -#if 1 - if (current_band != band) - si5351_disable_output(); -#endif - + band = si5351_get_band(freq / mul); switch (band) { - case 0: - // fractional divider mode. only PLL A is used. - if (current_band == 1 || current_band == 2) - si5351_setupPLL(SI5351_PLL_A, 32, 0, 1); - // Set PLL twice on changing from band 2 - if (current_band == 2) - si5351_setupPLL(SI5351_PLL_A, 32, 0, 1); - - if (rdiv == SI5351_R_DIV_8) { - freq *= 8; - ofreq *= 8; - } else if (rdiv == SI5351_R_DIV_64) { - freq *= 64; - ofreq *= 64; - } - - si5351_set_frequency_fixedpll(0, SI5351_PLL_A, PLLFREQ, ofreq, - rdiv, drive_strength, omul); - si5351_set_frequency_fixedpll(1, SI5351_PLL_A, PLLFREQ, freq, - rdiv, drive_strength, mul); - //if (current_band != 0) - si5351_set_frequency_fixedpll(2, SI5351_PLL_A, PLLFREQ, CLK2_FREQUENCY, - SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1); - break; - - case 1: - // Set PLL twice on changing from band 2 - if (current_band == 2) { - si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul); - si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul); - } - - // div by 6 mode. both PLL A and B are dedicated for CLK0, CLK1 - si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul); - si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul); - si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq / mul * 6, CLK2_FREQUENCY, - SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1); - break; - - case 2: - // div by 4 mode. both PLL A and B are dedicated for CLK0, CLK1 - si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 4, drive_strength, omul); - si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 4, drive_strength, mul); - si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq / mul * 4, CLK2_FREQUENCY, - SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1); - break; + case 1: + // Setup CH0 and CH1 constant PLLA freq at band change, and set CH2 freq = + // CLK2_FREQUENCY + if (current_band != 1) { + si5351_setupPLL(SI5351_REG_PLL_A, PLL_N, 0, 1); + si5351_set_frequency_fixedpll( + 2, XTALFREQ * PLL_N, CLK2_FREQUENCY, SI5351_R_DIV_1, + SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_PLL_SELECT_A); + delay = DELAY_BANDCHANGE_1; + } else { + delay = DELAY_BAND_1; + } + // Calculate and set CH0 and CH1 divider + si5351_set_frequency_fixedpll(0, (uint64_t)omul * XTALFREQ * PLL_N, ofreq, rdiv, + drive_strength | SI5351_CLK_PLL_SELECT_A); + si5351_set_frequency_fixedpll(1, (uint64_t)mul * XTALFREQ * PLL_N, freq, rdiv, + drive_strength | SI5351_CLK_PLL_SELECT_A); + break; + case 2: // fdiv = 6 + case 3: // fdiv = 4; + fdiv = (band == 2) ? 6 : 4; + // Setup CH0 and CH1 constant fdiv divider at change + if (current_band != band) { + si5351_setupMultisynth(0, fdiv, 0, 1, SI5351_R_DIV_1, + drive_strength | SI5351_CLK_PLL_SELECT_A); + si5351_setupMultisynth(1, fdiv, 0, 1, SI5351_R_DIV_1, + drive_strength | SI5351_CLK_PLL_SELECT_B); + delay = DELAY_BANDCHANGE_2; + } else { + delay = DELAY_BAND_2; + } + // Calculate and set CH0 and CH1 PLL freq + si5351_setupPLL_freq(SI5351_REG_PLL_A, ofreq, fdiv, + omul); // set PLLA freq = (ofreq/omul)*fdiv + si5351_setupPLL_freq(SI5351_REG_PLL_B, freq, fdiv, + mul); // set PLLB freq = ( freq/ mul)*fdiv + // Calculate CH2 freq = CLK2_FREQUENCY, depend from calculated before CH1 PLLB = (freq/mul)*fdiv + si5351_set_frequency_fixedpll( + 2, (uint64_t)freq * fdiv, CLK2_FREQUENCY * mul, SI5351_R_DIV_1, + SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_PLL_SELECT_B); + break; } - if (current_band != band) { - si5351_reset_pll(); -#if 1 - si5351_enable_output(); -#endif - delay += DELAY_BANDCHANGE; + si5351_reset_pll(SI5351_PLL_RESET_A|SI5351_PLL_RESET_B); + current_band = band; } - if (band == 0) - delay += DELAY_LOWBAND; - - current_band = band; return delay; } diff --git a/si5351.h b/si5351.h index 6606454..315ce3c 100644 --- a/si5351.h +++ b/si5351.h @@ -17,73 +17,61 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -#define SI5351_PLL_A 0 -#define SI5351_PLL_B 1 -#define SI5351_MULTISYNTH_DIV_4 4 -#define SI5351_MULTISYNTH_DIV_6 6 -#define SI5351_MULTISYNTH_DIV_8 8 -#define SI5351_R_DIV_1 (0<<4) -#define SI5351_R_DIV_2 (1<<4) -#define SI5351_R_DIV_4 (2<<4) -#define SI5351_R_DIV_8 (3<<4) -#define SI5351_R_DIV_16 (4<<4) -#define SI5351_R_DIV_32 (5<<4) -#define SI5351_R_DIV_64 (6<<4) -#define SI5351_R_DIV_128 (7<<4) -#define SI5351_DIVBY4 (3<<2) +#define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3 +#define SI5351_CLK0_EN (1<<0) +#define SI5351_CLK1_EN (1<<1) +#define SI5351_CLK2_EN (1<<2) -#define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3 -#define SI5351_REG_16_CLK0_CONTROL 16 -#define SI5351_REG_17_CLK1_CONTROL 17 -#define SI5351_REG_18_CLK2_CONTROL 18 -#define SI5351_REG_26_PLL_A 26 -#define SI5351_REG_34_PLL_B 34 -#define SI5351_REG_42_MULTISYNTH0 42 -#define SI5351_REG_50_MULTISYNTH1 50 -#define SI5351_REG_58_MULTISYNTH2 58 +// Reg 16-18 CLKX_CONTROL +#define SI5351_REG_16_CLK0_CONTROL 16 +#define SI5351_REG_17_CLK1_CONTROL 17 +#define SI5351_REG_18_CLK2_CONTROL 18 +#define SI5351_CLK_POWERDOWN (1<<7) +#define SI5351_CLK_INTEGER_MODE (1<<6) +#define SI5351_CLK_PLL_SELECT_A (0<<5) +#define SI5351_CLK_PLL_SELECT_B (1<<5) +#define SI5351_CLK_INVERT (1<<4) +#define SI5351_CLK_INPUT_MASK (3<<2) +#define SI5351_CLK_INPUT_XTAL (0<<2) +#define SI5351_CLK_INPUT_CLKIN (1<<2) +#define SI5351_CLK_INPUT_MULTISYNTH_0_4 (2<<2) +#define SI5351_CLK_INPUT_MULTISYNTH_N (3<<2) +#define SI5351_CLK_DRIVE_STRENGTH_MASK (3<<0) +#define SI5351_CLK_DRIVE_STRENGTH_2MA (0<<0) +#define SI5351_CLK_DRIVE_STRENGTH_4MA (1<<0) +#define SI5351_CLK_DRIVE_STRENGTH_6MA (2<<0) +#define SI5351_CLK_DRIVE_STRENGTH_8MA (3<<0) -#define SI5351_CLK_POWERDOWN (1<<7) -#define SI5351_CLK_INTEGER_MODE (1<<6) -#define SI5351_CLK_PLL_SELECT_B (1<<5) -#define SI5351_CLK_INVERT (1<<4) +#define SI5351_REG_PLL_A 26 +#define SI5351_REG_PLL_B 34 -#define SI5351_CLK_INPUT_MASK (3<<2) -#define SI5351_CLK_INPUT_XTAL (0<<2) -#define SI5351_CLK_INPUT_CLKIN (1<<2) -#define SI5351_CLK_INPUT_MULTISYNTH_0_4 (2<<2) -#define SI5351_CLK_INPUT_MULTISYNTH_N (3<<2) +#define SI5351_REG_42_MULTISYNTH0 42 +#define SI5351_REG_50_MULTISYNTH1 50 +#define SI5351_REG_58_MULTISYNTH2 58 +#define SI5351_DIVBY4 (3<<2) +#define SI5351_R_DIV_1 (0<<4) +#define SI5351_R_DIV_2 (1<<4) +#define SI5351_R_DIV_4 (2<<4) +#define SI5351_R_DIV_8 (3<<4) +#define SI5351_R_DIV_16 (4<<4) +#define SI5351_R_DIV_32 (5<<4) +#define SI5351_R_DIV_64 (6<<4) +#define SI5351_R_DIV_128 (7<<4) -#define SI5351_CLK_DRIVE_STRENGTH_MASK (3<<0) -#define SI5351_CLK_DRIVE_STRENGTH_2MA (0<<0) -#define SI5351_CLK_DRIVE_STRENGTH_4MA (1<<0) -#define SI5351_CLK_DRIVE_STRENGTH_6MA (2<<0) -#define SI5351_CLK_DRIVE_STRENGTH_8MA (3<<0) - - -#define SI5351_REG_177_PLL_RESET 177 -#define SI5351_PLL_RESET_B (1<<7) -#define SI5351_PLL_RESET_A (1<<5) +#define SI5351_REG_177_PLL_RESET 177 +#define SI5351_PLL_RESET_B (1<<7) +#define SI5351_PLL_RESET_A (1<<5) #define SI5351_REG_183_CRYSTAL_LOAD 183 -#define SI5351_CRYSTAL_LOAD_6PF (1<<6) -#define SI5351_CRYSTAL_LOAD_8PF (2<<6) -#define SI5351_CRYSTAL_LOAD_10PF (3<<6) - -#define SI5351_CRYSTAL_FREQ_25MHZ 25000000 +#define SI5351_CRYSTAL_LOAD_6PF (1<<6) +#define SI5351_CRYSTAL_LOAD_8PF (2<<6) +#define SI5351_CRYSTAL_LOAD_10PF (3<<6) void si5351_init(void); +void si5351_disable_output(void); +void si5351_enable_output(void); -void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */ - uint8_t mult, - uint32_t num, - uint32_t denom); -void si5351_setupMultisynth(uint8_t output, - uint8_t pllSource, - uint32_t div, - uint32_t num, - uint32_t denom, - uint32_t rdiv, - uint8_t drive_strength); - -void si5351_set_frequency(int channel, int freq, uint8_t drive_strength); +void si5351_set_frequency_offset(int32_t offset); +int si5351_set_frequency(uint32_t freq, uint8_t drive_strength); +uint32_t si5351_get_frequency(void); diff --git a/tlv320aic3204.c b/tlv320aic3204.c index cb86ad5..21fbe84 100644 --- a/tlv320aic3204.c +++ b/tlv320aic3204.c @@ -25,74 +25,78 @@ #define wait_ms(ms) chThdSleepMilliseconds(ms) -static const uint8_t conf_data_pll[] = { - // len, ( reg, data ), - 2, 0x00, 0x00, /* Initialize to Page 0 */ - 2, 0x01, 0x01, /* Initialize the device through software reset */ - 2, 0x04, 0x43, /* PLL Clock High, MCLK, PLL */ +static const uint8_t conf_data[] = { +// reg, data, +// PLL clock config + 0x00, 0x00, /* Initialize to Page 0 */ + 0x01, 0x01, /* Initialize the device through software reset */ + 0x04, 0x43, /* PLL Clock High, MCLK, PLL */ #ifdef REFCLK_8000KHZ /* 8.000MHz*10.7520 = 86.016MHz, 86.016MHz/(2*7*128) = 48kHz */ - 2, 0x05, 0x91, /* Power up PLL, P=1,R=1 */ - 2, 0x06, 0x0a, /* J=10 */ - 2, 0x07, 29, /* D=7520 = (29<<8) + 96 */ - 2, 0x08, 96, + 0x05, 0x91, /* Power up PLL, P=1,R=1 */ + 0x06, 0x0a, /* J=10 */ + 0x07, 29, /* D=7520 = (29<<8) + 96 */ + 0x08, 96, #endif - 0 // sentinel -}; +// Clock config, default fs=48kHz + 0x0b, 0x82, /* Power up the NDAC divider with value 2 */ + 0x0c, 0x87, /* Power up the MDAC divider with value 7 */ + 0x0d, 0x00, /* Program the OSR of DAC to 128 */ + 0x0e, 0x80, + 0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */ + //0x3c, 25, /* Set the DAC Mode to PRB_P25 */ + 0x1b, 0x0c, /* Set the BCLK,WCLK as output */ + 0x1e, 0x80 + 28, /* Enable the BCLKN divider with value 28 */ + 0x25, 0xee, /* DAC power up */ -// default fs=48kHz -static const uint8_t conf_data_clk[] = { - 2, 0x0b, 0x82, /* Power up the NDAC divider with value 2 */ - 2, 0x0c, 0x87, /* Power up the MDAC divider with value 7 */ - 2, 0x0d, 0x00, /* Program the OSR of DAC to 128 */ - 2, 0x0e, 0x80, - 2, 0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */ - //2, 0x3c, 25, /* Set the DAC Mode to PRB_P25 */ - 2, 0x1b, 0x0c, /* Set the BCLK,WCLK as output */ - 2, 0x1e, 0x80 + 28, /* Enable the BCLKN divider with value 28 */ - 2, 0x25, 0xee, /* DAC power up */ + 0x12, 0x82, /* Power up the NADC divider with value 2 */ + 0x13, 0x87, /* Power up the MADC divider with value 7 */ + 0x14, 0x80, /* Program the OSR of ADC to 128 */ + 0x3d, 0x01, /* Select ADC PRB_R1 */ +// Data routing + 0x00, 0x01, /* Select Page 1 */ + 0x01, 0x08, /* Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO*/ + 0x02, 0x01, /* Enable Master Analog Power Control */ + 0x7b, 0x01, /* Set the REF charging time to 40ms */ + 0x14, 0x25, /* HP soft stepping settings for optimal pop performance at power up Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling capacitor. Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound. */ + 0x0a, 0x33, /* Set the Input Common Mode to 0.9V and Output Common Mode for Headphone to 1.65V */ - 2, 0x12, 0x82, /* Power up the NADC divider with value 2 */ - 2, 0x13, 0x87, /* Power up the MADC divider with value 7 */ - 2, 0x14, 0x80, /* Program the OSR of ADC to 128 */ - 2, 0x3d, 0x01, /* Select ADC PRB_R1 */ - 0 // sentinel + 0x3d, 0x00, /* Select ADC PTM_R4 */ + 0x47, 0x32, /* Set MicPGA startup delay to 3.1ms */ + 0x7b, 0x01, /* Set the REF charging time to 40ms */ + 0x34, 0x10, /* Route IN2L to LEFT_P with 10K */ + 0x36, 0x10, /* Route IN2R to LEFT_N with 10K */ +//0x37, 0x04, /* Route IN3R to RIGHT_P with 10K */ +//0x39, 0x04, /* Route IN3L to RIGHT_N with 10K */ +//0x3b, 0x00, /* Unmute Left MICPGA, Gain selection of 32dB to make channel gain 0dB */ +//0x3c, 0x00, /* Unmute Right MICPGA, Gain selection of 32dB to make channel gain 0dB */ }; -static const uint8_t conf_data_routing[] = { - 2, 0x00, 0x01, /* Select Page 1 */ - 2, 0x01, 0x08, /* Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO*/ - 2, 0x02, 0x01, /* Enable Master Analog Power Control */ - 2, 0x7b, 0x01, /* Set the REF charging time to 40ms */ - 2, 0x14, 0x25, /* HP soft stepping settings for optimal pop performance at power up Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling capacitor. Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound. */ - 2, 0x0a, 0x33, /* Set the Input Common Mode to 0.9V and Output Common Mode for Headphone to 1.65V */ +static const uint8_t conf_data_unmute[] = { +// reg, data, + 0x00, 0x00, /* Select Page 0 */ + 0x51, 0xc0, /* Power up Left and Right ADC Channels */ + 0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */ +}; - 2, 0x3d, 0x00, /* Select ADC PTM_R4 */ - 2, 0x47, 0x32, /* Set MicPGA startup delay to 3.1ms */ - 2, 0x7b, 0x01, /* Set the REF charging time to 40ms */ - 2, 0x34, 0x10, /* Route IN2L to LEFT_P with 10K */ - 2, 0x36, 0x10, /* Route IN2R to LEFT_N with 10K */ - 2, 0x37, 0x04, /* Route IN3R to RIGHT_P with 10K */ - 2, 0x39, 0x04, /* Route IN3L to RIGHT_N with 10K */ - 2, 0x3b, 0, /* Unmute Left MICPGA, Gain selection of 32dB to make channel gain 0dB */ - 2, 0x3c, 0, /* Unmute Right MICPGA, Gain selection of 32dB to make channel gain 0dB */ - 0 // sentinel +static const uint8_t conf_data_ch3_select[] = { +// reg, data, + 0x00, 0x01, /* Select Page 1 */ + 0x37, 0x04, /* Route IN3R to RIGHT_P with input impedance of 10K */ + 0x39, 0x04, /* Route IN3L to RIGHT_N with input impedance of 10K */ }; -const uint8_t conf_data_unmute[] = { - 2, 0x00, 0x00, /* Select Page 0 */ - 2, 0x51, 0xc0, /* Power up Left and Right ADC Channels */ - 2, 0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */ - 0 // sentinel +static const uint8_t conf_data_ch1_select[] = { +// reg, data, + 0x00, 0x01, /* Select Page 1 */ + 0x37, 0x40, /* Route IN1R to RIGHT_P with input impedance of 10K */ + 0x39, 0x10, /* Route IN1L to RIGHT_N with input impedance of 10K */ }; -static void +static inline void tlv320aic3204_bulk_write(const uint8_t *buf, int len) { - int addr = AIC3204_ADDR; - i2cAcquireBus(&I2CD1); - (void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000); - i2cReleaseBus(&I2CD1); + (void)i2cMasterTransmitTimeout(&I2CD1, AIC3204_ADDR, buf, len, NULL, 0, 1000); } #if 0 @@ -109,49 +113,32 @@ tlv320aic3204_read(uint8_t d0) #endif static void -tlv320aic3204_config(const uint8_t *data) +tlv320aic3204_config(const uint8_t *data, int len) { - const uint8_t *p = data; - while (*p) { - uint8_t len = *p++; - tlv320aic3204_bulk_write(p, len); - p += len; - } + i2cAcquireBus(&I2CD1); + for (; len--; data += 2) + tlv320aic3204_bulk_write(data, 2); + i2cReleaseBus(&I2CD1); } void tlv320aic3204_init(void) { - tlv320aic3204_config(conf_data_pll); - tlv320aic3204_config(conf_data_clk); - tlv320aic3204_config(conf_data_routing); + tlv320aic3204_config(conf_data, sizeof(conf_data)/2); wait_ms(40); - tlv320aic3204_config(conf_data_unmute); + tlv320aic3204_config(conf_data_unmute, sizeof(conf_data_unmute)/2); } void tlv320aic3204_select(int channel) { - const uint8_t ch3[] = { - 2, 0x00, 0x01, /* Select Page 1 */ - 2, 0x37, 0x04, /* Route IN3R to RIGHT_P with input impedance of 10K */ - 2, 0x39, 0x04, /* Route IN3L to RIGHT_N with input impedance of 10K */ - 0 // sentinel - }; - const uint8_t ch1[] = { - 2, 0x00, 0x01, /* Select Page 1 */ - 2, 0x37, 0x40, /* Route IN1R to RIGHT_P with input impedance of 10K */ - 2, 0x39, 0x10, /* Route IN1L to RIGHT_N with input impedance of 10K */ - 0 // sentinel - }; - tlv320aic3204_config(channel ? ch1 : ch3); + tlv320aic3204_config(channel ? conf_data_ch1_select : conf_data_ch3_select, sizeof(conf_data_ch3_select)/2); } void tlv320aic3204_set_gain(int lgain, int rgain) { - uint8_t data[] = { - 2, 0x00, 0x01, /* Select Page 1 */ - 2, 0x3b, lgain, /* Unmute Left MICPGA, set gain */ - 2, 0x3c, rgain, /* Unmute Right MICPGA, set gain */ - 0 // sentinel - }; - tlv320aic3204_config(data); + uint8_t data[] = { + 0x00, 0x01, /* Select Page 1 */ + 0x3b, lgain, /* Unmute Left MICPGA, set gain */ + 0x3c, rgain, /* Unmute Right MICPGA, set gain */ + }; + tlv320aic3204_config(data, sizeof(data)/2); } diff --git a/ui.c b/ui.c index f35f504..391af98 100644 --- a/ui.c +++ b/ui.c @@ -22,34 +22,34 @@ #include "hal.h" #include "chprintf.h" #include "nanovna.h" -#include +//#include #include - uistat_t uistat = { digit: 6, current_trace: 0, lever_mode: LM_MARKER, marker_delta: FALSE, + marker_tracking : FALSE, }; -#define NO_EVENT 0 -#define EVT_BUTTON_SINGLE_CLICK 0x01 -#define EVT_BUTTON_DOUBLE_CLICK 0x02 -#define EVT_BUTTON_DOWN_LONG 0x04 -#define EVT_UP 0x10 -#define EVT_DOWN 0x20 -#define EVT_REPEAT 0x40 +#define NO_EVENT 0 +#define EVT_BUTTON_SINGLE_CLICK 0x01 +#define EVT_BUTTON_DOUBLE_CLICK 0x02 +#define EVT_BUTTON_DOWN_LONG 0x04 +#define EVT_UP 0x10 +#define EVT_DOWN 0x20 +#define EVT_REPEAT 0x40 -#define BUTTON_DOWN_LONG_TICKS 5000 /* 1sec */ -#define BUTTON_DOUBLE_TICKS 5000 /* 500ms */ -#define BUTTON_REPEAT_TICKS 1000 /* 100ms */ -#define BUTTON_DEBOUNCE_TICKS 200 +#define BUTTON_DOWN_LONG_TICKS 5000 /* 1sec */ +#define BUTTON_DOUBLE_TICKS 2500 /* 500ms */ +#define BUTTON_REPEAT_TICKS 625 /* 125ms */ +#define BUTTON_DEBOUNCE_TICKS 200 /* lever switch assignment */ -#define BIT_UP1 3 -#define BIT_PUSH 2 -#define BIT_DOWN1 1 +#define BIT_UP1 3 +#define BIT_PUSH 2 +#define BIT_DOWN1 1 #define READ_PORT() palReadPort(GPIOA) #define BUTTON_MASK 0b1111 @@ -59,7 +59,7 @@ static uint32_t last_button_down_ticks; static uint32_t last_button_repeat_ticks; static int8_t inhibit_until_release = FALSE; -uint8_t operation_requested = OP_NONE; +volatile uint8_t operation_requested = OP_NONE; int8_t previous_marker = -1; @@ -71,8 +71,14 @@ enum { KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_CW, KM_SCALE, KM_REFPOS, KM_EDELAY, KM_VELOCITY_FACTOR, KM_SCALEDELAY }; +#define NUMINPUT_LEN 10 + static uint8_t ui_mode = UI_NORMAL; static uint8_t keypad_mode; +static uint8_t keypads_last_index; +static char kp_buf[NUMINPUT_LEN+1]; +static int8_t kp_index = 0; +static uint8_t menu_current_level = 0; static int8_t selection = 0; // Set structure align as WORD (save flash memory) @@ -86,78 +92,71 @@ typedef struct { #pragma pack(pop) // Touch screen -static int8_t last_touch_status = FALSE; +#define EVT_TOUCH_NONE 0 +#define EVT_TOUCH_DOWN 1 +#define EVT_TOUCH_PRESSED 2 +#define EVT_TOUCH_RELEASED 3 + +static int8_t last_touch_status = EVT_TOUCH_NONE; static int16_t last_touch_x; static int16_t last_touch_y; //int16_t touch_cal[4] = { 1000, 1000, 10*16, 12*16 }; //int16_t touch_cal[4] = { 620, 600, 130, 180 }; -#define EVT_TOUCH_NONE 0 -#define EVT_TOUCH_DOWN 1 -#define EVT_TOUCH_PRESSED 2 -#define EVT_TOUCH_RELEASED 3 -int awd_count; +//int awd_count; //int touch_x, touch_y; -#define NUMINPUT_LEN 10 - #define KP_CONTINUE 0 #define KP_DONE 1 #define KP_CANCEL 2 -char kp_buf[11]; -int8_t kp_index = 0; - -void ui_mode_normal(void); -void ui_mode_menu(void); -void ui_mode_numeric(int _keypad_mode); -void ui_mode_keypad(int _keypad_mode); -void draw_menu(void); -void leave_ui_mode(void); -void erase_menu_buttons(void); -void ui_process_keypad(void); +static void ui_mode_normal(void); +static void ui_mode_menu(void); +static void ui_mode_numeric(int _keypad_mode); +static void ui_mode_keypad(int _keypad_mode); +static void draw_menu(void); +static void leave_ui_mode(void); +static void erase_menu_buttons(void); +static void ui_process_keypad(void); static void ui_process_numeric(void); +static void menu_move_back(void); static void menu_push_submenu(const menuitem_t *submenu); static int btn_check(void) { int cur_button = READ_PORT() & BUTTON_MASK; - int changed = last_button ^ cur_button; - int status = 0; + int changed = last_button ^ cur_button; + int status = 0; uint32_t ticks = chVTGetSystemTime(); - if (changed & (1<= BUTTON_DEBOUNCE_TICKS) { - if (cur_button & (1<= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS) { + // button released + status |= EVT_BUTTON_SINGLE_CLICK; + if (inhibit_until_release) { + status = 0; + inhibit_until_release = FALSE; } - last_button_down_ticks = ticks; } - } - + } if (changed & (1<= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) { status |= EVT_UP; } - last_button_down_ticks = ticks; } if (changed & (1<= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) { status |= EVT_DOWN; } - last_button_down_ticks = ticks; } + last_button_down_ticks = ticks; last_button = cur_button; - return status; + return status; } static int btn_wait_release(void) @@ -167,15 +166,14 @@ static int btn_wait_release(void) int changed = last_button ^ cur_button; uint32_t ticks = chVTGetSystemTime(); int status = 0; - if (!inhibit_until_release) { if ((cur_button & (1<= BUTTON_DOWN_LONG_TICKS) { + && ticks >= last_button_down_ticks + BUTTON_DOWN_LONG_TICKS) { inhibit_until_release = TRUE; return EVT_BUTTON_DOWN_LONG; } if ((changed & (1<= BUTTON_DOWN_LONG_TICKS - && ticks - last_button_repeat_ticks >= BUTTON_REPEAT_TICKS) { - if (cur_button & (1<= last_button_down_ticks + BUTTON_DOWN_LONG_TICKS + && ticks >= last_button_repeat_ticks + BUTTON_REPEAT_TICKS) { + if (cur_button & (1< TOUCH_THRESHOLD; + return adc_single_read(ADC_CHSELR_CHSEL7) > TOUCH_THRESHOLD; } -int touch_check(void) +static int +touch_check(void) { int stat = touch_status(); if (stat) { @@ -285,56 +282,48 @@ int touch_check(void) if (stat != last_touch_status) { last_touch_status = stat; - if (stat) { - return EVT_TOUCH_PRESSED; - } else { - return EVT_TOUCH_RELEASED; - } - } else { - if (stat) - return EVT_TOUCH_DOWN; - else - return EVT_TOUCH_NONE; + return stat ? EVT_TOUCH_PRESSED : EVT_TOUCH_RELEASED; } + return stat ? EVT_TOUCH_DOWN : EVT_TOUCH_NONE; } -void touch_wait_release(void) +static inline void +touch_wait_release(void) { - int status; - /* wait touch release */ - do { - status = touch_check(); - } while(status != EVT_TOUCH_RELEASED); + while (touch_check() != EVT_TOUCH_RELEASED) + ; +} + +static inline void +touch_wait_pressed(void) +{ + while (touch_check() != EVT_TOUCH_PRESSED) + ; } void touch_cal_exec(void) { - int status; int x1, x2, y1, y2; - - adc_stop(ADC1); - setForegroundColor(DEFAULT_FG_COLOR); - setBackgroundColor(DEFAULT_BG_COLOR); - ili9341_fill(0, 0, 320, 240, DEFAULT_BG_COLOR); + + adc_stop(); + ili9341_set_foreground(DEFAULT_FG_COLOR); + ili9341_set_background(DEFAULT_BG_COLOR); + ili9341_clear_screen(); ili9341_line(0, 0, 0, 32); ili9341_line(0, 0, 32, 0); ili9341_drawstring("TOUCH UPPER LEFT", 10, 10); - do { - status = touch_check(); - } while(status != EVT_TOUCH_RELEASED); + touch_wait_release(); x1 = last_touch_x; y1 = last_touch_y; - ili9341_fill(0, 0, 320, 240, DEFAULT_BG_COLOR); + ili9341_clear_screen(); ili9341_line(320-1, 240-1, 320-1, 240-32); ili9341_line(320-1, 240-1, 320-32, 240-1); ili9341_drawstring("TOUCH LOWER RIGHT", 230, 220); - do { - status = touch_check(); - } while(status != EVT_TOUCH_RELEASED); + touch_wait_release(); x2 = last_touch_x; y2 = last_touch_y; @@ -350,30 +339,26 @@ touch_cal_exec(void) void touch_draw_test(void) { - int status; int x0, y0; int x1, y1; - adc_stop(ADC1); + adc_stop(); - ili9341_fill(0, 0, 320, 240, DEFAULT_BG_COLOR); - setForegroundColor(DEFAULT_FG_COLOR); - setBackgroundColor(DEFAULT_BG_COLOR); + ili9341_set_foreground(DEFAULT_FG_COLOR); + ili9341_set_background(DEFAULT_BG_COLOR); + ili9341_clear_screen(); ili9341_drawstring("TOUCH TEST: DRAG PANEL", OFFSETX, 233); - do { - status = touch_check(); - } while(status != EVT_TOUCH_PRESSED); + touch_wait_pressed(); touch_position(&x0, &y0); do { - status = touch_check(); touch_position(&x1, &y1); ili9341_line(x0, y0, x1, y1); x0 = x1; y0 = y1; chThdSleepMilliseconds(50); - } while(status != EVT_TOUCH_RELEASED); + } while (touch_check() != EVT_TOUCH_RELEASED); touch_start_watchdog(); } @@ -386,31 +371,21 @@ touch_position(int *x, int *y) *y = (last_touch_y - config.touch_cal[1]) * 16 / config.touch_cal[3]; } - void show_version(void) { - int x = 5, y = 5; - - adc_stop(ADC1); - ili9341_fill(0, 0, 320, 240, DEFAULT_BG_COLOR); - - setForegroundColor(DEFAULT_FG_COLOR); - setBackgroundColor(DEFAULT_BG_COLOR); - ili9341_drawstring_size(BOARD_NAME, x, y, 4); - y += 25; - - ili9341_drawstring("2016-2019 Copyright @edy555", x, y += 10); - ili9341_drawstring("Licensed under GPL. See: https://github.com/ttrftech/NanoVNA", x, y += 10); - ili9341_drawstring("Version: " VERSION, x, y += 10); - ili9341_drawstring("Build Time: " __DATE__ " - " __TIME__, x, y += 10); - y += 5; - ili9341_drawstring("Kernel: " CH_KERNEL_VERSION, x, y += 10); - ili9341_drawstring("Compiler: " PORT_COMPILER_NAME, x, y += 10); - ili9341_drawstring("Architecture: " PORT_ARCHITECTURE_NAME " Core Variant: " PORT_CORE_VARIANT_NAME, x, y += 10); - ili9341_drawstring("Port Info: " PORT_INFO, x, y += 10); - ili9341_drawstring("Platform: " PLATFORM_NAME, x, y += 10); - + int x = 5, y = 5, i = 0; + adc_stop(); + ili9341_set_foreground(DEFAULT_FG_COLOR); + ili9341_set_background(DEFAULT_BG_COLOR); + + ili9341_clear_screen(); + uint16_t shift = 0b0000010000111110; + ili9341_drawstring_size(info_about[i++], x , y, 4); + while (info_about[i]) { + do {shift>>=1; y+=5;} while (shift&1); + ili9341_drawstring(info_about[i++], x, y+=5); + } while (true) { if (touch_check() == EVT_TOUCH_PRESSED) break; @@ -424,13 +399,13 @@ show_version(void) void enter_dfu(void) { - adc_stop(ADC1); + adc_stop(); int x = 5, y = 5; - setForegroundColor(DEFAULT_FG_COLOR); - setBackgroundColor(DEFAULT_BG_COLOR); + ili9341_set_foreground(DEFAULT_FG_COLOR); + ili9341_set_background(DEFAULT_BG_COLOR); // leave a last message - ili9341_fill(0, 0, 320, 240, DEFAULT_BG_COLOR); + ili9341_clear_screen(); ili9341_drawstring("DFU: Device Firmware Update Mode", x, y += 10); ili9341_drawstring("To exit DFU mode, please reset device yourself.", x, y += 10); @@ -439,6 +414,15 @@ enter_dfu(void) NVIC_SystemReset(); } +static void +select_lever_mode(int mode) +{ + if (uistat.lever_mode != mode) { + uistat.lever_mode = mode; + redraw_request |= REDRAW_FREQUENCY | REDRAW_MARKER; + } +} + // type of menu item enum { MT_NONE, @@ -451,10 +435,6 @@ enum { typedef void (*menuaction_cb_t)(int item, uint8_t data); - -static void menu_move_back(void); - - static void menu_calop_cb(int item, uint8_t data) { @@ -488,9 +468,9 @@ menu_cal2_cb(int item, uint8_t data) case 3: // CORRECTION // toggle applying correction cal_status ^= CALSTAT_APPLY; - draw_menu(); break; } + draw_menu(); draw_cal_status(); //menu_move_back(); } @@ -499,12 +479,11 @@ static void menu_recall_cb(int item, uint8_t data) { (void)item; - if (caldata_recall(data) == 0) { - menu_move_back(); - ui_mode_normal(); - update_grid(); - draw_cal_status(); - } + caldata_recall(data); + menu_move_back(); + ui_mode_normal(); + update_grid(); + draw_cal_status(); } static void @@ -563,7 +542,7 @@ choose_active_trace(void) if (trace[uistat.current_trace].enabled) // do nothing return; - for (i = 0; i < 4; i++) + for (i = 0; i < TRACES_MAX; i++) if (trace[i].enabled) { uistat.current_trace = i; return; @@ -625,17 +604,17 @@ menu_transform_cb(int item, uint8_t data) (void)item; (void)data; domain_mode ^= DOMAIN_TIME; - uistat.lever_mode = LM_MARKER; + select_lever_mode(LM_MARKER); draw_frequencies(); ui_mode_normal(); } static void -menu_velocity_cb(int item, uint8_t data){ +menu_velocity_cb(int item, uint8_t data) +{ (void)item; (void)data; - int status = btn_wait_release(); - if (status & EVT_BUTTON_DOWN_LONG) { + if (btn_wait_release() & EVT_BUTTON_DOWN_LONG) { ui_mode_numeric(KM_VELOCITY_FACTOR); ui_process_numeric(); } else { @@ -656,7 +635,7 @@ static void choose_active_marker(void) { int i; - for (i = 0; i < 4; i++) + for (i = 0; i < MARKERS_MAX; i++) if (markers[i].enabled) { active_marker = i; return; @@ -669,10 +648,9 @@ menu_scale_cb(int item, uint8_t data) { (void)item; if (data == KM_SCALE && trace[uistat.current_trace].type == TRC_DELAY) { - data = KM_SCALEDELAY; + data = KM_SCALEDELAY; } - int status = btn_wait_release(); - if (status & EVT_BUTTON_DOWN_LONG) { + if (btn_wait_release() & EVT_BUTTON_DOWN_LONG) { ui_mode_numeric(data); ui_process_numeric(); } else { @@ -685,16 +663,13 @@ static void menu_stimulus_cb(int item, uint8_t data) { (void)data; - int status; switch (item) { case 0: /* START */ case 1: /* STOP */ case 2: /* CENTER */ case 3: /* SPAN */ case 4: /* CW */ - uistat.lever_mode = item == 3 ? LM_SPAN : LM_CENTER; - status = btn_wait_release(); - if (status & EVT_BUTTON_DOWN_LONG) { + if (btn_wait_release() & EVT_BUTTON_DOWN_LONG) { ui_mode_numeric(item); ui_process_numeric(); } else { @@ -711,11 +686,10 @@ menu_stimulus_cb(int item, uint8_t data) } } - static uint32_t get_marker_frequency(int marker) { - if (marker < 0 || marker >= 4) + if (marker < 0 || marker >= MARKERS_MAX) return 0; if (!markers[marker].enabled) return 0; @@ -775,7 +749,7 @@ static void menu_marker_search_cb(int item, uint8_t data) { (void)data; - int i; + int i = -1; if (active_marker == -1) return; @@ -784,26 +758,22 @@ menu_marker_search_cb(int item, uint8_t data) case 1: /* minimum */ set_marker_search(item); i = marker_search(); - if (i != -1) - markers[active_marker].index = i; break; case 2: /* search Left */ i = marker_search_left(markers[active_marker].index); - if (i != -1) - markers[active_marker].index = i; break; case 3: /* search right */ i = marker_search_right(markers[active_marker].index); - if (i != -1) - markers[active_marker].index = i; break; case 4: /* tracking */ - marker_tracking = !marker_tracking; + uistat.marker_tracking = !uistat.marker_tracking; break; } + if (i != -1) + markers[active_marker].index = i; draw_menu(); - redraw_marker(active_marker, TRUE); - uistat.lever_mode = LM_SEARCH; + redraw_marker(active_marker); + select_lever_mode(LM_SEARCH); } static void @@ -811,11 +781,11 @@ menu_marker_smith_cb(int item, uint8_t data) { (void)item; marker_smith_format = data; - redraw_marker(active_marker, TRUE); + redraw_marker(active_marker); draw_menu(); } -void +static void active_marker_select(int item) { if (item == -1) { @@ -835,7 +805,8 @@ static void menu_marker_sel_cb(int item, uint8_t data) { (void)data; - if (item >= 0 && item < 4) { + int t; + if (item >= 0 && item < MARKERS_MAX) { if (markers[item].enabled) { if (item == active_marker) { // disable if active trace is selected @@ -849,21 +820,18 @@ menu_marker_sel_cb(int item, uint8_t data) active_marker_select(item); } } else if (item == 4) { /* all off */ - markers[0].enabled = FALSE; - markers[1].enabled = FALSE; - markers[2].enabled = FALSE; - markers[3].enabled = FALSE; + for (t = 0; t < MARKERS_MAX; t++) + markers[t].enabled = FALSE; previous_marker = -1; active_marker = -1; } else if (item == 5) { /* marker delta */ uistat.marker_delta = !uistat.marker_delta; } - redraw_marker(active_marker, TRUE); + redraw_marker(active_marker); draw_menu(); - uistat.lever_mode = LM_MARKER; } -const menuitem_t menu_calop[] = { +static const menuitem_t menu_calop[] = { { MT_CALLBACK, CAL_OPEN, "OPEN", menu_calop_cb }, { MT_CALLBACK, CAL_SHORT, "SHORT", menu_calop_cb }, { MT_CALLBACK, CAL_LOAD, "LOAD", menu_calop_cb }, @@ -1069,8 +1037,7 @@ const menuitem_t menu_top[] = { }; #define MENU_STACK_DEPTH_MAX 4 -uint8_t menu_current_level = 0; -const menuitem_t *menu_stack[4] = { +const menuitem_t *menu_stack[MENU_STACK_DEPTH_MAX] = { menu_top, NULL, NULL, NULL }; @@ -1085,7 +1052,8 @@ ensure_selection(void) selection = i-1; } -static void menu_move_back(void) +static void +menu_move_back(void) { if (menu_current_level == 0) return; @@ -1095,7 +1063,8 @@ static void menu_move_back(void) draw_menu(); } -static void menu_push_submenu(const menuitem_t *submenu) +static void +menu_push_submenu(const menuitem_t *submenu) { if (menu_current_level < MENU_STACK_DEPTH_MAX-1) menu_current_level++; @@ -1106,7 +1075,8 @@ static void menu_push_submenu(const menuitem_t *submenu) } /* -static void menu_move_top(void) +static void +menu_move_top(void) { if (menu_current_level == 0) return; @@ -1117,7 +1087,8 @@ static void menu_move_top(void) } */ -void menu_invoke(int item) +static void +menu_invoke(int item) { const menuitem_t *menu = menu_stack[menu_current_level]; menu = &menu[item]; @@ -1147,91 +1118,106 @@ void menu_invoke(int item) } } -#define KP_X(x) (48*(x) + 2 + (320-64-192)) -#define KP_Y(y) (48*(y) + 2) - -#define KP_PERIOD 10 -#define KP_MINUS 11 -#define KP_X1 12 -#define KP_K 13 -#define KP_M 14 -#define KP_G 15 -#define KP_BS 16 -#define KP_INF 17 -#define KP_DB 18 +#define MENU_BUTTON_WIDTH 60 +#define MENU_BUTTON_HEIGHT 30 +#define NUM_INPUT_HEIGHT 30 + +#define KP_WIDTH 48 +#define KP_HEIGHT 48 +// Key x, y position (0 - 15) on screen +#define KP_GET_X(posx) ((posx)*KP_WIDTH + (320-64-KP_WIDTH*4)) +#define KP_GET_Y(posy) ((posy)*KP_HEIGHT + 12 ) + +// Key names +#define KP_0 0 +#define KP_1 1 +#define KP_2 2 +#define KP_3 3 +#define KP_4 4 +#define KP_5 5 +#define KP_6 6 +#define KP_7 7 +#define KP_8 8 +#define KP_9 9 +#define KP_PERIOD 10 +#define KP_MINUS 11 +#define KP_X1 12 +#define KP_K 13 +#define KP_M 14 +#define KP_G 15 +#define KP_BS 16 +#define KP_INF 17 +#define KP_DB 18 #define KP_PLUSMINUS 19 -#define KP_KEYPAD 20 -#define KP_N 21 -#define KP_P 22 +#define KP_KEYPAD 20 +#define KP_N 21 +#define KP_P 22 -// Set struct data align as BYTE for save flash memory -#pragma pack(push, 1) typedef struct { - uint16_t x, y; - int8_t c; + uint8_t x:4; + uint8_t y:4; + int8_t c; } keypads_t; -#pragma pack(pop) -const keypads_t *keypads; -uint8_t keypads_last_index; - -const keypads_t keypads_freq[] = { - { KP_X(1), KP_Y(3), KP_PERIOD }, - { KP_X(0), KP_Y(3), 0 }, - { KP_X(0), KP_Y(2), 1 }, - { KP_X(1), KP_Y(2), 2 }, - { KP_X(2), KP_Y(2), 3 }, - { KP_X(0), KP_Y(1), 4 }, - { KP_X(1), KP_Y(1), 5 }, - { KP_X(2), KP_Y(1), 6 }, - { KP_X(0), KP_Y(0), 7 }, - { KP_X(1), KP_Y(0), 8 }, - { KP_X(2), KP_Y(0), 9 }, - { KP_X(3), KP_Y(0), KP_G }, - { KP_X(3), KP_Y(1), KP_M }, - { KP_X(3), KP_Y(2), KP_K }, - { KP_X(3), KP_Y(3), KP_X1 }, - { KP_X(2), KP_Y(3), KP_BS }, +static const keypads_t *keypads; + +static const keypads_t keypads_freq[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, KP_0 }, + { 0, 2, KP_1 }, + { 1, 2, KP_2 }, + { 2, 2, KP_3 }, + { 0, 1, KP_4 }, + { 1, 1, KP_5 }, + { 2, 1, KP_6 }, + { 0, 0, KP_7 }, + { 1, 0, KP_8 }, + { 2, 0, KP_9 }, + { 3, 0, KP_G }, + { 3, 1, KP_M }, + { 3, 2, KP_K }, + { 3, 3, KP_X1 }, + { 2, 3, KP_BS }, { 0, 0, -1 } }; -const keypads_t keypads_scale[] = { - { KP_X(1), KP_Y(3), KP_PERIOD }, - { KP_X(0), KP_Y(3), 0 }, - { KP_X(0), KP_Y(2), 1 }, - { KP_X(1), KP_Y(2), 2 }, - { KP_X(2), KP_Y(2), 3 }, - { KP_X(0), KP_Y(1), 4 }, - { KP_X(1), KP_Y(1), 5 }, - { KP_X(2), KP_Y(1), 6 }, - { KP_X(0), KP_Y(0), 7 }, - { KP_X(1), KP_Y(0), 8 }, - { KP_X(2), KP_Y(0), 9 }, - { KP_X(3), KP_Y(3), KP_X1 }, - { KP_X(2), KP_Y(3), KP_BS }, +static const keypads_t keypads_scale[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, KP_0 }, + { 0, 2, KP_1 }, + { 1, 2, KP_2 }, + { 2, 2, KP_3 }, + { 0, 1, KP_4 }, + { 1, 1, KP_5 }, + { 2, 1, KP_6 }, + { 0, 0, KP_7 }, + { 1, 0, KP_8 }, + { 2, 0, KP_9 }, + { 3, 3, KP_X1 }, + { 2, 3, KP_BS }, { 0, 0, -1 } }; -const keypads_t keypads_time[] = { - { KP_X(1), KP_Y(3), KP_PERIOD }, - { KP_X(0), KP_Y(3), 0 }, - { KP_X(0), KP_Y(2), 1 }, - { KP_X(1), KP_Y(2), 2 }, - { KP_X(2), KP_Y(2), 3 }, - { KP_X(0), KP_Y(1), 4 }, - { KP_X(1), KP_Y(1), 5 }, - { KP_X(2), KP_Y(1), 6 }, - { KP_X(0), KP_Y(0), 7 }, - { KP_X(1), KP_Y(0), 8 }, - { KP_X(2), KP_Y(0), 9 }, - { KP_X(3), KP_Y(1), KP_N }, - { KP_X(3), KP_Y(2), KP_P }, - { KP_X(3), KP_Y(3), KP_MINUS }, - { KP_X(2), KP_Y(3), KP_BS }, +static const keypads_t keypads_time[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, KP_0 }, + { 0, 2, KP_1 }, + { 1, 2, KP_2 }, + { 2, 2, KP_3 }, + { 0, 1, KP_4 }, + { 1, 1, KP_5 }, + { 2, 1, KP_6 }, + { 0, 0, KP_7 }, + { 1, 0, KP_8 }, + { 2, 0, KP_9 }, + { 3, 1, KP_N }, + { 3, 2, KP_P }, + { 3, 3, KP_MINUS }, + { 2, 3, KP_BS }, { 0, 0, -1 } }; -const keypads_t * const keypads_mode_tbl[] = { +static const keypads_t * const keypads_mode_tbl[] = { keypads_freq, // start keypads_freq, // stop keypads_freq, // center @@ -1244,77 +1230,78 @@ const keypads_t * const keypads_mode_tbl[] = { keypads_time // scale of delay }; -const char * const keypad_mode_label[] = { +static const char * const keypad_mode_label[] = { "START", "STOP", "CENTER", "SPAN", "CW FREQ", "SCALE", "REFPOS", "EDELAY", "VELOCITY%", "DELAY" }; -void +static void draw_keypad(void) { int i = 0; - while (keypads[i].x) { + while (keypads[i].c >= 0) { uint16_t bg = config.menu_normal_color; if (i == selection) bg = config.menu_active_color; - setForegroundColor(DEFAULT_MENU_TEXT_COLOR); - setBackgroundColor(bg); - ili9341_fill(keypads[i].x, keypads[i].y, 44, 44, bg); - ili9341_drawfont(keypads[i].c, keypads[i].x+14, keypads[i].y+10); + ili9341_set_foreground(DEFAULT_MENU_TEXT_COLOR); + ili9341_set_background(bg); + int x = KP_GET_X(keypads[i].x); + int y = KP_GET_Y(keypads[i].y); + ili9341_fill(x+2, y+2, KP_WIDTH-4, KP_HEIGHT-4, bg); + ili9341_drawfont(keypads[i].c, + x + (KP_WIDTH - NUM_FONT_GET_WIDTH) / 2, + y + (KP_HEIGHT - NUM_FONT_GET_HEIGHT) / 2); i++; } } -void +static void draw_numeric_area_frame(void) { - ili9341_fill(0, 208, 320, 32, DEFAULT_MENU_COLOR); - setForegroundColor(DEFAULT_MENU_TEXT_COLOR); - setBackgroundColor(DEFAULT_MENU_COLOR); - ili9341_drawstring(keypad_mode_label[keypad_mode], 10, 220); + ili9341_fill(0, 240-NUM_INPUT_HEIGHT, 320, NUM_INPUT_HEIGHT, config.menu_normal_color); + ili9341_set_foreground(DEFAULT_MENU_TEXT_COLOR); + ili9341_set_background(config.menu_normal_color); + ili9341_drawstring(keypad_mode_label[keypad_mode], 10, 240-(FONT_GET_HEIGHT+NUM_INPUT_HEIGHT)/2); //ili9341_drawfont(KP_KEYPAD, 300, 216); } -void +static void draw_numeric_input(const char *buf) { - int i = 0; - int x = 64; + int i; + int x; int focused = FALSE; uint16_t xsim = 0b0010010000000000; - for (i = 0; i < 10 && buf[i]; i++, xsim<<=1) { + for (i = 0, x = 64; i < 10 && buf[i]; i++, xsim<<=1) { uint16_t fg = DEFAULT_MENU_TEXT_COLOR; - uint16_t bg = DEFAULT_MENU_COLOR; + uint16_t bg = config.menu_normal_color; int c = buf[i]; if (c == '.') c = KP_PERIOD; else if (c == '-') c = KP_MINUS; - else if (c >= '0' && c <= '9') + else// if (c >= '0' && c <= '9') c = c - '0'; - else - c = -1; - if (uistat.digit == 8-i) { + if (ui_mode == UI_NUMERIC && uistat.digit == 8-i) { fg = DEFAULT_SPEC_INPUT_COLOR; focused = TRUE; - if (uistat.digit_mode) - bg = DEFAULT_MENU_COLOR; +// if (uistat.digit_mode) +// bg = DEFAULT_MENU_COLOR; } - setForegroundColor(fg); - setBackgroundColor(bg); - if (c >= 0) - ili9341_drawfont(c, x, 208+4); - else if (focused) - ili9341_drawfont(0, x, 208+4); - else - ili9341_fill(x, 208+4, 20, 24, bg); - - x += xsim&0x8000 ? 18+8 : 18; - } - if (i < 10) { - ili9341_fill(x, 208+4, 20*(10-i), 24, DEFAULT_MENU_COLOR); + ili9341_set_foreground(fg); + ili9341_set_background(bg); + if (c >= 0) // c is number + ili9341_drawfont(c, x, 240-NUM_INPUT_HEIGHT+4); + else if (focused) // c not number, but focused + ili9341_drawfont(0, x, 240-NUM_INPUT_HEIGHT+4); + else // erase + ili9341_fill(x, 240-NUM_INPUT_HEIGHT+4, NUM_FONT_GET_HEIGHT, NUM_FONT_GET_WIDTH+2+8, bg); + + x += xsim&0x8000 ? NUM_FONT_GET_WIDTH+2+8 : NUM_FONT_GET_WIDTH+2; } + // erase last + ili9341_fill(x, 240-NUM_INPUT_HEIGHT+4, NUM_FONT_GET_WIDTH+2+8, NUM_FONT_GET_WIDTH+2+8, config.menu_normal_color); } static int @@ -1332,7 +1319,7 @@ static void menu_item_modify_attribute(const menuitem_t *menu, int item, uint16_t *fg, uint16_t *bg) { - if (menu == menu_trace && item < 4) { + if (menu == menu_trace && item < TRACES_MAX) { if (trace[item].enabled) *bg = config.trace_color[item]; } else if (menu == menu_marker_sel) { @@ -1348,7 +1335,7 @@ menu_item_modify_attribute(const menuitem_t *menu, int item, } } } else if (menu == menu_marker_search) { - if (item == 4 && marker_tracking) { + if (item == 4 && uistat.marker_tracking) { *bg = DEFAULT_MENU_TEXT_COLOR; *fg = config.menu_normal_color; } @@ -1369,7 +1356,7 @@ menu_item_modify_attribute(const menuitem_t *menu, int item, *fg = config.menu_normal_color; } } else if (menu == menu_stimulus) { - if (item == 5 /* PAUSE */ && !sweep_enabled) { + if (item == 5 /* PAUSE */ && !(sweep_mode&SWEEP_ENABLE)) { *bg = DEFAULT_MENU_TEXT_COLOR; *fg = config.menu_normal_color; } @@ -1398,7 +1385,7 @@ menu_item_modify_attribute(const menuitem_t *menu, int item, } } -void +static void draw_menu_buttons(const menuitem_t *menu) { int i = 0; @@ -1406,31 +1393,31 @@ draw_menu_buttons(const menuitem_t *menu) const char *l1, *l2; if (menu[i].type == MT_NONE) break; - if (menu[i].type == MT_BLANK) + if (menu[i].type == MT_BLANK) continue; - int y = 32*i; + int y = MENU_BUTTON_HEIGHT*i; uint16_t bg = config.menu_normal_color; uint16_t fg = DEFAULT_MENU_TEXT_COLOR; // focus only in MENU mode but not in KEYPAD mode if (ui_mode == UI_MENU && i == selection) bg = config.menu_active_color; - ili9341_fill(320-60, y, 60, 30, bg); + ili9341_fill(320-MENU_BUTTON_WIDTH, y, MENU_BUTTON_WIDTH, MENU_BUTTON_HEIGHT-2, bg); menu_item_modify_attribute(menu, i, &fg, &bg); - setForegroundColor(fg); - setBackgroundColor(bg); + ili9341_set_foreground(fg); + ili9341_set_background(bg); if (menu_is_multiline(menu[i].label, &l1, &l2)) { - ili9341_fill(320-57, y+6, 54, 19, bg); - ili9341_drawstring(l1, 320-55, y+8); - ili9341_drawstring(l2, 320-55, y+16); + ili9341_fill(320-MENU_BUTTON_WIDTH+3, y+5, MENU_BUTTON_WIDTH-6, 2+FONT_GET_HEIGHT+1+FONT_GET_HEIGHT+2, bg); + ili9341_drawstring(l1, 320-MENU_BUTTON_WIDTH+5, y+7); + ili9341_drawstring(l2, 320-MENU_BUTTON_WIDTH+5, y+7+FONT_GET_HEIGHT+1); } else { - ili9341_fill(320-57, y+10, 54, 11, bg); - ili9341_drawstring(menu[i].label, 320-55, y+12); + ili9341_fill(320-MENU_BUTTON_WIDTH+3, y+8, MENU_BUTTON_WIDTH-6, 2+FONT_GET_HEIGHT+2, bg); + ili9341_drawstring(menu[i].label, 320-MENU_BUTTON_WIDTH+5, y+10); } } } -void +static void menu_select_touch(int i) { selection = i; @@ -1440,7 +1427,7 @@ menu_select_touch(int i) menu_invoke(i); } -void +static void menu_apply_touch(void) { int touch_x, touch_y; @@ -1451,11 +1438,10 @@ menu_apply_touch(void) for (i = 0; i < 7; i++) { if (menu[i].type == MT_NONE) break; - if (menu[i].type == MT_BLANK) + if (menu[i].type == MT_BLANK) continue; - int y = 32*i; - if (y-2 < touch_y && touch_y < y+30+2 - && 320-60 < touch_x) { + int y = MENU_BUTTON_HEIGHT*i; + if (y < touch_y && touch_y < y+MENU_BUTTON_HEIGHT && 320-MENU_BUTTON_WIDTH < touch_x) { menu_select_touch(i); return; } @@ -1465,25 +1451,25 @@ menu_apply_touch(void) ui_mode_normal(); } -void +static void draw_menu(void) { draw_menu_buttons(menu_stack[menu_current_level]); } -void +static void erase_menu_buttons(void) { - ili9341_fill(320-60, 0, 60, 32*7, DEFAULT_BG_COLOR); + ili9341_fill(320-MENU_BUTTON_WIDTH, 0, MENU_BUTTON_WIDTH, MENU_BUTTON_HEIGHT*7, DEFAULT_BG_COLOR); } -void +static void erase_numeric_input(void) { - ili9341_fill(0, 240-32, 320, 32, DEFAULT_BG_COLOR); + ili9341_fill(0, 240-NUM_INPUT_HEIGHT, 320, NUM_INPUT_HEIGHT, DEFAULT_BG_COLOR); } -void +static void leave_ui_mode() { if (ui_mode == UI_MENU) { @@ -1496,7 +1482,7 @@ leave_ui_mode() } } -void +static void fetch_numeric_target(void) { switch (keypad_mode) { @@ -1531,7 +1517,7 @@ fetch_numeric_target(void) uistat.value = get_trace_scale(uistat.current_trace) * 1e12; break; } - + { uint32_t x = uistat.value; int n = 0; @@ -1539,10 +1525,11 @@ fetch_numeric_target(void) x /= 10; uistat.digit = n; } - uistat.previous_value = uistat.value; +// uistat.previous_value = uistat.value; } -void set_numeric_value(void) +static void +set_numeric_value(void) { switch (keypad_mode) { case KM_START: @@ -1575,51 +1562,51 @@ void set_numeric_value(void) } } -void +static void draw_numeric_area(void) { char buf[10]; - chsnprintf(buf, sizeof buf, "%9d", uistat.value); + plot_printf(buf, sizeof buf, "%9d", uistat.value); draw_numeric_input(buf); } -void +static void ui_mode_menu(void) { - if (ui_mode == UI_MENU) + if (ui_mode == UI_MENU) return; ui_mode = UI_MENU; /* narrowen plotting area */ - area_width = AREA_WIDTH_NORMAL - (64-8); - area_height = HEIGHT+1; + area_width = AREA_WIDTH_NORMAL - MENU_BUTTON_WIDTH; + area_height = AREA_HEIGHT_NORMAL; ensure_selection(); draw_menu(); } -void +static void ui_mode_numeric(int _keypad_mode) { - if (ui_mode == UI_NUMERIC) + if (ui_mode == UI_NUMERIC) return; leave_ui_mode(); - + // keypads array keypad_mode = _keypad_mode; ui_mode = UI_NUMERIC; area_width = AREA_WIDTH_NORMAL; - area_height = 240-32;//HEIGHT - 32; + area_height = 240-NUM_INPUT_HEIGHT;//AREA_HEIGHT_NORMAL - 32; draw_numeric_area_frame(); fetch_numeric_target(); draw_numeric_area(); } -void +static void ui_mode_keypad(int _keypad_mode) { - if (ui_mode == UI_KEYPAD) + if (ui_mode == UI_KEYPAD) return; // keypads array @@ -1631,7 +1618,7 @@ ui_mode_keypad(int _keypad_mode) keypads_last_index = i; ui_mode = UI_KEYPAD; - area_width = AREA_WIDTH_NORMAL - (64-8); + area_width = AREA_WIDTH_NORMAL - MENU_BUTTON_WIDTH; area_height = HEIGHT - 32; draw_menu(); draw_keypad(); @@ -1639,14 +1626,14 @@ ui_mode_keypad(int _keypad_mode) draw_numeric_input(""); } -void +static void ui_mode_normal(void) { - if (ui_mode == UI_NORMAL) + if (ui_mode == UI_NORMAL) return; - area_width = AREA_WIDTH_NORMAL; - area_height = HEIGHT+1; + area_width = AREA_WIDTH_NORMAL; + area_height = AREA_HEIGHT_NORMAL; leave_ui_mode(); ui_mode = UI_NORMAL; } @@ -1659,34 +1646,32 @@ lever_move_marker(int status) if ((status & EVT_DOWN) && markers[active_marker].index > 0) { markers[active_marker].index--; markers[active_marker].frequency = frequencies[markers[active_marker].index]; - redraw_marker(active_marker, FALSE); + redraw_marker(active_marker); } - if ((status & EVT_UP) && markers[active_marker].index < 100) { + if ((status & EVT_UP) && markers[active_marker].index < sweep_points-1) { markers[active_marker].index++; markers[active_marker].frequency = frequencies[markers[active_marker].index]; - redraw_marker(active_marker, FALSE); + redraw_marker(active_marker); } } status = btn_wait_release(); } while (status != 0); if (active_marker >= 0) - redraw_marker(active_marker, TRUE); + redraw_marker(active_marker); } static void lever_search_marker(int status) { + int i = -1; if (active_marker >= 0) { - if (status & EVT_DOWN) { - int i = marker_search_left(markers[active_marker].index); - if (i != -1) - markers[active_marker].index = i; - } else if (status & EVT_UP) { - int i = marker_search_right(markers[active_marker].index); - if (i != -1) - markers[active_marker].index = i; - } - redraw_marker(active_marker, TRUE); + if (status & EVT_DOWN) + i = marker_search_left(markers[active_marker].index); + else if (status & EVT_UP) + i = marker_search_right(markers[active_marker].index); + if (i != -1) + markers[active_marker].index = i; + redraw_marker(active_marker); } } @@ -1698,15 +1683,15 @@ step_round(uint32_t v) { // decade step uint32_t x = 1; - for (x = 1; x*10 < v; x *= 10) + for (x = 1; x*10 < v; x*= 10) ; - + // 1-2-5 step if (x * 2 > v) return x; else if (x * 5 > v) return x * 2; - else + else return x * 5; } @@ -1724,18 +1709,35 @@ lever_zoom_span(int status) } static void -lever_move_center(int status) +lever_move(int status, int mode) { - uint32_t center = get_sweep_frequency(ST_CENTER); + uint32_t center = get_sweep_frequency(mode); uint32_t span = get_sweep_frequency(ST_SPAN); span = step_round(span / 3); if (status & EVT_UP) { - set_sweep_frequency(ST_CENTER, center + span); + set_sweep_frequency(mode, center + span); } else if (status & EVT_DOWN) { - set_sweep_frequency(ST_CENTER, center - span); + set_sweep_frequency(mode, center - span); } } +#define STEPRATIO 0.2 + +static void +lever_edelay(int status) +{ + float value = get_electrical_delay(); + float ratio = STEPRATIO; + if (value < 0) + ratio = -ratio; + if (status & EVT_UP) { + value = (1 - ratio) * value; + } else if (status & EVT_DOWN) { + value = (1 + ratio) * value; + } + set_electrical_delay(value); +} + static void ui_process_normal(void) { @@ -1744,11 +1746,21 @@ ui_process_normal(void) if (status & EVT_BUTTON_SINGLE_CLICK) { ui_mode_menu(); } else { - switch (uistat.lever_mode) { + switch (uistat.lever_mode) { case LM_MARKER: lever_move_marker(status); break; case LM_SEARCH: lever_search_marker(status); break; - case LM_CENTER: lever_move_center(status); break; - case LM_SPAN: lever_zoom_span(status); break; + case LM_CENTER: + lever_move(status, FREQ_IS_STARTSTOP() ? ST_START : ST_CENTER); + break; + case LM_SPAN: + if (FREQ_IS_STARTSTOP()) + lever_move(status, ST_STOP); + else + lever_zoom_span(status); + break; + case LM_EDELAY: + lever_edelay(status); + break; } } } @@ -1768,14 +1780,13 @@ ui_process_menu(void) if (menu_stack[menu_current_level][selection+1].type == MT_NONE) goto menuclose; selection++; - draw_menu(); } if (status & EVT_DOWN) { if (selection == 0) goto menuclose; selection--; - draw_menu(); } + draw_menu(); status = btn_wait_release(); } while (status != 0); } @@ -1787,11 +1798,11 @@ menuclose: } static int -keypad_click(int key) +keypad_click(int key) { int c = keypads[key].c; if ((c >= KP_X1 && c <= KP_G) || c == KP_N || c == KP_P) { - float scale = 1; + int32_t scale = 1; if (c >= KP_X1 && c <= KP_G) { int n = c - KP_X1; while (n-- > 0) @@ -1800,7 +1811,7 @@ keypad_click(int key) scale *= 1000; } /* numeric input done */ - float value = my_atof(kp_buf) * scale; + double value = my_atof(kp_buf) * scale; switch (keypad_mode) { case KM_START: set_sweep_frequency(ST_START, value); @@ -1835,9 +1846,9 @@ keypad_click(int key) } return KP_DONE; - } else if (c <= 9 && kp_index < NUMINPUT_LEN) + } else if (c <= 9 && kp_index < NUMINPUT_LEN) { kp_buf[kp_index++] = '0' + c; - else if (c == KP_PERIOD && kp_index < NUMINPUT_LEN) { + } else if (c == KP_PERIOD && kp_index < NUMINPUT_LEN) { // check period in former input int j; for (j = 0; j < kp_index && kp_buf[j] != '.'; j++) @@ -1867,9 +1878,10 @@ keypad_apply_touch(void) touch_position(&touch_x, &touch_y); - while (keypads[i].x) { - if (keypads[i].x-2 < touch_x && touch_x < keypads[i].x+44+2 - && keypads[i].y-2 < touch_y && touch_y < keypads[i].y+44+2) { + while (keypads[i].c >= 0) { + int x = KP_GET_X(keypads[i].x); + int y = KP_GET_Y(keypads[i].y); + if (x < touch_x && touch_x < x+KP_WIDTH && y < touch_y && touch_y < y+KP_HEIGHT) { // draw focus selection = i; draw_keypad(); @@ -1917,11 +1929,11 @@ numeric_apply_touch(void) uistat.value += step; } draw_numeric_area(); - + touch_wait_release(); uistat.digit_mode = FALSE; draw_numeric_area(); - + return; } @@ -1951,35 +1963,28 @@ ui_process_numeric(void) do { if (uistat.digit_mode) { if (status & EVT_DOWN) { - if (uistat.digit < 8) { + if (uistat.digit < 8) uistat.digit++; - draw_numeric_area(); - } else { + else goto exit; - } } if (status & EVT_UP) { - if (uistat.digit > 0) { + if (uistat.digit > 0) uistat.digit--; - draw_numeric_area(); - } else { + else goto exit; - } } } else { int32_t step = 1; int n; for (n = uistat.digit; n > 0; n--) step *= 10; - if (status & EVT_DOWN) { + if (status & EVT_DOWN) uistat.value += step; - draw_numeric_area(); - } - if (status & EVT_UP) { + if (status & EVT_UP) uistat.value -= step; - draw_numeric_area(); - } } + draw_numeric_area(); status = btn_wait_release(); } while (status != 0); } @@ -1992,11 +1997,11 @@ ui_process_numeric(void) ui_mode_normal(); } -void +static void ui_process_keypad(void) { int status; - adc_stop(ADC1); + adc_stop(); kp_index = 0; while (TRUE) { @@ -2004,20 +2009,13 @@ ui_process_keypad(void) if (status & (EVT_UP|EVT_DOWN)) { int s = status; do { - if (s & EVT_UP) { - selection--; - if (selection < 0) + if (s & EVT_UP) + if (--selection < 0) selection = keypads_last_index; - draw_keypad(); - } - if (s & EVT_DOWN) { - selection++; - if (keypads[selection].c < 0) { - // reaches to tail + if (s & EVT_DOWN) + if (++selection > keypads_last_index) selection = 0; - } - draw_keypad(); - } + draw_keypad(); s = btn_wait_release(); } while (s != 0); } @@ -2025,11 +2023,10 @@ ui_process_keypad(void) if (status == EVT_BUTTON_SINGLE_CLICK) { if (keypad_click(selection)) /* exit loop on done or cancel */ - break; + break; } - status = touch_check(); - if (status == EVT_TOUCH_PRESSED) { + if (touch_check() == EVT_TOUCH_PRESSED) { int key = keypad_apply_touch(); if (key >= 0 && keypad_click(key)) /* exit loop on done or cancel */ @@ -2050,24 +2047,22 @@ ui_process_lever(void) switch (ui_mode) { case UI_NORMAL: ui_process_normal(); - break; + break; case UI_MENU: ui_process_menu(); - break; + break; case UI_NUMERIC: ui_process_numeric(); - break; + break; case UI_KEYPAD: ui_process_keypad(); - break; + break; } } - static void drag_marker(int t, int m) { - int status; /* wait touch release */ do { int touch_x, touch_y; @@ -2079,17 +2074,9 @@ drag_marker(int t, int m) if (index >= 0) { markers[m].index = index; markers[m].frequency = frequencies[index]; - redraw_marker(m, TRUE); + redraw_marker(m); } - - status = touch_check(); - } while(status != EVT_TOUCH_RELEASED); -} - -static int -sq_distance(int x0, int y0) -{ - return x0*x0 + y0*y0; + } while (touch_check()!= EVT_TOUCH_RELEASED); } static int @@ -2101,26 +2088,28 @@ touch_pickup_marker(void) touch_x -= OFFSETX; touch_y -= OFFSETY; - for (m = 0; m < 4; m++) { + for (m = 0; m < MARKERS_MAX; m++) { if (!markers[m].enabled) continue; - for (t = 0; t < 4; t++) { + for (t = 0; t < TRACES_MAX; t++) { int x, y; if (!trace[t].enabled) continue; marker_position(m, t, &x, &y); - - if (sq_distance(x - touch_x, y - touch_y) < 400) { + x -= touch_x; + y -= touch_y; + if ((x * x + y * y) < 20 * 20) { if (active_marker != m) { previous_marker = active_marker; active_marker = m; - redraw_marker(active_marker, TRUE); + redraw_marker(active_marker); } // select trace uistat.current_trace = t; - + select_lever_mode(LM_MARKER); + // drag marker until release drag_marker(t, m); return TRUE; @@ -2131,29 +2120,49 @@ touch_pickup_marker(void) return FALSE; } +static int +touch_lever_mode_select(void) +{ + int touch_x, touch_y; + touch_position(&touch_x, &touch_y); + if (touch_y > HEIGHT) { + select_lever_mode(touch_x < FREQUENCIES_XPOS2 ? LM_CENTER : LM_SPAN); + return TRUE; + } + if (touch_y < 25) { + if (touch_x < FREQUENCIES_XPOS2 && get_electrical_delay() != 0.0) { + select_lever_mode(LM_EDELAY); + } else { + select_lever_mode(LM_MARKER); + } + return TRUE; + } + return FALSE; +} static void ui_process_touch(void) { - awd_count++; - adc_stop(ADC1); +// awd_count++; + adc_stop(); int status = touch_check(); if (status == EVT_TOUCH_PRESSED || status == EVT_TOUCH_DOWN) { switch (ui_mode) { case UI_NORMAL: - - if (touch_pickup_marker()) { + // Try drag marker + if (touch_pickup_marker()) + break; + // Try select lever mode (top and bottom screen) + if (touch_lever_mode_select()) { + touch_wait_release(); break; } - + // switch menu mode after release touch_wait_release(); - - // switch menu mode - selection = -1; + selection = -1; // hide keyboard mode selection ui_mode_menu(); break; - case UI_MENU: menu_apply_touch(); break; @@ -2169,22 +2178,19 @@ void ui_process_touch(void) void ui_process(void) { - switch (operation_requested) { - case OP_LEVER: + if (operation_requested&OP_LEVER) ui_process_lever(); - break; - case OP_TOUCH: + if (operation_requested&OP_TOUCH) ui_process_touch(); - break; - } operation_requested = OP_NONE; } /* Triggered when the button is pressed or released. The LED4 is set to ON.*/ -static void extcb1(EXTDriver *extp, expchannel_t channel) { +static void extcb1(EXTDriver *extp, expchannel_t channel) +{ (void)extp; (void)channel; - operation_requested = OP_LEVER; + operation_requested|=OP_LEVER; //cur_button = READ_PORT() & BUTTON_MASK; } @@ -2223,7 +2229,8 @@ static const GPTConfig gpt3cfg = { 0 }; -void +#if 0 +static void test_touch(int *x, int *y) { adc_stop(ADC1); @@ -2233,18 +2240,19 @@ test_touch(int *x, int *y) touch_start_watchdog(); } +#endif void handle_touch_interrupt(void) { - operation_requested = OP_TOUCH; + operation_requested|= OP_TOUCH; } void ui_init() { adc_init(); - + /* * Activates the EXT driver 1. */