diff --git a/.cproject b/.cproject
new file mode 100644
index 0000000..1e880c3
--- /dev/null
+++ b/.cproject
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitignore b/.gitignore
index d2fc5aa..675f5d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,7 @@ python
TAGS
.emacs-dirvars
*png
+*.bak
+version.txt
+dorelease.bat
+ChibiOS
diff --git a/.project b/.project
new file mode 100644
index 0000000..f5b7df6
--- /dev/null
+++ b/.project
@@ -0,0 +1,27 @@
+
+
+ nanoVNA-Erik
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+ org.eclipse.cdt.core.ccnature
+
+
diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
new file mode 100644
index 0000000..47218fa
--- /dev/null
+++ b/.settings/language.settings.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Font7x13b.c b/Font7x13b.c
new file mode 100644
index 0000000..b3656b2
--- /dev/null
+++ b/Font7x13b.c
@@ -0,0 +1,3959 @@
+/* Generated by convbdf on Mon Apr 29 14:40:18 2019. */
+
+/* Font information:
+ name: 7x13B
+ facename: -Misc-Fixed-Bold-R-Normal--13-120-75-75-C-70-ISO8859-2
+ w x h: 7x13
+ size: 127
+ ascent: 11
+ descent: 2
+ first char: 0 (0x00)
+ last char: 126 (0x7e)
+ default char: 0 (0x00)
+ proportional: no
+ Public domain font. Share and enjoy. Copyright (c) 1996 BIZNET Poland, Inc. All Rights Reserved.
+*/
+
+#include
+
+/* Font character bitmap data. */
+const uint16_t x7x13b_bits [] =
+{
+
+ /* Character 0 (0x00):
+ width 7
+ +-------+
+ | |
+ | ***** |
+ | ***** |
+ | ***** |
+ | ***** |
+ | ***** |
+ | ***** |
+ | ***** |
+ | ***** |
+ | ***** |
+ | ***** |
+ | ***** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x7c00,
+ 0x7c00,
+ 0x7c00,
+ 0x7c00,
+ 0x7c00,
+ 0x7c00,
+ 0x7c00,
+ 0x7c00,
+ 0x7c00,
+ 0x7c00,
+ 0x7c00,
+ 0x0000,
+
+ /* Character 1 (0x01):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | ** |
+ | **** |
+ |****** |
+ | **** |
+ | ** |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x7800,
+ 0xfc00,
+ 0x7800,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 2 (0x02):
+ width 7
+ +-------+
+ | |
+ |** ** |
+ | ** |
+ |** ** |
+ | ** |
+ |** ** |
+ | ** |
+ |** ** |
+ | ** |
+ |** ** |
+ | ** |
+ |** ** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0xcc00,
+ 0x3000,
+ 0xcc00,
+ 0x3000,
+ 0xcc00,
+ 0x3000,
+ 0xcc00,
+ 0x3000,
+ 0xcc00,
+ 0x3000,
+ 0xcc00,
+ 0x0000,
+
+ /* Character 3 (0x03):
+ width 7
+ +-------+
+ | |
+ |** ** |
+ |** ** |
+ |***** |
+ |** ** |
+ |** ** |
+ | |
+ | **** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0xd800,
+ 0xd800,
+ 0xf800,
+ 0xd800,
+ 0xd800,
+ 0x0000,
+ 0x3c00,
+ 0x1800,
+ 0x1800,
+ 0x1800,
+ 0x1800,
+ 0x0000,
+
+ /* Character 4 (0x04):
+ width 7
+ +-------+
+ | |
+ |**** |
+ |** |
+ |*** |
+ |** |
+ |** |
+ | |
+ | **** |
+ | ** |
+ | *** |
+ | ** |
+ | ** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0xf000,
+ 0xc000,
+ 0xe000,
+ 0xc000,
+ 0xc000,
+ 0x0000,
+ 0x3c00,
+ 0x3000,
+ 0x3800,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+
+ /* Character 5 (0x05):
+ width 7
+ +-------+
+ | |
+ | *** |
+ |** |
+ |** |
+ |** |
+ | *** |
+ | |
+ | *** |
+ | ** * |
+ | *** |
+ | ** * |
+ | ** * |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x7000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0x7000,
+ 0x0000,
+ 0x3800,
+ 0x3400,
+ 0x3800,
+ 0x3400,
+ 0x3400,
+ 0x0000,
+
+ /* Character 6 (0x06):
+ width 7
+ +-------+
+ | |
+ |** |
+ |** |
+ |** |
+ |** |
+ |**** |
+ | |
+ | **** |
+ | ** |
+ | *** |
+ | ** |
+ | ** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xf000,
+ 0x0000,
+ 0x3c00,
+ 0x3000,
+ 0x3800,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+
+ /* Character 7 (0x07):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 8 (0x08):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | ** |
+ |****** |
+ |****** |
+ | ** |
+ | ** |
+ | |
+ |****** |
+ |****** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x3000,
+ 0xfc00,
+ 0xfc00,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+ 0xfc00,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 9 (0x09):
+ width 7
+ +-------+
+ | |
+ |** ** |
+ |*** ** |
+ |****** |
+ |** *** |
+ |** ** |
+ | |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | **** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0xcc00,
+ 0xec00,
+ 0xfc00,
+ 0xdc00,
+ 0xcc00,
+ 0x0000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3c00,
+ 0x0000,
+
+ /* Character 10 (0x0a):
+ width 7
+ +-------+
+ | |
+ |** ** |
+ |** ** |
+ | * * |
+ | **** |
+ | ** |
+ | |
+ | **** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0x4800,
+ 0x7800,
+ 0x3000,
+ 0x0000,
+ 0x3c00,
+ 0x1800,
+ 0x1800,
+ 0x1800,
+ 0x1800,
+ 0x0000,
+
+ /* Character 11 (0x0b):
+ width 7
+ +-------+
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |**** |
+ |**** |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0xf000,
+ 0xf000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 12 (0x0c):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ |**** |
+ |**** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xf000,
+ 0xf000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+
+ /* Character 13 (0x0d):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | *****|
+ | *****|
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x3e00,
+ 0x3e00,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+
+ /* Character 14 (0x0e):
+ width 7
+ +-------+
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | *****|
+ | *****|
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3e00,
+ 0x3e00,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 15 (0x0f):
+ width 7
+ +-------+
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |*******|
+ |*******|
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ +-------+ */
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0xfe00,
+ 0xfe00,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+
+ /* Character 16 (0x10):
+ width 7
+ +-------+
+ | |
+ | |
+ |*******|
+ |*******|
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xfe00,
+ 0xfe00,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 17 (0x11):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ |*******|
+ |*******|
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xfe00,
+ 0xfe00,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 18 (0x12):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ |*******|
+ |*******|
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xfe00,
+ 0xfe00,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 19 (0x13):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ |*******|
+ |*******|
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xfe00,
+ 0xfe00,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 20 (0x14):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ |*******|
+ |*******|
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xfe00,
+ 0xfe00,
+ 0x0000,
+
+ /* Character 21 (0x15):
+ width 7
+ +-------+
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | *****|
+ | *****|
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ +-------+ */
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3e00,
+ 0x3e00,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+
+ /* Character 22 (0x16):
+ width 7
+ +-------+
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |**** |
+ |**** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ +-------+ */
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0xf000,
+ 0xf000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+
+ /* Character 23 (0x17):
+ width 7
+ +-------+
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |*******|
+ |*******|
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0xfe00,
+ 0xfe00,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 24 (0x18):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ |*******|
+ |*******|
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xfe00,
+ 0xfe00,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+
+ /* Character 25 (0x19):
+ width 7
+ +-------+
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ +-------+ */
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+
+ /* Character 26 (0x1a):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | * |
+ | ** |
+ |****** |
+ |****** |
+ | ** |
+ | * |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+0x0000,
+0x0000,
+0x0000,
+0x2000,
+0x6000,
+0xfc00,
+0xfc00,
+0x6000,
+0x2000,
+0x0000,
+0x0000,
+0x0000,
+0x0000,
+ /* Character 27 (0x1b):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | * |
+ | ** |
+ |****** |
+ |****** |
+ | ** |
+ | * |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+0x0000,
+0x0000,
+0x0000,
+0x1000,
+0x1800,
+0xfc00,
+0xfc00,
+0x1800,
+0x1000,
+0x0000,
+0x0000,
+0x0000,
+0x0000,
+
+
+ /* Character 28 (0x1c):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |****** |
+ | ** ** |
+ | ** ** |
+ | ** ** |
+ |*** ** |
+ |** ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0x6c00,
+ 0x6c00,
+ 0x6c00,
+ 0xec00,
+ 0xcc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 29 (0x1d):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |****** |
+ |** |
+ |** |
+ +-------+ */
+0x0000,
+0x0000,
+0x0000,
+0x0000,
+0x0000,
+0xcc00,
+0xcc00,
+0xcc00,
+0xcc00,
+0xcc00,
+0xfc00,
+0xc000,
+0xc000,
+ /* Character 30 (0x1e):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | * * |
+ | * * |
+ |** ** |
+ | |
+ | |
+ +-------+ */
+0x0000,
+0x0000,
+0x7800,
+0xcc00,
+0xcc00,
+0xcc00,
+0xcc00,
+0xcc00,
+0x4800,
+0x4800,
+0xcc00,
+0x0000,
+0x0000,
+
+ /* Character 31 (0x1f):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+0x0000,
+0x0000,
+0x7800,
+0xcc00,
+0xcc00,
+0x7800,
+0x0000,
+0x0000,
+0x0000,
+0x0000,
+0x0000,
+0x0000,
+0x0000,
+
+ /* Character 32 (0x20):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 33 (0x21):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 34 (0x22):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** ** |
+ | ** ** |
+ | ** ** |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x6c00,
+ 0x6c00,
+ 0x6c00,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 35 (0x23):
+ width 7
+ +-------+
+ | |
+ | |
+ | * * |
+ | * * |
+ | ***** |
+ | ***** |
+ | * * |
+ | ***** |
+ | ***** |
+ | * * |
+ | * * |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x2800,
+ 0x2800,
+ 0x7c00,
+ 0x7c00,
+ 0x2800,
+ 0x7c00,
+ 0x7c00,
+ 0x2800,
+ 0x2800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 36 (0x24):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | **** |
+ |* ** * |
+ |* ** |
+ | **** |
+ | ** * |
+ |* ** * |
+ | **** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x7800,
+ 0xb400,
+ 0xb000,
+ 0x7800,
+ 0x3400,
+ 0xb400,
+ 0x7800,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 37 (0x25):
+ width 7
+ +-------+
+ | |
+ | |
+ |*** * |
+ |* * ** |
+ |*** * |
+ | ** |
+ | ** |
+ | ** |
+ | * *** |
+ |** * * |
+ |* *** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xe400,
+ 0xac00,
+ 0xe800,
+ 0x1800,
+ 0x3000,
+ 0x6000,
+ 0x5c00,
+ 0xd400,
+ 0x9c00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 38 (0x26):
+ width 7
+ +-------+
+ | |
+ | |
+ | *** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | *** |
+ |** * * |
+ |** *** |
+ |** ** |
+ | *** * |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7000,
+ 0xd800,
+ 0xd800,
+ 0xd800,
+ 0x7000,
+ 0xd400,
+ 0xdc00,
+ 0xd800,
+ 0x7400,
+ 0x0000,
+ 0x0000,
+
+ /* Character 39 (0x27):
+ width 7
+ +-------+
+ | |
+ | |
+ | *** |
+ | *** |
+ | ** |
+ | ** |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x3800,
+ 0x3800,
+ 0x3000,
+ 0x6000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 40 (0x28):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x1800,
+ 0x3000,
+ 0x3000,
+ 0x6000,
+ 0x6000,
+ 0x6000,
+ 0x3000,
+ 0x3000,
+ 0x1800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 41 (0x29):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x6000,
+ 0x3000,
+ 0x3000,
+ 0x1800,
+ 0x1800,
+ 0x1800,
+ 0x3000,
+ 0x3000,
+ 0x6000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 42 (0x2a):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | * * |
+ | ** |
+ |****** |
+ |****** |
+ | ** |
+ | * * |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x4800,
+ 0x3000,
+ 0xfc00,
+ 0xfc00,
+ 0x3000,
+ 0x4800,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 43 (0x2b):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | ** |
+ | ** |
+ |****** |
+ |****** |
+ | ** |
+ | ** |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x3000,
+ 0xfc00,
+ 0xfc00,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 44 (0x2c):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | *** |
+ | *** |
+ | ** |
+ | ** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x3800,
+ 0x3800,
+ 0x3000,
+ 0x6000,
+ 0x0000,
+
+ /* Character 45 (0x2d):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ |****** |
+ |****** |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 46 (0x2e):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | ** |
+ | **** |
+ | ** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x7800,
+ 0x3000,
+ 0x0000,
+
+ /* Character 47 (0x2f):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |** |
+ |** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0c00,
+ 0x0c00,
+ 0x1800,
+ 0x1800,
+ 0x3000,
+ 0x6000,
+ 0x6000,
+ 0xc000,
+ 0xc000,
+ 0x0000,
+ 0x0000,
+ /* Character 48 (0x30):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | * * |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | * * |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x4800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x4800,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 49 (0x31):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | *** |
+ |* ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |****** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x7000,
+ 0xb000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 50 (0x32):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** ** |
+ | ** |
+ | *** |
+ | ** |
+ |** |
+ |** |
+ |****** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xcc00,
+ 0x0c00,
+ 0x3800,
+ 0x6000,
+ 0xc000,
+ 0xc000,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 51 (0x33):
+ width 7
+ +-------+
+ | |
+ | |
+ |****** |
+ | ** |
+ | ** |
+ | ** |
+ | **** |
+ | ** |
+ | ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0x0c00,
+ 0x1800,
+ 0x3000,
+ 0x7800,
+ 0x0c00,
+ 0x0c00,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 52 (0x34):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | *** |
+ | **** |
+ | ** ** |
+ |** ** |
+ |** ** |
+ |****** |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0c00,
+ 0x1c00,
+ 0x3c00,
+ 0x6c00,
+ 0xcc00,
+ 0xcc00,
+ 0xfc00,
+ 0x0c00,
+ 0x0c00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 53 (0x35):
+ width 7
+ +-------+
+ | |
+ | |
+ |****** |
+ |** |
+ |** |
+ |***** |
+ |** ** |
+ | ** |
+ | ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0xc000,
+ 0xc000,
+ 0xf800,
+ 0xcc00,
+ 0x0c00,
+ 0x0c00,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 54 (0x36):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** |
+ |** |
+ |***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xc000,
+ 0xc000,
+ 0xf800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 55 (0x37):
+ width 7
+ +-------+
+ | |
+ | |
+ |****** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0x0c00,
+ 0x0c00,
+ 0x1800,
+ 0x1800,
+ 0x3000,
+ 0x3000,
+ 0x6000,
+ 0x6000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 56 (0x38):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | **** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 57 (0x39):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | ***** |
+ | ** |
+ | ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7c00,
+ 0x0c00,
+ 0x0c00,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 58 (0x3a):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | ** |
+ | **** |
+ | ** |
+ | |
+ | |
+ | ** |
+ | **** |
+ | ** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x7800,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x7800,
+ 0x3000,
+ 0x0000,
+
+ /* Character 59 (0x3b):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | ** |
+ | **** |
+ | ** |
+ | |
+ | *** |
+ | *** |
+ | ** |
+ | ** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x7800,
+ 0x3000,
+ 0x0000,
+ 0x3800,
+ 0x3800,
+ 0x3000,
+ 0x6000,
+ 0x0000,
+
+ /* Character 60 (0x3c):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0c00,
+ 0x1800,
+ 0x3000,
+ 0x6000,
+ 0xc000,
+ 0x6000,
+ 0x3000,
+ 0x1800,
+ 0x0c00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 61 (0x3d):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |****** |
+ | |
+ | |
+ |****** |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 62 (0x3e):
+ width 7
+ +-------+
+ | |
+ | |
+ |** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xc000,
+ 0x6000,
+ 0x3000,
+ 0x1800,
+ 0x0c00,
+ 0x1800,
+ 0x3000,
+ 0x6000,
+ 0xc000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 63 (0x3f):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** ** |
+ | ** |
+ | *** |
+ | ** |
+ | |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xcc00,
+ 0x0c00,
+ 0x3800,
+ 0x3000,
+ 0x0000,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 64 (0x40):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |* ** |
+ |* ** |
+ |* **** |
+ |* * ** |
+ |* **** |
+ |* |
+ |* ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0x8c00,
+ 0x8c00,
+ 0xbc00,
+ 0xac00,
+ 0xbc00,
+ 0x8000,
+ 0x8c00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 65 (0x41):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |****** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xfc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 66 (0x42):
+ width 7
+ +-------+
+ | |
+ | |
+ |***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |***** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xf800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xf800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xf800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 67 (0x43):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** |
+ |** |
+ |** |
+ |** |
+ |** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 68 (0x44):
+ width 7
+ +-------+
+ | |
+ | |
+ |***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |***** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xf800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xf800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 69 (0x45):
+ width 7
+ +-------+
+ | |
+ | |
+ |****** |
+ |** |
+ |** |
+ |** |
+ |***** |
+ |** |
+ |** |
+ |** |
+ |****** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xf800,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 70 (0x46):
+ width 7
+ +-------+
+ | |
+ | |
+ |****** |
+ |** |
+ |** |
+ |** |
+ |***** |
+ |** |
+ |** |
+ |** |
+ |** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xf800,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 71 (0x47):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** |
+ |** |
+ |** *** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | ***** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xc000,
+ 0xc000,
+ 0xdc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7c00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 72 (0x48):
+ width 7
+ +-------+
+ | |
+ | |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |****** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xfc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 73 (0x49):
+ width 7
+ +-------+
+ | |
+ | |
+ |****** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |****** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 74 (0x4a):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0c00,
+ 0x0c00,
+ 0x0c00,
+ 0x0c00,
+ 0x0c00,
+ 0x0c00,
+ 0x0c00,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 75 (0x4b):
+ width 7
+ +-------+
+ | |
+ | |
+ |** * |
+ |** ** |
+ |** ** |
+ |**** |
+ |*** |
+ |**** |
+ |** ** |
+ |** ** |
+ |** * |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xc400,
+ 0xcc00,
+ 0xd800,
+ 0xf000,
+ 0xe000,
+ 0xf000,
+ 0xd800,
+ 0xcc00,
+ 0xc400,
+ 0x0000,
+ 0x0000,
+
+ /* Character 76 (0x4c):
+ width 7
+ +-------+
+ | |
+ | |
+ |** |
+ |** |
+ |** |
+ |** |
+ |** |
+ |** |
+ |** |
+ |** |
+ |****** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 77 (0x4d):
+ width 7
+ +-------+
+ | |
+ | |
+ |* * |
+ |** ** |
+ |****** |
+ |****** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x8400,
+ 0xcc00,
+ 0xfc00,
+ 0xfc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 78 (0x4e):
+ width 7
+ +-------+
+ | |
+ | |
+ |** ** |
+ |** ** |
+ |*** ** |
+ |*** ** |
+ |****** |
+ |** *** |
+ |** *** |
+ |** ** |
+ |** ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0xec00,
+ 0xec00,
+ 0xfc00,
+ 0xdc00,
+ 0xdc00,
+ 0xcc00,
+ 0xcc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 79 (0x4f):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 80 (0x50):
+ width 7
+ +-------+
+ | |
+ | |
+ |***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |***** |
+ |** |
+ |** |
+ |** |
+ |** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xf800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xf800,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 81 (0x51):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |*** ** |
+ |** *** |
+ | **** |
+ | ** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xec00,
+ 0xdc00,
+ 0x7800,
+ 0x0c00,
+ 0x0000,
+
+ /* Character 82 (0x52):
+ width 7
+ +-------+
+ | |
+ | |
+ |***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |***** |
+ |**** |
+ |** ** |
+ |** ** |
+ |** * |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xf800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xf800,
+ 0xf000,
+ 0xd800,
+ 0xcc00,
+ 0xc400,
+ 0x0000,
+ 0x0000,
+
+ /* Character 83 (0x53):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** |
+ |** |
+ | **** |
+ | ** |
+ | ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xc000,
+ 0xc000,
+ 0x7800,
+ 0x0c00,
+ 0x0c00,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 84 (0x54):
+ width 7
+ +-------+
+ | |
+ | |
+ |****** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 85 (0x55):
+ width 7
+ +-------+
+ | |
+ | |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 86 (0x56):
+ width 7
+ +-------+
+ | |
+ | |
+ |** ** |
+ |** ** |
+ |** ** |
+ | * * |
+ | * * |
+ | **** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x4800,
+ 0x4800,
+ 0x7800,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 87 (0x57):
+ width 7
+ +-------+
+ | |
+ | |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |****** |
+ |****** |
+ |** ** |
+ |* * |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xfc00,
+ 0xfc00,
+ 0xcc00,
+ 0x8400,
+ 0x0000,
+ 0x0000,
+
+ /* Character 88 (0x58):
+ width 7
+ +-------+
+ | |
+ | |
+ |* * |
+ |** ** |
+ | * * |
+ | **** |
+ | ** |
+ | **** |
+ | * * |
+ |** ** |
+ |* * |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x8400,
+ 0xcc00,
+ 0x4800,
+ 0x7800,
+ 0x3000,
+ 0x7800,
+ 0x4800,
+ 0xcc00,
+ 0x8400,
+ 0x0000,
+ 0x0000,
+
+ /* Character 89 (0x59):
+ width 7
+ +-------+
+ | |
+ | |
+ |** ** |
+ |** ** |
+ | **** |
+ | **** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0x7800,
+ 0x7800,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 90 (0x5a):
+ width 7
+ +-------+
+ | |
+ | |
+ |****** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |** |
+ |** |
+ |****** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0x0c00,
+ 0x0c00,
+ 0x1800,
+ 0x3000,
+ 0x6000,
+ 0xc000,
+ 0xc000,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 91 (0x5b):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0x6000,
+ 0x6000,
+ 0x6000,
+ 0x6000,
+ 0x6000,
+ 0x6000,
+ 0x6000,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 92 (0x5c):
+ width 7
+ +-------+
+ | |
+ | |
+ |** |
+ |** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xc000,
+ 0xc000,
+ 0x6000,
+ 0x6000,
+ 0x3000,
+ 0x1800,
+ 0x1800,
+ 0x0c00,
+ 0x0c00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 93 (0x5d):
+ width 7
+ +-------+
+ | |
+ | |
+ | **** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0x1800,
+ 0x1800,
+ 0x1800,
+ 0x1800,
+ 0x1800,
+ 0x1800,
+ 0x1800,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 94 (0x5e):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | **** |
+ |** ** |
+ |* * |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x7800,
+ 0xcc00,
+ 0x8400,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 95 (0x5f):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ |****** |
+ |****** |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0xfc00,
+ 0x0000,
+
+ /* Character 96 (0x60):
+ width 7
+ +-------+
+ | |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x6000,
+ 0x3000,
+ 0x1800,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 97 (0x61):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | **** |
+ | ** |
+ | ***** |
+ |** ** |
+ |** ** |
+ | ***** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0x0c00,
+ 0x7c00,
+ 0xcc00,
+ 0xcc00,
+ 0x7c00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 98 (0x62):
+ width 7
+ +-------+
+ | |
+ | |
+ |** |
+ |** |
+ |** |
+ |***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |***** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xf800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xf800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 99 (0x63):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** |
+ |** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xc000,
+ 0xc000,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 100 (0x64):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | ** |
+ | ** |
+ | ***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | ***** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0c00,
+ 0x0c00,
+ 0x0c00,
+ 0x7c00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7c00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 101 (0x65):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | **** |
+ |** ** |
+ |****** |
+ |** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xfc00,
+ 0xc000,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 102 (0x66):
+ width 7
+ +-------+
+ | |
+ | |
+ | *** |
+ | ** ** |
+ | ** |
+ | ** |
+ |**** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x3800,
+ 0x6c00,
+ 0x6000,
+ 0x6000,
+ 0xf000,
+ 0x6000,
+ 0x6000,
+ 0x6000,
+ 0x6000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 103 (0x67):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | *** * |
+ |** ** |
+ |** ** |
+ | **** |
+ |** |
+ | **** |
+ |** ** |
+ | **** |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x7400,
+ 0xcc00,
+ 0xcc00,
+ 0x7800,
+ 0xc000,
+ 0x7800,
+ 0xcc00,
+ 0x7800,
+
+ /* Character 104 (0x68):
+ width 7
+ +-------+
+ | |
+ | |
+ |** |
+ |** |
+ |** |
+ |***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xf800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 105 (0x69):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | ** |
+ | |
+ | *** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |****** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+ 0x7000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 106 (0x6a):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | ** |
+ | |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |** ** |
+ | **** |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0c00,
+ 0x0c00,
+ 0x0000,
+ 0x0c00,
+ 0x0c00,
+ 0x0c00,
+ 0x0c00,
+ 0x0c00,
+ 0x0c00,
+ 0xcc00,
+ 0x7800,
+
+ /* Character 107 (0x6b):
+ width 7
+ +-------+
+ | |
+ | |
+ |** |
+ |** |
+ |** |
+ |** ** |
+ |** ** |
+ |**** |
+ |**** |
+ |** ** |
+ |** ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xcc00,
+ 0xd800,
+ 0xf000,
+ 0xf000,
+ 0xd800,
+ 0xcc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 108 (0x6c):
+ width 7
+ +-------+
+ | |
+ | |
+ | *** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ |****** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 109 (0x6d):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |** ** |
+ |****** |
+ |****** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xd800,
+ 0xfc00,
+ 0xfc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 110 (0x6e):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xf800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 111 (0x6f):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | **** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 112 (0x70):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |***** |
+ |** |
+ |** |
+ |** |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xf800,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xf800,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+
+ /* Character 113 (0x71):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | ***** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | ***** |
+ | ** |
+ | ** |
+ | ** |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x7c00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7c00,
+ 0x0c00,
+ 0x0c00,
+ 0x0c00,
+
+ /* Character 114 (0x72):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |***** |
+ |** ** |
+ |** |
+ |** |
+ |** |
+ |** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xf800,
+ 0xcc00,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0xc000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 115 (0x73):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | **** |
+ |** ** |
+ | ** |
+ | ** |
+ |** ** |
+ | **** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x7800,
+ 0xcc00,
+ 0x6000,
+ 0x1800,
+ 0xcc00,
+ 0x7800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 116 (0x74):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | ** |
+ | ** |
+ |***** |
+ | ** |
+ | ** |
+ | ** |
+ | ** ** |
+ | *** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x6000,
+ 0x6000,
+ 0xf800,
+ 0x6000,
+ 0x6000,
+ 0x6000,
+ 0x6c00,
+ 0x3800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 117 (0x75):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | ***** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7c00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 118 (0x76):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |** ** |
+ |** ** |
+ |** ** |
+ | **** |
+ | **** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7800,
+ 0x7800,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 119 (0x77):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |** ** |
+ |** ** |
+ |** ** |
+ |****** |
+ |****** |
+ | * * |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xfc00,
+ 0xfc00,
+ 0x4800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 120 (0x78):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |** ** |
+ |** ** |
+ | **** |
+ | **** |
+ |** ** |
+ |** ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0x7800,
+ 0x7800,
+ 0xcc00,
+ 0xcc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 121 (0x79):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |** ** |
+ |** ** |
+ |** ** |
+ |** ** |
+ | ***** |
+ | ** |
+ |** ** |
+ | **** |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0xcc00,
+ 0x7c00,
+ 0x0c00,
+ 0xcc00,
+ 0x7800,
+
+ /* Character 122 (0x7a):
+ width 7
+ +-------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ |****** |
+ | ** |
+ | ** |
+ | ** |
+ |** |
+ |****** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0xfc00,
+ 0x0c00,
+ 0x1800,
+ 0x6000,
+ 0xc000,
+ 0xfc00,
+ 0x0000,
+ 0x0000,
+
+ /* Character 123 (0x7b):
+ width 7
+ +-------+
+ | |
+ | |
+ | *** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | *** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x3800,
+ 0x6000,
+ 0x6000,
+ 0x3000,
+ 0x6000,
+ 0x3000,
+ 0x6000,
+ 0x6000,
+ 0x3800,
+ 0x0000,
+ 0x0000,
+
+ /* Character 124 (0x7c):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x3000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 125 (0x7d):
+ width 7
+ +-------+
+ | |
+ | |
+ | *** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | ** |
+ | *** |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x7000,
+ 0x1800,
+ 0x1800,
+ 0x3000,
+ 0x1800,
+ 0x3000,
+ 0x1800,
+ 0x1800,
+ 0x7000,
+ 0x0000,
+ 0x0000,
+
+ /* Character 126 (0x7e):
+ width 7
+ +-------+
+ | |
+ | |
+ | ** * |
+ |****** |
+ |* ** |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-------+ */
+ 0x0000,
+ 0x0000,
+ 0x6400,
+ 0xfc00,
+ 0x9800,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+};
+
+
diff --git a/Makefile b/Makefile
index bec51b8..aec3636 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,8 @@
# Compiler options here.
ifeq ($(USE_OPT),)
- USE_OPT = -O2 -fno-inline-small-functions -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nano.specs -fstack-usage
+ USE_OPT = -Og -fno-inline-small-functions -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nano.specs -fstack-usage
+# USE_OPT = -O2 -fno-inline-small-functions -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nano.specs -fstack-usage
endif
# C specific options here (added to USE_OPT).
@@ -54,7 +55,7 @@ endif
##############################################################################
ifeq ($(VERSION),)
- VERSION="$(shell git describe --tags)"
+ VERSION="tinySA_$(shell git describe --tags)"
endif
##############################################################################
@@ -64,7 +65,7 @@ endif
# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
- USE_PROCESS_STACKSIZE = 0x200
+ USE_PROCESS_STACKSIZE = 0x240
endif
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
@@ -82,7 +83,7 @@ endif
#
# Define project name here
-PROJECT = ch
+PROJECT = tinySA
# Imported source files and paths
#CHIBIOS = ../ChibiOS-RT
@@ -119,7 +120,7 @@ CSRC = $(STARTUPSRC) \
$(BOARDSRC) \
$(STREAMSSRC) \
usbcfg.c \
- main.c si5351.c tlv320aic3204.c dsp.c plot.c ui.c ili9341.c numfont20x22.c Font5x7.c flash.c adc.c
+ main.c plot.c ui.c ili9341.c numfont20x22.c Font5x7.c flash.c adc.c si4432.c Font7x13b.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
@@ -225,6 +226,7 @@ flash: build/ch.bin
dfu-util -d 0483:df11 -a 0 -s 0x08000000:leave -D build/ch.bin
dfu:
+ c:/work/dfu/HEX2DFU build/ch.hex build/ch.dfu
-@printf "reset dfu\r" >/dev/cu.usbmodem401
diff --git a/NANOVNA_STM32_F072/board.h b/NANOVNA_STM32_F072/board.h
index c64cf75..06944c9 100644
--- a/NANOVNA_STM32_F072/board.h
+++ b/NANOVNA_STM32_F072/board.h
@@ -21,8 +21,8 @@
* Board identifier.
*/
#define BOARD_NANOVNA_STM32_F072
-#define BOARD_NAME "NanoVNA"
-
+#define BOARD_NAME "tinySA v0.2"
+#define BOARD_VERSION 0
/*
* Board frequencies.
*/
@@ -47,14 +47,16 @@
/* on-board */
-#define GPIOA_BUTTON 0
+//#define GPIO_PE_SEL 0
#define GPIOA_LEVER1 1
#define GPIOA_LEVER2 2
#define GPIOA_PUSH 3
-#define GPIOA_DAC2 5
+//#define GPIO_RX_SEL 4
+//#define GPIO_LO_SEL 5
#define GPIOA_XP 6
#define GPIOA_YP 7
#define GPIOA_MCO 8
+#define GPIOA_TX 9
#define GPIOA_USB_DISC 10
#define GPIOA_USB_DM 11
#define GPIOA_USB_DP 12
@@ -71,14 +73,19 @@
#define GPIOB_LCD_CS 6
#define GPIOB_LCD_CD 7
#define GPIOB_I2C1_SCL 8
-#define GPIOB_I2C1_SDA 9
-#define GPIOB_SD_GP2 10
+#define GPIO_RF_PWR 9
+#define GPIO_SPI2_CLK 10
#define GPIOB_SD_CS 11
-#define GPIOB_I2S2_WCLK 12
-#define GPIOB_I2S2_BCLK 13
-#define GPIOB_I2S2_MOSI 15
+#define GPIO_SPI2_SDO 14
+#define GPIO_SPI2_SDI 15
+
+// Port C
+#define GPIO_PE_SEL 13
+#define GPIO_RX_SEL 14
+#define GPIO_LO_SEL 15
-#define GPIOC_LED 13
+
+#define GPIOB_LED 11
#define GPIOF_OSC_IN 0
#define GPIOF_OSC_OUT 1
@@ -115,19 +122,19 @@
* PA13 - SWDIO (alternate 0).
* PA14 - SWCLK (alternate 0).
*/
-#define VAL_GPIOA_MODER (PIN_MODE_INPUT(0U) | \
+#define VAL_GPIOA_MODER (PIN_MODE_INPUT(0U) | \
PIN_MODE_INPUT(1U) | \
PIN_MODE_INPUT(2U) | \
PIN_MODE_INPUT(3U) | \
- PIN_MODE_INPUT(4U) | \
- PIN_MODE_ANALOG(GPIOA_DAC2) | \
+ PIN_MODE_INPUT(4U) | \
+ PIN_MODE_INPUT(5U) | \
PIN_MODE_ANALOG(GPIOA_XP) | \
PIN_MODE_ANALOG(GPIOA_YP) | \
PIN_MODE_ALTERNATE(GPIOA_MCO) | \
PIN_MODE_INPUT(9U) | \
PIN_MODE_OUTPUT(GPIOA_USB_DISC) | \
- PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \
- PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \
+ PIN_MODE_INPUT(GPIOA_USB_DM) | \
+ PIN_MODE_INPUT(GPIOA_USB_DP) | \
PIN_MODE_ALTERNATE(GPIOA_JTMS) | \
PIN_MODE_ALTERNATE(GPIOA_JTCK) | \
PIN_MODE_OUTPUT(GPIOA_LCD_RESET))
@@ -151,40 +158,40 @@
PIN_OSPEED_2M(1) | \
PIN_OSPEED_2M(2) | \
PIN_OSPEED_2M(3) | \
- PIN_OSPEED_2M(4) | \
- PIN_OSPEED_2M(5) | \
+ PIN_OSPEED_100M(4) | \
+ PIN_OSPEED_100M(5) | \
PIN_OSPEED_2M(6) | \
PIN_OSPEED_2M(7) | \
PIN_OSPEED_100M(GPIOA_MCO) | \
PIN_OSPEED_100M(9) | \
- PIN_OSPEED_100M(GPIOA_USB_DISC) | \
+ PIN_OSPEED_100M(10) | \
PIN_OSPEED_100M(GPIOA_USB_DM) | \
PIN_OSPEED_100M(GPIOA_USB_DP) | \
PIN_OSPEED_100M(GPIOA_JTMS) | \
PIN_OSPEED_100M(GPIOA_JTCK) | \
PIN_OSPEED_100M(GPIOA_LCD_RESET))
-#define VAL_GPIOA_PUPDR (PIN_PUPDR_PULLDOWN(0) | \
+#define VAL_GPIOA_PUPDR ( PIN_PUPDR_PULLDOWN(0) | \
PIN_PUPDR_PULLDOWN(1) | \
PIN_PUPDR_PULLDOWN(2) | \
PIN_PUPDR_PULLDOWN(3) | \
- PIN_PUPDR_PULLUP(4) | \
- PIN_PUPDR_FLOATING(5) | \
+ PIN_PUPDR_PULLDOWN(4) | \
+ PIN_PUPDR_PULLDOWN(5) | \
PIN_PUPDR_FLOATING(6) | \
PIN_PUPDR_FLOATING(7) | \
PIN_PUPDR_PULLUP(GPIOA_MCO) | \
PIN_PUPDR_PULLUP(9) | \
- PIN_PUPDR_FLOATING(GPIOA_USB_DISC) | \
+ PIN_PUPDR_PULLUP(GPIOA_USB_DISC) | \
PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \
PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \
PIN_PUPDR_PULLDOWN(GPIOA_JTMS) | \
PIN_PUPDR_PULLDOWN(GPIOA_JTCK) | \
PIN_PUPDR_PULLDOWN(GPIOA_LCD_RESET))
-#define VAL_GPIOA_ODR (PIN_ODR_HIGH(0) | \
+#define VAL_GPIOA_ODR ( PIN_ODR_HIGH(0) | \
PIN_ODR_HIGH(1) | \
PIN_ODR_HIGH(2) | \
PIN_ODR_HIGH(3) | \
PIN_ODR_HIGH(4) | \
- PIN_ODR_LOW(5) | \
+ PIN_ODR_HIGH(5) | \
PIN_ODR_HIGH(6) | \
PIN_ODR_HIGH(7) | \
PIN_ODR_HIGH(GPIOA_MCO) | \
@@ -234,14 +241,14 @@
PIN_MODE_ALTERNATE(GPIOB_SPI_MOSI) | \
PIN_MODE_OUTPUT(6) | \
PIN_MODE_OUTPUT(7) | \
- PIN_MODE_ALTERNATE(GPIOB_I2C1_SCL) | \
- PIN_MODE_ALTERNATE(GPIOB_I2C1_SDA) | \
- PIN_MODE_OUTPUT(10) | \
+ PIN_MODE_OUTPUT(8) | \
+ PIN_MODE_OUTPUT(GPIO_RF_PWR) | \
+ PIN_MODE_OUTPUT(GPIO_SPI2_CLK) | \
PIN_MODE_OUTPUT(11) | \
- PIN_MODE_ALTERNATE(GPIOB_I2S2_WCLK) | \
- PIN_MODE_ALTERNATE(GPIOB_I2S2_BCLK) | \
- PIN_MODE_ALTERNATE(14) | \
- PIN_MODE_ALTERNATE(GPIOB_I2S2_MOSI))
+ PIN_MODE_OUTPUT(12) | \
+ PIN_MODE_OUTPUT(13) | \
+ PIN_MODE_INPUT(GPIO_SPI2_SDO) | \
+ PIN_MODE_OUTPUT(GPIO_SPI2_SDI))
#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(0) | \
PIN_OTYPE_PUSHPULL(1) | \
PIN_OTYPE_PUSHPULL(2) | \
@@ -250,14 +257,14 @@
PIN_OTYPE_PUSHPULL(5) | \
PIN_OTYPE_PUSHPULL(6) | \
PIN_OTYPE_PUSHPULL(7) | \
- PIN_OTYPE_PUSHPULL(GPIOB_I2C1_SCL) | \
- PIN_OTYPE_PUSHPULL(GPIOB_I2C1_SDA) | \
- PIN_OTYPE_PUSHPULL(10) | \
+ PIN_OTYPE_PUSHPULL(8) | \
+ PIN_OTYPE_PUSHPULL(GPIO_RF_PWR) | \
+ PIN_OTYPE_PUSHPULL(GPIO_SPI2_CLK) | \
PIN_OTYPE_PUSHPULL(11) | \
- PIN_OTYPE_PUSHPULL(GPIOB_I2S2_WCLK) | \
- PIN_OTYPE_PUSHPULL(GPIOB_I2S2_BCLK) | \
- PIN_OTYPE_PUSHPULL(14) | \
- PIN_OTYPE_PUSHPULL(GPIOB_I2S2_MOSI))
+ PIN_OTYPE_PUSHPULL(12) | \
+ PIN_OTYPE_PUSHPULL(13) | \
+ PIN_OTYPE_PUSHPULL(GPIO_SPI2_SDO) | \
+ PIN_OTYPE_PUSHPULL(GPIO_SPI2_SDI))
#define VAL_GPIOB_OSPEEDR (PIN_PUPDR_FLOATING(GPIOB_XN) | \
PIN_PUPDR_FLOATING(GPIOB_YN) | \
PIN_OSPEED_100M(2) | \
@@ -266,14 +273,14 @@
PIN_OSPEED_100M(5) | \
PIN_OSPEED_100M(6) | \
PIN_OSPEED_100M(7) | \
- PIN_OSPEED_100M(GPIOB_I2C1_SCL) | \
- PIN_OSPEED_100M(GPIOB_I2C1_SDA) | \
+ PIN_OSPEED_100M(8) | \
+ PIN_OSPEED_100M(9) | \
PIN_OSPEED_100M(10) | \
PIN_OSPEED_100M(11) | \
- PIN_OSPEED_100M(GPIOB_I2S2_WCLK) | \
- PIN_OSPEED_100M(GPIOB_I2S2_BCLK) | \
+ PIN_OSPEED_100M(12) | \
+ PIN_OSPEED_100M(13) | \
PIN_OSPEED_100M(14) | \
- PIN_OSPEED_100M(GPIOB_I2S2_MOSI))
+ PIN_OSPEED_100M(15))
#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(0) | \
PIN_PUPDR_PULLUP(1) | \
PIN_PUPDR_PULLUP(2) | \
@@ -282,14 +289,14 @@
PIN_PUPDR_PULLUP(5) | \
PIN_PUPDR_PULLUP(6) | \
PIN_PUPDR_PULLUP(7) | \
- PIN_PUPDR_PULLUP(GPIOB_I2C1_SCL) | \
- PIN_PUPDR_PULLUP(GPIOB_I2C1_SDA) | \
+ PIN_PUPDR_PULLUP(8) | \
+ PIN_PUPDR_PULLUP(9) | \
PIN_PUPDR_PULLUP(10) | \
PIN_PUPDR_PULLUP(11) | \
- PIN_PUPDR_PULLUP(GPIOB_I2S2_WCLK) | \
- PIN_PUPDR_PULLUP(GPIOB_I2S2_BCLK) | \
+ PIN_PUPDR_PULLUP(12) | \
+ PIN_PUPDR_PULLUP(13) | \
PIN_PUPDR_PULLUP(14) | \
- PIN_PUPDR_PULLUP(GPIOB_I2S2_MOSI))
+ PIN_PUPDR_PULLUP(14))
#define VAL_GPIOB_ODR (PIN_ODR_HIGH(0) | \
PIN_ODR_HIGH(1) | \
PIN_ODR_HIGH(2) | \
@@ -298,14 +305,14 @@
PIN_ODR_HIGH(5) | \
PIN_ODR_HIGH(6) | \
PIN_ODR_HIGH(7) | \
- PIN_ODR_HIGH(GPIOB_I2C1_SCL) | \
- PIN_ODR_HIGH(GPIOB_I2C1_SDA) | \
+ PIN_ODR_HIGH(8) | \
+ PIN_ODR_HIGH(9) | \
PIN_ODR_HIGH(10) | \
PIN_ODR_HIGH(11) | \
- PIN_ODR_HIGH(GPIOB_I2S2_WCLK) | \
- PIN_ODR_HIGH(GPIOB_I2S2_BCLK) | \
+ PIN_ODR_HIGH(12) | \
+ PIN_ODR_HIGH(13) | \
PIN_ODR_HIGH(14) | \
- PIN_ODR_HIGH(GPIOB_I2S2_MOSI))
+ PIN_ODR_HIGH(15))
#define VAL_GPIOB_AFRL (PIN_AFIO_AF(0, 0) | \
PIN_AFIO_AF(1, 0) | \
PIN_AFIO_AF(2, 0) | \
@@ -314,20 +321,21 @@
PIN_AFIO_AF(GPIOB_SPI_MISO, 0) | \
PIN_AFIO_AF(6, 0) | \
PIN_AFIO_AF(7, 0))
-#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_I2C1_SCL, 1) | \
- PIN_AFIO_AF(GPIOB_I2C1_SDA, 1) | \
+#define VAL_GPIOB_AFRH (PIN_AFIO_AF(8, 1) | \
+ PIN_AFIO_AF(9, 1) | \
PIN_AFIO_AF(10, 0) | \
PIN_AFIO_AF(11, 0) | \
- PIN_AFIO_AF(GPIOB_I2S2_WCLK, 0) | \
- PIN_AFIO_AF(GPIOB_I2S2_BCLK, 0) | \
+ PIN_AFIO_AF(12, 0) | \
+ PIN_AFIO_AF(13, 0) | \
PIN_AFIO_AF(14, 0) | \
- PIN_AFIO_AF(GPIOB_I2S2_MOSI, 0))
+ PIN_AFIO_AF(15, 0))
/*
* GPIOC setup:
*
* PC13 - LED (output pushpull maximum).
* PC14 - USB DISC (output pushpull maximum).
*/
+
#define VAL_GPIOC_MODER (PIN_MODE_INPUT(0) | \
PIN_MODE_INPUT(1) | \
PIN_MODE_INPUT(2) | \
@@ -341,9 +349,9 @@
PIN_MODE_INPUT(10) | \
PIN_MODE_INPUT(11) | \
PIN_MODE_INPUT(12) | \
- PIN_MODE_OUTPUT(GPIOC_LED) | \
- PIN_MODE_INPUT(14) | \
- PIN_MODE_INPUT(15))
+ PIN_MODE_OUTPUT(GPIO_PE_SEL) | \
+ PIN_MODE_OUTPUT(GPIO_RX_SEL) | \
+ PIN_MODE_OUTPUT(GPIO_LO_SEL))
#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(0) | \
PIN_OTYPE_PUSHPULL(1) | \
PIN_OTYPE_PUSHPULL(2) | \
@@ -357,7 +365,7 @@
PIN_OTYPE_PUSHPULL(10) | \
PIN_OTYPE_PUSHPULL(11) | \
PIN_OTYPE_PUSHPULL(12) | \
- PIN_OTYPE_PUSHPULL(GPIOC_LED) | \
+ PIN_OTYPE_PUSHPULL(13) | \
PIN_OTYPE_PUSHPULL(14) | \
PIN_OTYPE_PUSHPULL(15))
#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_100M(0) | \
@@ -373,7 +381,7 @@
PIN_OSPEED_100M(10) | \
PIN_OSPEED_100M(11) | \
PIN_OSPEED_100M(12) | \
- PIN_OSPEED_100M(GPIOC_LED) | \
+ PIN_OSPEED_100M(13) | \
PIN_OSPEED_100M(14) | \
PIN_OSPEED_100M(15))
#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(0) | \
@@ -389,8 +397,8 @@
PIN_PUPDR_PULLUP(10) | \
PIN_PUPDR_PULLUP(11) | \
PIN_PUPDR_PULLUP(12) | \
- PIN_PUPDR_FLOATING(GPIOC_LED) | \
- PIN_PUPDR_FLOATING(14) | \
+ PIN_PUPDR_PULLUP(13) | \
+ PIN_PUPDR_PULLUP(14) | \
PIN_PUPDR_PULLUP(15))
#define VAL_GPIOC_ODR (PIN_ODR_HIGH(0) | \
PIN_ODR_HIGH(1) | \
@@ -405,7 +413,7 @@
PIN_ODR_HIGH(10) | \
PIN_ODR_HIGH(11) | \
PIN_ODR_HIGH(12) | \
- PIN_ODR_HIGH(GPIOC_LED) | \
+ PIN_ODR_HIGH(13) | \
PIN_ODR_HIGH(14) | \
PIN_ODR_HIGH(15))
#define VAL_GPIOC_AFRL (PIN_AFIO_AF(0, 0) | \
@@ -421,7 +429,7 @@
PIN_AFIO_AF(10, 0) | \
PIN_AFIO_AF(11, 0) | \
PIN_AFIO_AF(12, 0) | \
- PIN_AFIO_AF(GPIOC_LED, 0) | \
+ PIN_AFIO_AF(13, 0) | \
PIN_AFIO_AF(14, 0) | \
PIN_AFIO_AF(15, 0))
@@ -743,6 +751,7 @@
PIN_AFIO_AF(14, 0) | \
PIN_AFIO_AF(15, 0))
+
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
diff --git a/STM32F072xB.ld b/STM32F072xB.ld
index 577e87f..8f7b034 100644
--- a/STM32F072xB.ld
+++ b/STM32F072xB.ld
@@ -19,14 +19,14 @@
*/
MEMORY
{
- flash0 : org = 0x08000000, len = 96k
+ flash0 : org = 0x08000000, len = 108k
flash1 : org = 0x00000000, len = 0
flash2 : org = 0x00000000, len = 0
flash3 : org = 0x00000000, len = 0
flash4 : org = 0x00000000, len = 0
flash5 : org = 0x00000000, len = 0
flash6 : org = 0x00000000, len = 0
- flash7 : org = 0x08018000, len = 32k
+ flash7 : org = 0x0801B000, len = 20k
ram0 : org = 0x20000000, len = 16k
ram1 : org = 0x00000000, len = 0
ram2 : org = 0x00000000, len = 0
diff --git a/chconf.h b/chconf.h
index fd54b74..08860ae 100644
--- a/chconf.h
+++ b/chconf.h
@@ -147,7 +147,7 @@
*
* @note The default is @p TRUE.
*/
-#define CH_CFG_USE_REGISTRY FALSE
+#define CH_CFG_USE_REGISTRY TRUE
/**
* @brief Threads synchronization APIs.
diff --git a/chprintf.c b/chprintf.c
index fbfd1cd..3e19b26 100644
--- a/chprintf.c
+++ b/chprintf.c
@@ -52,7 +52,7 @@ static const uint32_t pow10[FLOAT_PRECISION+1] = {
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};
+static char smallPrefix[] = {'m', 'u', 'n', 'p', 'f', 'a', 'z', 'y', 0};
#pragma pack(pop)
@@ -195,12 +195,15 @@ static char *ftoaS(char *p, float num, uint32_t precision) {
;
prefix = num > 1e-3 ? ptr[-1] : 0;
}
- // Auto set prescision
+ if (prefix)
+ precision--;
+
+ // Auto set precision
uint32_t l = num;
- if (l < 10)
- precision+=2;
- else if (l < 100)
- precision+=1;
+ if (l > 100)
+ precision-=2;
+ else if (l > 10)
+ precision-=1;
p=ftoa(p, num, precision);
if (prefix)
*p++ = prefix;
diff --git a/dsp.c b/dsp.c
deleted file mode 100644
index 4b616dc..0000000
--- a/dsp.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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 "nanovna.h"
-
-#ifdef ENABLED_DUMP
-int16_t samp_buf[SAMPLE_LEN];
-int16_t ref_buf[SAMPLE_LEN];
-#endif
-
-const int16_t sincos_tbl[48][2] = {
- { 10533, 31029 }, { 27246, 18205 }, { 32698, -2143 }, { 24636, -21605 },
- { 6393, -32138 }, {-14493, -29389 }, {-29389, -14493 }, {-32138, 6393 },
- {-21605, 24636 }, { -2143, 32698 }, { 18205, 27246 }, { 31029, 10533 },
- { 31029, -10533 }, { 18205, -27246 }, { -2143, -32698 }, {-21605, -24636 },
- {-32138, -6393 }, {-29389, 14493 }, {-14493, 29389 }, { 6393, 32138 },
- { 24636, 21605 }, { 32698, 2143 }, { 27246, -18205 }, { 10533, -31029 },
- {-10533, -31029 }, {-27246, -18205 }, {-32698, 2143 }, {-24636, 21605 },
- { -6393, 32138 }, { 14493, 29389 }, { 29389, 14493 }, { 32138, -6393 },
- { 21605, -24636 }, { 2143, -32698 }, {-18205, -27246 }, {-31029, -10533 },
- {-31029, 10533 }, {-18205, 27246 }, { 2143, 32698 }, { 21605, 24636 },
- { 32138, 6393 }, { 29389, -14493 }, { 14493, -29389 }, { -6393, -32138 },
- {-24636, -21605 }, {-32698, -2143 }, {-27246, 18205 }, {-10533, 31029 }
-};
-
-float acc_samp_s;
-float acc_samp_c;
-float acc_ref_s;
-float acc_ref_c;
-
-void
-dsp_process(int16_t *capture, size_t length)
-{
- uint32_t *p = (uint32_t*)capture;
- uint32_t len = length / 2;
- uint32_t i;
- int32_t samp_s = 0;
- int32_t samp_c = 0;
- int32_t ref_s = 0;
- int32_t ref_c = 0;
-
- for (i = 0; i < len; i++) {
- uint32_t sr = *p++;
- int16_t ref = sr & 0xffff;
- int16_t smp = (sr>>16) & 0xffff;
-#ifdef ENABLED_DUMP
- ref_buf[i] = ref;
- samp_buf[i] = smp;
-#endif
- int32_t s = sincos_tbl[i][0];
- int32_t c = sincos_tbl[i][1];
- samp_s += smp * s / 16;
- samp_c += smp * c / 16;
- ref_s += ref * s / 16;
- ref_c += ref * c / 16;
-#if 0
- uint32_t sc = *(uint32_t)&sincos_tbl[i];
- samp_s = __SMLABB(sr, sc, samp_s);
- samp_c = __SMLABT(sr, sc, samp_c);
- ref_s = __SMLATB(sr, sc, ref_s);
- ref_c = __SMLATT(sr, sc, ref_c);
-#endif
- }
- acc_samp_s += samp_s;
- acc_samp_c += samp_c;
- acc_ref_s += ref_s;
- acc_ref_c += ref_c;
-}
-
-void
-calculate_gamma(float gamma[2])
-{
-#if 1
- // calculate reflection coeff. by samp divide by ref
- float rs = acc_ref_s;
- float rc = acc_ref_c;
- float rr = rs * rs + rc * rc;
- //rr = sqrtf(rr) * 1e8;
- float ss = acc_samp_s;
- float sc = acc_samp_c;
- gamma[0] = (sc * rc + ss * rs) / rr;
- gamma[1] = (ss * rc - sc * rs) / rr;
-#elif 0
- gamma[0] = acc_samp_s;
- gamma[1] = acc_samp_c;
-#else
- gamma[0] = acc_ref_s;
- gamma[1] = acc_ref_c;
-#endif
-}
-
-void
-fetch_amplitude(float gamma[2])
-{
- gamma[0] = acc_samp_s * 1e-9;
- gamma[1] = acc_samp_c * 1e-9;
-}
-
-void
-fetch_amplitude_ref(float gamma[2])
-{
- gamma[0] = acc_ref_s * 1e-9;
- gamma[1] = acc_ref_c * 1e-9;
-}
-
-void
-reset_dsp_accumerator(void)
-{
- acc_ref_s = 0;
- acc_ref_c = 0;
- acc_samp_s = 0;
- acc_samp_c = 0;
-}
diff --git a/ffconf.h b/ffconf.h
deleted file mode 100644
index ae0d38d..0000000
--- a/ffconf.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/* CHIBIOS FIX */
-#include "ch.h"
-
-/*---------------------------------------------------------------------------/
-/ FatFs - FAT file system module configuration file R0.09 (C)ChaN, 2011
-/----------------------------------------------------------------------------/
-/
-/ CAUTION! Do not forget to make clean the project after any changes to
-/ the configuration options.
-/
-/----------------------------------------------------------------------------*/
-#ifndef _FFCONF
-#define _FFCONF 6502 /* Revision ID */
-
-
-/*---------------------------------------------------------------------------/
-/ Functions and Buffer Configurations
-/----------------------------------------------------------------------------*/
-
-#define _FS_TINY 0 /* 0:Normal or 1:Tiny */
-/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
-/ object instead of the sector buffer in the individual file object for file
-/ data transfer. This reduces memory consumption 512 bytes each file object. */
-
-
-#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
-/* Setting _FS_READONLY to 1 defines read only configuration. This removes
-/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
-/ f_truncate and useless f_getfree. */
-
-
-#define _FS_MINIMIZE 0 /* 0 to 3 */
-/* The _FS_MINIMIZE option defines minimization level to remove some functions.
-/
-/ 0: Full function.
-/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
-/ are removed.
-/ 2: f_opendir and f_readdir are removed in addition to 1.
-/ 3: f_lseek is removed in addition to 2. */
-
-
-#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */
-/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
-
-
-#define _USE_MKFS 1 /* 0:Disable or 1:Enable */
-/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
-
-
-#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
-/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
-
-
-#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
-/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
-
-
-
-/*---------------------------------------------------------------------------/
-/ Locale and Namespace Configurations
-/----------------------------------------------------------------------------*/
-
-#define _CODE_PAGE 1251
-/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
-/ Incorrect setting of the code page can cause a file open failure.
-/
-/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows)
-/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
-/ 949 - Korean (DBCS, OEM, Windows)
-/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
-/ 1250 - Central Europe (Windows)
-/ 1251 - Cyrillic (Windows)
-/ 1252 - Latin 1 (Windows)
-/ 1253 - Greek (Windows)
-/ 1254 - Turkish (Windows)
-/ 1255 - Hebrew (Windows)
-/ 1256 - Arabic (Windows)
-/ 1257 - Baltic (Windows)
-/ 1258 - Vietnam (OEM, Windows)
-/ 437 - U.S. (OEM)
-/ 720 - Arabic (OEM)
-/ 737 - Greek (OEM)
-/ 775 - Baltic (OEM)
-/ 850 - Multilingual Latin 1 (OEM)
-/ 858 - Multilingual Latin 1 + Euro (OEM)
-/ 852 - Latin 2 (OEM)
-/ 855 - Cyrillic (OEM)
-/ 866 - Russian (OEM)
-/ 857 - Turkish (OEM)
-/ 862 - Hebrew (OEM)
-/ 874 - Thai (OEM, Windows)
-/ 1 - ASCII only (Valid for non LFN cfg.)
-*/
-
-
-#define _USE_LFN 1 /* 0 to 3 */
-#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
-/* The _USE_LFN option switches the LFN support.
-/
-/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
-/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
-/ 2: Enable LFN with dynamic working buffer on the STACK.
-/ 3: Enable LFN with dynamic working buffer on the HEAP.
-/
-/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN,
-/ Unicode handling functions ff_convert() and ff_wtoupper() must be added
-/ to the project. When enable to use heap, memory control functions
-/ ff_memalloc() and ff_memfree() must be added to the project. */
-
-
-#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
-/* To switch the character code set on FatFs API to Unicode,
-/ enable LFN feature and set _LFN_UNICODE to 1. */
-
-
-#define _FS_RPATH 0 /* 0 to 2 */
-/* The _FS_RPATH option configures relative path feature.
-/
-/ 0: Disable relative path feature and remove related functions.
-/ 1: Enable relative path. f_chdrive() and f_chdir() are available.
-/ 2: f_getcwd() is available in addition to 1.
-/
-/ Note that output of the f_readdir fnction is affected by this option. */
-
-
-
-/*---------------------------------------------------------------------------/
-/ Physical Drive Configurations
-/----------------------------------------------------------------------------*/
-
-#define _VOLUMES 1
-/* Number of volumes (logical drives) to be used. */
-
-
-#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */
-/* Maximum sector size to be handled.
-/ Always set 512 for memory card and hard disk but a larger value may be
-/ required for on-board flash memory, floppy disk and optical disk.
-/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size
-/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */
-
-
-#define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */
-/* When set to 0, each volume is bound to the same physical drive number and
-/ it can mount only first primaly partition. When it is set to 1, each volume
-/ is tied to the partitions listed in VolToPart[]. */
-
-
-#define _USE_ERASE 1 /* 0:Disable or 1:Enable */
-/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command
-/ should be added to the disk_ioctl functio. */
-
-
-
-/*---------------------------------------------------------------------------/
-/ System Configurations
-/----------------------------------------------------------------------------*/
-
-#define _WORD_ACCESS 1 /* 0 or 1 */
-/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS
-/ option defines which access method is used to the word data on the FAT volume.
-/
-/ 0: Byte-by-byte access.
-/ 1: Word access. Do not choose this unless following condition is met.
-/
-/ When the byte order on the memory is big-endian or address miss-aligned word
-/ access results incorrect behavior, the _WORD_ACCESS must be set to 0.
-/ If it is not the case, the value can also be set to 1 to improve the
-/ performance and code size.
-*/
-
-
-/* A header file that defines sync object types on the O/S, such as
-/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */
-
-#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */
-#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
-#define _SYNC_t Semaphore * /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
-
-/* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module.
-/
-/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
-/ 1: Enable reentrancy. Also user provided synchronization handlers,
-/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj
-/ function must be added to the project. */
-
-
-#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */
-/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value
- defines how many files can be opened simultaneously. */
-
-
-#endif /* _FFCONFIG */
diff --git a/fft.h b/fft.h
deleted file mode 100644
index dbaa32f..0000000
--- a/fft.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * fft.h is Based on
- * Free FFT and convolution (C)
- *
- * Copyright (c) 2019 Project Nayuki. (MIT License)
- * https://www.nayuki.io/page/free-small-fft-in-multiple-languages
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- * - The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * - The Software is provided "as is", without warranty of any kind, express or
- * implied, including but not limited to the warranties of merchantability,
- * fitness for a particular purpose and noninfringement. In no event shall the
- * authors or copyright holders be liable for any claim, damages or other
- * liability, whether in an action of contract, tort or otherwise, arising from,
- * out of or in connection with the Software or the use or other dealings in the
- * Software.
- */
-
-
-#include
-#include
-
-static uint16_t reverse_bits(uint16_t x, int n) {
- uint16_t result = 0;
- int i;
- for (i = 0; i < n; i++, x >>= 1)
- result = (result << 1) | (x & 1U);
- return result;
-}
-
-/***
- * dir = forward: 0, inverse: 1
- * https://www.nayuki.io/res/free-small-fft-in-multiple-languages/fft.c
- */
-static void fft256(float array[][2], const uint8_t dir) {
- const uint16_t n = 256;
- const uint8_t levels = 8; // log2(n)
-
- const uint8_t real = dir & 1;
- const uint8_t imag = ~real & 1;
- uint16_t i;
- uint16_t size;
-
- for (i = 0; i < n; i++) {
- uint16_t j = reverse_bits(i, levels);
- if (j > i) {
- float temp = array[i][real];
- array[i][real] = array[j][real];
- array[j][real] = temp;
- temp = array[i][imag];
- array[i][imag] = array[j][imag];
- array[j][imag] = temp;
- }
- }
-
- // Cooley-Tukey decimation-in-time radix-2 FFT
- for (size = 2; size <= n; size *= 2) {
- uint16_t halfsize = size / 2;
- uint16_t tablestep = n / size;
- uint16_t i;
- for (i = 0; i < n; i += size) {
- 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 * 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;
- array[j][imag] += tpim;
- }
- }
- if (size == n) // Prevent overflow in 'size *= 2'
- break;
- }
-}
-
-static inline void fft256_forward(float array[][2]) {
- fft256(array, 0);
-}
-
-static inline void fft256_inverse(float array[][2]) {
- fft256(array, 1);
-}
diff --git a/flash.c b/flash.c
index a66315d..62dc281 100644
--- a/flash.c
+++ b/flash.c
@@ -120,48 +120,62 @@ config_recall(void)
return 0;
}
-const uint32_t saveareas[SAVEAREA_MAX] = {
+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 };
+ SAVE_PROP_CONFIG_4_ADDR,
+ SAVE_PROP_CONFIG_5_ADDR,
+ SAVE_PROP_CONFIG_6_ADDR,
+ SAVE_PROP_CONFIG_7_ADDR,
+ SAVE_PROP_CONFIG_8_ADDR,
+};
int16_t lastsaveid = 0;
int
caldata_save(int id)
{
- uint16_t *src = (uint16_t*)¤t_props;
+ uint16_t *src = (uint16_t*)&setting;
uint16_t *dst;
- int count = sizeof(properties_t) / sizeof(uint16_t);
+ int count = sizeof(setting_t) / sizeof(uint16_t);
if (id < 0 || id >= SAVEAREA_MAX)
return -1;
dst = (uint16_t*)saveareas[id];
- current_props.magic = CONFIG_MAGIC;
- current_props.checksum = checksum(
- ¤t_props, sizeof current_props - sizeof current_props.checksum);
+ setting.magic = CONFIG_MAGIC;
+ setting.checksum = checksum(
+ &setting, sizeof setting - sizeof setting.checksum);
flash_unlock();
/* erase flash pages */
void *p = dst;
- void *tail = p + sizeof(properties_t);
+ void *tail = p + sizeof(setting_t);
while (p < tail) {
flash_erase_page((uint32_t)p);
p += FLASH_PAGESIZE;
}
- /* write to flahs */
+ /* write to flash */
+ while (count-- > 0) {
+ flash_program_half_word((uint32_t)dst, *src++);
+ dst++;
+ }
+
+ // Flash stored trace
+ count = sizeof(stored_t) / sizeof(uint16_t);
+ src = (uint16_t*)&stored_t[0];
while (count-- > 0) {
flash_program_half_word((uint32_t)dst, *src++);
dst++;
}
/* after saving data, make active configuration points to flash */
- active_props = (properties_t*)saveareas[id];
+// active_props = (setting_t*)saveareas[id];
lastsaveid = id;
return 0;
@@ -170,39 +184,42 @@ caldata_save(int id)
int
caldata_recall(int id)
{
- properties_t *src;
- void *dst = ¤t_props;
+ setting_t *src;
+ void *dst = &setting;
if (id < 0 || id >= SAVEAREA_MAX)
- goto load_default;
+ return -1;
// point to saved area on the flash memory
- src = (properties_t*)saveareas[id];
+ src = (setting_t*)saveareas[id];
if (src->magic != CONFIG_MAGIC)
- goto load_default;
- if (checksum(src, sizeof *src - sizeof src->checksum) != src->checksum)
- goto load_default;
+ return -1;
+ if (checksum(src, sizeof setting - sizeof src->checksum) != src->checksum)
+ return -1;
/* active configuration points to save data on flash memory */
- active_props = src;
+// active_props = src;
lastsaveid = id;
/* duplicated saved data onto sram to be able to modify marker/trace */
- memcpy(dst, src, sizeof(properties_t));
+ memcpy(dst, src, sizeof(setting_t));
+ // Restore stored trace
+ memcpy(stored_t, &src[1], sizeof(stored_t));
+
+ update_frequencies();
+ set_scale(setting.scale);
+ set_reflevel(setting.reflevel);
return 0;
-load_default:
- load_default_properties();
- return -1;
}
-
-const properties_t *
+#if 0
+const setting_t *
caldata_ref(int id)
{
- const properties_t *src;
+ const setting_t *src;
if (id < 0 || id >= SAVEAREA_MAX)
return NULL;
- src = (const properties_t*)saveareas[id];
+ src = (const setting_t*)saveareas[id];
if (src->magic != CONFIG_MAGIC)
return NULL;
@@ -210,6 +227,7 @@ caldata_ref(int id)
return NULL;
return src;
}
+#endif
const uint32_t save_config_prop_area_size = SAVE_CONFIG_AREA_SIZE;
diff --git a/halconf.h b/halconf.h
index 38341a0..af6c283 100644
--- a/halconf.h
+++ b/halconf.h
@@ -76,14 +76,14 @@
* @brief Enables the I2C subsystem.
*/
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
-#define HAL_USE_I2C TRUE
+#define HAL_USE_I2C FALSE
#endif
/**
* @brief Enables the I2S subsystem.
*/
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
-#define HAL_USE_I2S TRUE
+#define HAL_USE_I2S FALSE
#endif
/**
@@ -132,7 +132,7 @@
* @brief Enables the SERIAL subsystem.
*/
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
-#define HAL_USE_SERIAL FALSE
+#define HAL_USE_SERIAL TRUE
#endif
/**
diff --git a/ili9341.c b/ili9341.c
index f1e4674..5496c3c 100644
--- a/ili9341.c
+++ b/ili9341.c
@@ -27,8 +27,8 @@ 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 LCD_WIDTH
+#define ILI9341_HEIGHT LCD_HEIGHT
// Display commands list
#define ILI9341_NOP 0x00
@@ -294,9 +294,11 @@ static const uint8_t ili9341_init_seq[] = {
// POWER_CONTROL_2
ILI9341_POWER_CONTROL_2, 1, 0x11,
// VCOM_CONTROL_1
- ILI9341_VCOM_CONTROL_1, 2, 0x35, 0x3E,
+// ILI9341_VCOM_CONTROL_1, 2, 0x35, 0x3E,
+ ILI9341_VCOM_CONTROL_1, 2, 0x3e, 0x28,
// VCOM_CONTROL_2
ILI9341_VCOM_CONTROL_2, 1, 0xBE,
+// ILI9341_VCOM_CONTROL_2, 1, 0x86,
// MEMORY_ACCESS_CONTROL
//ILI9341_MEMORY_ACCESS_CONTROL, 1, 0x48, // portlait
ILI9341_MEMORY_ACCESS_CONTROL, 1, DISPLAY_ROTATION_0, // landscape
@@ -309,9 +311,9 @@ static const uint8_t ili9341_init_seq[] = {
// 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,
+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,
+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
@@ -383,41 +385,8 @@ void ili9341_bulk(int x, int y, int w, int h)
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;
-}
-
-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;
-}
#else
+
//
// Use DMA for send data
//
@@ -469,7 +438,7 @@ void ili9341_bulk(int x, int y, int w, int h)
STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_MINC);
dmaStreamFlush(w * h);
}
-
+#if 1 // Read DMA hangs
// 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)
@@ -485,6 +454,7 @@ void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out)
// 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)
+ chSysLock();
dmaStreamSetMemory0(dmarx, rgbbuf);
dmaStreamSetTransactionSize(dmarx, data_size);
dmaStreamSetMode(dmarx, rxdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
@@ -499,7 +469,18 @@ void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out)
dmaStreamEnable(dmarx);
// Wait DMA completion
dmaWaitCompletion(dmatx);
+#if 0
+ int count = 0;
+ while ((dmarx)->channel->CNDTR > 0U) {
+ chThdSleepMicroseconds(100);
+ if (count++ > 10)
+ break;
+ }
+ dmaStreamDisable(dmarx);
+#else
dmaWaitCompletion(dmarx);
+#endif
+ chSysUnlock();
CS_HIGH;
// Parce recived data
@@ -515,13 +496,49 @@ void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out)
rgbbuf += 3;
}
}
+#else
+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;
+}
+
+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;
+}
+
+#endif
#endif
void ili9341_clear_screen(void)
{
ili9341_fill(0, 0, ILI9341_WIDTH, ILI9341_HEIGHT, background_color);
}
-
+#if 0
void ili9341_set_foreground(uint16_t fg)
{
foreground_color = fg;
@@ -531,7 +548,7 @@ void ili9341_set_background(uint16_t bg)
{
background_color = bg;
}
-
+#endif
void ili9341_set_rotation(uint8_t r)
{
// static const uint8_t rotation_const[]={DISPLAY_ROTATION_0, DISPLAY_ROTATION_90,
@@ -553,7 +570,7 @@ void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height
ili9341_bulk(x, y, width, height);
}
-static void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
+void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
const uint16_t *bitmap)
{
uint16_t *buf = spi_buffer;
@@ -567,6 +584,12 @@ static void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_
ili9341_bulk(x, y, width, height);
}
+int ili9341_size = 1;
+
+void ili9341_charsize(int s)
+{
+ ili9341_size = s;
+}
void ili9341_drawchar(uint8_t ch, int x, int y)
{
blit8BitWidthBitmap(x, y, FONT_GET_WIDTH(ch), FONT_GET_HEIGHT, FONT_GET_DATA(ch));
@@ -583,6 +606,16 @@ void ili9341_drawstring(const char *str, int x, int y)
}
}
+void ili9341_drawstring_7x13(const char *str, int x, int y)
+{
+ while (*str) {
+ uint8_t ch = *str++;
+ const uint16_t *char_buf = &x7x13b_bits[(ch * 13)]; // All chars start at row 2
+ blit16BitWidthBitmap(x, y, 7, 13, char_buf); // Only 'Q' has 12 rows, 'g' requires 13 rows
+ x += 7;
+ }
+}
+
void ili9341_drawstringV(const char *str, int x, int y)
{
ili9341_set_rotation(DISPLAY_ROTATION_270);
@@ -693,15 +726,15 @@ void ili9341_test(int mode)
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));
+ ili9341_fill(0, 0, LCD_WIDTH, LCD_HEIGHT, 0);
+ for (y = 0; y < LCD_HEIGHT; y++) {
+ ili9341_fill(0, y, LCD_WIDTH, 1, RGB(LCD_HEIGHT-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_fill(0, 0, LCD_WIDTH, LCD_HEIGHT, 0);
+ for (y = 0; y < LCD_HEIGHT; y++) {
+ for (x = 0; x < LCD_WIDTH; x++) {
ili9341_pixel(x, y, (y<<8)|x);
}
}
diff --git a/main.c b/main.c
index 91f475c..40efb1d 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,4 @@
/*
- * Copyright (c) 2016-2017, 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
@@ -17,18 +15,34 @@
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
+//#define HAL_USE_SERIAL 1
+//#define STM32_SERIAL_USE_USART1 1
#include "ch.h"
#include "hal.h"
+
+//#include "hal_serial.h"
+
#include "usbcfg.h"
+#ifdef __VNA__
#include "si5351.h"
+#endif
#include "nanovna.h"
+#ifdef __VNA__
#include "fft.h"
+#endif
#include
#include
#include
+extern float minFreq;
+extern float maxFreq;
+float frequencyStart;
+float frequencyStop;
+int32_t frequencyExtra;
+#define START_MIN minFreq
+#define STOP_MAX maxFreq
/*
* Shell settings
*/
@@ -60,7 +74,7 @@ static volatile vna_shellcmd_t shell_function = 0;
//#define ENABLED_DUMP
// Allow get threads debug info
-//#define ENABLE_THREADS_COMMAND
+#define ENABLE_THREADS_COMMAND
// RTC time not used
//#define ENABLE_TIME_COMMAND
// Enable vbat_offset command, allow change battery voltage correction in config
@@ -69,13 +83,15 @@ static volatile vna_shellcmd_t shell_function = 0;
#define ENABLE_INFO_COMMAND
// Enable color command, allow change config color for traces, grid, menu
#define ENABLE_COLOR_COMMAND
-
+#ifdef __VNA__
static void apply_error_term_at(int i);
static void apply_edelay_at(int i);
static void cal_interpolate(int s);
-static void update_frequencies(void);
+#endif
+void update_frequencies(void);
static void set_frequencies(uint32_t start, uint32_t stop, uint16_t points);
static bool sweep(bool break_on_operation);
+#ifdef __VNA__
static void transform_domain(void);
#define DRIVE_STRENGTH_AUTO (-1)
@@ -85,14 +101,16 @@ static void transform_domain(void);
#define cal_auto_interpolate TRUE
static int8_t drive_strength = DRIVE_STRENGTH_AUTO;
+#endif
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,
+ "2019-2020 Copyright @Erik Kaashoek",
"2016-2020 Copyright @edy555",
- "Licensed under GPL. See: https://github.com/ttrftech/NanoVNA",
+ "SW licensed under GPL. See: https://github.com/erikkaashoek/tinySA",
"Version: " VERSION,
"Build Time: " __DATE__ " - " __TIME__,
"Kernel: " CH_KERNEL_VERSION,
@@ -102,20 +120,36 @@ const char *info_about[]={
"Platform: " PLATFORM_NAME,
0 // sentinel
};
+extern int dirty;
+
+bool completed = false;
-static THD_WORKING_AREA(waThread1, 640);
+static THD_WORKING_AREA(waThread1, 900);
static THD_FUNCTION(Thread1, arg)
{
(void)arg;
chRegSetThreadName("sweep");
+ ui_process();
+
while (1) {
- bool completed = false;
if (sweep_mode&(SWEEP_ENABLE|SWEEP_ONCE)) {
- completed = sweep(true);
+// if (dirty)
+ completed = sweep(true);
sweep_mode&=~SWEEP_ONCE;
+ } else if (sweep_mode & SWEEP_SELFTEST) {
+ // call from lowest level to save stack space
+ self_test(setting.test);
+ sweep_mode = SWEEP_ENABLE;
+ } else if (sweep_mode & SWEEP_REMOTE) {
+ sweep_remote();
+ } else if (sweep_mode & SWEEP_CALIBRATE) {
+ // call from lowest level to save stack space
+ calibrate();
+ sweep_mode = SWEEP_ENABLE;
} else {
- __WFI();
+// if (setting.mode != -1)
+ __WFI();
}
// Run Shell command in sweep thread
if (shell_function) {
@@ -128,8 +162,10 @@ static THD_FUNCTION(Thread1, arg)
ui_process();
// Process collected data, calculate trace coordinates and plot only if scan
// completed
- if (sweep_mode & SWEEP_ENABLE && completed) {
+ if (/* sweep_mode & SWEEP_ENABLE && */ completed) {
+#ifdef __VNA__
if ((domain_mode & DOMAIN_MODE) == DOMAIN_TIME) transform_domain();
+#endif
// Prepare draw graphics, cache all lines, mark screen cells for redraw
plot_into_index(measured);
redraw_request |= REDRAW_CELLS | REDRAW_BATTERY;
@@ -148,6 +184,12 @@ static THD_FUNCTION(Thread1, arg)
}
}
+int
+is_paused(void)
+{
+ return !(sweep_mode & SWEEP_ENABLE);
+}
+
static inline void
pause_sweep(void)
{
@@ -166,6 +208,7 @@ toggle_sweep(void)
sweep_mode ^= SWEEP_ENABLE;
}
+#ifdef __VNA__
static float
bessel0(float x)
{
@@ -261,9 +304,10 @@ transform_domain(void)
}
}
}
+#endif
// Shell commands output
-static int shell_printf(const char *fmt, ...)
+int shell_printf(const char *fmt, ...)
{
va_list ap;
int formatted_bytes;
@@ -287,9 +331,10 @@ VNA_SHELL_FUNCTION(cmd_resume)
// restore frequencies array and cal
update_frequencies();
+#ifdef __VNA__
if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY))
cal_interpolate(lastsaveid);
-
+#endif
resume_sweep();
}
@@ -316,6 +361,7 @@ VNA_SHELL_FUNCTION(cmd_reset)
;
}
+#ifdef __VNA__
const int8_t gain_table[] = {
0, // 0 ~ 300MHz
40, // 300 ~ 600MHz
@@ -341,9 +387,12 @@ adjust_gain(uint32_t newfreq)
}
return 0;
}
+#endif
int set_frequency(uint32_t freq)
{
+ (void) freq;
+#ifdef __VNA__
int delay = adjust_gain(freq);
int8_t ds = drive_strength;
if (ds == DRIVE_STRENGTH_AUTO) {
@@ -351,6 +400,8 @@ int set_frequency(uint32_t freq)
}
delay += si5351_set_frequency(freq, ds);
return delay;
+#endif
+ return 1;
}
// Use macro, std isdigit more big
@@ -368,6 +419,11 @@ static int32_t my_atoi(const char *p)
if (*p == '+') p++;
while ((c = *p++ - '0') < 10)
value = value * 10 + c;
+ switch (*(--p)) {
+ case 'k': value *= 1000; break;
+ case 'M': value *= 1000000; break;
+ case 'G': value *= 1000000000; break;
+ }
return neg ? -value : value;
}
@@ -431,6 +487,16 @@ my_atof(const char *p)
exp++;
}
}
+ switch (*p) {
+ case 'k': x *= 1e+3; break;
+ case 'M': x *= 1e+6; break;
+ case 'G': x *= 1e+9; break;
+ case 'm': x /= 1e+3; break;
+ case 'u': x /= 1e+6; break;
+ case 'n': x /= 1e+9; break;
+ case 'p': x /= 1e+12; break;
+ }
+
if (neg)
x = -x;
return x;
@@ -467,7 +533,7 @@ static int get_str_index(char *v, const char *list)
}
return -1;
}
-
+#ifdef __VNA__
VNA_SHELL_FUNCTION(cmd_offset)
{
if (argc != 1) {
@@ -476,6 +542,7 @@ VNA_SHELL_FUNCTION(cmd_offset)
}
si5351_set_frequency_offset(my_atoi(argv[0]));
}
+#endif
VNA_SHELL_FUNCTION(cmd_freq)
{
@@ -490,16 +557,18 @@ VNA_SHELL_FUNCTION(cmd_freq)
usage:
shell_printf("usage: freq {frequency(Hz)}\r\n");
}
-
+#ifdef __VNA__
VNA_SHELL_FUNCTION(cmd_power)
{
if (argc != 1) {
shell_printf("usage: power {0-3|-1}\r\n");
return;
}
+ (void)argv;
drive_strength = my_atoi(argv[0]);
// set_frequency(frequency);
}
+#endif
#ifdef ENABLE_TIME_COMMAND
#if HAL_USE_RTC == FALSE
@@ -528,6 +597,7 @@ VNA_SHELL_FUNCTION(cmd_dac)
dacPutChannelX(&DACD2, 0, value);
}
+#ifdef __VNA__
VNA_SHELL_FUNCTION(cmd_threshold)
{
uint32_t value;
@@ -539,6 +609,7 @@ VNA_SHELL_FUNCTION(cmd_threshold)
value = my_atoui(argv[0]);
config.harmonic_freq_threshold = value;
}
+#endif
VNA_SHELL_FUNCTION(cmd_saveconfig)
{
@@ -565,6 +636,7 @@ VNA_SHELL_FUNCTION(cmd_clearconfig)
"Do reset manually to take effect. Then do touch cal and save.\r\n");
}
+#ifdef __VNA__
static struct {
int16_t rms[2];
int16_t ave[2];
@@ -596,22 +668,9 @@ const int8_t bandwidth_accumerate_count[] = {
};
float measured[2][POINTS_COUNT][2];
-
-static inline void
-dsp_start(int count)
-{
- wait_count = count;
- accumerate_count = bandwidth_accumerate_count[bandwidth];
- reset_dsp_accumerator();
-}
-
-static inline void
-dsp_wait(void)
-{
- while (accumerate_count > 0)
- __WFI();
-}
-
+#endif
+measurement_t measured;
+#ifdef __VNA__
#ifdef ENABLED_DUMP
static void
duplicate_buffer_to_dump(int16_t *p)
@@ -664,26 +723,23 @@ static const I2SConfig i2sconfig = {
0, // i2scfgr
2 // i2spr
};
+#endif
+#define MAX_DATA 2
VNA_SHELL_FUNCTION(cmd_data)
{
int i;
int sel = 0;
- float (*array)[2];
if (argc == 1)
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");
+
+ if (sel >= 0 && sel <= MAX_DATA) {
+ for (i = 0; i < sweep_points; i++)
+ shell_printf("%f\r\n", measured[sel][i]);
+ return;
+ }
+ shell_printf("usage: data [0-2]\r\n");
}
#ifdef ENABLED_DUMP
@@ -715,15 +771,15 @@ VNA_SHELL_FUNCTION(cmd_capture)
(void)argc;
(void)argv;
int i, y;
-#if SPI_BUFFER_SIZE < (3*320 + 1)
+#if SPI_BUFFER_SIZE < (3*LCD_WIDTH + 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) {
+ for (y = 0; y < LCD_HEIGHT; 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++) {
+ ili9341_read_memory(0, y, LCD_WIDTH, 2, 2 * LCD_WIDTH, spi_buffer);
+ for (i = 0; i < 4 * LCD_WIDTH; i++) {
streamPut(shell_stream, *buf++);
}
}
@@ -745,7 +801,7 @@ VNA_SHELL_FUNCTION(cmd_gamma)
shell_printf("%d %d\r\n", gamma[0], gamma[1]);
}
#endif
-
+#ifdef __VNA__
static void (*sample_func)(float *gamma) = calculate_gamma;
VNA_SHELL_FUNCTION(cmd_sample)
@@ -769,34 +825,42 @@ VNA_SHELL_FUNCTION(cmd_sample)
usage:
shell_printf("usage: sample {%s}\r\n", cmd_sample_list);
}
-
+#endif
config_t config = {
.magic = CONFIG_MAGIC,
.dac_value = 1922,
.grid_color = DEFAULT_GRID_COLOR,
.menu_normal_color = DEFAULT_MENU_COLOR,
.menu_active_color = DEFAULT_MENU_ACTIVE_COLOR,
- .trace_color = { DEFAULT_TRACE_1_COLOR, DEFAULT_TRACE_2_COLOR, DEFAULT_TRACE_3_COLOR, DEFAULT_TRACE_4_COLOR },
+ .trace_color = { DEFAULT_TRACE_1_COLOR, DEFAULT_TRACE_2_COLOR, DEFAULT_TRACE_3_COLOR},
// .touch_cal = { 693, 605, 124, 171 }, // 2.4 inch LCD panel
.touch_cal = { 338, 522, 153, 192 }, // 2.8 inch LCD panel
.freq_mode = FREQ_MODE_START_STOP,
+#ifdef __VNA__
.harmonic_freq_threshold = 300000000,
- .vbat_offset = 500
+#endif
+ .vbat_offset = 500,
+ .low_level_offset = 100, // Uncalibrated
+ .high_level_offset = 100, // Uncalibrated
+ .correction_frequency = { 100000, 200000, 400000, 1000000, 2000000, 50000000, 100000000, 200000000, 300000000, 350000000 },
+ .correction_value = { +4.0, +2.0, +1.5, +0.5, 0.0, 0.0, +1.0, +1.0, +2.5, +5.0 },
};
-properties_t current_props;
-properties_t *active_props = ¤t_props;
+//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 }
+ { 0, TRC_LOGMAG, 0, 0, 10.0, (float) NGRIDY+1 }, //Temp
+ { 0, TRC_LOGMAG, 1, 0, 10.0, (float) NGRIDY+1 }, //Stored
+ { 1, TRC_LOGMAG, 2, 0, 10.0, (float) NGRIDY+1 } //Actual
};
static const marker_t def_markers[MARKERS_MAX] = {
- { 1, 30, 0 }, { 0, 40, 0 }, { 0, 60, 0 }, { 0, 80, 0 }
+ { M_ENABLED, M_REFERENCE | M_TRACKING, 30, 0 },
+ { M_DISABLED, M_NORMAL, 40, 0 },
+ { M_DISABLED, M_NORMAL, 60, 0 },
+ { M_DISABLED, M_NORMAL, 80, 0 }
};
// Load propeties default settings
@@ -804,28 +868,38 @@ 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;
+// current_props._setting.frequency0 = 0; // start = 0Hz
+// current_props._setting.frequency1 = 350000000; // end = 350MHz
+// current_props._setting.frequency_IF= 433800000,
+
+ setting._sweep_points = POINTS_COUNT;
+ #ifdef VNA__
+ setting._cal_status = 0;
//This data not loaded by default
-//current_props._frequencies[POINTS_COUNT];
-//current_props._cal_data[5][POINTS_COUNT][2];
+//setting._frequencies[POINTS_COUNT];
+//setting._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;
+ setting._electrical_delay = 0.0;
+#endif
+ memcpy(setting._trace, def_trace, sizeof(def_trace));
+ memcpy(setting._markers, def_markers, sizeof(def_markers));
+#ifdef __VNA__
+ setting._velocity_factor = 0.7;
+#endif
+ setting._active_marker = 0;
+#ifdef __VNA__
+ setting._domain_mode = 0;
+ setting._marker_smith_format = MS_RLC;
+#endif
+ reset_settings(M_LOW);
//Checksum add on caldata_save
-//current_props.checksum = 0;
+//setting.checksum = 0;
}
void
ensure_edit_config(void)
{
+#ifdef __VNA__
if (active_props == ¤t_props)
return;
@@ -833,8 +907,14 @@ ensure_edit_config(void)
active_props = ¤t_props;
// move to uncal state
cal_status = 0;
+#endif
}
+#include "sa_core.c"
+#ifdef __VNA__
+#define DSP_START(delay) wait_count = delay;
+#define DSP_WAIT_READY while (wait_count) __WFI();
+
#define DELAY_CHANNEL_CHANGE 2
// main loop for measurement
@@ -842,7 +922,7 @@ bool sweep(bool break_on_operation)
{
int i, delay;
// blink LED while scanning
- palClearPad(GPIOC, GPIOC_LED);
+ palClearPad(GPIOB, GPIOB_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;
@@ -876,9 +956,10 @@ bool sweep(bool break_on_operation)
return false;
}
// blink LED while scanning
- palSetPad(GPIOC, GPIOC_LED);
+ palSetPad(GPIOB, GPIOB_LED);
return true;
}
+#endif
VNA_SHELL_FUNCTION(cmd_scan)
{
@@ -892,7 +973,7 @@ VNA_SHELL_FUNCTION(cmd_scan)
start = my_atoui(argv[0]);
stop = my_atoui(argv[1]);
- if (start == 0 || stop == 0 || start > stop) {
+ if (start > stop) {
shell_printf("frequency range is invalid\r\n");
return;
}
@@ -905,8 +986,10 @@ VNA_SHELL_FUNCTION(cmd_scan)
}
set_frequencies(start, stop, points);
+#ifdef __VNA__
if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY))
cal_interpolate(lastsaveid);
+#endif
pause_sweep();
sweep(false);
// Output data after if set (faster data recive)
@@ -915,8 +998,9 @@ VNA_SHELL_FUNCTION(cmd_scan)
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]);
+ if (mask & 2) shell_printf("%f ", measured[0][i]);
+ if (mask & 4) shell_printf("%f ", measured[1][i]);
+ if (mask & 8) shell_printf("%f ", measured[2][i]);
shell_printf("\r\n");
}
}
@@ -971,9 +1055,11 @@ set_frequencies(uint32_t start, uint32_t stop, uint16_t points)
// disable at out of sweep range
for (; i < POINTS_COUNT; i++)
frequencies[i] = 0;
+ setting.frequency_step = delta;
+ update_rbw();
}
-static void
+void
update_frequencies(void)
{
uint32_t start, stop;
@@ -992,7 +1078,9 @@ update_frequencies(void)
void
set_sweep_frequency(int type, uint32_t freq)
{
+#ifdef __VNA__
int cal_applied = cal_status & CALSTAT_APPLY;
+#endif
// Check frequency for out of bounds (minimum SPAN can be any value)
if (type != ST_SPAN && freq < START_MIN)
@@ -1003,78 +1091,80 @@ set_sweep_frequency(int type, uint32_t freq)
ensure_edit_config();
switch (type) {
case ST_START:
- config.freq_mode &= ~FREQ_MODE_CENTER_SPAN;
- if (frequency0 != freq) {
- frequency0 = freq;
+ setting.freq_mode &= ~FREQ_MODE_CENTER_SPAN;
+ if (setting.frequency0 != freq) {
+ setting.frequency0 = freq;
// if start > stop then make start = stop
- if (frequency1 < freq) frequency1 = freq;
+ if (setting.frequency1 < freq) setting.frequency1 = freq;
}
break;
case ST_STOP:
- config.freq_mode &= ~FREQ_MODE_CENTER_SPAN;
- if (frequency1 != freq) {
- frequency1 = freq;
+ setting.freq_mode &= ~FREQ_MODE_CENTER_SPAN;
+ if (setting.frequency1 != freq) {
+ setting.frequency1 = freq;
// if start > stop then make start = stop
- if (frequency0 > freq) frequency0 = freq;
+ if (setting.frequency0 > freq) setting.frequency0 = freq;
}
break;
case ST_CENTER:
- config.freq_mode |= FREQ_MODE_CENTER_SPAN;
- uint32_t center = frequency0 / 2 + frequency1 / 2;
+ setting.freq_mode |= FREQ_MODE_CENTER_SPAN;
+ uint32_t center = setting.frequency0 / 2 + setting.frequency1 / 2;
if (center != freq) {
- uint32_t span = frequency1 - frequency0;
+ uint32_t span = setting.frequency1 - setting.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;
+ setting.frequency0 = freq - span / 2;
+ setting.frequency1 = freq + span / 2;
}
break;
case ST_SPAN:
- config.freq_mode |= FREQ_MODE_CENTER_SPAN;
- if (frequency1 - frequency0 != freq) {
- uint32_t center = frequency0 / 2 + frequency1 / 2;
+ setting.freq_mode |= FREQ_MODE_CENTER_SPAN;
+ if (setting.frequency1 - setting.frequency0 != freq) {
+ uint32_t center = setting.frequency0 / 2 + setting.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;
+ setting.frequency0 = center - freq / 2;
+ setting.frequency1 = center + freq / 2;
}
break;
case ST_CW:
- config.freq_mode |= FREQ_MODE_CENTER_SPAN;
- if (frequency0 != freq || frequency1 != freq) {
- frequency0 = freq;
- frequency1 = freq;
+ setting.freq_mode |= FREQ_MODE_CENTER_SPAN;
+ if (setting.frequency0 != freq || setting.frequency1 != freq) {
+ setting.frequency0 = freq;
+ setting.frequency1 = freq;
}
break;
}
update_frequencies();
+#ifdef __VNA__
if (cal_auto_interpolate && cal_applied)
cal_interpolate(lastsaveid);
+#endif
}
uint32_t
get_sweep_frequency(int type)
{
// Obsolete, ensure correct start/stop, start always must be < stop
- if (frequency0 > frequency1) {
- uint32_t t = frequency0;
- frequency0 = frequency1;
- frequency1 = t;
+ if (setting.frequency0 > setting.frequency1) {
+ uint32_t t = setting.frequency0;
+ setting.frequency0 = setting.frequency1;
+ setting.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 frequency1 - frequency0;
- case ST_CW: return frequency0;
+ case ST_START: return setting.frequency0;
+ case ST_STOP: return setting.frequency1;
+ case ST_CENTER: return setting.frequency0/2 + setting.frequency1/2;
+ case ST_SPAN: return setting.frequency1 - setting.frequency0;
+ case ST_CW: return setting.frequency0;
}
return 0;
}
@@ -1115,7 +1205,7 @@ usage:
"\tsweep {%s} {freq(Hz)}\r\n", sweep_cmd);
}
-
+#ifdef __VNA__
static void
eterm_set(int term, float re, float im)
{
@@ -1532,13 +1622,15 @@ VNA_SHELL_FUNCTION(cmd_recall)
usage:
shell_printf("recall {id}\r\n");
}
+#endif
static const struct {
const char *name;
uint16_t refpos;
float scale_unit;
} trace_info[] = {
- { "LOGMAG", NGRIDY-1, 10.0 },
+ { "LOGMAG", NGRIDY, 10.0 },
+#ifdef __VNA__
{ "PHASE", NGRIDY/2, 90.0 },
{ "DELAY", NGRIDY/2, 1e-9 },
{ "SMITH", 0, 1.00 },
@@ -1549,12 +1641,17 @@ static const struct {
{ "IMAG", NGRIDY/2, 0.25 },
{ "R", NGRIDY/2, 100.0 },
{ "X", NGRIDY/2, 100.0 }
+#endif
};
+#ifdef __VNA__
static const char * const trc_channel_name[] = {
"CH0", "CH1"
};
-
+#endif
+const char * const trc_channel_name[] = {
+ "ACTUAL", "STORED", "COMPUTED"
+};
const char *get_trace_typename(int t)
{
return trace_info[trace[t].type].name;
@@ -1623,7 +1720,7 @@ VNA_SHELL_FUNCTION(cmd_trace)
if (argc == 0) {
for (t = 0; t < TRACES_MAX; t++) {
if (trace[t].enabled) {
- const char *type = get_trace_typename(t);
+ const char *type = unit_string[setting.unit]; // 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);
@@ -1633,63 +1730,78 @@ VNA_SHELL_FUNCTION(cmd_trace)
return;
}
- if (strcmp(argv[0], "all") == 0 &&
- argc > 1 && strcmp(argv[1], "off") == 0) {
- for (t = 0; t < TRACES_MAX; t++)
- set_trace_type(t, TRC_OFF);
- goto exit;
- }
-
- t = my_atoi(argv[0]);
- if (t < 0 || t >= TRACES_MAX)
- goto usage;
- if (argc == 1) {
+ if ('0' <= argv[0][0] && argv[0][0] <= '9') {
+ t = my_atoi(argv[0]);
+ if (argc != 1 || t < 0 || t >= TRACES_MAX)
+ goto usage;
const char *type = get_trace_typename(t);
const char *channel = trc_channel_name[trace[t].channel];
shell_printf("%d %s %s\r\n", t, type, channel);
return;
}
-#if MAX_TRACE_TYPE != 12
-#error "Trace type enum possibly changed, check cmd_trace function"
+#if MAX_UNIT_TYPE != 4
+#error "Unit 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;
+ static const char cmd_type_list[] = "dBm|dBmV|dBuV|V|W";
+ if (argc == 1) {
+ int type = get_str_index(argv[0], cmd_type_list);
+ if (type >= 0) {
+ set_unit(type);
+ goto update;
+ }
+ goto usage;
}
- // 0 1
- static const char cmd_scale_ref_list[] = "scale|refpos";
- if (argc >= 3) {
- switch (get_str_index(argv[1], cmd_scale_ref_list)) {
+ static const char cmd_store_list[] = "store|clear|subtract";
+ if (argc == 1) {
+ int type = get_str_index(argv[0], cmd_store_list);
+ if (type >= 0) {
+ switch(type) {
case 0:
- //trace[t].scale = my_atof(argv[2]);
- set_trace_scale(t, my_atof(argv[2]));
- goto exit;
+ set_storage();
+ goto update;
case 1:
- //trace[t].refpos = my_atof(argv[2]);
- set_trace_refpos(t, my_atof(argv[2]));
- goto exit;
- default:
- goto usage;
+ set_clear_storage();
+ goto update;
+ case 2:
+ set_subtract_storage();
+ goto update;
+ }
}
+ goto usage;
}
-check_ch_num:
- if (argc > 2) {
- int src = my_atoi(argv[2]);
- if (src != 0 && src != 1)
- goto usage;
- trace[t].channel = src;
+ // 0 1
+ static const char cmd_scale_ref_list[] = "scale|reflevel";
+ if (argc == 2) {
+ switch (get_str_index(argv[0], cmd_scale_ref_list)) {
+ case 0:
+ if (strcmp(argv[1],"auto") == 0) {
+ set_auto_reflevel(true);
+ } else {
+ user_set_scale(my_atof(argv[1]));
+ }
+ goto update;
+ case 1:
+ //trace[t].refpos = my_atof(argv[2]);
+ if (strcmp(argv[1],"auto") == 0) {
+ set_auto_reflevel(true);
+ } else {
+ user_set_reflevel(my_atof(argv[1]));
+ }
+ goto update;
+ }
+ goto usage;
}
-exit:
+update:
+redraw_request |= REDRAW_CAL_STATUS;
return;
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);
+ shell_printf("trace {%s}\r\n"\
+ "trace {%s}\r\n"\
+ "trace {%s} {value|auto}\r\n", cmd_store_list, cmd_type_list, cmd_scale_ref_list);
}
+#ifdef __VNA__
void set_electrical_delay(float picoseconds)
{
if (electrical_delay != picoseconds) {
@@ -1714,6 +1826,7 @@ VNA_SHELL_FUNCTION(cmd_edelay)
set_electrical_delay(my_atof(argv[0]));
}
}
+#endif
VNA_SHELL_FUNCTION(cmd_marker)
@@ -1722,7 +1835,7 @@ VNA_SHELL_FUNCTION(cmd_marker)
if (argc == 0) {
for (t = 0; t < MARKERS_MAX; t++) {
if (markers[t].enabled) {
- shell_printf("%d %d %d\r\n", t+1, markers[t].index, markers[t].frequency);
+ shell_printf("%d %d %d %.2f\r\n", t+1, markers[t].index, markers[t].frequency, actual_t[markers[t].index]);
}
}
return;
@@ -1738,7 +1851,7 @@ VNA_SHELL_FUNCTION(cmd_marker)
if (t < 0 || t >= MARKERS_MAX)
goto usage;
if (argc == 1) {
- shell_printf("%d %d %d\r\n", t+1, markers[t].index, markers[t].frequency);
+ shell_printf("%d %d %d %.2f\r\n", t+1, markers[t].index, markers[t].frequency, actual_t[markers[t].index]);
active_marker = t;
// select active marker
markers[t].enabled = TRUE;
@@ -1799,6 +1912,7 @@ VNA_SHELL_FUNCTION(cmd_frequencies)
}
}
+#ifdef __VNA__
static void
set_domain_mode(int mode) // accept DOMAIN_FREQ or DOMAIN_TIME
{
@@ -1863,6 +1977,7 @@ VNA_SHELL_FUNCTION(cmd_transform)
usage:
shell_printf("usage: transform {%s} [...]\r\n", cmd_transform_list);
}
+#endif
VNA_SHELL_FUNCTION(cmd_test)
{
@@ -1872,14 +1987,14 @@ VNA_SHELL_FUNCTION(cmd_test)
#if 0
int i;
for (i = 0; i < 100; i++) {
- palClearPad(GPIOC, GPIOC_LED);
+ palClearPad(GPIOB, GPIOB_LED);
set_frequency(10000000);
- palSetPad(GPIOC, GPIOC_LED);
+ palSetPad(GPIOB, GPIOB_LED);
chThdSleepMilliseconds(50);
- palClearPad(GPIOC, GPIOC_LED);
+ palClearPad(GPIOB, GPIOB_LED);
set_frequency(90000000);
- palSetPad(GPIOC, GPIOC_LED);
+ palSetPad(GPIOB, GPIOB_LED);
chThdSleepMilliseconds(50);
}
#endif
@@ -1891,9 +2006,9 @@ VNA_SHELL_FUNCTION(cmd_test)
mode = my_atoi(argv[0]);
for (i = 0; i < 20; i++) {
- palClearPad(GPIOC, GPIOC_LED);
+ palClearPad(GPIOB, GPIOB_LED);
ili9341_test(mode);
- palSetPad(GPIOC, GPIOC_LED);
+ palSetPad(GPIOB, GPIOB_LED);
chThdSleepMilliseconds(50);
}
#endif
@@ -1920,6 +2035,7 @@ VNA_SHELL_FUNCTION(cmd_test)
}
}
+#ifdef __VNA__
VNA_SHELL_FUNCTION(cmd_gain)
{
int rvalue;
@@ -1980,6 +2096,7 @@ VNA_SHELL_FUNCTION(cmd_stat)
// extern int awd_count;
// shell_printf("awd: %d\r\n", awd_count);
}
+#endif
#ifndef VERSION
#define VERSION "unknown"
@@ -2082,7 +2199,7 @@ VNA_SHELL_FUNCTION(cmd_threads)
thread_t *tp;
(void)argc;
(void)argv;
- shell_printf("stklimit| stack|stk free| addr|refs|prio| state| name"VNA_SHELL_NEWLINE_STR);
+ shell_printf("stklimit| |stk free| addr|refs|prio| state| name"VNA_SHELL_NEWLINE_STR);
tp = chRegFirstThread();
do {
uint32_t max_stack_use = 0U;
@@ -2103,6 +2220,8 @@ VNA_SHELL_FUNCTION(cmd_threads)
}
#endif
+#include "sa_cmd.c"
+
//=============================================================================
VNA_SHELL_FUNCTION(cmd_help);
@@ -2121,7 +2240,9 @@ static const VNAShellCommand commands[] =
{"version" , cmd_version , 0},
{"reset" , cmd_reset , 0},
{"freq" , cmd_freq , CMD_WAIT_MUTEX},
+#ifdef __VNA__
{"offset" , cmd_offset , 0},
+#endif
#ifdef ENABLE_TIME_COMMAND
{"time" , cmd_time , 0},
#endif
@@ -2133,11 +2254,13 @@ static const VNAShellCommand commands[] =
{"dump" , cmd_dump , 0},
#endif
{"frequencies" , cmd_frequencies , 0},
+#ifdef __VNA__
{"port" , cmd_port , 0},
{"stat" , cmd_stat , 0},
{"gain" , cmd_gain , 0},
{"power" , cmd_power , 0},
{"sample" , cmd_sample , 0},
+#endif
// {"gamma" , cmd_gamma , 0},
{"scan" , cmd_scan , CMD_WAIT_MUTEX},
{"sweep" , cmd_sweep , 0},
@@ -2146,19 +2269,25 @@ static const VNAShellCommand commands[] =
{"touchtest" , cmd_touchtest , CMD_WAIT_MUTEX},
{"pause" , cmd_pause , 0},
{"resume" , cmd_resume , 0},
+#ifdef __VNA__
{"cal" , cmd_cal , CMD_WAIT_MUTEX},
{"save" , cmd_save , 0},
{"recall" , cmd_recall , CMD_WAIT_MUTEX},
+#endif
{"trace" , cmd_trace , 0},
{"marker" , cmd_marker , 0},
+#ifdef __VNA__
{"edelay" , cmd_edelay , 0},
+#endif
{"capture" , cmd_capture , CMD_WAIT_MUTEX},
{"vbat" , cmd_vbat , 0},
#ifdef ENABLE_VBAT_OFFSET_COMMAND
{"vbat_offset" , cmd_vbat_offset , 0},
#endif
+#ifdef __VNA__
{"transform" , cmd_transform , 0},
{"threshold" , cmd_threshold , 0},
+#endif
{"help" , cmd_help , 0},
#ifdef ENABLE_INFO_COMMAND
{"info" , cmd_info , 0},
@@ -2166,6 +2295,34 @@ static const VNAShellCommand commands[] =
#ifdef ENABLE_COLOR_COMMAND
{"color" , cmd_color , 0},
#endif
+ { "if", cmd_if, 0 },
+ { "attenuate", cmd_attenuate, 0 },
+ { "level", cmd_level, 0 },
+ { "leveloffset", cmd_leveloffset, 0 },
+ { "levelsweep", cmd_levelsweep, 0 },
+ { "modulation", cmd_modulation, 0 },
+ { "rbw", cmd_rbw, 0 },
+ { "mode", cmd_mode, 0 },
+ { "spur", cmd_spur, 0 },
+ { "load", cmd_load, 0 },
+ { "selftest", cmd_selftest, 0 },
+#ifdef __ULTRA_SA__
+ { "x", cmd_x, 0 },
+#endif
+ { "y", cmd_y, 0 },
+ { "i", cmd_i, 0 },
+ { "v", cmd_v, 0 },
+ { "a", cmd_a, 0 },
+ { "b", cmd_b, 0 },
+ { "t", cmd_t, 0 },
+ { "e", cmd_e, 0 },
+ { "s", cmd_s, 0 },
+ { "m", cmd_m, 0 },
+ { "p", cmd_p, 0 },
+ { "w", cmd_w, 0 },
+ { "o", cmd_o, 0 },
+ { "d", cmd_d, 0 },
+ { "correction", cmd_correction, 0 },
#ifdef ENABLE_THREADS_COMMAND
{"threads" , cmd_threads , 0},
#endif
@@ -2282,7 +2439,7 @@ THD_FUNCTION(myshellThread, p)
{
(void)p;
chRegSetThreadName("shell");
- shell_printf(VNA_SHELL_NEWLINE_STR"NanoVNA Shell"VNA_SHELL_NEWLINE_STR);
+ shell_printf(VNA_SHELL_NEWLINE_STR"tinySA Shell"VNA_SHELL_NEWLINE_STR);
while (true) {
shell_printf(VNA_SHELL_PROMPT_STR);
if (VNAShell_readLine(shell_line, VNA_SHELL_MAX_LENGTH))
@@ -2293,6 +2450,7 @@ THD_FUNCTION(myshellThread, p)
}
#endif
+#ifdef __VNA__
// I2C clock bus setting: depend from STM32_I2C1SW in mcuconf.h
static const I2CConfig i2ccfg = {
.timingr = // TIMINGR register initialization. (use I2C timing configuration tool for STM32F3xx and STM32F0xx microcontrollers (AN4235))
@@ -2320,13 +2478,77 @@ static const I2CConfig i2ccfg = {
.cr1 = 0, // CR1 register initialization.
.cr2 = 0 // CR2 register initialization.
};
-
static DACConfig dac1cfg1 = {
//init: 2047U,
init: 1922U,
datamode: DAC_DHRM_12BIT_RIGHT
};
+#endif
+
+
+static const GPTConfig gpt4cfg = {
+ 1000000, // 1 MHz timer clock.
+ NULL, // No callback
+ 0, 0
+};
+
+void my_microsecond_delay(int t)
+{
+ if (t>0) gptPolledDelay(&GPTD14, t); // t us delay
+}
+#if 0
+/*
+ * UART driver configuration structure.
+ */
+static UARTConfig uart_cfg_1 = {
+ NULL, //txend1,
+ NULL, //txend2,
+ NULL, //rxend,
+ NULL, //rxchar,
+ NULL, //rxerr,
+ 800000,
+ 0,
+ 0, //USART_CR2_LINEN,
+ 0
+};
+#endif
+
+#if 0
+static const SerialConfig default_config =
+{
+ 9600,
+ 0,
+ USART_CR2_STOP2_BITS,
+ 0
+};
+
+void myWrite(char *buf)
+{
+ int len = strlen(buf);
+ while(len-- > 0) {
+ sdPut(&SD1,*buf++);
+ osalThreadSleepMicroseconds(1000);
+ }
+}
+
+static int serial_count = 0;
+int mySerialReadline(unsigned char *buf, int len)
+{
+ int i;
+ do {
+ i = sdReadTimeout(&SD1,&buf[serial_count], 20-serial_count,TIME_IMMEDIATE);
+ serial_count += i;
+ if (i > 0)
+ osalThreadSleepMicroseconds(1000);
+ } while (serial_count < len && i > 0);
+ if (buf[serial_count-1] == '\n') {
+ serial_count = 0;
+ return(i);
+ } else
+ return 0;
+}
+#endif
// Main thread stack size defined in makefile USE_PROCESS_STACKSIZE = 0x200
// Profile stack usage (enable threads command by def ENABLE_THREADS_COMMAND) show:
@@ -2339,8 +2561,10 @@ int main(void)
//palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN);
//palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN);
+#ifdef __VNA__
i2cStart(&I2CD1, &i2ccfg);
si5351_init();
+#endif
// MCO on PA8
//palSetPadMode(GPIOA, 8, PAL_MODE_ALTERNATE(0));
@@ -2359,26 +2583,83 @@ int main(void)
usbStart(serusbcfg.usbp, &usbcfg);
usbConnectBus(serusbcfg.usbp);
-/*
+ /*
+ * Powercycle the RF part to reset SI4432
+ */
+
+ palClearPad(GPIOB, GPIO_RF_PWR);
+ chThdSleepMilliseconds(200);
+ palSetPad(GPIOB, GPIO_RF_PWR);
+ chThdSleepMilliseconds(500);
+
+
+#if 0
+ /*
+ * UART initialize
+ */
+ uartStart(&UARTD1, &uart_cfg_1);
+
+ uartStartSend(&UARTD1, 1, "H");
+ uartStartReceive(&UARTD1, 1, buf);
+#endif
+
+#if 0
+ palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(1)); // USART1 TX.
+ palSetPadMode(GPIOA,10, PAL_MODE_ALTERNATE(1)); // USART1 RX.
+
+ uint8_t buf[10];
+ sdStart(&SD1,&default_config);
+ osalThreadSleepMilliseconds(10);
+ mySerialWrite("Hallo!?\n");
+
+ osalThreadSleepMilliseconds(10);
+
+ mySerialReadline(buf, 10);
+
+ sdReadTimeout(&SD1,buf,10, 10);
+
+ sdWrite(&SD1,(const uint8_t *)"Test123",7);
+ osalThreadSleepMicroseconds(10);
+ sdReadTimeout(&SD1,buf,10,TIME_IMMEDIATE);
+ sdReadTimeout(&SD1,buf,10, 10);
+ int i = sdReadTimeout(&SD1,buf,10,TIME_IMMEDIATE);
+
+#endif
+#ifdef __ULTRA_SA__
+ ADF4351_Setup();
+#endif
+ /*
* SPI LCD Initialize
*/
ili9341_init();
+/*
+ * Initiate 1 micro second timer
+ */
+ gptStart(&GPTD14, &gpt4cfg);
+ gptPolledDelay(&GPTD14, 10); // 10 us delay
+
/* restore config */
config_recall();
+ if (caldata_recall(0) == -1) {
+ load_default_properties();
+ }
/* restore frequencies and calibration 0 slot properties from flash memory */
- caldata_recall(0);
-
+#ifdef __VNA__
dac1cfg1.init = config.dac_value;
/*
* Starting DAC1 driver, setting up the output pin as analog as suggested
* by the Reference Manual.
*/
dacStart(&DACD2, &dac1cfg1);
-
+#endif
+ setupSA();
+ sweep_points = 290;
/* initial frequencies */
update_frequencies();
+
+#ifdef __VNA__
/*
* I2S Initialize
*/
@@ -2387,11 +2668,28 @@ int main(void)
i2sObjectInit(&I2SD2);
i2sStart(&I2SD2, &i2sconfig);
i2sStartExchange(&I2SD2);
-
+#endif
+ area_height = AREA_HEIGHT_NORMAL;
ui_init();
//Initialize graph plotting
plot_init();
+
+// if (setting.mode != -1) {
+// menu_mode_cb(setting.mode,0);
+// }
redraw_frame();
+
+ set_mode(M_HIGH);
+ sweep(true);
+ osalThreadSleepMilliseconds(100);
+
+ set_mode(M_LOW);
+ sweep(true);
+
+ set_refer_output(-1);
+ ui_mode_menu(); // Show menu when autostarting mode
+
+
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO-1, Thread1, NULL);
while (1) {
@@ -2405,7 +2703,7 @@ int main(void)
myshellThread, NULL);
chThdWait(shelltp);
#else
- shell_printf(VNA_SHELL_NEWLINE_STR"NanoVNA Shell"VNA_SHELL_NEWLINE_STR);
+ shell_printf(VNA_SHELL_NEWLINE_STR"tinySA Shell"VNA_SHELL_NEWLINE_STR);
do {
shell_printf(VNA_SHELL_PROMPT_STR);
if (VNAShell_readLine(shell_line, VNA_SHELL_MAX_LENGTH))
diff --git a/mcuconf.h b/mcuconf.h
index a1da287..241b42d 100644
--- a/mcuconf.h
+++ b/mcuconf.h
@@ -104,7 +104,7 @@
#define STM32_GPT_USE_TIM1 FALSE
#define STM32_GPT_USE_TIM2 FALSE
#define STM32_GPT_USE_TIM3 TRUE
-#define STM32_GPT_USE_TIM14 FALSE
+#define STM32_GPT_USE_TIM14 TRUE
#define STM32_GPT_TIM1_IRQ_PRIORITY 2
#define STM32_GPT_TIM2_IRQ_PRIORITY 2
#define STM32_GPT_TIM3_IRQ_PRIORITY 2
@@ -113,7 +113,7 @@
/*
* I2C driver system settings.
*/
-#define STM32_I2C_USE_I2C1 TRUE
+#define STM32_I2C_USE_I2C1 FALSE
#define STM32_I2C_USE_I2C2 FALSE
#define STM32_I2C_BUSY_TIMEOUT 50
#define STM32_I2C_I2C1_IRQ_PRIORITY 3
@@ -133,7 +133,7 @@
* I2S driver system settings.
*/
#define STM32_I2S_USE_SPI1 FALSE
-#define STM32_I2S_USE_SPI2 TRUE
+#define STM32_I2S_USE_SPI2 FALSE
#define STM32_I2S_SPI1_MODE (STM32_I2S_MODE_MASTER | \
STM32_I2S_MODE_RX)
#define STM32_I2S_SPI2_MODE (STM32_I2S_MODE_SLAVE | \
diff --git a/nanovna.h b/nanovna.h
index ec03e18..a8f6484 100644
--- a/nanovna.h
+++ b/nanovna.h
@@ -1,5 +1,4 @@
-/*
- * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com
+/* Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com
* All rights reserved.
*
* This is free software; you can redistribute it and/or modify
@@ -22,10 +21,44 @@
// Need enable HAL_USE_SPI in halconf.h
#define __USE_DISPLAY_DMA__
+#define __SA__
+//#define __SIMULATION__
+//#define __PIPELINE__
+#define __SCROLL__
+#define __ICONS__
+#define __MEASURE__
+#define __SELFTEST__
+#define __CALIBRATE__
+#define __FAST_SWEEP__ // Pre-fill SI4432 RSSI buffer to get fastest sweep in zero span mode
+
+//#define __ULTRA__ // Add harmonics mode on low input.
+//#define __ULTRA_SA__ // Adds ADF4351 control for extra high 1st IF stage
+#define __SPUR__ // Does spur reduction by shifting IF
+
/*
* main.c
*/
+#ifdef __SA__
+#define POINTS_COUNT 290
+#define MARKER_COUNT 4
+
+#define TRACES_MAX 3
+#define TRACE_AGE 3
+#define TRACE_ACTUAL 2
+#define TRACE_STORED 1
+#define TRACE_TEMP 0
+// #define age_t measured[TRACE_AGE]
+#define stored_t measured[TRACE_STORED]
+#define actual_t measured[TRACE_ACTUAL]
+#define temp_t measured[TRACE_TEMP]
+
+#define CORRECTION_POINTS 10 // Frequency dependent level correction table entries
+
+typedef float measurement_t[TRACES_MAX][POINTS_COUNT];
+extern measurement_t measured;
+#endif
+#ifdef __VNA__
// Minimum frequency set
#define START_MIN 50000
// Maximum frequency set
@@ -81,25 +114,120 @@ extern float measured[2][POINTS_COUNT][2];
void cal_collect(int type);
void cal_done(void);
-
+#endif
#define MAX_FREQ_TYPE 5
enum stimulus_type {
ST_START=0, ST_STOP, ST_CENTER, ST_SPAN, ST_CW
};
+void update_frequencies(void);
void set_sweep_frequency(int type, uint32_t frequency);
uint32_t get_sweep_frequency(int type);
-
+void my_microsecond_delay(int t);
double my_atof(const char *p);
+int shell_printf(const char *fmt, ...);
void toggle_sweep(void);
+void toggle_mute(void);
void load_default_properties(void);
-#define SWEEP_ENABLE 0x01
-#define SWEEP_ONCE 0x02
+extern float perform(bool b, int i, uint32_t f, int e);
+enum {
+ AV_OFF, AV_MIN, AV_MAX_HOLD, AV_MAX_DECAY, AV_4, AV_16
+};
+enum {
+ M_LOW, M_HIGH, M_GENLOW, M_GENHIGH, M_ULTRA
+};
+
+enum {
+ MO_NONE, MO_AM_1kHz, MO_AM_10Hz, MO_NFM, MO_WFM, MO_EXTERNAL,
+};
+
+#define MODE_OUTPUT(x) ((x) == M_GENLOW || (x) == M_GENHIGH )
+#ifdef __ULTRA__
+#define MODE_INPUT(x) ((x) == M_LOW || (x) == M_HIGH || (x) == M_ULTRA )
+#else
+#define MODE_INPUT(x) ((x) == M_LOW || (x) == M_HIGH )
+#endif
+#define MODE_HIGH(x) ((x) == M_HIGH || (x) == M_GENHIGH )
+#define MODE_LOW(x) ((x) == M_LOW || (x) == M_GENLOW )
+#define MODE_SELECT(x) (MODE_HIGH(x) ? 1 : 0)
+
+#define SWEEP_ENABLE 0x01
+#define SWEEP_ONCE 0x02
+#define SWEEP_CALIBRATE 0x04
+#define SWEEP_SELFTEST 0x08
+#define SWEEP_REMOTE 0x10
+
extern int8_t sweep_mode;
+extern bool completed;
extern const char *info_about[];
+// ------------------------------- sa_core.c ----------------------------------
+void reset_settings(int);
+//void ui_process_touch(void);
+void SetPowerGrid(int);
+void SetRefLevel(float);
+void set_refer_output(int);
+void toggle_below_IF(void);
+int get_refer_output(void);
+void set_attenuation(int);
+int get_attenuation(void);
+void set_harmonic(int);
+//extern int setting.harmonic;
+int search_is_greater(void);
+void set_auto_attenuation(void);
+void set_auto_reflevel(int);
+int is_paused(void);
+void set_actual_power(float);
+void SetGenerate(int);
+void set_RBW(int);
+void set_drive(int d);
+void set_IF(int f);
+void set_step_delay(int t);
+void set_repeat(int);
+void set_level_sweep(float);
+void set_level(float);
+void set_sweep_time(float);
+//extern int setting.repeat;
+//extern int setting.rbw;
+#ifdef __SPUR__
+//extern int setting.spur;
+void SetSpur(int v);
+#endif
+void set_average(int);
+int GetAverage(void);
+//extern int setting.average;
+void set_storage(void);
+void set_clear_storage(void);
+void set_subtract_storage(void);
+void toggle_waterfall(void);
+void set_mode(int);
+int GetMode(void);
+void set_reflevel(float);
+void user_set_reflevel(float);
+#define REFLEVEL_MAX 9999.0
+#define REFLEVEL_MIN 1.0e-12
+void set_scale(float);
+void user_set_scale(float);
+void AllDirty(void);
+void MenuDirty(void);
+void toggle_LNA(void);
+void toggle_AGC(void);
+void redrawHisto(void);
+void self_test(int);
+void set_decay(int);
+void set_noise(int);
+void toggle_tracking_output(void);
+extern int32_t frequencyExtra;
+void set_10mhz(int);
+void set_modulation(int);
+//extern int setting.modulation;
+void set_measurement(int);
+// extern int settingSpeed;
+//extern int setting.step_delay;
+void sweep_remote(void);
+#ifdef __VNA__
/*
* dsp.c
*/
@@ -121,7 +249,9 @@ void reset_dsp_accumerator(void);
void calculate_gamma(float *gamma);
void fetch_amplitude(float *gamma);
void fetch_amplitude_ref(float *gamma);
+#endif
+#ifdef __VNA__
/*
* tlv320aic3204.c
*/
@@ -130,21 +260,32 @@ extern void tlv320aic3204_init(void);
extern void tlv320aic3204_set_gain(int lgain, int rgain);
extern void tlv320aic3204_select(int channel);
+#endif
/*
* plot.c
*/
// Offset of plot area
-#define OFFSETX 10
-#define OFFSETY 0
-
-// WIDTH better be n*(POINTS_COUNT-1)
-#define WIDTH 300
+#define OFFSETX 30
+#define OFFSETY 0
+#define BUTTON_WIDTH 60
+#ifdef __SCROLL__
+#define HEIGHT _height
+extern int _height;
+#define HEIGHT_SCROLL 180
+#define HEIGHT_NOSCROLL 232
+#else
// HEIGHT = 8*GRIDY
#define HEIGHT 232
+// WIDTH better be n*(POINTS_COUNT-1)
+#endif
+#define WIDTH 290
+
+#define CELLWIDTH (32)
+#define CELLHEIGHT (32)
-//#define NGRIDY 10
-#define NGRIDY 8
+#define NGRIDY 10
+//#define NGRIDY 9
#define FREQUENCIES_XPOS1 OFFSETX
#define FREQUENCIES_XPOS2 200
@@ -155,8 +296,8 @@ extern void tlv320aic3204_select(int channel);
#define GRIDY (HEIGHT / NGRIDY)
//
-#define CELLOFFSETX 5
-#define AREA_WIDTH_NORMAL (CELLOFFSETX + WIDTH + 1 + 4)
+#define CELLOFFSETX 0
+#define AREA_WIDTH_NORMAL (CELLOFFSETX + WIDTH)
#define AREA_HEIGHT_NORMAL ( HEIGHT + 1)
// Smith/polar chart
@@ -169,6 +310,7 @@ extern int16_t area_height;
// font
extern const uint8_t x5x7_bits [];
+extern const uint16_t x7x13b_bits [];
#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
@@ -190,8 +332,6 @@ extern const uint16_t numfont16x22[];
#define S_OHM "\036"
// trace
-#define TRACES_MAX 4
-
#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
@@ -209,6 +349,15 @@ enum trace_type {
// Electrical Delay
// Phase
+#define MAX_UNIT_TYPE 4
+enum unit_type {
+ U_DBM=0, U_DBMV, U_DBUV, U_VOLT, U_WATT, U_DBC // dBc only for displaying delta marker info
+};
+#define UNIT_IS_LINEAR(T) ( T >= U_VOLT ? true : false)
+#define UNIT_IS_LOG(T) ( T >= U_VOLT ? false : true)
+
+float value(float);
+
typedef struct trace {
uint8_t enabled;
uint8_t type;
@@ -231,13 +380,21 @@ typedef struct config {
uint16_t trace_color[TRACES_MAX];
int16_t touch_cal[4];
int8_t freq_mode;
+#ifdef __VNA__
uint32_t harmonic_freq_threshold;
+#endif
uint16_t vbat_offset;
- uint8_t _reserved[22];
+ int16_t low_level_offset;
+ int16_t high_level_offset;
+ uint32_t correction_frequency[CORRECTION_POINTS];
+ float correction_value[CORRECTION_POINTS];
+// uint8_t _reserved[22];
uint32_t checksum;
} config_t;
extern config_t config;
+//#define settingLevelOffset config.level_offset
+int get_level_offset(void);
void set_trace_type(int t, int type);
void set_trace_channel(int t, int channel);
@@ -246,21 +403,31 @@ void set_trace_refpos(int t, float refpos);
float get_trace_scale(int t);
float get_trace_refpos(int t);
const char *get_trace_typename(int t);
+extern int in_selftest;
+#ifdef __VNA
void set_electrical_delay(float picoseconds);
float get_electrical_delay(void);
float groupdelay_from_array(int i, float array[POINTS_COUNT][2]);
-
+#endif
// marker
+enum {
+ M_NORMAL=0,M_REFERENCE=1, M_DELTA=2, M_NOISE=4, M_TRACKING=8, M_DELETE=16 // Tracking must be last.
+};
-#define MARKERS_MAX 4
+enum {
+ M_DISABLED = false, M_ENABLED = true
+};
-typedef struct marker {
+typedef struct {
int8_t enabled;
+ int8_t mtype;
int16_t index;
uint32_t frequency;
} marker_t;
+#define MARKERS_MAX 4
+
extern int8_t previous_marker;
extern int8_t marker_tracking;
@@ -272,7 +439,7 @@ void redraw_frame(void);
void request_to_draw_cells_behind_menu(void);
void request_to_draw_cells_behind_numeric_input(void);
void redraw_marker(int marker);
-void plot_into_index(float measured[2][POINTS_COUNT][2]);
+void plot_into_index(measurement_t measured);
void force_set_markmap(void);
void draw_frequencies(void);
void draw_all(bool flush);
@@ -287,6 +454,10 @@ void set_marker_search(int mode);
int marker_search(void);
int marker_search_left(int from);
int marker_search_right(int from);
+int marker_search_left_max(int from);
+int marker_search_right_max(int from);
+int marker_search_left_min(int from);
+int marker_search_right_min(int from);
// _request flag for update screen
#define REDRAW_CELLS (1<<0)
@@ -302,25 +473,36 @@ extern volatile uint8_t redraw_request;
*/
// SPI bus revert byte order
//gggBBBbb RRRrrGGG
-#define RGB565(r,g,b) ( (((g)&0x1c)<<11) | (((b)&0xf8)<<5) | ((r)&0xf8) | (((g)&0xe0)>>5) )
+#define byteReverse16(x) (uint16_t)(((x) << 8) & 0xff00) | (((x) >> 8) & 0xff)
+#define RGB565(r,g,b) byteReverse16( ((((uint16_t)r)<<8)&0b1111100000000000) | ((((uint16_t)g)<<3)&0b0000011111100000) | ((((uint16_t)b)>>3)&0b0000000000011111) )
+
+//#define RGB565(r,g,b) ( (((g)&0x1c)<<11) | (((b)&0xf8)<<5) | ((r)&0xf8) | (((g)&0xe0)>>5) )
#define RGBHEX(hex) ( (((hex)&0x001c00)<<3) | (((hex)&0x0000f8)<<5) | (((hex)&0xf80000)>>16) | (((hex)&0x00e000)>>13) )
// Define size of screen buffer in pixels (one pixel 16bit size)
-#define SPI_BUFFER_SIZE 2048
+#define SPI_BUFFER_SIZE 1024
+
+#define LCD_WIDTH 320
+#define LCD_HEIGHT 240
#define DEFAULT_FG_COLOR RGB565(255,255,255)
#define DEFAULT_BG_COLOR RGB565( 0, 0, 0)
+#define DARK_GREY RGB565(140,140,140)
+#define LIGHT_GREY RGB565(220,220,220)
#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_TRACE_1_COLOR RGB565(255, 0, 0) /* RGB565(255,255, 0) */
+#define DEFAULT_TRACE_2_COLOR RGB565( 0,255, 0)/* RGB565( 0,255,255) */
+#define DEFAULT_TRACE_3_COLOR RGB565(255,255, 0)/* 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 BRIGHT_COLOR_BLUE RGB565(200,200,255)
+#define BRIGHT_COLOR_RED RGB565(255,200,200)
+#define BRIGHT_COLOR_GREEN RGB565(200,255,200)
extern uint16_t foreground_color;
extern uint16_t background_color;
@@ -331,12 +513,18 @@ void ili9341_init(void);
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);
+#if 0
void ili9341_set_foreground(uint16_t fg);
void ili9341_set_background(uint16_t fg);
+#else
+#define ili9341_set_foreground(fg) { foreground_color = fg; }
+#define ili9341_set_background(bg) { background_color = bg;}
+#endif
void ili9341_clear_screen(void);
void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *bitmap);
void ili9341_drawchar(uint8_t ch, int x, int y);
void ili9341_drawstring(const char *str, int x, int y);
+void ili9341_drawstring_7x13(const char *str, int x, int y);
void ili9341_drawstringV(const char *str, int x, int y);
int ili9341_drawchar_size(uint8_t ch, int x, int y, uint8_t size);
void ili9341_drawstring_size(const char *str, int x, int y, uint8_t size);
@@ -349,73 +537,192 @@ void show_logo(void);
/*
* flash.c
*/
-#define SAVEAREA_MAX 5
-// Begin addr 0x08018000
-#define SAVE_CONFIG_AREA_SIZE 0x00008000
+
+
+typedef struct setting
+{
+ uint32_t magic;
+// uint32_t _frequency0;
+// uint32_t _frequency1;
+ int mode;
+ uint16_t _sweep_points;
+ int attenuate;
+ int auto_attenuation;
+ int step_atten;
+ int rbw;
+ int below_IF;
+ int average;
+ int show_stored;
+ int subtract_stored;
+ int drive; // 0-7 , 7=+20dBm, 3dB steps
+ int agc;
+ int lna;
+ int auto_reflevel;
+ float reflevel;
+ float scale;
+ int tracking;
+ int modulation;
+ int step_delay;
+ int frequency_step;
+ int test;
+ int harmonic;
+ int decay;
+ int noise;
+ float vbw;
+ int tracking_output;
+ int repeat;
+ uint32_t frequency0;
+ uint32_t frequency1;
+ uint32_t frequency_IF;
+ int freq_mode;
+ int measurement;
+ int refer;
+ int spur;
+ trace_t _trace[TRACES_MAX];
+ marker_t _markers[MARKERS_MAX];
+ int8_t _active_marker;
+ int8_t unit;
+ float offset;
+ float trigger_level;
+ int trigger;
+ int linearity_step;
+ float level;
+ float level_sweep;
+ float sweep_time;
+ float actual_sweep_time;
+ int test_argument;
+ int auto_IF;
+ unsigned int unit_scale_index;
+ float unit_scale;
+ int mute;
+ uint32_t checksum;
+}setting_t;
+
+extern setting_t setting;
+
+extern int setting_frequency_10mhz;
+void reset_settings(int m);
+
+
+#define S_IS_AUTO(x) ((x)&2)
+#define S_STATE(X) ((X)&1)
+enum { S_OFF=0, S_ON=1, S_AUTO_OFF=2, S_AUTO_ON=3 };
+
+#ifdef __FAST_SWEEP__
+#define MINIMUM_SWEEP_TIME 3 // Minimum sweep time on zero span in miliseconds
+#else
+#define MINIMUM_SWEEP_TIME 15 // Minimum sweep time on zero span in miliseconds
+#endif
+#define REPEAT_TIME 134.0 // Time per extra repeat in uS
+#define MEASURE_TIME 175.0 // Time per vbwstep without stepdelay in uS
+
+extern uint32_t frequencies[POINTS_COUNT];
+extern const float unit_scale_value[];
+extern const char * const unit_scale_text[];
+
+#if 1
+#define SAVEAREA_MAX 9
// config save area
-#define SAVE_CONFIG_ADDR 0x08018000
+#define SAVE_CONFIG_ADDR 0x0801B000
+// setting_t save area
+#define SAVE_PROP_CONFIG_0_ADDR 0x0801B800
+#define SAVE_PROP_CONFIG_1_ADDR 0x0801C000
+#define SAVE_PROP_CONFIG_2_ADDR 0x0801C800
+#define SAVE_PROP_CONFIG_3_ADDR 0x0801D000
+#define SAVE_PROP_CONFIG_4_ADDR 0x0801D800
+#define SAVE_PROP_CONFIG_5_ADDR 0x0801E000
+#define SAVE_PROP_CONFIG_6_ADDR 0x0801E800
+#define SAVE_PROP_CONFIG_7_ADDR 0x0801F000
+#define SAVE_PROP_CONFIG_8_ADDR 0x0801F800
+
+#define SAVE_CONFIG_AREA_SIZE (0x0801F800 - SAVE_CONFIG_ADDR) // Should include all save slots
+
+#else
+#define SAVEAREA_MAX 4
+// Begin addr 0x0801C000
+#define SAVE_CONFIG_AREA_SIZE 0x00004000
+// config save area
+#define SAVE_CONFIG_ADDR 0x0801C000
// 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_0_ADDR 0x0801C800
+#define SAVE_PROP_CONFIG_1_ADDR 0x0801D000
+#define SAVE_PROP_CONFIG_2_ADDR 0x0801D800
+#define SAVE_PROP_CONFIG_3_ADDR 0x0801E000
#define SAVE_PROP_CONFIG_4_ADDR 0x0801e800
-
+#endif
+#if 0
typedef struct properties {
uint32_t magic;
- uint32_t _frequency0;
- uint32_t _frequency1;
+ preset_t setting;
+// uint32_t _frequency0;
+// uint32_t _frequency1;
uint16_t _sweep_points;
+#ifdef __VNA__
uint16_t _cal_status;
- uint32_t _frequencies[POINTS_COUNT];
+#endif
+#ifdef __SA__
+// uint32_t _frequency_IF; //IF frequency
+#endif
+// uint32_t _frequencies[POINTS_COUNT];
+#ifdef __VNA__
float _cal_data[5][POINTS_COUNT][2];
float _electrical_delay; // picoseconds
-
+#endif
trace_t _trace[TRACES_MAX];
marker_t _markers[MARKERS_MAX];
-
- float _velocity_factor; // %
int8_t _active_marker;
+#ifdef __VNA__
+ float _velocity_factor; // %
uint8_t _domain_mode; /* 0bxxxxxffm : where ff: TD_FUNC m: DOMAIN_MODE */
uint8_t _marker_smith_format;
uint8_t _bandwidth;
- uint8_t _reserved[50];
+#endif
+ uint8_t _reserved[2];
uint32_t checksum;
} properties_t;
+#endif
+
//sizeof(properties_t) == 0x1200
#define CONFIG_MAGIC 0x434f4e45 /* 'CONF' */
extern int16_t lastsaveid;
-extern properties_t *active_props;
-extern properties_t current_props;
+//extern properties_t *active_props;
+
+//extern properties_t current_props;
-#define frequency0 current_props._frequency0
-#define frequency1 current_props._frequency1
-#define sweep_points current_props._sweep_points
+//#define frequency0 current_props._frequency0
+//#define frequency1 current_props._frequency1
+#define sweep_points setting._sweep_points
+#ifdef __VNA__
#define cal_status current_props._cal_status
-#define frequencies current_props._frequencies
+#endif
+#ifdef __SA__
+//#define frequency_IF current_props._frequency_IF
+#endif
+//#define frequencies current_props._frequencies
+#ifdef __VNA__
#define cal_data active_props->_cal_data
#define electrical_delay current_props._electrical_delay
-
-#define trace current_props._trace
-#define markers current_props._markers
-#define active_marker current_props._active_marker
+#endif
+#define trace setting._trace
+#define markers setting._markers
+#define active_marker setting._active_marker
+#ifdef __VNA__
#define domain_mode current_props._domain_mode
#define velocity_factor current_props._velocity_factor
#define marker_smith_format current_props._marker_smith_format
#define bandwidth current_props._bandwidth
+#endif
-#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);
+#define FREQ_IS_STARTSTOP() (!(setting.freq_mode&FREQ_MODE_CENTER_SPAN))
+#define FREQ_IS_CENTERSPAN() (setting.freq_mode&FREQ_MODE_CENTER_SPAN)
+#define FREQ_IS_CW() (setting.frequency0 == setting.frequency1)
int caldata_recall(int id);
-const properties_t *caldata_ref(int id);
-
+int caldata_save(int id);
+//const properties_t *caldata_ref(int id);
int config_save(void);
int config_recall(void);
@@ -426,11 +733,17 @@ void clear_all_config_prop_data(void);
*/
extern void ui_init(void);
extern void ui_process(void);
+int current_menu_is_form(void);
+
+void menu_mode_cb(int, uint8_t);
+void ui_mode_normal(void);
+void ui_mode_menu(void);
// Irq operation process set
#define OP_NONE 0x00
#define OP_LEVER 0x01
#define OP_TOUCH 0x02
+#define OP_CONSOLE 0x04
//#define OP_FREQCHANGE 0x04
extern volatile uint8_t operation_requested;
@@ -448,11 +761,13 @@ 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
+ float value; // for editing at numeric input area
// uint32_t previous_value;
uint8_t lever_mode;
uint8_t marker_delta;
+ uint8_t marker_noise;
uint8_t marker_tracking;
+ char text[20];
} uistat_t;
extern uistat_t uistat;
@@ -486,11 +801,63 @@ int16_t adc_vbat_read(void);
*/
int plot_printf(char *str, int, const char *fmt, ...);
#define PULSE do { palClearPad(GPIOC, GPIOC_LED); palSetPad(GPIOC, GPIOC_LED);} while(0)
+//extern int setting_attenuate;
+//extern int settingPowerCal;
+//extern int setting_step_delay;
+//extern int actualStepDelay;
+//extern int setting_mode;
+void update_rbw(void);
+int get_actual_RBW(void);
+
+#define byte uint8_t
+extern volatile int SI4432_Sel; // currently selected SI4432
+void SI4432_Write_Byte(byte ADR, byte DATA );
+byte SI4432_Read_Byte( byte ADR );
+
+void SI4432_Init(void);
+void SI4432_Drive(int);
+float SI4432_RSSI(uint32_t i, int s);
+#ifdef __FAST_SWEEP__
+void SI4432_Fill(int s, int start);
+#endif
+void SI4432_Set_Frequency ( long Freq );
+float SI4432_SET_RBW(float WISH);
+void SI4432_SetReference(int freq);
// 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);}
+#define RESTART_PROFILE 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, 180);}
// Macros for convert define value to string
#define STR1(x) #x
#define define_to_STR(x) STR1(x)
+
+// sa_core.c
+int get_waterfall(void);
+void toggle_tracking(void);
+void calibrate(void);
+void reset_calibration(void);
+void set_reflevel(float);
+void set_offset(float);
+void set_unit(int);
+void set_RBW(int);
+void set_switches(int);
+void set_trigger_level(float);
+void set_trigger(int);
+//extern int setting_measurement;
+void self_test(int);
+//extern int setting_test;
+void wait_user(void);
+void calibrate(void);
+float to_dBm(float);
+float calc_min_sweep_time(void);
+extern float actual_rbw;
+
+enum {
+ M_OFF, M_IMD, M_OIP3, M_PHASE_NOISE, M_STOP_BAND, M_PASS_BAND, M_LINEARITY
+};
+
+enum {
+ T_AUTO, T_NORMAL, T_SINGLE, T_DONE
+};
/*EOF*/
diff --git a/numfont20x22.c b/numfont20x22.c
index 85498ec..9affa97 100644
--- a/numfont20x22.c
+++ b/numfont20x22.c
@@ -507,6 +507,7 @@ const uint16_t numfont16x22[] = {
0b0000000000000000,
0b0000000000000000,
+ 0b0000000000000000, // m
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
@@ -514,6 +515,51 @@ const uint16_t numfont16x22[] = {
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
+ 0b1111001100110000,
+ 0b1111011111111100,
+ 0b1111111111111110,
+ 0b1111111111111110,
+ 0b1111111111011111,
+ 0b1111101111001111,
+ 0b1111001111001111,
+ 0b1111001111001111,
+ 0b1111001111001111,
+ 0b1111001111001111,
+ 0b1111001111001111,
+ 0b1111001111001111,
+ 0b1111001111001111,
+ 0b1111001111001111,
+
+ 0b0000000000000000, // u
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b1111000000001111,
+ 0b1111000000001111,
+ 0b1111000000001111,
+ 0b1111000000001111,
+ 0b1111000000001111,
+ 0b1111000000001111,
+ 0b1111000000001111,
+ 0b1111000000001111,
+ 0b1111000000011111,
+ 0b1111100000111111,
+ 0b1111110001111111,
+ 0b0111111111111111,
+ 0b0011111111101111,
+ 0b0001111111001111,
+
+ 0b0000000000000000, // n
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
0b0000000000000000,
0b1111000111110000,
0b1111011111111100,
@@ -530,7 +576,7 @@ const uint16_t numfont16x22[] = {
0b1111000000001111,
0b1111000000001111,
- 0b0000000000000000,
+ 0b0000000000000000, // p
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
diff --git a/plot.c b/plot.c
index 01b1e85..933bc5a 100644
--- a/plot.c
+++ b/plot.c
@@ -1,6 +1,4 @@
-/*
- * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com
- * All rights reserved.
+/* 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
@@ -25,30 +23,37 @@
#include "chprintf.h"
#include "nanovna.h"
+#ifdef __SCROLL__
+int _height = HEIGHT_NOSCROLL;
+int waterfall = false;
+int fullscreen = true;
+#endif
static void cell_draw_marker_info(int x0, int y0);
static void draw_battery_status(void);
+void cell_draw_test_info(int x0, int y0);
+void frequency_string(char *buf, size_t len, int32_t freq);
static int16_t grid_offset;
static int16_t grid_width;
int16_t area_width = AREA_WIDTH_NORMAL;
-int16_t area_height = AREA_HEIGHT_NORMAL;
+int16_t area_height; // initialized in main() = 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)
+//#define CELLWIDTH (64) // moved to nanovna.h
+//#define CELLHEIGHT (32)
// Check buffer size
#if CELLWIDTH*CELLHEIGHT > SPI_BUFFER_SIZE
#error "Too small spi_buffer size SPI_BUFFER_SIZE < CELLWIDTH*CELLHEIGH"
#endif
// 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 MAX_MARKMAP_X ((LCD_WIDTH+CELLWIDTH-1)/CELLWIDTH)
+#define MAX_MARKMAP_Y ((LCD_HEIGHT+CELLHEIGHT-1)/CELLHEIGHT)
// Define markmap mask size
#if MAX_MARKMAP_X <= 8
typedef uint8_t map_t;
@@ -58,13 +63,37 @@ typedef uint16_t map_t;
typedef uint32_t map_t;
#endif
+uint16_t marker_color(int mtype)
+{
+ if (mtype & M_REFERENCE)
+ return(RGBHEX(0xFFFFFF));
+ if (mtype & M_DELTA)
+ return(RGBHEX(0x00FF00));
+ if (mtype & M_NOISE)
+ return(RGBHEX(0x00FFFF));
+ return(RGBHEX(0xFFFF00));
+}
+
+//#if 4 != M_TRACKING
+//#error "Wrong marker numbers"
+//#endif
+
+char marker_letter[5] =
+{
+ 'R',
+ ' ',
+ 'D',
+ 'N',
+ 'T'
+};
+
map_t markmap[2][MAX_MARKMAP_Y];
uint8_t current_mappage = 0;
// Trace data cache, for faster redraw cells
// CELL_X[16:31] x position
// CELL_Y[ 0:15] y position
-typedef uint32_t index_t;
+typedef uint32_t index_t;
static index_t trace_index[TRACES_MAX][POINTS_COUNT];
#define INDEX(x, y) ((((index_t)x)<<16)|(((index_t)y)))
@@ -87,6 +116,12 @@ void update_grid(void)
uint32_t fspan = get_sweep_frequency(ST_SPAN);
uint32_t grid;
+ if (fspan == 0) {
+ fspan = setting.actual_sweep_time; // Time in mS
+ fspan *= 1000;
+ fstart = 0;
+ }
+
while (gdigit > 100) {
grid = 5 * gdigit;
if (fspan / grid >= 4)
@@ -107,6 +142,7 @@ void update_grid(void)
redraw_request |= REDRAW_FREQUENCY;
}
+#ifdef __VNA__
static inline int
circle_inout(int x, int y, int r)
{
@@ -339,7 +375,7 @@ smith_grid3(int x, int y)
return 0;
}
#endif
-
+#endif
#if 0
static int
rectangular_grid(int x, int y)
@@ -421,12 +457,54 @@ draw_on_strut(int v0, int d, int color)
/*
* calculate log10(abs(gamma))
*/
-static float
-logmag(const float *v)
+float
+value(const float v)
{
- return log10f(v[0]*v[0] + v[1]*v[1]) * 10;
+ switch(setting.unit)
+ {
+ case U_DBMV:
+ return v + 30.0 + 20.0*log10(sqrt(50));
+ break;
+ case U_DBUV:
+ return v + 90.0 + 20.0*log10(sqrt(50.0));
+ break;
+ case U_VOLT:
+ return pow(10, (v-30.0)/20.0) * sqrt(50.0);
+ break;
+ case U_WATT:
+ return pow(10, v/10.0)/1000.0;
+ break;
+ }
+// case U_DBM:
+ return v; // raw data is in logmag*10 format
+
}
+float
+to_dBm(const float v)
+{
+ switch(setting.unit)
+ {
+ case U_DBMV:
+ return v - 30.0 - 20.0*log10(sqrt(50));
+ break;
+ case U_DBUV:
+ return v - 90.0 - 20.0*log10(sqrt(50.0));
+ break;
+ case U_VOLT:
+ return log10( v / (sqrt(50.0))) * 20.0 + 30.0 ;
+ break;
+ case U_WATT:
+ return log10(v*1000.0)*10.0;
+ break;
+ }
+// case U_DBM:
+ return v; // raw data is in logmag*10 format
+
+}
+
+
+#ifdef __VNA_
/*
* calculate phase[-2:2] of coefficient
*/
@@ -529,21 +607,23 @@ gamma2reactance(const float v[2])
float d = z0 / ((1-v[0])*(1-v[0])+v[1]*v[1]);
return 2*v[1] * d;
}
+#endif
static index_t
-trace_into_index(int t, int i, float array[POINTS_COUNT][2])
+trace_into_index(int t, int i, float array[POINTS_COUNT])
{
int y, x;
+ float coeff = array[i];
+ float refpos = get_trace_refpos(t);
+ float v=0;
+ float scale = get_trace_scale(t);
- float *coeff = array[i];
- 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-= logmag(coeff) * scale;
+ v = ( refpos - value(coeff) ) / scale;
break;
- case TRC_PHASE:
+#ifdef __VNA__
+ case TRC_PHASE:
v-= phase(coeff) * scale;
break;
case TRC_DELAY:
@@ -572,15 +652,17 @@ trace_into_index(int t, int i, float array[POINTS_COUNT][2])
case TRC_POLAR:
cartesian_scale(coeff[0], coeff[1], &x, &y, scale);
goto set_index;
- }
+#endif
+ }
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:
+// set_index:
return INDEX(x, y);
}
+#ifdef __VNA__
static void
format_smith_value(char *buf, int len, const float coeff[2], uint32_t frequency)
{
@@ -625,7 +707,9 @@ format_smith_value(char *buf, int len, const float coeff[2], uint32_t frequency)
break;
}
}
+#endif
+#ifdef __VNA__
static void
trace_get_value_string(int t, char *buf, int len, float array[POINTS_COUNT][2], int i)
{
@@ -738,7 +822,103 @@ trace_get_value_string_delta(int t, char *buf, int len, float array[POINTS_COUNT
}
plot_printf(buf, len, format, v);
}
+#endif
+
+extern const char *unit_string[];
+
+static void trace_get_value_string(
+ int t, char *buf, int len,
+ int i, float coeff[POINTS_COUNT],
+ uint32_t freq[POINTS_COUNT],
+ int point_count,
+ int ri, int mtype)
+{
+ (void) t;
+ (void)freq;
+ (void) point_count;
+ float v;
+ char buf2[11];
+ char buf3[8];
+ buf2[0]=' ';
+ uint32_t dfreq = 0;
+ float rlevel = 0;
+ int ii = i;
+ int unit_index = setting.unit;
+ if (mtype & M_DELTA) {
+ unit_index = setting.unit+5;
+ if (ri > i) {
+ dfreq = frequencies[ri] - frequencies[i];
+ ii = ri - i;
+ buf2[0] = '-';
+ } else {
+ dfreq = frequencies[i] - frequencies[ri];
+ ii = i - ri;
+ buf2[0] = '+';
+ }
+ rlevel = value(coeff[ri]);
+ } else {
+ dfreq = frequencies[i];
+ }
+ if (FREQ_IS_CW()) {
+ float t = ii*(setting.actual_sweep_time)*1000.0/290.0;
+#if 1
+ plot_printf(&buf2[1], sizeof(buf2) -1, "%.3FS" , t/1000000.0);
+#else
+ if (t>1000000.0){
+ plot_printf(&buf2[1], sizeof(buf2) -1, "%4f" , t/1000000.0);
+ buf2[5] = 'S';
+ buf2[6]=0;
+ }
+ else if (t>1000.0) {
+ plot_printf(&buf2[1], sizeof(buf2) -1, "%4f" , t/1000.0);
+ buf2[5] = 'm';
+ buf2[6] = 'S';
+ buf2[7]=0;
+ }
+ else {
+ plot_printf(&buf2[1], sizeof(buf2) -1, "%4f" , t);
+ buf2[5] = 'u';
+ buf2[6] = 'S';
+ buf2[7]=0;
+ }
+#endif
+ } else {
+ uint32_t resolution = get_sweep_frequency(ST_SPAN)/290;
+#if 0
+ if (resolution <= 2000)
+ plot_printf(&buf2[1], sizeof(buf2) -1, "%3.3f" , (dfreq + 500) / 1000000.0);
+ else if (resolution <= 20000)
+ plot_printf(&buf2[1], sizeof(buf2) -1, "%3.2f" , (dfreq + 5000) / 1000000.0);
+ else
+ plot_printf(&buf2[1], sizeof(buf2) -1, "%3.1f" , (dfreq + 50000) / 1000000.0);
+ }
+#else
+ int digits = 1;
+ if (resolution <= 2000)
+ digits = 3;
+ else if (resolution <= 20000)
+ digits = 2;
+ plot_printf(&buf2[1], sizeof(buf2) -1, "%3.*f" , digits, (dfreq + 50000) / 1000000.0);
+ }
+#endif
+ // frequency_string(&buf2[1], sizeof(buf2) -1, dfreq);
+ v = value(coeff[i]);
+ if (mtype & M_NOISE)
+ v = v - 10*log10(actual_rbw*1000.0);
+ if (v == -INFINITY)
+ plot_printf(buf, len, "-INF");
+ else {
+ v = v - rlevel;
+ if (UNIT_IS_LINEAR(setting.unit)) {
+ plot_printf(buf3, sizeof(buf3), "%.3F", v); // 5 characters incl u,m,etc...
+ } else {
+ plot_printf(buf3, sizeof(buf3), "%.1f", v);
+ }
+ plot_printf(buf, len, "%s %s%s%s", buf2, buf3, unit_string[unit_index],(mtype & M_NOISE?"/Hz":""));
+ }
+}
+#ifdef __VNA__
static int
trace_get_info(int t, char *buf, int len)
{
@@ -773,6 +953,7 @@ static float distance_of_index(int idx)
((float)(frequencies[1] - frequencies[0]) * (float)FFT_SIZE * 2.0);
return distance * velocity_factor;
}
+#endif
static inline void
mark_map(int x, int y)
@@ -1028,7 +1209,7 @@ markmap_marker(int marker)
int t;
if (!markers[marker].enabled)
return;
- for (t = 0; t < TRACES_MAX; t++) {
+ for (t = TRACE_ACTUAL; t <= TRACE_ACTUAL; t++) {
if (!trace[t].enabled)
continue;
index_t index = trace_index[t][markers[marker].index];
@@ -1038,7 +1219,7 @@ markmap_marker(int marker)
}
}
-static void
+void
markmap_all_markers(void)
{
int i;
@@ -1058,10 +1239,10 @@ marker_position(int m, int t, int *x, int *y)
*y = CELL_Y(index);
}
-static int greater(int x, int y) { return x > y; }
-static int lesser(int x, int y) { return x < y; }
+static int greater(int x, int y, int d) { return x - d > y; }
+static int lesser(int x, int y, int d) { return x - d < y; }
-static int (*compare)(int x, int y) = lesser;
+static int (*compare)(int x, int y, int d) = greater;
int
marker_search(void)
@@ -1072,11 +1253,11 @@ marker_search(void)
if (uistat.current_trace == -1)
return -1;
- int value = CELL_Y(trace_index[uistat.current_trace][0]);
+ int value = CELL_Y(trace_index[TRACE_ACTUAL][0]);
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);
+ int new_value = CELL_Y(trace_index[TRACE_ACTUAL][i]);
+ if ((*compare)(value, new_value, 0)) {
+ value = new_value;
found = i;
}
}
@@ -1090,30 +1271,38 @@ set_marker_search(int mode)
compare = (mode == 0) ? greater : lesser;
}
+int
+search_is_greater(void)
+{
+ return(compare == greater);
+}
+
+#define MINMAX_DELTA 10
+
int
marker_search_left(int from)
{
int i;
int found = -1;
-
if (uistat.current_trace == -1)
return -1;
- int value = CELL_Y(trace_index[uistat.current_trace][from]);
+ int value = CELL_Y(trace_index[TRACE_ACTUAL][from]);
for (i = from - 1; i >= 0; i--) {
- index_t index = trace_index[uistat.current_trace][i];
- if ((*compare)(value, CELL_Y(index)))
+ int new_value = CELL_Y(trace_index[TRACE_ACTUAL][i]);
+ if ((*compare)(value, new_value, MINMAX_DELTA))
break;
- value = CELL_Y(index);
}
for (; i >= 0; i--) {
- index_t index = trace_index[uistat.current_trace][i];
- if ((*compare)(CELL_Y(index), value)) {
+ int new_value = CELL_Y(trace_index[TRACE_ACTUAL][i]);
+ if ((*compare)(new_value, value, -MINMAX_DELTA)) {
break;
}
- found = i;
- value = CELL_Y(index);
+ if ((*compare)(value, new_value, 0)) {
+ found = i;
+ value = new_value;
+ }
}
return found;
}
@@ -1126,22 +1315,22 @@ marker_search_right(int from)
if (uistat.current_trace == -1)
return -1;
-
- int value = CELL_Y(trace_index[uistat.current_trace][from]);
+ int value = CELL_Y(trace_index[TRACE_ACTUAL][from]);
for (i = from + 1; i < sweep_points; i++) {
- index_t index = trace_index[uistat.current_trace][i];
- if ((*compare)(value, CELL_Y(index)))
+ int new_value = CELL_Y(trace_index[TRACE_ACTUAL][i]);
+ if ((*compare)(value, new_value, MINMAX_DELTA))
break;
- value = CELL_Y(index);
+ value = new_value;
}
-
for (; i < sweep_points; i++) {
- index_t index = trace_index[uistat.current_trace][i];
- if ((*compare)(CELL_Y(index), value)) {
+ int new_value = CELL_Y(trace_index[TRACE_ACTUAL][i]);
+ if ((*compare)(new_value, value, -MINMAX_DELTA)) {
break;
}
- found = i;
- value = CELL_Y(index);
+ if ((*compare)(value, new_value, 0)) {
+ found = i;
+ value = new_value;
+ }
}
return found;
}
@@ -1170,7 +1359,7 @@ search_nearest_index(int x, int y, int t)
}
void
-plot_into_index(float measured[2][POINTS_COUNT][2])
+plot_into_index(measurement_t measured)
{
int t, i;
for (t = 0; t < TRACES_MAX; t++) {
@@ -1258,6 +1447,7 @@ draw_cell(int m, int n)
}
}
}
+#ifdef __VNA__
// Smith greed line (1000 system ticks for all screen calls)
if (trace_type & (1 << TRC_SMITH)) {
for (y = 0; y < h; y++)
@@ -1281,6 +1471,7 @@ draw_cell(int m, int n)
#endif
#endif
// PULSE;
+#endif
// Draw traces (50-600 system ticks for all screen calls, depend from lines
// count and size)
#if 1
@@ -1317,17 +1508,27 @@ draw_cell(int m, int n)
for (i = 0; i < MARKERS_MAX; i++) {
if (!markers[i].enabled)
continue;
- for (t = 0; t < TRACES_MAX; t++) {
- if (!trace[t].enabled)
- continue;
+// for (t = 0; t < TRACES_MAX; t++) {
+// if (!trace[t].enabled)
+// continue;
+ t = TRACE_ACTUAL;
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 1
+
+ if (x + MARKER_WIDTH >= 0 && x < CELLWIDTH &&
+ y + MARKER_HEIGHT >= 0 && y < CELLHEIGHT)
+ draw_marker(x, y, marker_color(markers[i].mtype), i);
+#else
+
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);
- }
+ draw_marker(x, y, marker_color(markers[i].mtype), i);
+#endif
+ // 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)
@@ -1335,7 +1536,10 @@ draw_cell(int m, int n)
if (n == 0)
cell_draw_marker_info(x0, y0);
#endif
-// PULSE;
+#ifdef __SELFTEST__
+ cell_draw_test_info(x0, y0);
+#endif
+ // PULSE;
// Draw reference position (<10 system ticks for all screen calls)
for (t = 0; t < TRACES_MAX; t++) {
if (!trace[t].enabled)
@@ -1364,6 +1568,12 @@ draw_cell(int m, int n)
ili9341_bulk(OFFSETX + x0, OFFSETY + y0, w, h);
}
+extern float peakLevel;
+extern float min_level;
+int w_max = -130;
+int w_min = 0;
+
+
static void
draw_all_cells(bool flush_markmap)
{
@@ -1385,6 +1595,108 @@ draw_all_cells(bool flush_markmap)
// clear map for next plotting
clear_markmap();
}
+#ifdef __SCROLL__
+ int w = area_width;
+ if (w < 5) w = 5;
+ if (waterfall) {
+ for (m = 226; m >= HEIGHT+3; m -= 1) { // Scroll down
+ uint16_t *buf = &spi_buffer[0];
+ ili9341_read_memory(6*5, m, w, 1, w, buf);
+ ili9341_bulk(6*5,m+1, w,1);
+ }
+ for (int i=0; i<290; i++) { // Add new topline
+#if 0
+ int k = (actual_t[i]+120 + 10)* 3 / 2;
+ unsigned int r=0,g=0,b=0;
+ if (k < 64)
+ r = k*4;
+ else if (k<128) {
+ r = 255;
+ g = (k-64)*4;
+ } else {
+ r = 255;
+ g = 255;
+ b = (k-128)*4;
+ }
+#else
+ if (w_min > (int)min_level)
+ w_min = (int)min_level;
+ if (w_max < (int)peakLevel)
+ w_max = (int)peakLevel;
+/*
+ def rgb(minimum, maximum, value):
+ minimum, maximum = float(minimum), float(maximum)
+ ratio = 2 * (value-minimum) / (maximum - minimum)
+ b = int(max(0, 255*(1 - ratio)))
+ r = int(max(0, 255*(ratio - 1)))
+ g = 255 - b - r
+ return r, g, b
+ */
+
+ int r,g,b;
+#if 0
+ int ratio = (int)(1024 * (actual_t[i] - w_min) / (w_max - w_min));
+
+ r = ratio - 512;
+ if (r<0) r=0;
+ b = (1024 - ratio*4) - 512;
+ if (b<0) b=0;
+ g = 512-r-b;
+ if (r>255) r=255;
+ if (g>255) g=255;
+ if (b>255) b=255;
+
+#define gamma_correct(X,L) X = (L + X * (255 - L)/255 )
+ gamma_correct(r,160);
+ gamma_correct(g,160);
+ gamma_correct(b,160);
+
+#endif
+
+#if 1
+ float ratio = (int)(510.0 * (actual_t[i] - w_min) / (w_max - w_min));
+// ratio = (i*2); // Uncomment for testing the waterfall colors
+ b = 255 - ratio;
+ if (b > 255) b = 255;
+ if (b < 0) b = 0;
+ r = ratio - 255;
+ if (r > 255) r = 255;
+ if (r < 0) r = 0;
+// g = 255 - b; // if red is too weak to be seen.....
+ g = 255 - b - r;
+#if 1
+#define gamma_correct(X) X = (X < 64 ? X * 2 : X < 128 ? 128 + (X-64) : X < 192 ? 192 + (X - 128)/2 : 225 + (X - 192) / 4)
+ gamma_correct(r);
+ gamma_correct(g);
+ gamma_correct(b);
+#endif
+#endif
+
+#if 0
+ int k = (actual_t[i]+120)* 2 * 8;
+ k &= 255;
+ unsigned int r=0,g=0,b=0;
+ if (k < 64) {
+ b = 255;
+ g = k*2 + 128;
+ } else if (k < 128) {
+ g = 255;
+ b = 255 - (k-64)*2;
+ } else if (k < 192) {
+ g = 255;
+ r = (k-128)*2 + 128;
+ } else
+ {
+ g = 255 - (k-192)*2;
+ r = 255;
+ }
+#endif
+#endif
+ spi_buffer[i] = RGB565(r,g,b);
+ }
+ ili9341_bulk(6*5,HEIGHT+3, w,1);
+ }
+#endif
}
void
@@ -1428,7 +1740,10 @@ void
request_to_draw_cells_behind_menu(void)
{
// Values Hardcoded from ui.c
- invalidate_rect(320-70, 0, 319, 239);
+ if (current_menu_is_form())
+ invalidate_rect(25, 0, LCD_WIDTH-1, LCD_HEIGHT-1);
+ else
+ invalidate_rect(LCD_WIDTH-60 - 25, 0, LCD_WIDTH-1, LCD_HEIGHT-1);
redraw_request |= REDRAW_CELLS;
}
@@ -1436,7 +1751,7 @@ void
request_to_draw_cells_behind_numeric_input(void)
{
// Values Hardcoded from ui.c
- invalidate_rect(0, 240-32, 319, 239);
+ invalidate_rect(0, LCD_HEIGHT-32, LCD_WIDTH-1, LCD_HEIGHT-1);
redraw_request |= REDRAW_CELLS;
}
@@ -1464,7 +1779,36 @@ cell_drawchar(uint8_t ch, int x, int y)
return ch_size;
}
-static void
+static int
+cell_drawchar_size(uint8_t ch, int x, int y, int size)
+{
+ 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*size)
+ return ch_size*size;
+ for (c = 0; c < FONT_GET_HEIGHT; c++) {
+ for (int i=0; i < size; i++) {
+ bits = *char_buf;
+ if ((y + c*size+i) < 0 || (y + c*size+i) >= CELLHEIGHT)
+ continue;
+ for (r = 0; r < ch_size; r++) {
+ for (int j = 0; j < size; j++) {
+ if ((x+r*size + j) >= 0 && (x+r*size+j) < CELLWIDTH && (0x80 & bits))
+ cell_buffer[(y+c*size+i)*CELLWIDTH + (x+r*size+j)] = foreground_color;
+ }
+ bits <<= 1;
+ }
+ }
+ char_buf++;
+ }
+ return ch_size*size;
+}
+
+void
cell_drawstring(char *str, int x, int y)
{
if (y <= -FONT_GET_HEIGHT || y >= CELLHEIGHT)
@@ -1476,6 +1820,55 @@ cell_drawstring(char *str, int x, int y)
}
}
+void
+cell_drawstring_size(char *str, int x, int y, int size)
+{
+ if (y <= -FONT_GET_HEIGHT*2 || y >= CELLHEIGHT)
+ return;
+ while (*str) {
+ if (x >= CELLWIDTH)
+ return;
+ x += cell_drawchar_size(*str++, x, y, size);
+ }
+}
+
+static int
+cell_drawchar_7x13(uint8_t ch, int x, int y)
+{
+ uint16_t bits;
+ int c, r, ch_size;
+ ch_size = 7;
+ // 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 < 13; c++) {
+ bits = x7x13b_bits[(ch * 13) + c];
+ if ((y + c) < 0 || (y + c) >= CELLHEIGHT)
+ continue;
+ for (r = 0; r < ch_size; r++) {
+ if ((x+r) >= 0 && (x+r) < CELLWIDTH && (0x8000 & bits))
+ cell_buffer[(y+c)*CELLWIDTH + (x+r)] = foreground_color;
+ bits <<= 1;
+ }
+ }
+ return ch_size;
+}
+
+
+void
+cell_drawstring_7x13(char *str, int x, int y)
+{
+ if (y <= -13 || y >= CELLHEIGHT)
+ return;
+ while (*str) {
+ if (x >= CELLWIDTH)
+ return;
+ x += cell_drawchar_7x13(*str++, x, y);
+ }
+}
+
+#ifdef __VNA__
static void
cell_draw_marker_info(int x0, int y0)
{
@@ -1601,15 +1994,167 @@ cell_draw_marker_info(int x0, int y0)
cell_drawstring(buf, xpos, ypos);
}
}
+#endif
+static void cell_draw_marker_info(int x0, int y0)
+{
+ char buf[25];
+ int t;
+ int ref_marker = 0;
+ int j = 0;
+ for (int i = 0; i < MARKER_COUNT; i++) {
+ if (markers[i].enabled && markers[i].mtype & M_REFERENCE) {
+ ref_marker = i;
+ break;
+ }
+ }
+ for (int i = 0; i < MARKER_COUNT; i++) {
+ if (i >= 2 && setting.measurement == M_OIP3 && markers[2].enabled && markers[3].enabled) {
+ float il = value((actual_t[markers[2].index]));
+ float ir = value((actual_t[markers[3].index]));
+ float sl = value((actual_t[markers[0].index]));
+ float sr = value((actual_t[markers[1].index]));
+
+ float ip = sl+ (sr - il)/2;
+ plot_printf(buf, sizeof buf, "OIP3: %4.1fdB", ip);
+ j = 2;
+ int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0;
+ int ypos = 1 + (j/2)*(16) - y0;
+ cell_drawstring_7x13(buf, xpos, ypos);
+
+ ip = sr+ (sl - ir)/2;
+ plot_printf(buf, sizeof buf, "OIP3: %4.1fdB", ip);
+ j = 3;
+ xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0;
+ ypos = 1 + (j/2)*(16) - y0;
+ cell_drawstring_7x13(buf, xpos, ypos);
+ break;
+ }
+#if 0
+ if (i >= 2 && in_selftest) {
+ plot_printf(buf, sizeof buf, "DO NOT SWITCH OFF!!");
+ j = 2;
+ int xpos = 1 + CELLOFFSETX +25 - x0;
+ int ypos = 1 + 16 - y0;
+
+ cell_drawstring_7x13(buf, xpos, ypos);
+ break;
+ }
+#endif
+ if (!markers[i].enabled)
+ continue;
+ int idx = markers[i].index;
+ int ridx = markers[ref_marker].index;
+ for (t = TRACE_ACTUAL; t <= TRACE_ACTUAL; t++) { // Only show info on actual trace
+ if (!trace[t].enabled)
+ continue;
+#if 1
+ int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0;
+// int ypos = 1 + (j/2)*(13) - y0;
+ int ypos = 1 + (j/2)*(16) - y0;
+#else
+ int xpos = 1 + CELLOFFSETX - x0;
+ int ypos = 1 + j*(FONT_GET_HEIGHT*2+1) - y0;
+#endif
+ int k = 0;
+ if (i == active_marker) {
+// ili9341_set_foreground(DEFAULT_BG_COLOR);
+// ili9341_set_background(marker_color(markers[i].mtype));
+ buf[k++] = '\033'; // Right arrow (?)
+ } else {
+// ili9341_set_background(DEFAULT_BG_COLOR);
+// ili9341_set_foreground(marker_color(markers[i].mtype));
+ buf[k++] = ' ';
+// buf[k++] = ' ';
+ }
+ buf[k++] = i+'1';
+ if (markers[i].mtype & M_REFERENCE)
+ buf[k++] = 'R';
+ if (markers[i].mtype & M_TRACKING)
+ buf[k++] = 'T';
+ if (markers[i].mtype & M_DELTA)
+ buf[k++] = 'D';
+ if (markers[i].mtype & M_NOISE)
+ buf[k++] = 'N';
+ buf[k++] = ' ';
+ buf[k++] = 0;
+ ili9341_set_background(DEFAULT_BG_COLOR);
+ ili9341_set_foreground(marker_color(markers[i].mtype));
+// if (setting.unit)
+// cell_drawstring(buf, xpos, ypos);
+// else
+// cell_drawstring_7x13(buf, xpos, ypos);
+ int offs = strlen(buf);
+ trace_get_value_string(
+ t, &buf[offs], (sizeof buf) - offs,
+ idx, measured[trace[t].channel], frequencies, sweep_points, ridx, markers[i].mtype);
+ if (strlen(buf)*7> WIDTH/2 )
+ cell_drawstring(buf, xpos, ypos);
+ else
+ cell_drawstring_7x13(buf, xpos, ypos);
+ j++;
+ }
+ }
+}
+void frequency_string(char *buf, size_t len, int32_t freq)
+{
+ if (freq < 0) {
+ freq = -freq;
+ *buf++ = '-';
+ len -= 1;
+ }
+#ifdef __VNA__
+ if (freq < 1000) {
+ plot_printf(buf, len, "%d Hz", (int)freq);
+ } else if (freq < 1000000) {
+ plot_printf(buf, len, "%d.%03d kHz",
+ (int)(freq / 1000),
+ (int)(freq % 1000));
+ } else {
+ plot_printf(buf, len, "%d.%03d %03d MHz",
+ (int)(freq / 1000000),
+ (int)((freq / 1000) % 1000),
+ (int)(freq % 1000));
+ }
+#endif
+#ifdef __SA__
+/*
+ if (freq < 1000) {
+ plot_printf(buf, len, "%dHz", (int)freq);
+ } else if (freq < 1000000) {
+ plot_printf(buf, len, "%d.%03dkHz",
+ (int)(freq / 1000),
+ (int)(freq % 1000));
+ } else
+*/ {
+ plot_printf(buf, len, "%d.%03",
+ (int)(freq / 1000000),
+ (int)((freq / 1000) % 1000));
+ }
+#endif
+}
void
draw_frequencies(void)
{
char buf1[32];
char buf2[32]; buf2[0] = 0;
+ if (MODE_OUTPUT(setting.mode)) // No frequencies during output
+ return;
+ if (current_menu_is_form() && !in_selftest)
+ return;
+
+#ifdef __VNA__
if ((domain_mode & DOMAIN_MODE) == DOMAIN_FREQ) {
+#endif
if (FREQ_IS_CW()) {
plot_printf(buf1, sizeof(buf1), " CW %qHz", get_sweep_frequency(ST_CW));
+ float t = setting.actual_sweep_time; // in mS
+ ; // in mS
+ if (t>=1000)
+ plot_printf(buf2, sizeof(buf2), "%.2fS",t/1000.0);
+ else
+ plot_printf(buf2, sizeof(buf2), "%.2fmS", t);
+
} 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));
@@ -1617,21 +2162,27 @@ draw_frequencies(void)
plot_printf(buf1, sizeof(buf1), " CENTER %qHz", get_sweep_frequency(ST_CENTER));
plot_printf(buf2, sizeof(buf2), " SPAN %qHz", get_sweep_frequency(ST_SPAN));
}
+#ifdef __VNA__
} else {
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));
}
+#endif
ili9341_set_foreground(DEFAULT_FG_COLOR);
ili9341_set_background(DEFAULT_BG_COLOR);
- ili9341_fill(0, FREQUENCIES_YPOS, 320, FONT_GET_HEIGHT, DEFAULT_BG_COLOR);
+ ili9341_fill(0, FREQUENCIES_YPOS, LCD_WIDTH, 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];
+ int p2 = FREQUENCIES_XPOS2;
+ if (FREQ_IS_CW()) {
+ p2 = LCD_WIDTH - 7*strlen(buf2);
+ }
ili9341_drawstring(buf1, FREQUENCIES_XPOS1, FREQUENCIES_YPOS);
- ili9341_drawstring(buf2, FREQUENCIES_XPOS2, FREQUENCIES_YPOS);
+ ili9341_drawstring(buf2, p2, FREQUENCIES_YPOS);
}
-
+#ifdef __VNA__
void
draw_cal_status(void)
{
@@ -1660,7 +2211,7 @@ draw_cal_status(void)
if (cal_status & calibration_text[i].mask)
ili9341_drawstring(&calibration_text[i].text, x, y);
}
-
+#endif
// Draw battery level
#define BATTERY_TOP_LEVEL 4100
#define BATTERY_BOTTOM_LEVEL 3100
@@ -1692,7 +2243,7 @@ static void draw_battery_status(void)
// string_buf[x++] = 0b10000001;
string_buf[x++] = 0b11111111;
// Draw battery
- blit8BitWidthBitmap(1, 1, 8, x, string_buf);
+ blit8BitWidthBitmap(1, 200, 8, x, string_buf);
}
void
@@ -1711,6 +2262,32 @@ redraw_frame(void)
draw_cal_status();
}
+
+int get_waterfall(void)
+{
+ return(waterfall);
+}
+
+void
+toggle_waterfall(void)
+{
+ if (!waterfall) {
+ _height = HEIGHT_SCROLL;
+ ili9341_fill(5*5, HEIGHT, LCD_WIDTH - 5*5, 236-HEIGHT, 0);
+ waterfall = true;
+ fullscreen = false;
+ w_min = (int)min_level;
+ w_max = (int)peakLevel;
+ if (w_max < w_min + 20)
+ w_max = w_min + 20;
+
+ } else {
+ _height = HEIGHT_NOSCROLL;
+ waterfall = false;
+ fullscreen = true;
+ }
+ request_to_redraw_grid();
+}
void
plot_init(void)
{
diff --git a/sa_cmd.c b/sa_cmd.c
new file mode 100644
index 0000000..94176f6
--- /dev/null
+++ b/sa_cmd.c
@@ -0,0 +1,447 @@
+
+extern volatile int SI4432_Sel; // currently selected SI4432
+void SI4432_Write_Byte(byte ADR, byte DATA );
+byte SI4432_Read_Byte( byte ADR );
+int VFO = 0;
+int points = 101; // For 's' and 'm' commands
+
+VNA_SHELL_FUNCTION(cmd_mode)
+{
+ static const char cmd_low_high[] = "low|high";
+ static const char cmd_in_out[] = "input|output";
+ if (argc != 2) {
+ usage:
+ shell_printf("usage: mode %s %s\r\n", cmd_low_high,cmd_in_out);
+ return;
+ }
+ int lh = get_str_index(argv[0], cmd_low_high);
+ int io = get_str_index(argv[1], cmd_in_out);
+ if (lh<0 || io<0)
+ goto usage;
+ switch(lh+io*2)
+ {
+ case 0:
+ set_mode(M_LOW);
+ break;
+ case 1:
+ set_mode(M_HIGH);
+ break;
+ case 2:
+ set_mode(M_GENLOW);
+ break;
+ case 3:
+ set_mode(M_GENHIGH);
+ break;
+ }
+}
+
+VNA_SHELL_FUNCTION(cmd_modulation )
+{
+ static const char cmd_mod[] = "off|AM_1kHz|AM_10Hz|NFM|WFM|extern";
+ if (argc != 1) {
+ usage:
+ shell_printf("usage: modulation %s\r\n", cmd_mod);
+ return;
+ }
+ static const int cmd_mod_val[] = { MO_NONE, MO_AM_1kHz, MO_AM_10Hz, MO_NFM, MO_WFM, MO_EXTERNAL};
+ int m = get_str_index(argv[1], cmd_mod);
+ if (m<0)
+ goto usage;
+ set_modulation(cmd_mod_val[m]);
+}
+
+VNA_SHELL_FUNCTION(cmd_spur)
+{
+ if (argc != 1) {
+ usage:
+ shell_printf("usage: spur on|off\r\n");
+ return;
+ }
+ if (strcmp(argv[0],"on") == 0) {
+ setting.spur = 1;
+ } else if (strcmp(argv[0],"off") == 0) {
+ setting.spur = 0;
+ } else
+ goto usage;
+}
+
+VNA_SHELL_FUNCTION(cmd_load)
+{
+ if (argc != 1) {
+ usage:
+ shell_printf("usage: load 0..4\r\n");
+ return;
+ }
+ int a = my_atoi(argv[0]);
+ if (0 <= a && a <= 4) {
+ caldata_recall(a);
+ } else
+ goto usage;
+}
+
+
+VNA_SHELL_FUNCTION(cmd_attenuate)
+{
+ if (argc != 1) {
+ usage:
+ shell_printf("usage: attenuate 0..31|auto\r\n");
+ return;
+ }
+ if (strcmp(argv[0],"auto") == 0) {
+ set_auto_attenuation();
+ } else {
+ int a = my_atoi(argv[0]);
+ if (a < 0 || a>31)
+ goto usage;
+ set_attenuation(a);
+ }
+}
+
+VNA_SHELL_FUNCTION(cmd_level)
+{
+ if (argc != 1) {
+ shell_printf("usage: level -76..-6\r\n");
+ return;
+ }
+ float f = my_atof(argv[0]);
+ set_level(f);
+}
+
+
+
+VNA_SHELL_FUNCTION(cmd_levelsweep)
+{
+ if (argc != 1) {
+ shell_printf("usage: levelsweep -76..+76\r\n");
+ return;
+ }
+ float f = my_atof(argv[0]);
+ set_level_sweep(f);
+}
+
+VNA_SHELL_FUNCTION(cmd_leveloffset)
+{
+ if (argc == 0) {
+ shell_printf("leveloffset low %.1f\r\n", (float) config.low_level_offset);
+ shell_printf("leveloffset high %.1f\r\n", (float)config.high_level_offset);
+ return;
+ } else if (argc == 2) {
+ float v = my_atof(argv[1]);
+ if (strcmp(argv[0],"low") == 0)
+ config.low_level_offset = v;
+ else if (strcmp(argv[0],"high") == 0)
+ config.low_level_offset = v;
+ else
+ goto usage;
+ } else {
+ usage:
+ shell_printf("leveloffset [low|high] []\r\n");
+ }
+}
+
+
+VNA_SHELL_FUNCTION(cmd_rbw)
+{
+ if (argc != 1) {
+ usage:
+ shell_printf("usage: rbw 2..600|auto\r\n");
+ return;
+ }
+ if (strcmp(argv[0],"auto") == 0 || strcmp(argv[0],"0") == 0) {
+ set_RBW(0);
+ } else {
+ int a = my_atoi(argv[0]);
+ if (a < 2 || a>600)
+ goto usage;
+ set_RBW(a);
+ }
+}
+
+VNA_SHELL_FUNCTION(cmd_if)
+{
+ if (argc != 1) {
+ usage:
+ shell_printf("usage: if {433M..435M}\r\n");
+ return;
+ } else {
+ int a = my_atoi(argv[0]);
+ if (a!= 0 &&( a < 433000000 || a>435000000))
+ goto usage;
+ setting.auto_IF = false;
+ set_IF(a);
+ }
+}
+
+
+VNA_SHELL_FUNCTION(cmd_v)
+
+
+{
+ if (argc != 1) {
+ shell_printf("%d\r\n", SI4432_Sel);
+ return;
+ }
+ VFO = my_atoi(argv[0]);
+ shell_printf("VFO %d\r\n", VFO);
+}
+
+int xtoi(char *t)
+{
+
+ int v=0;
+ while (*t) {
+ if ('0' <= *t && *t <= '9')
+ v = v*16 + *t - '0';
+ else if ('a' <= *t && *t <= 'f')
+ v = v*16 + *t - 'a' + 10;
+ else if ('A' <= *t && *t <= 'F')
+ v = v*16 + *t - 'A' + 10;
+ else
+ return v;
+ t++;
+ }
+ return v;
+}
+
+VNA_SHELL_FUNCTION(cmd_y)
+{
+ int rvalue;
+ int lvalue = 0;
+ if (argc != 1 && argc != 2) {
+ shell_printf("usage: y {addr(0-95)} [value(0-FF)]\r\n");
+ return;
+ }
+ rvalue = xtoi(argv[0]);
+ SI4432_Sel = VFO;
+ if (argc == 2){
+ lvalue = xtoi(argv[1]);
+ SI4432_Write_Byte(rvalue, lvalue);
+ } else {
+ lvalue = SI4432_Read_Byte(rvalue);
+ shell_printf("%x\r\n", lvalue);
+ }
+}
+
+VNA_SHELL_FUNCTION(cmd_selftest)
+{
+ if (argc < 1 || argc > 2) {
+ shell_printf("usage: selftest (1-3) [arg]\r\n");
+ return;
+ }
+ setting.test = my_atoi(argv[0]);
+ if (argc == 1)
+ setting.test_argument = 0;
+ else
+ setting.test_argument = my_atoi(argv[1]);
+ sweep_mode = SWEEP_SELFTEST;
+}
+
+#ifdef __ULTRA_SA__
+VNA_SHELL_FUNCTION(cmd_x)
+{
+ uint32_t reg;
+
+
+ if (argc != 1) {
+ shell_printf("usage: x value(0-FFFFFFFF)\r\n");
+ return;
+ }
+ reg = xtoi(argv[0]);
+
+ if ((reg & 7) == 5) {
+ if (reg & (1<<22))
+ VFO = 1;
+ else
+ VFO = 0;
+ reg &= ~0xc00000; // Force led to show lock
+ reg |= 0x400000;
+ }
+
+ ADF4351_WriteRegister32(VFO, reg);
+ shell_printf("x=%x\r\n", reg);
+}
+#endif
+
+
+VNA_SHELL_FUNCTION(cmd_i)
+{
+ int rvalue;
+return; // Don't use!!!!
+ SI4432_Init();
+ shell_printf("SI4432 init done\r\n");
+ if (argc == 1) {
+ rvalue = xtoi(argv[0]);
+ set_switches(rvalue);
+ set_mode(rvalue);
+ shell_printf("SI4432 mode %d set\r\n", rvalue);
+ }
+}
+
+VNA_SHELL_FUNCTION(cmd_o)
+{
+ (void) argc;
+ uint32_t value = my_atoi(argv[0]);
+ if (VFO == 0)
+ setting.frequency_IF = value;
+ set_freq(VFO, value);
+}
+
+VNA_SHELL_FUNCTION(cmd_d)
+{
+ (void) argc;
+ (void) argv;
+// int32_t a = my_atoi(argv[0]);
+// setting.drive = a;
+}
+
+
+VNA_SHELL_FUNCTION(cmd_a)
+{
+ (void)argc;
+ if (argc != 1) {
+ shell_printf("a=%d\r\n", frequencyStart);
+ return;
+ }
+ int32_t value = my_atoi(argv[0]);
+ frequencyStart = value;
+}
+
+
+VNA_SHELL_FUNCTION(cmd_b)
+{
+ (void)argc;
+ if (argc != 1) {
+ shell_printf("b=%d\r\n", frequencyStop);
+ return;
+ }
+ int32_t value = my_atoi(argv[0]);
+ frequencyStop = value;
+}
+
+VNA_SHELL_FUNCTION(cmd_t)
+{
+ (void)argc;
+ (void)argv;
+}
+
+VNA_SHELL_FUNCTION(cmd_e)
+{
+ (void)argc;
+ if (argc != 1) {
+ shell_printf("e=%d\r\n", setting.tracking);
+ return;
+ }
+ setting.tracking = my_atoi(argv[0]);
+ if (setting.tracking == -1)
+ setting.tracking = false;
+ else
+ setting.tracking = true;
+
+ if (argc >1)
+ frequencyExtra = my_atoi(argv[1]);
+}
+
+VNA_SHELL_FUNCTION(cmd_s)
+{
+ (void)argc;
+ if (argc != 1) {
+ shell_printf("s=%d\r\n", points);
+ return;
+ }
+ points = my_atoi(argv[0]);
+}
+
+void sweep_remote(void)
+{
+ int old_step = setting.frequency_step;
+ uint32_t f_step = (frequencyStop-frequencyStart)/ points;
+ setting.frequency_step = f_step;
+ streamPut(shell_stream, '{');
+ dirty = true;
+ for (int i = 0; i>8) & 0xFF));
+ // enable led
+ }
+ streamPut(shell_stream, '}');
+ setting.frequency_step = old_step;
+ sweep_mode = 0;
+}
+
+VNA_SHELL_FUNCTION(cmd_m)
+{
+ (void)argc;
+ (void)argv;
+
+// set_mode(0);
+// setting.tracking = false; //Default test setup
+// setting.step_atten = false;
+// set_attenuation(0);
+// set_reflevel(-10);
+// set_sweep_frequency(ST_START,frequencyStart - setting.frequency_IF );
+// set_sweep_frequency(ST_STOP, frequencyStop - setting.frequency_IF);
+// draw_cal_status();
+
+ pause_sweep();
+// update_rbw();
+ chThdSleepMilliseconds(10);
+ sweep_mode = SWEEP_REMOTE;
+// update_rbw();
+}
+
+VNA_SHELL_FUNCTION(cmd_p)
+{
+ (void)argc;
+return;
+ int p = my_atoi(argv[0]);
+ int a = my_atoi(argv[1]);
+ if (p==5)
+ set_attenuation(-a);
+ if (p==6)
+ set_mode(a);
+ if (p==1)
+ if (get_refer_output() != a)
+ set_refer_output(a);
+}
+
+VNA_SHELL_FUNCTION(cmd_w)
+{
+ (void)argc;
+ int p = my_atoi(argv[0]);
+return;
+ set_RBW(p);
+}
+
+VNA_SHELL_FUNCTION(cmd_correction)
+{
+ (void)argc;
+ if (argc == 0) {
+ shell_printf("index frequency value\r\n");
+ for (int i=0; i= 1000)
+ a = 15.0 / 290.0; // time per step in CW mode with repeat
+ }
+ t = vbwSteps * sweep_points * (setting.spur ? 2 : 1) * ( (a + (setting.repeat - 1)* REPEAT_TIME/1000.0));
+ }
+ return t;
+}
+
+
+void set_refer_output(int v)
+{
+ setting.refer = v;
+ dirty = true;
+}
+
+void set_decay(int d)
+{
+ if (d < 0 || d > 200)
+ return;
+ setting.decay = d;
+ dirty = true;
+}
+
+void set_noise(int d)
+{
+ if (d < 2 || d > 50)
+ return;
+ setting.noise = d;
+ dirty = true;
+}
+
+void set_measurement(int m)
+{
+ setting.measurement = m;
+ if (m == M_LINEARITY) {
+ trace[TRACE_STORED].enabled = true;
+ for (int j = 0; j < setting._sweep_points; j++)
+ stored_t[j] = -150;
+ setting.linearity_step = 0;
+ setting.attenuate = 29;
+ setting.auto_attenuation = false;
+ }
+ dirty = true;
+}
+void set_drive(int d)
+{
+ setting.drive = d;
+ dirty = true;
+}
+
+void set_level_sweep(float l)
+{
+ setting.level_sweep = l;
+ dirty = true;
+}
+
+void set_sweep_time(float t)
+{
+ if (t < MINIMUM_SWEEP_TIME)
+ t = MINIMUM_SWEEP_TIME;
+ if (t > 600000.0)
+ t = 600000.0;
+ setting.sweep_time = t;
+ if (FREQ_IS_CW())
+ update_grid(); // Really only needed in zero span mode
+ dirty = true;
+}
+
+void set_tracking_output(int t)
+{
+ setting.tracking_output = t;
+ dirty = true;
+}
+
+void toggle_tracking_output(void)
+{
+ setting.tracking_output = !setting.tracking_output;
+ dirty = true;
+}
+
+void toggle_mute(void)
+{
+ setting.mute = !setting.mute;
+ dirty = true;
+}
+
+void toggle_below_IF(void)
+{
+ if (S_IS_AUTO(setting.below_IF ))
+ setting.below_IF = false;
+ else if (setting.below_IF)
+ setting.below_IF = S_AUTO_OFF;
+ else
+ setting.below_IF = true;
+ dirty = true;
+}
+
+void set_modulation(int m)
+{
+ setting.modulation = m;
+ dirty = true;
+}
+
+void set_repeat(int r)
+{
+ if (r > 0 && r <= 100) {
+ setting.repeat = r;
+ dirty = true;
+ }
+}
+
+void set_IF(int f)
+{
+ if (f == 0)
+ setting.auto_IF = true;
+ setting.frequency_IF = f;
+ dirty = true;
+}
+
+#define POWER_STEP 0 // Should be 5 dB but appearently it is lower
+#define POWER_OFFSET 15
+#define SWITCH_ATTENUATION 30
+
+
+void set_auto_attenuation(void)
+{
+ setting.auto_attenuation = true;
+ setting.attenuate = 30;
+}
+
+void set_auto_reflevel(int v)
+{
+ setting.auto_reflevel = v;
+}
+
+int get_attenuation(void)
+{
+ if (setting.mode == M_GENLOW) {
+ if (setting.step_atten)
+ return ( -(POWER_OFFSET + setting.attenuate - (setting.step_atten-1)*POWER_STEP + SWITCH_ATTENUATION));
+ else
+ return ( -POWER_OFFSET - setting.attenuate + (setting.drive & 7) * 3);
+ }
+ return(setting.attenuate);
+}
+
+void set_level(float v)
+{
+ setting.level = v;
+ set_attenuation((int)v);
+ dirty = true;
+}
+
+void set_attenuation(int a)
+{
+ if (setting.mode == M_GENLOW) {
+ setting.drive = 8; // Start at lowest drive level;
+ a = a + POWER_OFFSET;
+ if (a > 0) {
+ setting.drive++;
+ a = a - 3;
+ }
+ if (a > 0) {
+ setting.drive++;
+ a = a - 3;
+ }
+ if (a > 0) {
+ setting.drive++;
+ a = a - 3;
+ }
+ if (a > 0)
+ a = 0;
+ if( a > - SWITCH_ATTENUATION) {
+ setting.step_atten = 0;
+ } else {
+ a = a + SWITCH_ATTENUATION;
+ setting.step_atten = 1;
+ }
+ a = -a;
+ } else {
+ setting.step_atten = 0;
+ setting.auto_attenuation = false;
+ }
+ if (a<0)
+ a = 0;
+ if (a> 31)
+ a=31;
+// if (setting.attenuate == a)
+// return;
+ setting.attenuate = a;
+ dirty = true;
+}
+
+void set_storage(void)
+{
+ for (int i=0; i 360)
+ set_RBW(300);
+ dirty = true;
+}
+#endif
+
+void set_harmonic(int h)
+{
+ setting.harmonic = h;
+ minFreq = 684000000.0;
+ if (setting.harmonic * 240000000+434000000 > minFreq)
+ minFreq = setting.harmonic * 240000000.0+434000000.0;
+ maxFreq = 4360000000;
+ if (setting.harmonic != 0 && (960000000.0 * setting.harmonic + 434000000.0 )< 4360000000.0)
+ maxFreq = (960000000.0 * setting.harmonic + 434000000.0 );
+ set_sweep_frequency(ST_START, (uint32_t) minFreq);
+ set_sweep_frequency(ST_STOP, (uint32_t) maxFreq);
+}
+
+void set_step_delay(int d)
+{
+
+ if ((2 <= d && d < 300) || d > 30000)
+ return;
+ setting.step_delay = d;
+ dirty = true;
+}
+
+void set_average(int v)
+{
+ setting.average = v;
+ trace[TRACE_TEMP].enabled = (v != 0);
+ dirty = true;
+}
+
+void toggle_LNA(void)
+{
+ if (S_IS_AUTO(setting.lna ))
+ setting.lna = false;
+ else if (setting.lna)
+ setting.lna = S_AUTO_OFF;
+ else
+ setting.lna = true;
+ dirty = true;
+}
+
+void toggle_tracking(void)
+{
+ setting.tracking = !setting.tracking;
+ if (setting.tracking) {
+ set_refer_output(2);
+ set_sweep_frequency(ST_CENTER, 10000000);
+ set_sweep_frequency(ST_SPAN, 5000000);
+ } else {
+ set_refer_output(-1);
+ }
+ dirty = true;
+}
+
+void toggle_AGC(void)
+{
+ if (S_IS_AUTO(setting.agc ))
+ setting.agc = false;
+ else if (setting.agc)
+ setting.agc = S_AUTO_ON;
+ else
+ setting.agc = true;
+ dirty = true;
+}
+
+void set_unit(int u)
+{
+ if (setting.unit == u)
+ return;
+ float r = to_dBm(setting.reflevel); // Get neutral unit
+ float s = to_dBm(setting.scale);
+// float t = setting.trigger; // Is always in dBm
+ // float m = r - NGRIDSY*s;
+
+ setting.unit = u; // Switch unit
+
+ r = value(r); // Convert to target unit
+ s = value(s);
+ if (UNIT_IS_LINEAR(setting.unit)) {
+ if (r < REFLEVEL_MIN)
+ r = REFLEVEL_MIN; // Minimum value to ensure display
+ if (r >REFLEVEL_MAX)
+ r = REFLEVEL_MAX; // Maximum value
+ set_scale(r/NGRIDY);
+ set_reflevel(setting.scale*NGRIDY);
+ if (S_IS_AUTO(setting.agc))
+ setting.agc = S_AUTO_ON;
+ if (S_IS_AUTO(setting.lna))
+ setting.lna = S_AUTO_OFF;
+ } else {
+ r = 10 * round((r*1.2)/10.0);
+ set_reflevel(r);
+ set_scale(10);
+ if (S_IS_AUTO(setting.agc))
+ setting.agc = S_AUTO_ON;
+ if (S_IS_AUTO(setting.lna))
+ setting.lna = S_AUTO_OFF;
+ }
+ plot_into_index(measured);
+ force_set_markmap();
+ dirty = true;
+}
+float const unit_scale_value[]={1,0.001,0.000001,0.000000001,0.000000000001};
+const char * const unit_scale_text[]= {"","m", "u", "n", "p"};
+
+void user_set_reflevel(float level)
+{
+ set_auto_reflevel(false);
+ if (UNIT_IS_LINEAR(setting.unit) && level < setting.scale*NGRIDY) {
+ set_scale(level/NGRIDY);
+ set_reflevel(setting.scale*NGRIDY);
+ } else
+ set_reflevel(level);
+}
+
+void set_reflevel(float level)
+{
+
+ if (UNIT_IS_LINEAR(setting.unit)) {
+ if (level < REFLEVEL_MIN)
+ level = REFLEVEL_MIN;
+ if (level > REFLEVEL_MAX)
+ level = REFLEVEL_MAX;
+ }
+
+ setting.unit_scale_index = 0;
+ setting.unit_scale = 1.0;
+ while (UNIT_IS_LINEAR(setting.unit) && setting.unit_scale_index < sizeof(unit_scale_value)/sizeof(float) - 1) {
+ if (level > unit_scale_value[setting.unit_scale_index])
+ break;
+ setting.unit_scale_index++;
+ }
+ setting.unit_scale = unit_scale_value[setting.unit_scale_index];
+
+ setting.reflevel = level;
+ set_trace_refpos(0, /* NGRIDY - */ level /* / get_trace_scale(0) */);
+ set_trace_refpos(1, /* NGRIDY - */ level /* / get_trace_scale(0) */ );
+ set_trace_refpos(2, /* NGRIDY - */ level /* / get_trace_scale(0) */ );
+ redraw_request |= REDRAW_AREA | REDRAW_CAL_STATUS;
+// dirty = true;
+}
+
+void round_reflevel_to_scale(void) {
+ int multi = floor((setting.reflevel + setting.scale/2)/setting.scale);
+ if (UNIT_IS_LINEAR(setting.unit)) {
+ if (multi < NGRIDY) {
+ setting.reflevel = setting.scale*10; // Never negative bottom
+ }
+ } else {
+
+ }
+ setting.reflevel = multi*setting.scale;
+ set_trace_refpos(0,setting.reflevel);
+ set_trace_refpos(1,setting.reflevel);
+ set_trace_refpos(2,setting.reflevel);
+}
+
+void user_set_scale(float s)
+{
+ if (UNIT_IS_LINEAR(setting.unit))
+ set_auto_reflevel(false);
+ set_scale(s);
+ if (UNIT_IS_LINEAR(setting.unit) && setting.reflevel < setting.scale*NGRIDY)
+ set_reflevel(setting.scale*NGRIDY);
+}
+
+void set_scale(float t) {
+ if (UNIT_IS_LINEAR(setting.unit)) {
+ if (t < REFLEVEL_MIN/10.0)
+ t = REFLEVEL_MIN/10.0;
+ if (t > REFLEVEL_MAX/10.0)
+ t = REFLEVEL_MAX/10.0;
+ } else {
+ if (t > 20.0)
+ t = 20.0;
+ else if (t < 1)
+ t = 1.0;
+ }
+
+ float m = 1;
+// t = t * 1.2;
+ while (t > 10) { m *= 10; t/=10; }
+ while (t < 1.0) { m /= 10; t*=10; }
+ if (t>5.0001)
+ t = 10.0;
+ else if (t>2.0001)
+ t = 5.0;
+ else if (t > 1.0001)
+ t = 2.0;
+ else
+ t = 1.0;
+ t = t*m;
+ setting.scale = t;
+ set_trace_scale(0, t);
+ set_trace_scale(1, t);
+ set_trace_scale(2, t);
+ round_reflevel_to_scale();
+ redraw_request |= REDRAW_AREA | REDRAW_CAL_STATUS;
+}
+
+
+void set_offset(float offset)
+{
+ setting.offset = offset;
+ dirty = true;
+}
+
+void show_stored_trace_at(float v)
+{
+ for (int j = 0; j < setting._sweep_points; j++)
+ stored_t[j] = v;
+ trace[TRACE_STORED].enabled = true;
+}
+
+void set_trigger_level(float trigger_level)
+{
+ setting.trigger_level = trigger_level;
+ if (setting.trigger != T_AUTO) {
+ show_stored_trace_at(setting.trigger_level);
+ }
+ dirty = true;
+}
+
+void set_trigger(int trigger)
+{
+ setting.trigger = trigger;
+ if (trigger == T_AUTO) {
+ trace[TRACE_STORED].enabled = false;
+ } else {
+ show_stored_trace_at(setting.trigger_level);
+ }
+ sweep_mode = SWEEP_ENABLE;
+ dirty = true;
+}
+
+
+//int GetRefpos(void) {
+// return (NGRIDY - get_trace_refpos(2)) * get_trace_scale(2);
+//}
+
+//int GetScale(void) {
+// return get_trace_refpos(2);
+//}
+void set_mode(int m)
+{
+#ifdef __ULTRA__
+ if (m == 6)
+ m = M_ULTRA;
+#endif
+ dirty = true;
+ if (setting.mode == m)
+ return;
+ reset_settings(m);
+}
+
+void apply_settings(void)
+{
+ set_switches(setting.mode);
+ if (setting.mode == M_HIGH)
+ PE4302_Write_Byte(40); // Ensure defined input impedance of low port when using high input mode (power calibration)
+ else
+ PE4302_Write_Byte(setting.attenuate * 2);
+ SI4432_SetReference(setting.refer);
+ update_rbw();
+ if (setting.frequency_step == 0.0) {
+ if (setting.step_delay <= 1)
+ actualStepDelay = 0;
+ else
+ actualStepDelay = setting.step_delay;
+ } else if (setting.step_delay < 2){
+ if (actual_rbw >= 191.0) actualStepDelay = 280;
+ else if (actual_rbw >= 142.0) actualStepDelay = 350;
+ else if (actual_rbw >= 75.0) actualStepDelay = 450;
+ else if (actual_rbw >= 56.0) actualStepDelay = 650;
+ else if (actual_rbw >= 37.0) actualStepDelay = 700;
+ else if (actual_rbw >= 18.0) actualStepDelay = 1100;
+ else if (actual_rbw >= 9.0) actualStepDelay = 1700;
+ else if (actual_rbw >= 5.0) actualStepDelay = 3300;
+ else actualStepDelay = 6400;
+ if (setting.step_delay == 1)
+ actualStepDelay *= 2;
+ } else
+ actualStepDelay = setting.step_delay;
+}
+
+//------------------------------------------
+#if 0
+#define CORRECTION_POINTS 10
+
+static const uint32_t correction_frequency[CORRECTION_POINTS] =
+{ 100000, 200000, 400000, 1000000, 2000000, 50000000, 100000000, 200000000, 300000000, 350000000 };
+
+static const float correction_value[CORRECTION_POINTS] =
+{ +4.0, +2.0, +1.5, +0.5, 0.0, 0.0, +1.0, +1.0, +2.5, +5.0 };
+#endif
+
+float get_frequency_correction(uint32_t f)
+{
+ if (!(setting.mode == M_LOW))
+ return(0.0);
+ int i = 0;
+ while (f > config.correction_frequency[i] && i < CORRECTION_POINTS)
+ i++;
+ if (i >= CORRECTION_POINTS)
+ return(config.correction_value[CORRECTION_POINTS-1]);
+ if (i == 0)
+ return(config.correction_value[0]);
+ f = f - config.correction_frequency[i-1];
+ uint32_t m = config.correction_frequency[i] - config.correction_frequency[i-1] ;
+ float cv = config.correction_value[i-1] + (config.correction_value[i] - config.correction_value[i-1]) * (float)f / (float)m;
+ return(cv);
+}
+
+
+float peakLevel;
+float min_level;
+uint32_t peakFreq;
+int peakIndex;
+float temppeakLevel;
+int temppeakIndex;
+static unsigned long old_freq[4] = { 0, 0, 0, 0 };
+
+
+void setupSA(void)
+{
+ SI4432_Init();
+ old_freq[0] = 0;
+ old_freq[1] = 0;
+ SI4432_Sel = 0;
+ SI4432_Receive();
+
+ SI4432_Sel = 1;
+ SI4432_Transmit(0);
+ PE4302_init();
+ PE4302_Write_Byte(0);
+}
+
+void set_freq(int V, unsigned long freq)
+{
+ if (old_freq[V] != freq) {
+ if (V <= 1) {
+ SI4432_Sel = V;
+ if (freq < 240000000 || freq > 960000000) {
+ old_freq[V] = freq + 1;
+ return;
+ }
+ SI4432_Set_Frequency(freq);
+#ifdef __ULTRA_SA__
+ } else {
+ ADF4351_set_frequency(V-2,freq,3);
+#endif
+ }
+ old_freq[V] = freq;
+ }
+}
+
+void set_switch_transmit(void) {
+ SI4432_Write_Byte(0x0b, 0x1f);// Set switch to transmit
+ SI4432_Write_Byte(0x0c, 0x1d);
+}
+
+void set_switch_receive(void) {
+ SI4432_Write_Byte(0x0b, 0x1d);// Set switch to receive
+ SI4432_Write_Byte(0x0c, 0x1f);
+}
+
+void set_switch_off(void) {
+ SI4432_Write_Byte(0x0b, 0x1d);// Set both switch off
+ SI4432_Write_Byte(0x0c, 0x1f);
+}
+
+void set_AGC_LNA(void) {
+ unsigned char v = 0x40;
+ if (S_STATE(setting.agc)) v |= 0x20;
+ if (S_STATE(setting.lna)) v |= 0x10;
+ SI4432_Write_Byte(0x69, v);
+}
+
+void set_switches(int m)
+{
+ SI4432_Init();
+ old_freq[0] = 0;
+ old_freq[1] = 0;
+switch(m) {
+case M_LOW: // Mixed into 0
+#ifdef __ULTRA__
+case M_ULTRA:
+#endif
+ SI4432_Sel = 0;
+ SI4432_Receive();
+ if (setting.step_atten) {
+ set_switch_transmit();
+ } else {
+ set_switch_receive();
+ }
+ set_AGC_LNA();
+
+ SI4432_Sel = 1;
+ if (setting.tracking_output)
+ set_switch_transmit();
+ else
+ set_switch_off();
+// SI4432_Receive(); For noise testing only
+ SI4432_Transmit(setting.drive);
+ // SI4432_SetReference(setting.refer);
+ break;
+case M_HIGH: // Direct into 1
+mute:
+ // SI4432_SetReference(-1); // Stop reference output
+ SI4432_Sel = 0; // both as receiver to avoid spurs
+ set_switch_receive();
+ SI4432_Receive();
+
+ SI4432_Sel = 1;
+ SI4432_Receive();
+ set_switch_receive();
+ set_AGC_LNA();
+
+ break;
+case M_GENLOW: // Mixed output from 0
+ if (setting.mute)
+ goto mute;
+ SI4432_Sel = 0;
+ if (setting.step_atten) {
+ set_switch_off();
+ } else {
+ set_switch_transmit();
+ }
+ SI4432_Transmit(setting.drive);
+
+ SI4432_Sel = 1;
+ if (setting.modulation == MO_EXTERNAL) {
+ set_switch_transmit(); // High input for external LO scuh as tracking output of other tinySA
+ SI4432_Receive();
+ } else {
+ set_switch_off();
+ SI4432_Transmit(12); // Fix LO drive a 10dBm
+ }
+ break;
+case M_GENHIGH: // Direct output from 1
+ if (setting.mute)
+ goto mute;
+ SI4432_Sel = 0;
+ SI4432_Receive();
+ set_switch_receive();
+
+ SI4432_Sel = 1;
+ if (setting.drive < 8) {
+ set_switch_off();
+ } else {
+ set_switch_transmit();
+ }
+ SI4432_Transmit(setting.drive);
+
+ break;
+ }
+ SI4432_Sel = 1;
+ SI4432_Write_Byte(0x73, 0); // Back to nominal offset
+ SI4432_Write_Byte(0x74, 0);
+
+}
+
+void update_rbw(void)
+{
+ if (setting.frequency_step > 0 && MODE_INPUT(setting.mode)) {
+ setting.vbw = (setting.frequency_step)/1000.0;
+ } else {
+ setting.vbw = 300; // trick to get right default rbw in zero span mode
+ }
+ actual_rbw = setting.rbw;
+ if (actual_rbw == 0)
+ actual_rbw = 2*setting.vbw;
+ if (actual_rbw < 2.6)
+ actual_rbw = 2.6;
+ if (actual_rbw > 600)
+ actual_rbw = 600;
+
+ SI4432_Sel = MODE_SELECT(setting.mode);
+ actual_rbw = SI4432_SET_RBW(actual_rbw);
+
+ if (setting.frequency_step > 0 && MODE_INPUT(setting.mode)) {
+ if (setting.step_delay==1) // Precise
+ vbwSteps = ((int)(2 * (setting.vbw + (actual_rbw/2)) / (actual_rbw / 2)));
+ else
+ vbwSteps = ((int)(2 * (setting.vbw + (actual_rbw/2)) / actual_rbw));
+
+ if (vbwSteps < 1)
+ vbwSteps = 1;
+ } else {
+ setting.vbw = actual_rbw;
+ vbwSteps = 1;
+ }
+ dirty = true;
+}
+
+int binary_search_frequency(int f)
+{
+ int L = 0;
+ int R = (sizeof frequencies)/sizeof(int) - 1;
+ int fmin = f - ((int)actual_rbw ) * 1000;
+ int fplus = f + ((int)actual_rbw ) * 1000;
+ while (L <= R) {
+ int m = (L + R) / 2;
+ if ((int)frequencies[m] < fmin)
+ L = m + 1;
+ else if ((int)frequencies[m] > fplus)
+ R = m - 1;
+ else
+ return m; // index is m
+ }
+ return -1;
+}
+
+
+#define MAX_MAX 4
+int
+search_maximum(int m, int center, int span)
+{
+ center = binary_search_frequency(center);
+ if (center < 0)
+ return false;
+ int from = center - span/2;
+ int found = false;
+ int to = center + span/2;
+ int cur_max = 0; // Always at least one maximum
+ int max_index[4];
+ if (from<0)
+ from = 0;
+ if (to > setting._sweep_points-1)
+ to = setting._sweep_points-1;
+ temppeakIndex = 0;
+ temppeakLevel = actual_t[from];
+ max_index[cur_max] = from;
+ int downslope = true;
+
+ for (int i = from; i <= to; i++) {
+ if (downslope) {
+ if (temppeakLevel > actual_t[i]) { // Follow down
+ temppeakIndex = i; // Latest minimum
+ temppeakLevel = actual_t[i];
+ } else if (temppeakLevel + setting.noise < actual_t[i]) { // Local minimum found
+ temppeakIndex = i; // This is now the latest maximum
+ temppeakLevel = actual_t[i];
+ downslope = false;
+ }
+ } else {
+ if (temppeakLevel < actual_t[i]) { // Follow up
+ temppeakIndex = i;
+ temppeakLevel = actual_t[i];
+ } else if (temppeakLevel - setting.noise > actual_t[i]) { // Local max found
+
+ found = true;
+ int j = 0; // Insertion index
+ while (j= temppeakLevel) // Find where to insert
+ j++;
+ if (j < MAX_MAX) { // Larger then one of the previous found
+ int k = MAX_MAX-1;
+ while (k > j) { // Shift to make room for max
+ max_index[k] = max_index[k-1];
+ // maxlevel_index[k] = maxlevel_index[k-1]; // Only for debugging
+ k--;
+ }
+ max_index[j] = temppeakIndex;
+ // maxlevel_index[j] = actual_t[temppeakIndex]; // Only for debugging
+ if (cur_max < MAX_MAX) {
+ cur_max++;
+ }
+ //STOP_PROFILE
+ }
+ temppeakIndex = i; // Latest minimum
+ temppeakLevel = actual_t[i];
+
+ downslope = true;
+ }
+ }
+ }
+ markers[m].index = max_index[0];
+ return found;
+}
+
+//static int spur_old_stepdelay = 0;
+static const unsigned int spur_IF = 433800000;
+static const unsigned int spur_alternate_IF = 433900000;
+static const int spur_table[] =
+{
+ 580000, // 433.8 MHz table
+ 961000,
+ 1600000,
+ 1837000, // Real signal
+ 2755000, // Real signal
+ 2760000,
+ 2961000,
+ 4933000,
+ 4960000,
+ 6961000,
+ 6980000,
+ 8267000,
+ 8961000,
+ 10000000,
+ 10960000,
+ 11600000,
+ 16960000,
+ 22960000,
+ 28960000,
+ 29800000,
+ 38105000,
+ 49500000,
+#ifdef IF_AT_4339
+ 780000, // 433.9MHz table
+ 830000,
+ 880000,
+ 949000,
+ 1390000,
+ 1468000,
+ 1830000,
+ 1900000,
+ 2770000,
+ 2840000,
+ 2880000,
+ 4710000,
+ 4780000,
+ 4800000,
+ 4880000,
+ 6510000,
+ 6750000,
+ 6790000,
+ 6860000,
+ 7340000,
+ 8100000,
+ 8200000,
+ 8880000,
+// 9970000, 10MHz!!!!!!
+ 10870000,
+ 11420000,
+ 14880000,
+ 16820000,
+#endif
+};
+
+int binary_search(int f)
+{
+ int L = 0;
+ int R = (sizeof spur_table)/sizeof(int) - 1;
+ int fmin = f - ((int)actual_rbw ) * 1000;
+ int fplus = f + ((int)actual_rbw ) * 1000;
+ while (L <= R) {
+ int m = (L + R) / 2;
+ if (spur_table[m] < fmin)
+ L = m + 1;
+ else if (spur_table[m] > fplus)
+ R = m - 1;
+ else
+ return true; // index is m
+ }
+ return false;
+}
+
+
+int avoid_spur(int f)
+{
+// int window = ((int)actual_rbw ) * 1000*2;
+// if (window < 50000)
+// window = 50000;
+ if (! setting.mode == M_LOW || !setting.auto_IF || actual_rbw > 300.0)
+ return(false);
+ return binary_search(f);
+}
+
+static int modulation_counter = 0;
+
+static const int am_modulation[5] = { 4,0,1,5,7 };
+static const int nfm_modulation[5] = { 0, 2, 1, -1, -2};
+static const int wfm_modulation[5] = { 0, 190, 118, -118, -190 };
+
+char age[POINTS_COUNT];
+
+static int old_a = -150;
+
+float perform(bool break_on_operation, int i, uint32_t f, int tracking)
+{
+ if (i == 0 && dirty ) { // SCan initiation
+ apply_settings();
+ scandirty = true;
+ dirty = false;
+ if (setting.spur)
+ setting.spur = 1; // resync spur in case of previous abort
+ }
+
+ if (setting.mode == M_GENLOW && setting.level_sweep != 0.0) {
+ int a = setting.level + (i / 290.0) * setting.level_sweep;
+ if (a != old_a) {
+ old_a = a;
+ int d = 0; // Start at lowest drive level;
+ a = a + POWER_OFFSET;
+ if (a > 0) {
+ d++;
+ a = a - 3;
+ }
+ if (a > 0) {
+ d++;
+ a = a - 3;
+ }
+ if (a > 0) {
+ d++;
+ a = a - 3;
+ }
+ SI4432_Sel = 0;
+ SI4432_Drive(d);
+ if (a > 0)
+ a = 0;
+ if( a > - SWITCH_ATTENUATION) {
+ set_switch_transmit();
+ } else {
+ a = a + SWITCH_ATTENUATION;
+ set_switch_receive();
+ }
+ a = -a;
+ PE4302_Write_Byte(a * 2 );
+ }
+ }
+
+ if (setting.mode == M_LOW && S_IS_AUTO(setting.agc) && UNIT_IS_LOG(setting.unit)) {
+ unsigned char v;
+ static unsigned char old_v;
+ if (f < 500000)
+ v = 0x50; // Disable AGC and enable LNA
+ else
+ v = 0x60; // Enable AGC and disable LNA
+ if (old_v != v) {
+ SI4432_Write_Byte(0x69, v);
+ old_v = v;
+ }
+ }
+ if (MODE_OUTPUT(setting.mode) && (setting.modulation == MO_AM_1kHz||setting.modulation == MO_AM_10Hz)) { // AM modulation
+ int p = setting.attenuate * 2 + am_modulation[modulation_counter];
+ if (p>63)
+ p = 63;
+ if (p<0)
+ p = 0;
+ PE4302_Write_Byte(p);
+ if (modulation_counter == 4) { // 3dB modulation depth
+ modulation_counter = 0;
+ } else {
+ modulation_counter++;
+ }
+ if (setting.modulation == MO_AM_10Hz)
+ my_microsecond_delay(20000);
+ else
+ my_microsecond_delay(200);
+// chThdSleepMicroseconds(200);
+
+ } else if (MODE_OUTPUT(setting.mode) && (setting.modulation == MO_NFM || setting.modulation == MO_WFM )) { //FM modulation
+ SI4432_Sel = 1;
+ int offset;
+ if (setting.modulation == MO_NFM ) {
+ offset = nfm_modulation[modulation_counter] ;
+ SI4432_Write_Byte(0x73, (offset & 0xff )); // Use frequency hopping channel for FM modulation
+ SI4432_Write_Byte(0x74, ((offset >> 8) & 0x03 )); // Use frequency hopping channel for FM modulation
+ }
+ else {
+ offset = wfm_modulation[modulation_counter] ;
+ SI4432_Write_Byte(0x73, (offset & 0xff )); // Use frequency hopping channel for FM modulation
+ SI4432_Write_Byte(0x74, ((offset >> 8) & 0x03 )); // Use frequency hopping channel for FM modulation
+ }
+ if (modulation_counter == 4)
+ modulation_counter = 0;
+ else
+ modulation_counter++;
+ my_microsecond_delay(200);
+// chThdSleepMicroseconds(200);
+ }
+
+ float RSSI = -150.0;
+ int t = 0;
+ do { // ------------- Acquisition loop ----------
+ int offs = 0,sm;
+ uint32_t lf = (uint32_t)f;
+ if (vbwSteps > 1) { // Calculate sub steps
+ if (setting.step_delay == 1)
+ sm = 250; // steps of a quarter rbw
+ else
+ sm = 500; // steps of half the rbw
+ if (vbwSteps & 1) { // Uneven steps, center
+ offs = (t - (vbwSteps >> 1)) * sm;
+ } else { // Even, shift half step
+ offs = (t - (vbwSteps >> 1)) * sm + sm/2;
+ }
+ offs = (int)(offs * actual_rbw);
+ lf = (uint32_t)(f + offs);
+ }
+
+
+
+ // --------------- Set all the LO's ------------------------
+#ifdef __SPUR__
+ float spur_RSSI = 0;
+#endif
+
+
+ if (MODE_INPUT(setting.mode) && i > 0 && FREQ_IS_CW())
+ goto skip_LO_setting; // No LO changes during CW loop
+
+ long local_IF;
+ again:
+ if (MODE_HIGH(setting.mode))
+ local_IF = 0;
+ else {
+ if (setting.auto_IF) {
+ if (setting.spur)
+ local_IF = 433900000;
+ else
+ local_IF = 433800000;
+ }
+ else
+ local_IF = setting.frequency_IF;
+ }
+ if (setting.mode == M_LOW && tracking) { // Measure BPF
+ set_freq (0, local_IF + lf - reffer_freq[setting.refer]); // Offset so fundamental of reffer is visible
+ } else if (MODE_LOW(setting.mode)) {
+ if (setting.mode == M_LOW && !in_selftest && avoid_spur(f)) {
+ local_IF = spur_alternate_IF;
+#ifdef __SPUR__
+ } else if (setting.mode== M_LOW && setting.spur){
+ if (S_IS_AUTO(setting.below_IF) && lf < 150000000) // if below 150MHz and auto_below_IF swap IF
+ { // else low/above IF
+ if (setting.spur == 1)
+ setting.below_IF = S_AUTO_ON;
+ else
+ setting.below_IF = S_AUTO_OFF;
+ }
+ else
+ local_IF = local_IF + (int)(actual_rbw < 350.0 ? setting.spur*300000 : 0 );
+#endif
+ } else {
+// local_IF = setting.frequency_IF ;
+ }
+ if (setting.mode == M_GENLOW && setting.modulation == MO_EXTERNAL) // LO input via high port
+ local_IF += lf;
+ set_freq (0, local_IF);
+#ifdef __ULTRA__
+ } else if (setting.mode == M_ULTRA) { // No above/below IF mode in Ultra
+ local_IF = setting.frequency_IF + (int)(actual_rbw < 350.0 ? setting.spur*300000 : 0 );
+ set_freq (0, local_IF);
+ // local_IF = setting.frequency_IF + (int)(actual_rbw < 300.0?setting.spur * 1000 * actual_rbw:0);
+#endif
+ } else // This must be high mode
+ local_IF= 0;
+#ifdef __ULTRA__
+ if (setting.mode == M_ULTRA) { // Set LO to correct harmonic in Ultra mode
+// if (lf > 3406000000 )
+// setFreq (1, local_IF/5 + lf/5);
+// else
+ if (setting.spur != 1) { // Left of tables
+ if (lf > 3250000000 )
+ set_freq (1, lf/5 - local_IF/5);
+ if (lf > 1250000000 )
+ set_freq (1, lf/3 - local_IF/3);
+ else
+ set_freq (1, lf - local_IF);
+
+ } else { // Right of tables
+ if (lf >= 2350000000)
+ set_freq (1, lf/5 + local_IF/5);
+ else
+ set_freq (1, lf/3 + local_IF/3);
+ }
+ } else
+#endif
+ { // Else set LO ('s)
+#ifdef __ULTRA_SA__
+//#define IF_1 2550000000
+#define IF_2 2025000000 // First IF in Ultra SA mode
+
+ set_freq (2, IF_2 + lf); // Scanning LO up to IF2
+ set_freq (3, IF_2 - 433800000); // Down from IF2 to fixed second IF in Ultra SA mode
+ set_freq (1, 433800000); // Second IF fixe in Ultra SA mode
+#else
+ if (setting.mode == M_LOW && !setting.tracking && S_STATE(setting.below_IF))
+ set_freq (1, local_IF-lf);
+ else
+ set_freq (1, local_IF+lf);
+#endif
+ }
+ if (MODE_OUTPUT(setting.mode)) // No substepping and no RSSI in output mode
+ return(0);
+
+ // ---------------- Prepare RSSI ----------------------
+
+ float signal_path_loss;
+
+ skip_LO_setting:
+#ifdef __FAST_SWEEP__
+ if (i == 0 && setting.frequency_step == 0 && setting.trigger == T_AUTO && actualStepDelay == 0 && setting.repeat == 1 && setting.sweep_time < 1000) {
+ SI4432_Fill(MODE_SELECT(setting.mode), 0);
+ }
+#endif
+
+#ifdef __ULTRA__
+ if (setting.mode == M_ULTRA)
+ signal_path_loss = -15; // Loss in dB, -9.5 for v0.1, -12.5 for v0.2
+ else
+#endif
+ if (setting.mode == M_LOW)
+ signal_path_loss = -5.5; // Loss in dB, -9.5 for v0.1, -12.5 for v0.2
+ else
+ signal_path_loss = +7; // Loss in dB (+ is gain)
+
+ int wait_for_trigger = false;
+ int old_actual_step_delay = actualStepDelay;
+ if (i == 0 && setting.frequency_step == 0 && setting.trigger != T_AUTO) { // prepare for wait for trigger to happen
+ wait_for_trigger = true;
+ actualStepDelay = 0; // fastest possible in zero span trigger mode
+ }
+ float subRSSI;
+
+ static float correct_RSSI;
+ if (i == 0 || setting.frequency_step != 0 ) // only cases where the value can change
+ correct_RSSI = get_level_offset()+ setting.attenuate - signal_path_loss - setting.offset + get_frequency_correction(f);
+ wait:
+ subRSSI = SI4432_RSSI(lf, MODE_SELECT(setting.mode)) + correct_RSSI ;
+// if ( i < 3)
+// shell_printf("%d %.3f %.3f %.1f\r\n", i, local_IF/1000000.0, lf/1000000.0, subRSSI);
+
+ if (wait_for_trigger) { // wait for trigger to happen
+ if ((operation_requested || shell_function) && break_on_operation)
+ break; // abort
+ if (subRSSI < setting.trigger_level)
+ goto wait;
+#ifdef __FAST_SWEEP__
+ if (i == 0 && setting.frequency_step == 0 /* && setting.trigger == T_AUTO */ && old_actual_step_delay == 0 && setting.repeat == 1 && setting.sweep_time < 1000) {
+ SI4432_Fill(MODE_SELECT(setting.mode), 1);
+ }
+#endif
+ actualStepDelay = old_actual_step_delay; // Trigger happened, restore step delay
+ if (setting.trigger == T_SINGLE)
+ pause_sweep(); // Trigger once so pause after this sweep has completed!!!!!!!
+ }
+
+#ifdef __SPUR__
+ if (setting.spur == 1) { // If first spur pass
+ spur_RSSI = subRSSI;
+ setting.spur = -1;
+ goto again; // Skip all other processing
+ } else if (setting.spur == -1) { // If second spur pass
+ subRSSI = ( subRSSI < spur_RSSI ? subRSSI : spur_RSSI); // Take minimum of two
+ setting.spur = 1;
+ }
+#endif
+
+ if (RSSI < subRSSI) // Take max during subscanning
+ RSSI = subRSSI;
+ t++;
+ if ((operation_requested || shell_function ) && break_on_operation) // break subscanning if requested
+ break; // abort
+ } while (t < vbwSteps);
+ return(RSSI);
+}
+
+#define MAX_MAX 4
+int16_t max_index[MAX_MAX];
+int16_t cur_max = 0;
+
+static int low_count = 0;
+
+
+// main loop for measurement
+static bool sweep(bool break_on_operation)
+{
+ float RSSI;
+ int16_t downslope;
+// if (setting.mode== -1)
+// return;
+// START_PROFILE;
+again:
+ downslope = true;
+ palClearPad(GPIOB, GPIOB_LED);
+ temppeakLevel = -150;
+ float temp_min_level = 100;
+ // spur_old_stepdelay = 0;
+ int repeats = 1;
+// shell_printf("\r\n");
+ if (MODE_OUTPUT(setting.mode) && setting.modulation != MO_NONE) {
+ repeats = 1000; // to avoid interrupting the tone during UI processing
+ modulation_counter = 0;
+ }
+ float t = setting.sweep_time - calc_min_sweep_time(); // Time to delay in mS
+ if (t < 0)
+ t = 0;
+ t = t * 1000 / 290.0; // Now in uS per point
+ if (MODE_OUTPUT(setting.mode) && t < 500) // Minimum wait time to prevent LO from lockup
+ t = 500;
+ while (repeats--) {
+ for (int i = 0; i < sweep_points; i++) {
+
+ RSSI = perform(break_on_operation, i, frequencies[i], setting.tracking);
+ if (MODE_INPUT(setting.mode) || setting.modulation == MO_NONE) {
+ if (t < 30000)
+ my_microsecond_delay((int)t);
+ else
+ osalThreadSleepMilliseconds(((int)t)/1000);
+ }
+
+ // back to toplevel to handle ui operation
+ if ((operation_requested || shell_function) && break_on_operation)
+ return false;
+ if (MODE_OUTPUT(setting.mode)) {
+ continue; // Skip all other processing
+ }
+
+ if (MODE_INPUT(setting.mode)) {
+
+ if (setting.average != AV_OFF)
+ temp_t[i] = RSSI;
+ if (setting.subtract_stored) {
+ RSSI = RSSI - stored_t[i] ;
+ }
+// stored_t[i] = (SI4432_Read_Byte(0x69) & 0x0f) * 3.0 - 90.0; // Display the AGC value in the stored trace
+ if (scandirty || setting.average == AV_OFF) { // Level calculations
+ actual_t[i] = RSSI;
+ age[i] = 0;
+ } else {
+ switch(setting.average) {
+ case AV_MIN: if (actual_t[i] > RSSI) actual_t[i] = RSSI; break;
+ case AV_MAX_HOLD: if (actual_t[i] < RSSI) actual_t[i] = RSSI; break;
+ case AV_MAX_DECAY:
+ if (actual_t[i] < RSSI) {
+ actual_t[i] = RSSI;
+ age[i] = 0;
+ } else {
+ if (age[i] > setting.decay)
+ actual_t[i] -= 0.5;
+ else
+ age[i] += 1;
+ }
+ break;
+ case AV_4: actual_t[i] = (actual_t[i]*3 + RSSI) / 4.0; break;
+ case AV_16: actual_t[i] = (actual_t[i]*15 + RSSI) / 16.0; break;
+ }
+ }
+#if 1
+
+ // START_PROFILE
+ if (i == 0) { // Prepare peak finding
+ cur_max = 0; // Always at least one maximum
+ temppeakIndex = 0;
+ temppeakLevel = actual_t[i];
+ max_index[0] = 0;
+ downslope = true;
+ }
+ if (downslope) { // If in down slope peak finding
+ if (temppeakLevel > actual_t[i]) { // Follow down
+ temppeakIndex = i; // Latest minimum
+ temppeakLevel = actual_t[i];
+ } else if (temppeakLevel + setting.noise < actual_t[i] ) { // Local minimum found
+ temppeakIndex = i; // This is now the latest maximum
+ temppeakLevel = actual_t[i];
+ downslope = false;
+ }
+ } else { // up slope peak finding
+ if (temppeakLevel < actual_t[i]) { // Follow up
+ temppeakIndex = i;
+ temppeakLevel = actual_t[i];
+ } else if (actual_t[i] < temppeakLevel - setting.noise) { // Local max found
+
+
+ int j = 0; // Insert max in sorted table
+ while (j= temppeakLevel) // Find where to insert
+ j++;
+ if (j < MAX_MAX) { // Larger then one of the previous found
+ int k = MAX_MAX-1;
+ while (k > j) { // Shift to make room for max
+ max_index[k] = max_index[k-1];
+ // maxlevel_index[k] = maxlevel_index[k-1]; // Only for debugging
+ k--;
+ }
+ max_index[j] = temppeakIndex;
+ // maxlevel_index[j] = actual_t[temppeakIndex]; // Only for debugging
+ if (cur_max < MAX_MAX) {
+ cur_max++;
+ }
+ //STOP_PROFILE
+ }
+ // Insert done
+ temppeakIndex = i; // Latest minimum
+ temppeakLevel = actual_t[i];
+
+ downslope = true;
+ }
+ }
+ } // end of peak finding
+#else
+ if (frequencies[i] > 1000000) {
+ if (temppeakLevel < actual_t[i]) {
+ temppeakIndex = i;
+ temppeakLevel = actual_t[i];
+ }
+ }
+#endif
+ if (temp_min_level > actual_t[i]) // Remember minimum
+ temp_min_level = actual_t[i];
+
+ }
+
+ if (setting.trigger != T_AUTO && setting.frequency_step > 0) { // Trigger active
+ if (actual_t[max_index[0]] < setting.trigger_level) {
+ goto again;
+ } else {
+ if (setting.trigger == T_SINGLE)
+ pause_sweep(); // Stop scanning after completing this sweep if above trigger
+ }
+ scandirty = true; // To show trigger happened
+ }
+
+ if (scandirty) {
+ scandirty = false;
+ redraw_request |= REDRAW_CAL_STATUS;
+ }
+
+ if (!in_selftest && setting.mode == M_LOW && setting.auto_attenuation && max_index[0] > 0) { // Auto attenuate
+ int old_attenuate = setting.attenuate;
+ float actual_max_level = actual_t[max_index[0]] - setting.attenuate;
+ if (actual_max_level < - 31 && setting.attenuate >= 10) {
+ setting.attenuate -= 10;
+ } else if (actual_max_level < - 26 && setting.attenuate >= 5) {
+ setting.attenuate -= 5;
+ } else if (actual_max_level > - 19 && setting.attenuate <= 20) {
+ setting.attenuate += 10;
+ }
+ if (old_attenuate != setting.attenuate) {
+ redraw_request |= REDRAW_CAL_STATUS;
+ PE4302_Write_Byte(setting.attenuate * 2);
+ // dirty = true; // Must be above if(scandirty!!!!!)
+ }
+ }
+ if (!in_selftest && MODE_INPUT(setting.mode) && S_IS_AUTO(setting.agc) && UNIT_IS_LINEAR(setting.unit)) { // Auto AGC in linear mode
+ unsigned char v;
+ static unsigned char old_v;
+ float actual_max_level = actual_t[max_index[0]] - setting.attenuate;
+ if (actual_max_level > - 45)
+ v = 0x50; // Disable AGC and enable LNA
+ else
+ v = 0x60; // Enable AGC and disable LNA
+ if (old_v != v) {
+ SI4432_Write_Byte(0x69, v);
+ old_v = v;
+ }
+
+ }
+ if (max_index[0] > 0)
+ temppeakLevel = actual_t[max_index[0]];
+
+ float r = value(temppeakLevel);
+ float s_r = r / setting.scale;
+
+ if (!in_selftest && MODE_INPUT(setting.mode) && setting.auto_reflevel) { // Auto reflevel
+ if (UNIT_IS_LINEAR(setting.unit)) { // Linear scales can not have negative values
+ if (setting.reflevel > REFLEVEL_MIN) {
+ if (s_r < 2)
+ low_count = 5;
+ else if (s_r < 4)
+ low_count++;
+ else
+ low_count = 0;
+ }
+ if ((low_count > 4) || (setting.reflevel < REFLEVEL_MAX && s_r > NGRIDY) ) { // ensure minimum and maximum reflevel
+ if (r < REFLEVEL_MIN)
+ r = REFLEVEL_MIN;
+ if (r > REFLEVEL_MAX)
+ r = REFLEVEL_MAX;
+ if (r != setting.reflevel) {
+ //if (setting.scale * NGRIDY > r)
+ set_scale(r / NGRIDY);
+ set_reflevel(setting.scale*NGRIDY);
+ dirty = false; // Prevent reset of SI4432
+ redraw_request |= REDRAW_CAL_STATUS;
+ }
+ }
+ } else {
+ float s_min = value(temp_min_level)/setting.scale;
+ float s_ref = setting.reflevel/setting.scale;
+ if (s_r < s_ref - NGRIDY || s_min > s_ref) { //Completely outside
+ set_reflevel(setting.scale*(floor(s_r)+1));
+ redraw_request |= REDRAW_CAL_STATUS;
+// dirty = true; // Must be above if(scandirty!!!!!)
+ }else if (s_r > s_ref - 0.5 || s_min > s_ref - 8.8 ) { // maximum to high or minimum to high
+ set_reflevel(setting.reflevel + setting.scale);
+ redraw_request |= REDRAW_CAL_STATUS;
+// dirty = true; // Must be above if(scandirty!!!!!)
+ } else if (s_min < s_ref - 10.1 && s_r < s_ref - 1.5) { // minimum to low and maximum can move up
+ set_reflevel(setting.reflevel - setting.scale);
+ redraw_request |= REDRAW_CAL_STATUS;
+// dirty = true; // Must be above if(scandirty!!!!!)
+ }
+ dirty = false; // Prevent reset of SI4432
+ }
+ }
+#if 1
+ if (MODE_INPUT(setting.mode)) { // Assign maxima found to tracking markers
+ int i = 0;
+ int m = 0;
+ while (i < cur_max) { // For all maxima found
+ while (m < MARKERS_MAX) {
+ if (markers[m].enabled && markers[m].mtype & M_TRACKING) { // Available marker found
+ markers[m].index = max_index[i];
+ markers[m].frequency = frequencies[markers[m].index];
+ m++;
+ break; // Next maximum
+ }
+ m++; // Try next marker
+ }
+ i++;
+ }
+ while (m < MARKERS_MAX) { // Insufficient maxima found
+ if (markers[m].enabled && markers[m].mtype & M_TRACKING) { // More available markers found
+ markers[m].index = 0; // Enabled but no max so set to left most frequency
+ markers[m].frequency = frequencies[markers[m].index];
+ }
+ m++; // Try next marker
+ }
+#ifdef __MEASURE__
+ if (setting.measurement == M_IMD && markers[0].index > 10) { // IMD measurement
+ markers[1].enabled = search_maximum(1, frequencies[markers[0].index]*2, 8);
+ markers[2].enabled = search_maximum(2, frequencies[markers[0].index]*3, 12);
+ markers[3].enabled = search_maximum(3, frequencies[markers[0].index]*4, 16);
+ } else if (setting.measurement == M_OIP3 && markers[0].index > 10 && markers[1].index > 10) { // IOP measurement
+ int l = markers[0].index;
+ int r = markers[1].index;
+ if (r < l) {
+ l = markers[1].index;
+ r = markers[0].index;
+ markers[0].index = l;
+ markers[1].index = r;
+ }
+ uint32_t lf = frequencies[l];
+ uint32_t rf = frequencies[r];
+ markers[2].enabled = search_maximum(2, lf - (rf - lf), 12);
+ markers[3].enabled = search_maximum(3, rf + (rf - lf), 12);
+ } else if (setting.measurement == M_PHASE_NOISE && markers[0].index > 10) { // Phase noise measurement
+ markers[1].index = markers[0].index + (setting.mode == M_LOW ? 290/4 : -290/4); // Position phase noise marker at requested offset
+ } else if (setting.measurement == M_STOP_BAND && markers[0].index > 10) { // Stop band measurement
+ markers[1].index = marker_search_left_min(markers[0].index);
+ if (markers[1].index < 0) markers[1].index = 0;
+ markers[2].index = marker_search_right_min(markers[0].index);
+ if (markers[2].index < 0) markers[1].index = setting._sweep_points - 1;
+ } else if (setting.measurement == M_PASS_BAND && markers[0].index > 10) { // Pass band measurement
+ int t = markers[0].index;
+ float v = actual_t[t];
+ while (t > 0 && actual_t[t] > v - 3.0) // Find left -3dB point
+ t --;
+ if (t > 0)
+ markers[1].index = t;
+ t = markers[0].index;
+ while (t < setting._sweep_points - 1 && actual_t[t] > v - 3.0) // find right -3dB point
+ t ++;
+ if (t < setting._sweep_points - 1 )
+ markers[2].index = t;
+ }
+#endif
+ peakIndex = max_index[0];
+ peakLevel = actual_t[peakIndex];
+ peakFreq = frequencies[peakIndex];
+#else
+ int peak_marker = 0;
+ markers[peak_marker].enabled = true;
+ markers[peak_marker].index = peakIndex;
+ markers[peak_marker].frequency = frequencies[markers[peak_marker].index];
+#endif
+ min_level = temp_min_level;
+ }
+ }
+ if (setting.measurement == M_LINEARITY && setting.linearity_step < setting._sweep_points) {
+ setting.attenuate = 29 - setting.linearity_step * 30 / 290;
+ dirty = true;
+ stored_t[setting.linearity_step] = peakLevel;
+ setting.linearity_step++;
+ }
+
+ // redraw_marker(peak_marker, FALSE);
+// STOP_PROFILE;
+ palSetPad(GPIOB, GPIOB_LED);
+ return true;
+}
+
+//------------------------------- SEARCH ---------------------------------------------
+
+int
+marker_search_left_max(int from)
+{
+ int i;
+ int found = -1;
+ if (uistat.current_trace == -1)
+ return -1;
+
+ int value = actual_t[from];
+ for (i = from - 1; i >= 0; i--) {
+ int new_value = actual_t[i];
+ if (new_value < value) {
+ value = new_value;
+ found = i;
+ } else if (new_value > value + setting.noise )
+ break;
+ }
+
+ for (; i >= 0; i--) {
+ int new_value = actual_t[i];
+ if (new_value > value) {
+ value = new_value;
+ found = i;
+ } else if (new_value < value - setting.noise )
+ break;
+ }
+ return found;
+}
+
+int
+marker_search_right_max(int from)
+{
+ int i;
+ int found = -1;
+
+ if (uistat.current_trace == -1)
+ return -1;
+ int value = actual_t[from];
+ for (i = from + 1; i < sweep_points; i++) {
+ int new_value = actual_t[i];
+ if (new_value < value) { // follow down
+ value = new_value;
+ found = i;
+ } else if (new_value > value + setting.noise) // larger then lowest value + noise
+ break; // past the minimum
+ }
+ for (; i < sweep_points; i++) {
+ int new_value = actual_t[i];
+ if (new_value > value) { // follow up
+ value = new_value;
+ found = i;
+ } else if (new_value < value - setting.noise)
+ break;
+ }
+ return found;
+}
+
+#define MINMAX_DELTA 10
+
+
+int
+marker_search_left_min(int from)
+{
+ int i;
+ int found = from;
+ if (uistat.current_trace == -1)
+ return -1;
+
+ int value = actual_t[from];
+ for (i = from - 1; i >= 0; i--) {
+ int new_value = actual_t[i];
+ if (new_value > value) {
+ value = new_value; // follow up
+// found = i;
+ } else if (new_value < value - MINMAX_DELTA )
+ break; // past the maximum
+ }
+
+ for (; i >= 0; i--) {
+ int new_value = actual_t[i];
+ if (new_value < value) {
+ value = new_value; // follow down
+ found = i;
+ } else if (new_value > value + MINMAX_DELTA )
+ break;
+ }
+ return found;
+}
+
+int
+marker_search_right_min(int from)
+{
+ int i;
+ int found = from;
+
+ if (uistat.current_trace == -1)
+ return -1;
+ int value = actual_t[from];
+ for (i = from + 1; i < sweep_points; i++) {
+ int new_value = actual_t[i];
+ if (new_value > value) { // follow up
+ value = new_value;
+// found = i;
+ } else if (new_value < value - MINMAX_DELTA) // less then largest value - noise
+ break; // past the maximum
+ }
+ for (; i < sweep_points; i++) {
+ int new_value = actual_t[i];
+ if (new_value < value) { // follow down
+ value = new_value;
+ found = i;
+ } else if (new_value > value + MINMAX_DELTA) // larger then smallest value + noise
+ break;
+ }
+ return found;
+}
+
+
+
+
+
+// -------------------------- CAL STATUS ---------------------------------------------
+const char * const averageText[] = { "OFF", "MIN", "MAX", "MAXD", " A 4", "A 16"};
+const char * const dBText[] = { "1dB/", "2dB/", "5dB/", "10dB/", "20dB/"};
+const int refMHz[] = { 30, 15, 10, 4, 3, 2, 1 };
+
+float my_round(float v)
+{
+ float m = 1;
+ int sign = 1;
+ if (v < 0) {
+ sign = -1;
+ v = -v;
+ }
+ while (v < 100) {
+ v = v * 10;
+ m = m / 10;
+ }
+ while (v > 1000) {
+ v = v / 10;
+ m = m * 10;
+ }
+ v = (int)(v+0.5);
+ v = v * m;
+ if (sign == -1) {
+ v = -v;
+ }
+ return v;
+}
+
+const char * const unit_string[] = { "dBm", "dBmV", "dBuV", "V", "W", "dBc", "dBmVc", "dBuVc", "Vc", "Wc" }; // unit + 5 is delta unit
+
+static const float scale_value[]={50000, 20000, 10000, 5000, 2000, 1000, 500, 200, 100, 50, 20,10,5,2,1,0.5,0.2,0.1,0.05,0.02,0.01,0.005,0.002, 0.001,0.0005,0.0002, 0.0001};
+static const char * const scale_vtext[]= {"50000", "20000", "10000", "5000", "2000", "1000", "500", "200", "100", "50", "20","10","5","2","1","0.5","0.2","0.1","0.05","0.02","0.01", "0.005","0.002","0.001", "0.0005","0.0002","0.0001"};
+
+
+
+void draw_cal_status(void)
+{
+#define BLEN 10
+ char buf[BLEN];
+#define YSTEP 8
+ int x = 0;
+ int y = OFFSETY;
+ unsigned int color;
+ int rounding = false;
+ if (!UNIT_IS_LINEAR(setting.unit))
+ rounding = true;
+ const char * const unit = unit_string[setting.unit];
+
+
+#define XSTEP 40
+
+ if (MODE_OUTPUT(setting.mode)) { // No cal status during output
+ ili9341_fill(x, y, OFFSETX-5, HEIGHT, 0x0000);
+ return;
+ }
+ ili9341_fill(x, y, OFFSETX, HEIGHT, 0x0000);
+
+ // if (current_menu_is_form() && !in_selftest)
+// return;
+
+ ili9341_set_background(DEFAULT_BG_COLOR);
+
+ float yMax = setting.reflevel;
+ // Top level
+ if (rounding)
+ plot_printf(buf, BLEN, "%4d", (int)yMax);
+ else
+ plot_printf(buf, BLEN, "%.3F", (yMax/setting.unit_scale));
+// buf[5]=0;
+ if (level_is_calibrated()) {
+ if (setting.auto_reflevel)
+ color = DEFAULT_FG_COLOR;
+ else
+ color = BRIGHT_COLOR_GREEN;
+ }
+ else
+ color = BRIGHT_COLOR_RED;
+ ili9341_set_foreground(color);
+ ili9341_drawstring(buf, x, y);
+
+ // Unit
+#if 0
+ color = DEFAULT_FG_COLOR;
+ ili9341_set_foreground(color);
+ if (setting.auto_reflevel){
+ y += YSTEP + YSTEP/2 ;
+ ili9341_drawstring("AUTO", x, y);
+ }
+#endif
+ y += YSTEP + YSTEP/2 ;
+ plot_printf(buf, BLEN, "%s%s",unit_scale_text[setting.unit_scale_index], unit);
+ ili9341_drawstring(buf, x, y);
+
+ // Scale
+ color = DEFAULT_FG_COLOR;
+ ili9341_set_foreground(color);
+ y += YSTEP + YSTEP/2;
+#if 1
+ unsigned int i = 0;
+ while (i < sizeof(scale_value)/sizeof(float)) {
+ float t = (setting.scale/setting.unit_scale) / scale_value[i];;
+ if (t > 0.9 && t < 1.1){
+ plot_printf(buf, BLEN, "%s%s/",scale_vtext[i],unit_scale_text[setting.unit_scale_index]);
+ break;
+ }
+ i++;
+ }
+#else
+ plot_printf(buf, BLEN, "%.2F/",setting.scale);
+#endif
+ ili9341_drawstring(buf, x, y);
+
+ // Attenuation
+ if (setting.auto_attenuation)
+ color = DEFAULT_FG_COLOR;
+ else
+ color = BRIGHT_COLOR_GREEN;
+ ili9341_set_foreground(color);
+ y += YSTEP + YSTEP/2 ;
+ ili9341_drawstring("Attn:", x, y);
+
+ y += YSTEP;
+ plot_printf(buf, BLEN, "%ddB", setting.attenuate);
+ buf[6]=0;
+ ili9341_drawstring(buf, x, y);
+
+ // Average
+ if (setting.average>0) {
+ ili9341_set_foreground(BRIGHT_COLOR_BLUE);
+ y += YSTEP + YSTEP/2 ;
+ ili9341_drawstring("Calc:", x, y);
+
+ y += YSTEP;
+ plot_printf(buf, BLEN, "%s",averageText[setting.average]);
+ buf[6]=0;
+ ili9341_drawstring(buf, x, y);
+ }
+ // Spur
+#ifdef __SPUR__
+ if (setting.spur) {
+ ili9341_set_foreground(BRIGHT_COLOR_GREEN);
+ y += YSTEP + YSTEP/2 ;
+ ili9341_drawstring("Spur:", x, y);
+
+ y += YSTEP;
+ plot_printf(buf, BLEN, "ON");
+ ili9341_drawstring(buf, x, y);
+ }
+#endif
+
+ // RBW
+ if (setting.rbw)
+ color = BRIGHT_COLOR_GREEN;
+ else
+ color = DEFAULT_FG_COLOR;
+ ili9341_set_foreground(color);
+
+ y += YSTEP + YSTEP/2 ;
+ ili9341_drawstring("RBW:", x, y);
+
+ y += YSTEP;
+ plot_printf(buf, BLEN, "%dkHz", (int)actual_rbw);
+ buf[6]=0;
+ ili9341_drawstring(buf, x, y);
+
+ // VBW
+ if (setting.frequency_step > 0) {
+ ili9341_set_foreground(DEFAULT_FG_COLOR);
+ y += YSTEP + YSTEP/2 ;
+ ili9341_drawstring("VBW:", x, y);
+
+ y += YSTEP;
+ plot_printf(buf, BLEN, "%dkHz",(int)setting.vbw);
+ buf[6]=0;
+ ili9341_drawstring(buf, x, y);
+ }
+
+ // Sweep time
+ if (dirty)
+ color = BRIGHT_COLOR_RED;
+ else if (setting.step_delay)
+ color = BRIGHT_COLOR_GREEN;
+ else
+ color = DEFAULT_FG_COLOR;
+
+ ili9341_set_foreground(color);
+
+ y += YSTEP + YSTEP/2 ;
+ ili9341_drawstring("Scan:", x, y);
+
+ y += YSTEP;
+ float t = calc_min_sweep_time();
+ if (t < setting.sweep_time)
+ t = setting.sweep_time;
+ setting.actual_sweep_time = t;
+ if (t>=10000.0)
+ plot_printf(buf, BLEN, "%5d",(int)(t/1000));
+ else if (t>=1000)
+ plot_printf(buf, BLEN, "%5f",t/1000.0);
+ else {
+ plot_printf(buf, BLEN, "%4dm",(int)t);
+ buf[4] = 'm';
+ }
+ buf[5]='S';
+ buf[6]=0;
+ ili9341_drawstring(buf, x, y);
+
+ // Cal output
+ if (setting.refer >= 0) {
+ ili9341_set_foreground(BRIGHT_COLOR_RED);
+ y += YSTEP + YSTEP/2 ;
+ ili9341_drawstring("Ref:", x, y);
+
+ y += YSTEP;
+ plot_printf(buf, BLEN, "%dMHz",reffer_freq[setting.refer]/1000000);
+ buf[6]=0;
+ ili9341_drawstring(buf, x, y);
+ }
+
+ // Offset
+ if (setting.offset != 0.0) {
+ ili9341_set_foreground(BRIGHT_COLOR_RED);
+ y += YSTEP + YSTEP/2 ;
+ ili9341_drawstring("Amp:", x, y);
+
+ y += YSTEP;
+ plot_printf(buf, BLEN, "%.1fdB",setting.offset);
+ buf[6]=0;
+ ili9341_drawstring(buf, x, y);
+ }
+
+ // Repeat
+ if (setting.repeat != 1) {
+ ili9341_set_foreground(BRIGHT_COLOR_GREEN);
+ y += YSTEP + YSTEP/2 ;
+ ili9341_drawstring("Repeat:", x, y);
+
+ y += YSTEP;
+ plot_printf(buf, BLEN, "%d",setting.repeat);
+ buf[6]=0;
+ ili9341_drawstring(buf, x, y);
+ }
+
+ // Trigger
+ if (setting.trigger != T_AUTO) {
+ if (is_paused()) {
+ ili9341_set_foreground(BRIGHT_COLOR_GREEN);
+ } else {
+ ili9341_set_foreground(BRIGHT_COLOR_RED);
+ }
+ y += YSTEP + YSTEP/2 ;
+ ili9341_drawstring("TRIG:", x, y);
+
+ y += YSTEP;
+ if (rounding)
+ plot_printf(buf, BLEN, "%4f", value(setting.trigger_level));
+ else
+ plot_printf(buf, BLEN, "%.4F", value(setting.trigger_level));
+// plot_printf(buf, BLEN, "%4f", value(setting.trigger_level)/setting.unit_scale);
+ buf[6]=0;
+ ili9341_drawstring(buf, x, y);
+ }
+
+ // Mode
+ if (level_is_calibrated())
+ color = BRIGHT_COLOR_GREEN;
+ else
+ color = BRIGHT_COLOR_RED;
+ ili9341_set_foreground(color);
+ y += YSTEP + YSTEP/2 ;
+ if (MODE_LOW(setting.mode))
+ ili9341_drawstring_7x13("LOW", x, y);
+ else
+ ili9341_drawstring_7x13("HIGH", x, y);
+
+ // Compact status string
+// ili9341_set_background(DEFAULT_FG_COLOR);
+ ili9341_set_foreground(DEFAULT_FG_COLOR);
+ y += YSTEP + YSTEP/2 ;
+ strncpy(buf," ",BLEN);
+ if (setting.auto_attenuation)
+ buf[0] = 'a';
+ else
+ buf[0] = 'A';
+ if (setting.auto_IF)
+ buf[1] = 'f';
+ else
+ buf[1] = 'F';
+ if (setting.auto_reflevel)
+ buf[2] = 'r';
+ else
+ buf[2] = 'R';
+ if (S_IS_AUTO(setting.agc))
+ buf[3] = 'g';
+ else if (S_STATE(setting.agc))
+ buf[3] = 'G';
+ if (S_IS_AUTO(setting.lna))
+ buf[4] = 'n';
+ else if (S_STATE(setting.lna))
+ buf[4] = 'N';
+ if (S_IS_AUTO(setting.below_IF))
+ buf[5] = 'b';
+ else if (S_STATE(setting.below_IF))
+ buf[5] = 'B';
+ ili9341_drawstring(buf, x, y);
+
+ // Version
+ y += YSTEP + YSTEP/2 ;
+ strncpy(buf,&VERSION[8],6);
+ buf[6]=0;
+ ili9341_drawstring(buf, x, y);
+
+// ili9341_set_background(DEFAULT_BG_COLOR);
+
+ // Bottom level
+ y = HEIGHT-7 + OFFSETY;
+ if (rounding)
+ plot_printf(buf, BLEN, "%4d", (int)(yMax - setting.scale * NGRIDY));
+ else
+ plot_printf(buf, BLEN, "%.3F", ((yMax - setting.scale * NGRIDY)/setting.unit_scale));
+// buf[5]=0;
+ if (level_is_calibrated())
+ if (setting.auto_reflevel)
+ color = DEFAULT_FG_COLOR;
+ else
+ color = BRIGHT_COLOR_GREEN;
+ else
+ color = BRIGHT_COLOR_RED;
+ ili9341_set_foreground(color);
+ ili9341_drawstring(buf, x, y);
+
+}
+
+// -------------------- Self testing -------------------------------------------------
+
+enum {
+ TC_SIGNAL, TC_BELOW, TC_ABOVE, TC_FLAT, TC_MEASURE, TC_SET, TC_END,
+};
+
+enum {
+ TP_SILENT, TPH_SILENT, TP_10MHZ, TP_10MHZEXTRA, TP_10MHZ_SWITCH, TP_30MHZ, TPH_30MHZ
+};
+
+#define TEST_COUNT 17
+
+static const struct {
+ int kind;
+ int setup;
+ float center; // In MHz
+ float span; // In MHz
+ float pass;
+ int width;
+ float stop;
+} test_case [TEST_COUNT] =
+{// Condition Preparation Center Span Pass Width Stop
+ {TC_BELOW, TP_SILENT, 0.005, 0.01, 0,0, 0}, // 1 Zero Hz leakage
+ {TC_BELOW, TP_SILENT, 0.01, 0.01, -30, 0, 0}, // 2 Phase noise of zero Hz
+ {TC_SIGNAL, TP_10MHZ, 20, 7, -37, 30, -90 }, // 3
+ {TC_SIGNAL, TP_10MHZ, 30, 7, -32, 30, -90 }, // 4
+ {TC_BELOW, TP_SILENT, 200, 100, -75, 0, 0}, // 5 Wide band noise floor low mode
+ {TC_BELOW, TPH_SILENT, 600, 720, -75, 0, 0}, // 6 Wide band noise floor high mode
+ {TC_SIGNAL, TP_10MHZEXTRA, 10, 8, -20, 80, -80 }, // 7 BPF loss and stop band
+ {TC_FLAT, TP_10MHZEXTRA, 10, 4, -18, 20, -60}, // 8 BPF pass band flatness
+ {TC_BELOW, TP_30MHZ, 430, 60, -80, 0, -80}, // 9 LPF cutoff
+ {TC_SIGNAL, TP_10MHZ_SWITCH,20, 7, -58, 30, -95 }, // 10 Switch isolation
+ {TC_END, 0, 0, 0, 0, 0, 0},
+ {TC_MEASURE, TP_30MHZ, 30, 7, -22.5, 30, -70 }, // 12 Measure power level and noise
+ {TC_MEASURE, TP_30MHZ, 270, 4, -50, 30, -75 }, // 13 Measure powerlevel and noise
+ {TC_MEASURE, TPH_30MHZ, 270, 4, -40, 30, -65 }, // 14 Calibrate power high mode
+ {TC_END, 0, 0, 0, 0, 0, 0},
+ {TC_MEASURE, TP_30MHZ, 30, 1, -20, 30, -70 }, // 16 Measure RBW step time
+ {TC_END, 0, 0, 0, 0, 0, 0},
+};
+
+enum {
+ TS_WAITING, TS_PASS, TS_FAIL, TS_CRITICAL
+};
+static const char *(test_text [4]) =
+{
+ "Waiting", "Pass", "Fail", "Critical"
+};
+static const char *(test_fail_cause [TEST_COUNT]);
+
+static int test_status[TEST_COUNT];
+static int show_test_info = FALSE;
+static volatile int test_wait = false;
+static float test_value;
+
+static void test_acquire(int i)
+{
+ (void)i;
+ pause_sweep();
+#if 0
+ if (test_case[i].center < 300)
+ setting.mode = M_LOW;
+ else
+ setting.mode = M_HIGH;
+#endif
+// SetAverage(4);
+ sweep(false);
+// sweep(false);
+// sweep(false);
+// sweep(false);
+ plot_into_index(measured);
+ redraw_request |= REDRAW_CELLS | REDRAW_FREQUENCY;
+}
+
+extern void cell_drawstring_5x7(int w, int h, char *str, int x, int y, uint16_t fg);
+extern void cell_drawstring_7x13(int w, int h, char *str, int x, int y, uint16_t fg);
+void cell_drawstring(char *str, int x, int y);
+
+static char self_test_status_buf[35];
+void cell_draw_test_info(int x0, int y0)
+{
+#define INFO_SPACING 13
+// char self_test_status_buf[35];
+ if (!show_test_info)
+ return;
+ int i = -2;
+ do {
+ i++;
+ int xpos = 25 - x0;
+ int ypos = 50+i*INFO_SPACING - y0;
+ unsigned int color = RGBHEX(0xFFFFFF);
+ if (i == -1) {
+ plot_printf(self_test_status_buf, sizeof self_test_status_buf, "Self test status:");
+ } else if (test_case[i].kind == TC_END) {
+ if (test_wait)
+ plot_printf(self_test_status_buf, sizeof self_test_status_buf, "Touch screen to continue");
+ else
+ self_test_status_buf[0] = 0;
+ } else {
+ plot_printf(self_test_status_buf, sizeof self_test_status_buf, "Test %d: %s%s", i+1, test_fail_cause[i], test_text[test_status[i]] );
+ if (test_status[i] == TS_PASS)
+ color = RGBHEX(0x00FF00);
+ else if (test_status[i] == TS_CRITICAL)
+ color = RGBHEX(0xFFFF00);
+ else if (test_status[i] == TS_FAIL)
+ color = RGBHEX(0xFF7F7F);
+ else
+ color = RGBHEX(0x0000FF);
+ }
+ ili9341_set_foreground(color);
+ cell_drawstring(self_test_status_buf, xpos, ypos);
+ } while (test_case[i].kind != TC_END);
+}
+
+#define fabs(X) ((X)<0?-(X):(X))
+
+int validate_signal_within(int i, float margin)
+{
+ test_fail_cause[i] = "Signal level ";
+ if (fabs(peakLevel-test_case[i].pass) > 2*margin) {
+ return TS_FAIL;
+ }
+ if (fabs(peakLevel-test_case[i].pass) > margin) {
+ return TS_CRITICAL;
+ }
+ test_fail_cause[i] = "Frequency ";
+ if (peakFreq < test_case[i].center * 1000000 - 200000 || test_case[i].center * 1000000 + 200000 < peakFreq )
+ return TS_FAIL;
+ test_fail_cause[i] = "";
+ return TS_PASS;
+}
+
+int validate_peak_below(int i, float margin) {
+ return(test_case[i].pass - peakLevel > margin);
+}
+
+int validate_below(int tc, int from, int to) {
+ int status = TS_PASS;
+ float threshold=stored_t[from];
+ float sum = 0;
+ int sum_count = 0;
+ for (int j = from; j < to; j++) {
+ sum += actual_t[j];
+ sum_count++;
+ if (actual_t[j] > threshold) {
+ status = TS_FAIL;
+ break;
+ }
+ }
+ sum = sum / sum_count;
+ if (sum > threshold - 5)
+ status = TS_CRITICAL;
+ if (status != TS_PASS)
+ test_fail_cause[tc] = "Above ";
+ return(status);
+}
+
+int validate_flatness(int i) {
+ volatile int j;
+ test_fail_cause[i] = "Passband ";
+ for (j = peakIndex; j < setting._sweep_points; j++) {
+ if (actual_t[j] < peakLevel - 6) // Search right -3dB
+ break;
+ }
+ //shell_printf("\n\rRight width %d\n\r", j - peakIndex );
+ if (j - peakIndex < test_case[i].width)
+ return(TS_FAIL);
+ for (j = peakIndex; j > 0; j--) {
+ if (actual_t[j] < peakLevel - 6) // Search left -3dB
+ break;
+ }
+ //shell_printf("Left width %d\n\r", j - peakIndex );
+ if (peakIndex - j < test_case[i].width)
+ return(TS_FAIL);
+ test_fail_cause[i] = "";
+ return(TS_PASS);
+}
+
+int validate_above(int tc) {
+ int status = TS_PASS;
+ for (int j = 0; j < setting._sweep_points; j++) {
+ if (actual_t[j] < stored_t[j] + 5)
+ status = TS_CRITICAL;
+ else if (actual_t[j] < stored_t[j]) {
+ status = TS_FAIL;
+ break;
+ }
+ }
+ if (status != TS_PASS)
+ test_fail_cause[tc] = "Below ";
+ return(status);
+}
+
+
+int test_validate(int i)
+{
+// draw_all(TRUE);
+ int current_test_status = TS_PASS;
+ switch (test_case[i].kind) {
+ case TC_SET:
+ if (test_case[i].pass == 0) {
+ if (test_value != 0)
+ set_actual_power(test_value);
+ } else
+ set_actual_power(test_case[i].pass);
+ goto common;
+ case TC_MEASURE:
+ case TC_SIGNAL: // Validate signal
+ common: current_test_status = validate_signal_within(i, 5.0);
+ if (current_test_status == TS_PASS) { // Validate noise floor
+ current_test_status = validate_below(i, 0, setting._sweep_points/2 - test_case[i].width);
+ if (current_test_status == TS_PASS) {
+ current_test_status = validate_below(i, setting._sweep_points/2 + test_case[i].width, setting._sweep_points);
+ }
+ if (current_test_status != TS_PASS)
+ test_fail_cause[i] = "Stopband ";
+ }
+ if (current_test_status == TS_PASS && test_case[i].kind == TC_MEASURE)
+ test_value = peakLevel;
+ else
+ test_value = 0; // Not valid
+ break;
+ case TC_ABOVE: // Validate signal above curve
+ current_test_status = validate_above(i);
+ break;
+ case TC_BELOW: // Validate signal below curve
+ current_test_status = validate_below(i, 0, setting._sweep_points);
+ break;
+ case TC_FLAT: // Validate passband flatness
+ current_test_status = validate_flatness(i);
+ break;
+
+ }
+
+ // Report status
+
+ if (current_test_status != TS_PASS || test_case[i+1].kind == TC_END)
+ test_wait = true;
+ test_status[i] = current_test_status; // Must be set before draw_all() !!!!!!!!
+ // draw_frequencies();
+// draw_cal_status();
+ draw_all(TRUE);
+ resume_sweep();
+ return current_test_status;
+}
+
+void test_prepare(int i)
+{
+ setting.tracking = false; //Default test setup
+ setting.step_atten = false;
+ setting.frequency_IF = 433800000; // Default frequency
+ setting.auto_IF = true;
+ set_attenuation(0);
+ switch(test_case[i].setup) { // Prepare test conditions
+ case TPH_SILENT: // No input signal
+ set_mode(M_HIGH);
+ goto common_silent;
+ case TP_SILENT: // No input signal
+ set_mode(M_LOW);
+common_silent:
+ set_refer_output(-1);
+ for (int j = 0; j < setting._sweep_points; j++)
+ stored_t[j] = test_case[i].pass;
+ break;
+ case TP_10MHZ_SWITCH:
+ set_mode(M_LOW);
+ set_refer_output(2);
+ setting.step_atten = true;
+ goto common;
+ case TP_10MHZEXTRA: // Swept receiver
+ set_mode(M_LOW);
+ setting.tracking = true; //Sweep BPF
+ setting.auto_IF = false;
+ setting.frequency_IF = 434000000; // Center on SAW filters
+ set_refer_output(2);
+ goto common;
+ case TP_10MHZ: // 10MHz input
+ set_mode(M_LOW);
+ set_refer_output(2);
+ set_step_delay(1); // Precise scanning speed
+#ifdef __SPUR__
+ setting.spur = 1;
+#endif
+ common:
+
+ for (int j = 0; j < setting._sweep_points/2 - test_case[i].width; j++)
+ stored_t[j] = test_case[i].stop;
+ for (int j = setting._sweep_points/2 + test_case[i].width; j < setting._sweep_points; j++)
+ stored_t[j] = test_case[i].stop;
+ for (int j = setting._sweep_points/2 - test_case[i].width; j < setting._sweep_points/2 + test_case[i].width; j++)
+ stored_t[j] = test_case[i].pass;
+ break;
+ case TP_30MHZ:
+ set_mode(M_LOW);
+ set_refer_output(0);
+ // set_step_delay(1); // Do not set !!!!!
+#ifdef __SPUR__
+ setting.spur = 1;
+#endif
+ goto common;
+ case TPH_30MHZ:
+ set_mode(M_HIGH);
+ set_refer_output(0);
+ goto common;
+ }
+ setting.auto_attenuation = false;
+ setting.attenuate = 0;
+ trace[TRACE_STORED].enabled = true;
+ set_reflevel(test_case[i].pass+10);
+ set_sweep_frequency(ST_CENTER, (int32_t)(test_case[i].center * 1000000));
+ set_sweep_frequency(ST_SPAN, (int32_t)(test_case[i].span * 1000000));
+ draw_cal_status();
+}
+
+extern void menu_autosettings_cb(int item);
+extern float SI4432_force_RBW(int i);
+
+int last_spur = 0;
+int add_spur(int f)
+{
+ for (int i = 0; i < last_spur; i++) {
+ if (temp_t[i] == f) {
+ stored_t[i] += 1;
+ return stored_t[i];
+ }
+ }
+ if (last_spur < 290) {
+ temp_t[last_spur] = f;
+ stored_t[last_spur++] = 1;
+ }
+ return 1;
+}
+
+
+void self_test(int test)
+{
+ if (test ==1) {
+ in_selftest = true; // Spur search
+ reset_settings(M_LOW);
+ test_prepare(4);
+ int f = 400000; // Start search at 400kHz
+ // int i = 0; // Index in spur table (temp_t)
+ float p2, p1, p;
+
+#define FREQ_STEP 3000
+
+ set_RBW(FREQ_STEP/1000);
+ last_spur = 0;
+ for (int j = 0; j < 10; j++) {
+
+ p2 = perform(false, 0, f, false);
+ vbwSteps = 1;
+ f += FREQ_STEP;
+ p1 = perform(false, 1, f, false);
+ f += FREQ_STEP;
+ shell_printf("\n\rStarting with %4.2f, %4.2f and IF at %d\n\r", p2, p1, setting.frequency_IF);
+
+ f = 400000;
+ while (f < 100000000) {
+ p = perform(false, 1, f, false);
+#define SPUR_DELTA 6
+ if ( p2 < p1 - SPUR_DELTA && p < p1 - SPUR_DELTA) {
+ // temp_t[i++] = f - FREQ_STEP;
+ shell_printf("Spur of %4.2f at %d with count %d\n\r", p1,(f - FREQ_STEP)/1000, add_spur(f - FREQ_STEP));
+ }
+ // else
+ // shell_printf("%f at %d\n\r", p1,f - FREQ_STEP);
+ p2 = p1;
+ p1 = p;
+ f += FREQ_STEP;
+ }
+ }
+ shell_printf("\n\rTable for IF at %d\n\r", setting.frequency_IF);
+ for (int j = 0; j < last_spur; j++) {
+ if ((int)stored_t[j] > 1)
+ shell_printf("%d, %d\n\r", ((int)temp_t[j])/1000, (int)stored_t[j]);
+ }
+ } else if (test == 2) {
+ // Attenuator test
+ in_selftest = true;
+ reset_settings(M_LOW);
+ int i = 15; // calibrate attenuator at 30 MHz;
+ float reference_peak_level = 0;
+ test_prepare(i);
+ for (int j= 0; j < 32; j++ ) {
+ test_prepare(i);
+ set_attenuation(j);
+ float summed_peak_level = 0;
+ for (int k=0; k<10; k++) {
+ test_acquire(i); // Acquire test
+ test_validate(i); // Validate test
+ summed_peak_level += peakLevel;
+ }
+ peakLevel = summed_peak_level / 10;
+ if (j == 0)
+ reference_peak_level = peakLevel;
+ shell_printf("Target %d, actual %f, delta %f\n\r",j, peakLevel, peakLevel - reference_peak_level);
+ }
+ return;
+ } else if (test == 3) {
+ // RBW step time search
+ in_selftest = true;
+ reset_settings(M_LOW);
+ setting.auto_IF = false;
+ setting.frequency_IF=433900000;
+ ui_mode_normal();
+ int i = 15; // calibrate low mode power on 30 MHz;
+ test_prepare(i);
+ setting.step_delay = 8000;
+ for (int j= 0; j < 57; j++ ) {
+ test_prepare(i);
+ setting.step_delay = setting.step_delay * 5 / 4;
+ setting.rbw = SI4432_force_RBW(j);
+ shell_printf("RBW = %d, ",setting.rbw);
+ set_sweep_frequency(ST_SPAN, (int32_t)(setting.rbw * 10000));
+ setting.repeat = 10;
+ test_acquire(i); // Acquire test
+ test_validate(i); // Validate test
+ float saved_peakLevel = peakLevel;
+ if (peakLevel < -35) {
+ shell_printf("Peak level too low, abort\n\r");
+ return;
+ }
+
+ shell_printf("Start level = %f, ",peakLevel);
+ while (setting.step_delay > 10 && peakLevel > saved_peakLevel - 1) {
+ test_prepare(i);
+ setting.step_delay = setting.step_delay * 4 / 5;
+ // shell_printf("\n\rRBW = %f",SI4432_force_RBW(j));
+ set_sweep_frequency(ST_SPAN, (int32_t)(setting.rbw * 10000));
+ setting.repeat = 10;
+ test_acquire(i); // Acquire test
+ test_validate(i); // Validate test
+ // shell_printf(" Step %f, %d",peakLevel, setting.step_delay);
+ }
+ setting.step_delay = setting.step_delay * 5 / 4;
+ shell_printf("End level = %f, step time = %d\n\r",peakLevel, setting.step_delay);
+ }
+ } else if (test == 0) {
+ reset_settings(M_LOW); // Make sure we are in a defined state
+ in_selftest = true;
+ menu_autosettings_cb(0);
+ for (int i=0; i < TEST_COUNT; i++) { // All test cases waiting
+ if (test_case[i].kind == TC_END)
+ break;
+ test_status[i] = TS_WAITING;
+ test_fail_cause[i] = "";
+ }
+ show_test_info = TRUE;
+ int i=0;
+ if (setting.test_argument > 0)
+ i=setting.test_argument-1;
+ do {
+ test_prepare(i);
+ test_acquire(i); // Acquire test
+ test_status[i] = test_validate(i); // Validate test
+ if (test_status[i] != TS_PASS) {
+ wait_user();
+ }
+ i++;
+ } while (test_case[i].kind != TC_END && setting.test_argument == 0 );
+ ili9341_set_foreground(BRIGHT_COLOR_GREEN);
+ ili9341_drawstring_7x13("Self test complete", 50, 200);
+ ili9341_drawstring_7x13("Touch screen to continue", 50, 215);
+ wait_user();
+ ili9341_clear_screen();
+
+ sweep_mode = SWEEP_ENABLE;
+ show_test_info = FALSE;
+ set_refer_output(-1);
+ reset_settings(M_LOW);
+ in_selftest = false;
+ }
+}
+
+void reset_calibration(void)
+{
+ config.high_level_offset = 100;
+ config.low_level_offset = 100;
+}
+
+#define CALIBRATE_RBWS 1
+const int power_rbw [5] = { 100, 300, 30, 10, 3 };
+
+void calibrate(void)
+{
+#ifdef __CALIBRATE__
+ int local_test_status;
+ in_selftest = true;
+ reset_calibration();
+ reset_settings(M_LOW);
+ int i = 11; // calibrate low mode power on 30 MHz;
+ for (int j= 0; j < CALIBRATE_RBWS; j++ ) {
+ set_RBW(power_rbw[j]);
+ test_prepare(i);
+ test_acquire(i); // Acquire test
+ local_test_status = test_validate(i); // Validate test
+// chThdSleepMilliseconds(1000);
+ if (local_test_status != TS_PASS) {
+ ili9341_set_foreground(BRIGHT_COLOR_RED);
+ ili9341_drawstring_7x13("Calibration failed", 30, 120);
+ goto quit;
+ } else {
+ set_actual_power(-22.5); // Should be -22.5dBm
+ chThdSleepMilliseconds(1000);
+ }
+ }
+#if 0 // No high input calibration as CAL OUTPUT is unreliable
+
+ i = 12; // Measure 270MHz in low mode
+ set_RBW(100);
+ test_prepare(i);
+ test_acquire(i); // Acquire test
+ float last_peak_level = peakLevel;
+ local_test_status = test_validate(i); // Validate test
+ chThdSleepMilliseconds(1000);
+
+ config.high_level_offset = 0; /// Preliminary setting
+
+ i = 13; // Calibrate 270MHz in high mode
+ for (int j = 0; j < CALIBRATE_RBWS; j++) {
+ set_RBW(power_rbw[j]);
+ test_prepare(i);
+ test_acquire(i); // Acquire test
+ local_test_status = test_validate(i); // Validate test
+// if (local_test_status != TS_PASS) { // Do not validate due to variations in SI4432
+// ili9341_set_foreground(BRIGHT_COLOR_RED);
+// ili9341_drawstring_7x13("Calibration failed", 30, 120);
+// goto quit;
+// } else
+ set_actual_power(last_peak_level);
+ chThdSleepMilliseconds(1000);
+ }
+
+#endif
+
+ config_save();
+ ili9341_set_foreground(BRIGHT_COLOR_GREEN);
+ ili9341_drawstring_7x13("Calibration complete", 30, 120);
+quit:
+ ili9341_drawstring_7x13("Touch screen to continue", 30, 140);
+ wait_user();
+ ili9341_clear_screen();
+
+ in_selftest = false;
+ sweep_mode = SWEEP_ENABLE;
+ set_refer_output(0);
+ reset_settings(M_LOW);
+#endif
+}
+
+
diff --git a/si4432.c b/si4432.c
new file mode 100644
index 0000000..d855249
--- /dev/null
+++ b/si4432.c
@@ -0,0 +1,995 @@
+/* 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 "ch.h"
+#include "hal.h"
+#include "nanovna.h"
+#include
+#include "si4432.h"
+
+#define CS_SI0_HIGH palSetPad(GPIOC, GPIO_RX_SEL)
+#define CS_SI1_HIGH palSetPad(GPIOC, GPIO_LO_SEL)
+#define CS_PE_HIGH palSetPad(GPIOC, GPIO_PE_SEL)
+
+#define RF_POWER_HIGH palSetPad(GPIOB, GPIO_RF_PWR)
+
+
+#define CS_SI0_LOW palClearPad(GPIOC, GPIO_RX_SEL)
+#define CS_SI1_LOW palClearPad(GPIOC, GPIO_LO_SEL)
+#define CS_PE_LOW palClearPad(GPIOC, GPIO_PE_SEL)
+
+#define SPI2_CLK_HIGH palSetPad(GPIOB, GPIO_SPI2_CLK)
+#define SPI2_CLK_LOW palClearPad(GPIOB, GPIO_SPI2_CLK)
+
+#define SPI2_SDI_HIGH palSetPad(GPIOB, GPIO_SPI2_SDI)
+#define SPI2_SDI_LOW palClearPad(GPIOB, GPIO_SPI2_SDI)
+
+#define SPI2_SDO ((palReadPort(GPIOB) & (1< 6207) WISH=6207; // Final value in RBW_choices[]
+ if (WISH > 1379) dwn3 = 1 ;
+ for (i=3; i= (int)(sizeof RBW_choices) / 2 )
+ return 0;
+ return(RBW_choices[i*4-1]);
+}
+
+int setting_frequency_10mhz = 10000000;
+
+void set_10mhz(int f)
+{
+ setting_frequency_10mhz = f;
+}
+
+int SI4432_frequency_changed = false;
+
+void SI4432_Set_Frequency ( long Freq ) {
+ int hbsel;
+ long Carrier;
+ if (Freq >= 480000000) {
+ hbsel = 1;
+ Freq = Freq / 2;
+ } else {
+ hbsel = 0;
+ }
+ int sbsel = 1;
+ long N = Freq / setting_frequency_10mhz;
+ Carrier = ( 4 * ( Freq - N * setting_frequency_10mhz )) / 625;
+ int Freq_Band = ( N - 24 ) | ( hbsel << 5 ) | ( sbsel << 6 );
+#if 0
+ SI4432_Write_Byte ( 0x75, Freq_Band );
+ SI4432_Write_Byte ( 0x76, (Carrier>>8) & 0xFF );
+ SI4432_Write_Byte ( 0x77, Carrier & 0xFF );
+#else
+ SI4432_Write_3_Byte ( 0x75, Freq_Band, (Carrier>>8) & 0xFF, Carrier & 0xFF );
+#endif
+ SI4432_frequency_changed = true;
+}
+
+int actualStepDelay = 1500;
+//extern int setting.repeat;
+
+#ifdef __FAST_SWEEP__
+extern char age[POINTS_COUNT];
+static int buf_index = 0;
+static bool buf_read = false;
+
+void SI4432_Fill(int s, int start)
+{
+ SI4432_Sel = s;
+ int sel = SI_nSEL[SI4432_Sel];
+ float t = setting.sweep_time - calc_min_sweep_time(); // Time to delay in mS
+ if (t < 0)
+ t = 0;
+ int ti = t * 1000 / 290.0; // Now in uS per point if (t < 30000)
+ for (int i=start; i 0) {
+ my_microsecond_delay(100);
+ goto again;
+ }
+ if (setting.repeat > 1)
+ RSSI_RAW = RSSI_RAW / setting.repeat;
+ // if (MODE_INPUT(setting.mode) && RSSI_RAW == 0)
+ // SI4432_Init();
+ float dBm = ((float)RSSI_RAW)/32.0 + SI4432_RSSI_correction;
+#ifdef __SIMULATION__
+ dBm = Simulated_SI4432_RSSI(i,s);
+#endif
+//STOP_PROFILE
+ // Serial.println(dBm,2);
+ return dBm ;
+}
+
+
+void SI4432_Sub_Init(void)
+{
+ SI4432_Reset();
+
+
+ SI4432_Write_Byte(0x69, 0x60); //AGC override according to WBS3
+
+
+#if 0 // Not sure if these add any value
+ //set VCO and PLL Only for SI4432 V2
+ SI4432_Write_Byte(0x72, 0x1F); //write 0x1F to the Frequency Deviation register
+ // VCO tuning registers
+ SI4432_Write_Byte(0x5A, 0x7F); //write 0x7F to the VCO Current Trimming register
+ SI4432_Write_Byte(0x58, 0x80); //write 0xD7 to the ChargepumpCurrentTrimmingOverride register
+ SI4432_Write_Byte(0x59, 0x40); //write 0x40 to the Divider Current Trimming register
+#endif
+#if 0
+ //set the AGC, BAD FOR PERFORMANCE!!!!!!
+ SI4432_Write_Byte(0x6A, 0x0B); //write 0x0B to the AGC Override 2 register
+ //set ADC reference voltage to 0.9V, BAD FOR PERFORMANCE!!!!!!
+ SI4432_Write_Byte(0x68, 0x04); //write 0x04 to the Deltasigma ADC Tuning 2 register
+
+ SI4432_Write_Byte(0x1F, 0x03); //write 0x03 to the Clock Recovery Gearshift Override register
+
+#endif
+
+
+ SI4432_Write_Byte(0x05, 0x0);
+ SI4432_Write_Byte(0x06, 0x0);
+ // Enable receiver chain
+// SI4432_Write_Byte(0x07, 0x05);
+ // Clock Recovery Gearshift Value
+ SI4432_Write_Byte(0x1F, 0x00);
+ // IF Filter Bandwidth
+ SI4432_SET_RBW(10) ;
+// // Register 0x75 Frequency Band Select
+// byte sbsel = 1 ; // recommended setting
+// byte hbsel = 0 ; // low bands
+// byte fb = 19 ; // 430�439.9 MHz
+// byte FBS = (sbsel << 6 ) | (hbsel << 5 ) | fb ;
+// SI4432_Write_Byte(0x75, FBS) ;
+ SI4432_Write_Byte(0x75, 0x46) ;
+ // Register 0x76 Nominal Carrier Frequency
+ // WE USE 433.92 MHz
+ // Si443x-Register-Settings_RevB1.xls
+// SI4432_Write_Byte(0x76, 0x62) ;
+ SI4432_Write_Byte(0x76, 0x00) ;
+ // Register 0x77 Nominal Carrier Frequency
+ SI4432_Write_Byte(0x77, 0x00) ;
+ // RX MODEM SETTINGS
+ SI4432_Write_3_Byte(0x1C, 0x81, 0x3C, 0x02) ;
+// SI4432_Write_Byte(0x1C, 0x81) ;
+// SI4432_Write_Byte(0x1D, 0x3C) ;
+// SI4432_Write_Byte(0x1E, 0x02) ;
+ SI4432_Write_Byte(0x1F, 0x03) ;
+ // SI4432_Write_Byte(0x20, 0x78) ;
+ SI4432_Write_3_Byte(0x21, 0x01, 0x11, 0x11) ;
+// SI4432_Write_Byte(0x21, 0x01) ;
+// SI4432_Write_Byte(0x22, 0x11) ;
+// SI4432_Write_Byte(0x23, 0x11) ;
+ SI4432_Write_Byte(0x24, 0x01) ;
+ SI4432_Write_Byte(0x25, 0x13) ;
+ SI4432_Write_Byte(0x2A, 0xFF) ;
+
+ SI4432_Write_3_Byte(0x2C, 0x28, 0x0c, 0x28) ;
+// SI4432_Write_Byte(0x2C, 0x28) ;
+// SI4432_Write_Byte(0x2D, 0x0C) ;
+// SI4432_Write_Byte(0x2E, 0x28) ;
+
+
+ SI4432_Write_Byte(0x69, 0x60); // AGC, no LNA, fast gain increment
+
+
+// GPIO automatic antenna switching
+ SI4432_Write_Byte(0x0B, 0x12) ; // Normal
+ SI4432_Write_Byte(0x0C, 0x15) ;
+
+}
+
+#define V0_XTAL_CAPACITANCE 0x64
+#define V1_XTAL_CAPACITANCE 0x64
+
+
+
+void SI4432_Init()
+{
+
+ palClearPad(GPIOB, GPIO_RF_PWR);
+ chThdSleepMilliseconds(20);
+ palSetPad(GPIOB, GPIO_RF_PWR);
+ chThdSleepMilliseconds(20);
+
+
+ //DebugLine("IO set");
+ SI4432_Sel = 0;
+ SI4432_Sub_Init();
+
+ SI4432_Sel = 1;
+ SI4432_Sub_Init();
+//DebugLine("1 init done");
+
+ SI4432_Sel = 0;
+// SI4432_Receive();// Enable receiver chain
+// SI4432_Write_Byte(0x09, V0_XTAL_CAPACITANCE);// Tune the crystal
+ SI4432_Set_Frequency(433800000);
+ SI4432_Write_Byte(0x0D, 0x1F) ; // Set GPIO2 output to ground
+
+
+ SI4432_Sel = 1;
+// SI4432_Write_Byte(0x09, V1_XTAL_CAPACITANCE);// Tune the crystal
+ SI4432_Set_Frequency(443800000);
+ SI4432_Write_Byte(0x0D, 0x1F) ; // Set GPIO2 output to ground
+
+ // SI4432_Write_Byte(0x6D, 0x1C);//Set low power
+// SI4432_Transmit(0);
+
+// SI4432_Write_Byte(0x0D, 0xC0) ; // Set GPIO2 maximumdrive and clock output
+// SI4432_Write_Byte(0x0A, 0x02) ; // Set 10MHz output
+}
+
+void SI4432_SetReference(int freq)
+{
+ SI4432_Sel = 1; //Select Lo module
+ if (freq < 0 || freq > 7 ) {
+ SI4432_Write_Byte(0x0D, 0x1F) ; // Set GPIO2 to GND
+ } else {
+ SI4432_Write_Byte(0x0D, 0xC0) ; // Set GPIO2 maximumdrive and clock output
+ SI4432_Write_Byte(0x0A, freq & 0x07) ; // Set GPIO2 frequency
+ }
+}
+
+//------------PE4302 -----------------------------------------------
+
+// Comment out this define to use parallel mode PE4302
+
+#define PE4302_en 10
+
+void PE4302_init(void) {
+ CS_PE_LOW;
+}
+
+#define PE4302_DELAY 100
+#if 0
+void PE4302_shiftOut(uint8_t val)
+{
+ uint8_t i;
+ SI4432_log(SI4432_Sel);
+ SI4432_log(val);
+ for (i = 0; i < 8; i++) {
+ if (val & (1 << (7 - i)))
+ SPI2_SDI_HIGH;
+ else
+ SPI2_SDI_LOW;
+// chThdSleepMicroseconds(PE4302_DELAY);
+ SPI2_CLK_HIGH;
+// chThdSleepMicroseconds(PE4302_DELAY);
+ SPI2_CLK_LOW;
+// chThdSleepMicroseconds(PE4302_DELAY);
+ }
+}
+#endif
+void PE4302_Write_Byte(unsigned char DATA )
+{
+// chThdSleepMicroseconds(PE4302_DELAY);
+ SPI2_CLK_LOW;
+// chThdSleepMicroseconds(PE4302_DELAY);
+// PE4302_shiftOut(DATA);
+
+ shiftOut(DATA);
+// chThdSleepMicroseconds(PE4302_DELAY);
+ CS_PE_HIGH;
+// chThdSleepMicroseconds(PE4302_DELAY);
+ CS_PE_LOW;
+// chThdSleepMicroseconds(PE4302_DELAY);
+
+}
+
+#endif
+
+
+
+#if 0
+//-----------------SI4432 dummy------------------
+void SI4432_Write_Byte(unsigned char ADR, unsigned char DATA ) {}
+unsigned char SI4432_Read_Byte(unsigned char ADR) {return ADR;}
+float SI4432_SET_RBW(float WISH) {return (WISH > 600.0?600: (WISH<3.0?3:WISH));}
+void SI4432_SetReference(int p) {}
+void SI4432_Set_Frequency(long f) {}
+void PE4302_Write_Byte(unsigned char DATA ) {}
+void PE4302_init(void) {}
+#endif
+
+#ifdef __SIMULATION__
+unsigned long seed = 123456789;
+extern float actual_rbw;
+float myfrand(void)
+{
+ seed = (unsigned int) (1103515245 * seed + 12345) ;
+ return ((float) seed) / 1000000000.0;
+}
+#define NOISE ((myfrand()-2) * 2) // +/- 4 dBm noise
+extern int settingAttenuate;
+
+//#define LEVEL(i, f, v) (v * (1-(fabs(f - frequencies[i])/actual_rbw/1000)))
+
+float LEVEL(uint32_t i, uint32_t f, int v)
+{
+ float dv;
+ float df = fabs((float)f - (float)i);
+ if (df < actual_rbw*1000)
+ dv = df/(actual_rbw*1000);
+ else
+ dv = 1 + 50*(df - actual_rbw*1000)/(actual_rbw*1000);
+ return (v - dv - settingAttenuate);
+}
+
+float Simulated_SI4432_RSSI(uint32_t i, int s)
+{
+ SI4432_Sel = s;
+ float v = -100 + log10(actual_rbw)*10 + NOISE;
+ if(s == 0) {
+ v = fmax(LEVEL(i,10000000,-20),v);
+ v = fmax(LEVEL(i,20000000,-40),v);
+ v = fmax(LEVEL(i,30000000,-30),v);
+ v = fmax(LEVEL(i,40000000,-90),v);
+ } else {
+ v = fmax(LEVEL(i,320000000,-20),v);
+ v = fmax(LEVEL(i,340000000,-40),v);
+ v = fmax(LEVEL(i,360000000,-30),v);
+ v = fmax(LEVEL(i,380000000,-90),v);
+ }
+ return(v);
+}
+
+#endif
+//------------------------------- ADF4351 -------------------------------------
+
+#ifdef __ULTRA_SA__
+
+#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
+#define bitSet(value, bit) ((value) |= (1UL << (bit)))
+#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
+#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
+
+#define CS_ADF0_HIGH palSetPad(GPIOA, 9)
+#define CS_ADF1_HIGH palSetPad(GPIOA, 10)
+
+#define CS_ADF0_LOW palClearPad(GPIOA, 9)
+#define CS_ADF1_LOW palClearPad(GPIOA, 10)
+
+#define SPI3_CLK_HIGH palSetPad(GPIOA, 1)
+#define SPI3_CLK_LOW palClearPad(GPIOA, 1)
+
+#define SPI3_SDI_HIGH palSetPad(GPIOA, 2)
+#define SPI3_SDI_LOW palClearPad(GPIOA, 2)
+
+
+void ADF_shiftOut(uint8_t val)
+{
+ uint8_t i;
+ for (i = 0; i < 8; i++) {
+ if (val & (1 << (7 - i)))
+ SPI3_SDI_HIGH;
+ else
+ SPI3_SDI_LOW;
+// chThdSleepMicroseconds(10);
+ SPI3_CLK_HIGH;
+// chThdSleepMicroseconds(10);
+ SPI3_CLK_LOW;
+// chThdSleepMicroseconds(10);
+ }
+}
+
+//unsigned long registers[6] = {0x4580A8, 0x80080C9, 0x4E42, 0x4B3, 0xBC803C, 0x580005} ;
+//unsigned long registers[6] = {0x4C82C8, 0x80083E9, 0x6E42, 0x8004B3, 0x8C81FC, 0x580005} ;
+
+//uint32_t registers[6] = {0x320000, 0x8008011, 0x4E42, 0x4B3,0x8C803C , 0x580005} ; //25 MHz ref
+
+uint32_t registers[6] = {0xA00000, 0x8000011, 0x4E42, 0x4B3,0xDC003C , 0x580005} ; //10 MHz ref
+
+int debug = 0;
+int ADF4351_LE[2] = { 9, 10};
+int ADF4351_Mux = 7;
+
+
+//#define DEBUG(X) // Serial.print( X )
+//#define DEBUGLN(X) Serial.println( X )
+//#define DEBUGFLN(X,Y) Serial.println( X,Y )
+//#define DEBUGF(X,Y) Serial.print( X,Y )
+#define DEBUG(X)
+#define DEBUGLN(X)
+
+
+double RFout, //Output freq in MHz
+#if 0 //Black modules
+ PFDRFout[6] = {25.0,25.0,25.0,10.0,10.0,10.0}, //Reference freq in MHz
+ Chrystal[6] = {25.0,25.0,25.0,10.0,10.0,10.0},
+#else // Green modules
+ PFDRFout[6] = {10.0,10.0,10.0,10.0,10.0,10.0}, //Reference freq in MHz
+ Chrystal[6] = {10.0,10.0,10.0,10.0,10.0,10.0},
+#endif
+
+ OutputChannelSpacing = 0.010, // = 0.01
+ FRACF; // Temp
+
+unsigned int long RFint, // Output freq/10Hz
+ INTA, // Temp
+ RFcalc, //UI
+ MOD, //Temp
+ FRAC; //Temp
+
+byte OutputDivider; // Temp
+byte lock=2; //Not used
+
+// Lock = A4
+
+void ADF4351_Setup()
+{
+// palSetPadMode(GPIOA, 1, PAL_MODE_OUTPUT_PUSHPULL );
+// palSetPadMode(GPIOA, 2, PAL_MODE_OUTPUT_PUSHPULL );
+
+ SPI3_CLK_HIGH;
+ SPI3_SDI_HIGH;
+ CS_ADF0_HIGH;
+ CS_ADF1_HIGH;
+// bitSet (registers[2], 17); // R set to 8
+// bitClear (registers[2], 14); // R set to 8
+
+// while(1) {
+//
+ ADF4351_set_frequency(0,100000000,0);
+ ADF4351_set_frequency(1,150000000,0);
+// ADF4351_Set(0);
+// ADF4351_Set(1);
+// chThdSleepMilliseconds(1000);
+// }
+// bitSet (registers[2], 17); // R set to 8
+// bitClear (registers[2], 14); // R set to 8
+// for (int i=0; i<6; i++) pinMode(ADF4351_LE[i], OUTPUT); // Setup pins
+// for (int i=0; i<6; i++) digitalWrite(ADF4351_LE[i], HIGH);
+// pinMode(ADF4351_Mux, INPUT);
+// SPI.begin(); // Init SPI bus
+// SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
+ //SPI.setDataMode(SPI_MODE0); // CPHA = 0 Clock positive
+ //SPI.setBitOrder(MSBFIRST);
+}
+
+void ADF4351_WriteRegister32(int channel, const uint32_t value)
+{
+ palClearPad(GPIOA, ADF4351_LE[channel]);
+// chThdSleepMicroseconds(10);
+ for (int i = 3; i >= 0; i--) ADF_shiftOut((value >> (8 * i)) & 0xFF);
+// chThdSleepMicroseconds(10);
+ palSetPad(GPIOA, ADF4351_LE[channel]);
+// chThdSleepMicroseconds(10);
+ palClearPad(GPIOA, ADF4351_LE[channel]);
+// chThdSleepMicroseconds(10);
+}
+
+void ADF4351_disable_output()
+{
+ bitClear (registers[4], 5); // digital lock
+ ADF4351_Set(0);
+}
+
+void ADF4351_enable_output()
+{
+ bitSet (registers[4], 5); // digital lock
+ ADF4351_Set(0);
+}
+void ADF4351_Set(int channel)
+{ for (int i = 5; i >= 0; i--) {
+ ADF4351_WriteRegister32(channel, registers[i]);
+// if (debug) Serial.println(registers[i],HEX);
+}
+}
+
+void ADF4351_set_frequency(int channel, unsigned long freq, int drive) // freq / 10Hz
+{
+ ADF4351_prep_frequency(channel,freq, drive);
+ ADF4351_Set(channel);
+}
+
+void ADF4351_spur_mode(int S)
+{
+ if (S & 1) {
+ bitSet (registers[2], 29); // R set to 8
+ } else {
+ bitClear (registers[2], 29); // R set to 8
+ }
+ if (S & 2)
+ bitSet (registers[2], 30); // R set to 8
+ else
+ bitClear (registers[2], 30); // R set to 8
+}
+
+void ADF4351_R_counter(int R)
+{
+ int dbl = false;
+ if (R < 0) {
+ dbl = true;
+ R = -R;
+ }
+ if (R<1)
+ return;
+ if (dbl) {
+ bitSet (registers[2], 25); // Reference doubler
+ } else {
+ bitClear (registers[2], 25); // Reference doubler
+ }
+ for (int channel=0; channel < 6; channel++) {
+ PFDRFout[channel] = Chrystal[channel] * (dbl?2:1) / R;
+ }
+ registers[2] &= ~ (((unsigned long)0x3FF) << 14);
+ registers[2] |= (((unsigned long)R) << 14);
+}
+
+void ADF4351_CP(int p)
+{
+ registers[2] &= ~ (((unsigned long)0xF) << 9);
+ registers[2] |= (((unsigned long)p) << 9);
+}
+
+void ADF4351_level(int p)
+{
+ registers[4] &= ~ (((unsigned long)0x3) << 3);
+ registers[4] |= (((unsigned long)p) << 3);
+}
+
+void ADF4351_channel_spacing(int spacing)
+{
+ OutputChannelSpacing = 0.001 * spacing;
+}
+
+static uint32_t gcd(uint32_t x, uint32_t y)
+{
+ uint32_t z;
+ while (y != 0) {
+ z = x % y;
+ x = y;
+ y = z;
+ }
+ return x;
+}
+
+void ADF4351_prep_frequency(int channel, unsigned long freq, int drive) // freq / 10Hz
+{
+ (void)drive;
+// if (channel == 0)
+ RFout=freq/1000000.0; // To MHz
+// else
+ // RFout=freq/1000002.764; // To MHz
+
+ if (RFout >= 2200) {
+ OutputDivider = 1;
+ bitWrite (registers[4], 22, 0);
+ bitWrite (registers[4], 21, 0);
+ bitWrite (registers[4], 20, 0);
+ } else if (RFout >= 1100) {
+ OutputDivider = 2;
+ bitWrite (registers[4], 22, 0);
+ bitWrite (registers[4], 21, 0);
+ bitWrite (registers[4], 20, 1);
+ } else if (RFout >= 550) {
+ OutputDivider = 4;
+ bitWrite (registers[4], 22, 0);
+ bitWrite (registers[4], 21, 1);
+ bitWrite (registers[4], 20, 0);
+ } else if (RFout >= 275) {
+ OutputDivider = 8;
+ bitWrite (registers[4], 22, 0);
+ bitWrite (registers[4], 21, 1);
+ bitWrite (registers[4], 20, 1);
+ } else if (RFout >= 137.5) {
+ OutputDivider = 16;
+ bitWrite (registers[4], 22, 1);
+ bitWrite (registers[4], 21, 0);
+ bitWrite (registers[4], 20, 0);
+ } else if (RFout >= 68.75) {
+ OutputDivider = 32;
+ bitWrite (registers[4], 22, 1);
+ bitWrite (registers[4], 21, 0);
+ bitWrite (registers[4], 20, 1);
+ } else {
+ OutputDivider = 64;
+ bitWrite (registers[4], 22, 1);
+ bitWrite (registers[4], 21, 1);
+ bitWrite (registers[4], 20, 0);
+ }
+
+ INTA = (RFout * OutputDivider) / PFDRFout[channel];
+ MOD = (PFDRFout[channel] / OutputChannelSpacing) + 0.01;
+// MOD = 3125;
+ FRACF = (((RFout * OutputDivider) / PFDRFout[channel]) - INTA) * MOD;
+ FRAC = round(FRACF);
+
+ while (FRAC > 4095 || MOD > 4095) {
+ FRAC = FRAC >> 1;
+ MOD = MOD >> 1;
+ // Serial.println( "MOD/FRAC reduced");
+ }
+
+ int32_t k = gcd(FRAC, MOD);
+ if (k > 1) {
+ FRAC /= k;
+ MOD /= k;
+// Serial.print( "MOD/FRAC gcd reduced");
+ }
+// while (denom >= (1<<20)) {
+// num >>= 1;
+// denom >>= 1;
+// }
+
+
+// if (INTA <= 75) Serial.println( "INTA <= 75");
+// if (FRAC > 4095) Serial.println( "FRAC > 4095");
+// if (MOD > 4095) Serial.println( "MOD > 4095");
+
+
+// if (FRAC > 4095) Serial.println( "FRAC > 4095");
+// if (MOD > 4095) Serial.println( "MOD > 4095");
+// if (INTA > 4095) Serial.println( "INT > 4095");
+
+ if (debug) {
+ DEBUG(" ODIV=");
+ DEBUG(OutputDivider);
+ DEBUG(" INT=");
+ DEBUG(INTA);
+ DEBUG(" FRAC=");
+ DEBUG(FRAC);
+ DEBUG(" MOD=");
+ DEBUG(MOD);
+ DEBUG( " CalF=");
+// DEBUGFLN(PFDRFout[channel] *(INTA + ((double)FRAC)/MOD)/OutputDivider,6);
+
+// DEBUG(" FRACF=");
+// DEBUGF(FRACF,6);
+ }
+ registers[0] = 0;
+ registers[0] = INTA << 15; // OK
+ FRAC = FRAC << 3;
+ registers[0] = registers[0] + FRAC;
+ if (MOD == 1) MOD = 2;
+ registers[1] = 0;
+ registers[1] = MOD << 3;
+ registers[1] = registers[1] + 1 ; // restore address "001"
+ bitSet (registers[1], 27); // Prescaler at 8/9
+/*
+ drive = 1;
+ if (drive == 0) {
+ bitClear (registers[4], 3); // +5dBm + out
+ bitClear (registers[4], 4); // +5dBm
+ bitClear (registers[4], 6); // +5dBm - out
+ bitClear (registers[4], 7); // +5dBm
+ } else if (drive == 1) {
+ bitSet (registers[4], 6); // +5dBm
+ bitClear (registers[4], 7); // +5dBm - out
+ bitSet (registers[4], 3); // +5dBm
+ bitClear (registers[4], 4); // +5dBm + out
+ } else if (drive == 2) {
+ bitClear (registers[4], 6); // +5dBm - out
+ bitSet (registers[4], 7); // +5dBm
+ bitClear (registers[4], 3); // +5dBm + out
+ bitSet (registers[4], 4); // +5dBm
+ }
+ else {
+ bitSet (registers[4], 6); // +5dBm - out
+ bitSet (registers[4], 7); // +5dBm
+ bitSet (registers[4], 3); // +5dBm + out
+ bitSet (registers[4], 4); // +5dBm
+ }
+*/
+// bitSet (registers[4], 5); // enable + output
+// bitClear (registers[4], 8); // enable B output
+
+#if 0
+ if (FRAC == 0)
+ bitSet (registers[2], 8); // INT mode
+ else
+ bitClear (registers[2], 8); // INT mode
+ bitSet (registers[2], 13); // Double buffered
+
+ bitSet (registers[2], 28); // Digital lock == "110" sur b28 b27 b26
+ bitSet (registers[2], 27); // digital lock
+ bitClear (registers[2], 26); // digital lock
+
+ //bitSet (registers[4], 10); // Mute till lock
+// bitSet (registers[3], 23); // Fast lock
+ #endif
+// bitSet (registers[4], 10); // Mute till lock
+// ADF4351_Set(channel);
+}
+
+
+
+#endif
diff --git a/si4432.h b/si4432.h
new file mode 100644
index 0000000..8473302
--- /dev/null
+++ b/si4432.h
@@ -0,0 +1,44 @@
+#ifndef __SI4432_H__
+
+#define __SI4432_H__
+
+#define byte uint8_t
+extern volatile int SI4432_Sel; // currently selected SI4432
+void SI4432_Write_Byte(byte ADR, byte DATA );
+byte SI4432_Read_Byte( byte ADR );
+
+void SI4432_Init(void);
+float SI4432_RSSI(uint32_t i, int s);
+#ifdef __SIMULATION__
+float Simulated_SI4432_RSSI(uint32_t i, int s);
+#endif
+void SI4432_Set_Frequency ( long Freq );
+void SI4432_Transmit(int d);
+void SI4432_Receive(void);
+float SI4432_SET_RBW(float WISH);
+void PE4302_Write_Byte(unsigned char DATA );
+void PE4302_init(void);
+
+#ifdef __ULTRA_SA__
+extern int ADF4351_LE[];
+extern int debug;
+void ADF4351_Setup(void);
+
+
+void ADF4351_WriteRegister32(int channel, const uint32_t value);
+void ADF4351_set_frequency(int channel, uint32_t freq, int drive_strength);
+void ADF4351_prep_frequency(int channel, uint32_t freq, int drive_strength);
+//int ADF4351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength);
+void ADF4351_Set(int channel);
+void ADF4351_enable_output(void);
+void ADF4351_disable_output(void);
+void ADF4351_spur_mode(int S);
+void ADF4351_R_counter(int R);
+void ADF4351_channel_spacing(int spacing);
+void ADF4351_CP(int p);
+void ADF4351_level(int p);
+int ADF4351_locked(void);
+#endif
+
+
+#endif //__SI4432_H__
diff --git a/si5351.c b/si5351.c
deleted file mode 100644
index 8f7c9c5..0000000
--- a/si5351.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * 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
- * 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 "hal.h"
-#include "nanovna.h"
-#include "si5351.h"
-
-// 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_bulk_write(const uint8_t *buf, int len)
-{
- i2cAcquireBus(&I2CD1);
- (void)i2cMasterTransmitTimeout(&I2CD1, SI5351_I2C_ADDR, buf, len, NULL, 0, 1000);
- i2cReleaseBus(&I2CD1);
-}
-
-#if 0
-static bool si5351_bulk_read(uint8_t reg, uint8_t* buf, int len)
-{
- i2cAcquireBus(&I2CD1);
- 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, ...
-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_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 | 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,
-#endif
- 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, ~(SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN),
- 0 // sentinel
-};
-
-void
-si5351_init(void)
-{
- const uint8_t *p = si5351_configs;
- while (*p) {
- uint8_t len = *p++;
- si5351_bulk_write(p, len);
- p += len;
- }
-}
-
-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)
-{
- // 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_disable_output(void)
-{
- si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xFF);
- si5351_bulk_write(disable_output, sizeof(disable_output));
- current_band = 0;
-}
-
-void si5351_enable_output(void)
-{
- 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;
-}
-
-// 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)
-{
- /* 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 + int((128*num)/denom) - 512
- * P2 register is a 20-bit value using the following formula:
- * P2[19:0] = (128 * num) % denom
- * P3 register is a 20-bit value using the following formula:
- * P3[19:0] = denom
- */
- /* Set the main PLL config registers */
- 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;
- }
- // Pll MSN(A|B) registers Datasheet
- uint8_t reg[9];
- 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);
-}
-
-// 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
-{
- /* 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 + int((128*b)/c) - 512
- * P2 register is a 20-bit value using the following formula:
- * P2[19:0] = (128 * b) % c
- * P3 register is a 20-bit value using the following formula:
- * P3[19:0] = c
- */
- /* Set the main PLL config registers */
- 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[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 */
- uint8_t dat = chctrl | SI5351_CLK_INPUT_MULTISYNTH_N;
- if (num == 0)
- dat |= SI5351_CLK_INTEGER_MODE;
-
-#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
-}
-
-// Find better approximate values for n/d
-#define MAX_DENOMINATOR ((1 << 20) - 1)
-static inline void approximate_fraction(uint32_t *n, uint32_t *d)
-{
- // 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;
- }
- *n = p1;
- *d = q1;
- }
-}
-
-// 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)
-{
- 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);
-}
-
-// 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);
-}
-
-#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);
-}
-
-void
-si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength)
-{
- if (freq <= 100000000) {
- si5351_setupPLL(SI5351_PLL_B, 32, 0, 1);
- si5351_set_frequency_fixedpll(channel, SI5351_PLL_B, PLLFREQ, freq, SI5351_R_DIV_1, drive_strength, 1);
- } else if (freq < 150000000) {
- si5351_set_frequency_fixeddiv(channel, SI5351_PLL_B, freq, 6, drive_strength, 1);
- } else {
- si5351_set_frequency_fixeddiv(channel, SI5351_PLL_B, freq, 4, drive_strength, 1);
- }
-}
-#endif
-
-/*
- * 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
- */
-int
-si5351_set_frequency(uint32_t freq, uint8_t drive_strength)
-{
- uint8_t band;
- int delay = DELAY_NORMAL;
- 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;
- omul = 11;
- } else if (freq >= config.harmonic_freq_threshold * 5U) {
- mul = 7;
- omul = 9;
- } else if (freq >= config.harmonic_freq_threshold * 3U) {
- mul = 5;
- omul = 7;
- } else if (freq >= config.harmonic_freq_threshold) {
- mul = 3;
- omul = 5;
- } 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;
- }
- band = si5351_get_band(freq / mul);
- switch (band) {
- 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(SI5351_PLL_RESET_A|SI5351_PLL_RESET_B);
- current_band = band;
- }
- return delay;
-}
diff --git a/si5351.h b/si5351.h
deleted file mode 100644
index 315ce3c..0000000
--- a/si5351.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.
- */
-
-#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)
-
-// 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_REG_PLL_A 26
-#define SI5351_REG_PLL_B 34
-
-#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_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)
-
-void si5351_init(void);
-void si5351_disable_output(void);
-void si5351_enable_output(void);
-
-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
deleted file mode 100644
index 21fbe84..0000000
--- a/tlv320aic3204.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * 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 "hal.h"
-#include "nanovna.h"
-
-#define REFCLK_8000KHZ
-#define AIC3204_ADDR 0x18
-
-#define wait_ms(ms) chThdSleepMilliseconds(ms)
-
-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 */
- 0x05, 0x91, /* Power up PLL, P=1,R=1 */
- 0x06, 0x0a, /* J=10 */
- 0x07, 29, /* D=7520 = (29<<8) + 96 */
- 0x08, 96,
-#endif
-// 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 */
-
- 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 */
-
- 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_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 */
-};
-
-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 */
-};
-
-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 inline void
-tlv320aic3204_bulk_write(const uint8_t *buf, int len)
-{
- (void)i2cMasterTransmitTimeout(&I2CD1, AIC3204_ADDR, buf, len, NULL, 0, 1000);
-}
-
-#if 0
-static int
-tlv320aic3204_read(uint8_t d0)
-{
- int addr = AIC3204_ADDR;
- uint8_t buf[] = { d0 };
- i2cAcquireBus(&I2CD1);
- i2cMasterTransmitTimeout(&I2CD1, addr, buf, 1, buf, 1, 1000);
- i2cReleaseBus(&I2CD1);
- return buf[0];
-}
-#endif
-
-static void
-tlv320aic3204_config(const uint8_t *data, int len)
-{
- i2cAcquireBus(&I2CD1);
- for (; len--; data += 2)
- tlv320aic3204_bulk_write(data, 2);
- i2cReleaseBus(&I2CD1);
-}
-
-void tlv320aic3204_init(void)
-{
- tlv320aic3204_config(conf_data, sizeof(conf_data)/2);
- wait_ms(40);
- tlv320aic3204_config(conf_data_unmute, sizeof(conf_data_unmute)/2);
-}
-
-void tlv320aic3204_select(int channel)
-{
- 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[] = {
- 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 3e10a58..818f63d 100644
--- a/ui.c
+++ b/ui.c
@@ -1,5 +1,4 @@
-/*
- * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com
+/* Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com
* All rights reserved.
*
* This is free software; you can redistribute it and/or modify
@@ -30,7 +29,9 @@ uistat_t uistat = {
current_trace: 0,
lever_mode: LM_MARKER,
marker_delta: FALSE,
+ marker_noise: FALSE,
marker_tracking : FALSE,
+ text : "",
};
#define NO_EVENT 0
@@ -52,7 +53,11 @@ uistat_t uistat = {
#define BIT_DOWN1 1
#define READ_PORT() palReadPort(GPIOA)
-#define BUTTON_MASK 0b1111
+#ifdef __ULTRA_SA__
+#define BUTTON_MASK 0
+#else
+#define BUTTON_MASK 0b1110
+#endif
static uint16_t last_button = 0b0000;
static uint32_t last_button_down_ticks;
@@ -67,9 +72,11 @@ enum {
UI_NORMAL, UI_MENU, UI_NUMERIC, UI_KEYPAD
};
+#ifdef __VNA__
enum {
KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_CW, KM_SCALE, KM_REFPOS, KM_EDELAY, KM_VELOCITY_FACTOR, KM_SCALEDELAY
};
+#endif
#define NUMINPUT_LEN 10
@@ -78,8 +85,9 @@ 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 char *kp_help_text = NULL;
static uint8_t menu_current_level = 0;
-static int8_t selection = 0;
+static int selection = 0;
// Set structure align as WORD (save flash memory)
#pragma pack(push, 2)
@@ -111,8 +119,8 @@ static int16_t last_touch_y;
#define KP_DONE 1
#define KP_CANCEL 2
-static void ui_mode_normal(void);
-static void ui_mode_menu(void);
+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);
@@ -120,9 +128,11 @@ 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 choose_active_marker(void);
static void menu_move_back(void);
static void menu_push_submenu(const menuitem_t *submenu);
+//static const menuitem_t menu_marker_type[];
static int btn_check(void)
{
@@ -287,11 +297,11 @@ touch_check(void)
return stat ? EVT_TOUCH_DOWN : EVT_TOUCH_NONE;
}
-static inline void
+void
touch_wait_release(void)
{
while (touch_check() != EVT_TOUCH_RELEASED)
- ;
+ chThdSleepMilliseconds(20);
}
static inline void
@@ -319,8 +329,8 @@ touch_cal_exec(void)
y1 = last_touch_y;
ili9341_clear_screen();
- ili9341_line(320-1, 240-1, 320-1, 240-32);
- ili9341_line(320-1, 240-1, 320-32, 240-1);
+ ili9341_line(LCD_WIDTH-1, LCD_HEIGHT-1, LCD_WIDTH-1, LCD_HEIGHT-32);
+ ili9341_line(LCD_WIDTH-1, LCD_HEIGHT-1, LCD_WIDTH-32, LCD_HEIGHT-1);
ili9341_drawstring("TOUCH LOWER RIGHT", 230, 220);
touch_wait_release();
@@ -329,8 +339,8 @@ touch_cal_exec(void)
config.touch_cal[0] = x1;
config.touch_cal[1] = y1;
- config.touch_cal[2] = (x2 - x1) * 16 / 320;
- config.touch_cal[3] = (y2 - y1) * 16 / 240;
+ config.touch_cal[2] = (x2 - x1) * 16 / LCD_WIDTH;
+ config.touch_cal[3] = (y2 - y1) * 16 / LCD_HEIGHT;
//redraw_all();
touch_start_watchdog();
@@ -430,11 +440,20 @@ enum {
MT_SUBMENU,
MT_CALLBACK,
MT_CANCEL,
- MT_CLOSE
+ MT_TITLE,
+ MT_CLOSE,
+ MT_KEYPAD,
+ MT_ICON = 0x10,
+ MT_LOW = 0x40, // Only applicable to low mode
+ MT_FORM = 0x80, // Large button menu
};
+#define MT_BACK 0x40
+#define MT_LEAVE 0x20
+#define MT_MASK(x) (0xF & (x))
typedef void (*menuaction_cb_t)(int item, uint8_t data);
+#ifdef __VNA__
static void
menu_calop_cb(int item, uint8_t data)
{
@@ -654,9 +673,11 @@ static void
menu_scale_cb(int item, uint8_t data)
{
(void)item;
+#ifdef __VNA__
if (data == KM_SCALE && trace[uistat.current_trace].type == TRC_DELAY) {
data = KM_SCALEDELAY;
}
+#endif
if (btn_wait_release() & EVT_BUTTON_DOWN_LONG) {
ui_mode_numeric(data);
ui_process_numeric();
@@ -692,6 +713,7 @@ menu_stimulus_cb(int item, uint8_t data)
break;
}
}
+#endif
static uint32_t
get_marker_frequency(int marker)
@@ -706,11 +728,12 @@ get_marker_frequency(int marker)
static void
menu_marker_op_cb(int item, uint8_t data)
{
+ (void)item;
uint32_t freq = get_marker_frequency(active_marker);
if (freq == 0)
return; // no active marker
- switch (item) {
+ switch (data) {
case 0: /* MARKER->START */
case 1: /* MARKER->STOP */
case 2: /* MARKER->CENTER */
@@ -737,6 +760,7 @@ menu_marker_op_cb(int item, uint8_t data)
}
}
break;
+#ifdef __VNA__
case 4: /* MARKERS->EDELAY */
{
if (uistat.current_trace == -1)
@@ -746,34 +770,45 @@ menu_marker_op_cb(int item, uint8_t data)
set_electrical_delay(electrical_delay + (v / 1e-12));
}
break;
+#endif
}
+ menu_move_back();
ui_mode_normal();
- draw_cal_status();
+ redraw_request |= REDRAW_CAL_STATUS;
//redraw_all();
}
static void
menu_marker_search_cb(int item, uint8_t data)
{
- (void)data;
+ (void)item;
int i = -1;
if (active_marker == -1)
return;
-
- switch (item) {
+ if (data < 4)
+ markers[active_marker].mtype &= ~M_TRACKING;
+ switch (data) {
+ case 0: /* search Left */
+ i = marker_search_left_min(markers[active_marker].index);
+ break;
+ case 1: /* search right */
+ i = marker_search_right_min(markers[active_marker].index);
+ break;
+#if 0
case 0: /* maximum */
case 1: /* minimum */
- set_marker_search(item);
+ set_marker_search(data);
i = marker_search();
break;
+#endif
case 2: /* search Left */
- i = marker_search_left(markers[active_marker].index);
+ i = marker_search_left_max(markers[active_marker].index);
break;
case 3: /* search right */
- i = marker_search_right(markers[active_marker].index);
+ i = marker_search_right_max(markers[active_marker].index);
break;
case 4: /* tracking */
- uistat.marker_tracking = !uistat.marker_tracking;
+ markers[active_marker].mtype ^= M_TRACKING;
break;
}
if (i != -1)
@@ -782,7 +817,7 @@ menu_marker_search_cb(int item, uint8_t data)
redraw_marker(active_marker);
select_lever_mode(LM_SEARCH);
}
-
+#ifdef __VNA__
static void
menu_marker_smith_cb(int item, uint8_t data)
{
@@ -791,6 +826,7 @@ menu_marker_smith_cb(int item, uint8_t data)
redraw_marker(active_marker);
draw_menu();
}
+#endif
static void
active_marker_select(int item)
@@ -812,32 +848,46 @@ static void
menu_marker_sel_cb(int item, uint8_t data)
{
(void)data;
- int t;
+// int t;
if (item >= 0 && item < MARKERS_MAX) {
if (markers[item].enabled) {
if (item == active_marker) {
// disable if active trace is selected
- markers[item].enabled = FALSE;
+ markers[item].enabled = M_DISABLED;
active_marker_select(-1);
} else {
active_marker_select(item);
}
} else {
- markers[item].enabled = TRUE;
+ markers[item].enabled = M_ENABLED;
active_marker_select(item);
+ markers[item].mtype = M_NORMAL;
+ markers[item].mtype |= (uistat.marker_delta ? M_DELTA : 0);
+ markers[item].mtype |= (uistat.marker_noise ? M_NOISE : 0);
+ markers[item].mtype |= (uistat.marker_tracking ? M_TRACKING : 0);
}
+ // if (markers[item].enabled)
+ // menu_push_submenu(menu_marker_type);
+#if 0
} else if (item == 4) { /* all off */
for (t = 0; t < MARKERS_MAX; t++)
- markers[t].enabled = FALSE;
+ markers[t].enabled = M_DISABLED;
previous_marker = -1;
active_marker = -1;
- } else if (item == 5) { /* marker delta */
+#endif
+ } else if (item == 4) { /* marker delta */
uistat.marker_delta = !uistat.marker_delta;
+ } else if (item == 5) { /* marker noise */
+ uistat.marker_noise = !uistat.marker_noise;
+ // if (uistat.marker_noise) uistat.marker_delta = true; //Default behavior
+ } else if (item == 6) { /* marker tracking */
+ uistat.marker_tracking = !uistat.marker_tracking;
+ // if (uistat.marker_tracking) uistat.marker_noise = false; //Default behavior
}
redraw_marker(active_marker);
draw_menu();
}
-
+#ifdef __VNA__
static const menuitem_t menu_calop[] = {
{ MT_CALLBACK, CAL_OPEN, "OPEN", menu_calop_cb },
{ MT_CALLBACK, CAL_SHORT, "SHORT", menu_calop_cb },
@@ -1053,8 +1103,19 @@ const menuitem_t menu_top[] = {
{ MT_SUBMENU, 0, "CONFIG", menu_config },
{ MT_NONE, 0, NULL, NULL } // sentinel
};
+#endif
+
+
+#define MENU_BUTTON_WIDTH 60
+#define MENU_BUTTON_START (LCD_WIDTH-MENU_BUTTON_WIDTH)
+#define MENU_FORM_WIDTH 295
+#define MENU_FORM_START (LCD_WIDTH - MENU_FORM_WIDTH)
+#define MENU_BUTTON_HEIGHT 30
+#define NUM_INPUT_HEIGHT 30
+
+#include "ui_sa.c"
-#define MENU_STACK_DEPTH_MAX 4
+#define MENU_STACK_DEPTH_MAX 5
const menuitem_t *menu_stack[MENU_STACK_DEPTH_MAX] = {
menu_top, NULL, NULL, NULL
};
@@ -1063,8 +1124,12 @@ static void
ensure_selection(void)
{
const menuitem_t *menu = menu_stack[menu_current_level];
- int i;
- for (i = 0; menu[i].type != MT_NONE; i++)
+ int i=0;
+ if (MT_MASK(menu[0].type) == MT_TITLE && selection == 0) {
+ selection = 1;
+ return;
+ }
+ for (i = 0; MT_MASK(menu[i].type) != MT_NONE; i++)
;
if (selection >= i)
selection = i-1;
@@ -1075,23 +1140,51 @@ menu_move_back(void)
{
if (menu_current_level == 0)
return;
+ erase_menu_buttons();
menu_current_level--;
+ if (selection >= 0)
+ selection = 0;
ensure_selection();
- erase_menu_buttons();
+
+ if (current_menu_is_form()) {
+ redraw_frame();
+ area_width = 0;
+ } else {
+ redraw_frame();
+ request_to_redraw_grid();
+ area_width = AREA_WIDTH_NORMAL - MENU_BUTTON_WIDTH;
+ }
+
draw_menu();
}
static void
menu_push_submenu(const menuitem_t *submenu)
{
+ ui_mode = UI_MENU; // Only needed for auto mode setting
+ erase_menu_buttons();
if (menu_current_level < MENU_STACK_DEPTH_MAX-1)
menu_current_level++;
menu_stack[menu_current_level] = submenu;
+ if (selection >= 0)
+ selection = 0;
ensure_selection();
- erase_menu_buttons();
+ if (menu_is_form(submenu)) {
+ redraw_frame();
+ area_width = 0;
+ } else {
+ redraw_frame();
+ request_to_redraw_grid();
+ area_width = AREA_WIDTH_NORMAL - MENU_BUTTON_WIDTH;
+ }
draw_menu();
}
+int current_menu_is_form(void)
+{
+ return menu_is_form(menu_stack[menu_current_level]);
+}
+
/*
static void
menu_move_top(void)
@@ -1108,10 +1201,11 @@ menu_move_top(void)
static void
menu_invoke(int item)
{
+ int status;
const menuitem_t *menu = menu_stack[menu_current_level];
menu = &menu[item];
- switch (menu->type) {
+ switch (MT_MASK(menu->type)) {
case MT_NONE:
case MT_BLANK:
case MT_CLOSE:
@@ -1127,25 +1221,40 @@ menu_invoke(int item)
if (cb == NULL)
return;
(*cb)(item, menu->data);
+// if (!(menu->type & MT_FORM))
+ redraw_request |= REDRAW_CAL_STATUS;
break;
}
case MT_SUBMENU:
menu_push_submenu((const menuitem_t*)menu->reference);
break;
+
+ case MT_KEYPAD:
+ status = btn_wait_release();
+ if (status & EVT_BUTTON_DOWN_LONG) {
+ ui_mode_numeric(menu->data);
+ // ui_process_numeric();
+ } else {
+ if (menu->type & MT_FORM) {
+ area_width = AREA_WIDTH_NORMAL - MENU_BUTTON_WIDTH;
+ redraw_frame(); // Remove form numbers
+ }
+ kp_help_text = (char *)menu->reference;
+ ui_mode_keypad(menu->data);
+ ui_process_keypad();
+ }
+ redraw_request |= REDRAW_CAL_STATUS;
+ break;
}
}
-#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_X(posx) ((posx)*KP_WIDTH + (LCD_WIDTH-64-KP_WIDTH*4))
#define KP_GET_Y(posy) ((posy)*KP_HEIGHT + 12 )
-
+#ifdef __VNA__
// Key names
#define KP_0 0
#define KP_1 1
@@ -1251,6 +1360,11 @@ static const keypads_t * const keypads_mode_tbl[] = {
static const char * const keypad_mode_label[] = {
"START", "STOP", "CENTER", "SPAN", "CW FREQ", "SCALE", "REFPOS", "EDELAY", "VELOCITY%", "DELAY"
};
+#endif
+
+static const char * const keypad_scale_text[] = { "1", "2", "5", "10", "20" , "50", "100", "200", "500"};
+//static const int keypad_scale_value[] = { 1, 2, 5, 10, 20 , 50, 100, 200, 500};
+
static void
draw_keypad(void)
@@ -1264,21 +1378,37 @@ draw_keypad(void)
ili9341_set_background(bg);
int x = KP_GET_X(keypads[i].x);
int y = KP_GET_Y(keypads[i].y);
+// ili9341_fill(x, y, KP_WIDTH, KP_HEIGHT, DEFAULT_MENU_TEXT_COLOR); // black area around button, causes flicker....
ili9341_fill(x+2, y+2, KP_WIDTH-4, KP_HEIGHT-4, bg);
- ili9341_drawfont(keypads[i].c,
+ if (keypads[i].c < 32) { // KP_1
+ ili9341_drawfont(keypads[i].c,
x + (KP_WIDTH - NUM_FONT_GET_WIDTH) / 2,
y + (KP_HEIGHT - NUM_FONT_GET_HEIGHT) / 2);
+ } else {
+ const char *t = keypad_scale_text[keypads[i].c - KP_1];
+ ili9341_drawstring_size(t,
+ x + (KP_WIDTH - 5*strlen(t)*2) / 2,
+ y + (KP_HEIGHT - 13) / 2,2);
+ }
i++;
}
}
+static int
+menu_is_multiline(const char *label, const char **l1, const char **l2);
static void
draw_numeric_area_frame(void)
{
- ili9341_fill(0, 240-NUM_INPUT_HEIGHT, 320, NUM_INPUT_HEIGHT, config.menu_normal_color);
+ const char *l1;
+ const char *l2;
+ ili9341_fill(0, LCD_HEIGHT-NUM_INPUT_HEIGHT, LCD_WIDTH, 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);
+ if (menu_is_multiline(keypad_mode_label[keypad_mode], &l1, &l2)) {
+ ili9341_drawstring_7x13(l1, 10, LCD_HEIGHT-NUM_INPUT_HEIGHT+1);
+ ili9341_drawstring_7x13(l2, 10, LCD_HEIGHT-NUM_INPUT_HEIGHT/2 + 1);
+ } else
+ ili9341_drawstring_7x13(keypad_mode_label[keypad_mode], 10, LCD_HEIGHT-(FONT_GET_HEIGHT+NUM_INPUT_HEIGHT)/2);
//ili9341_drawfont(KP_KEYPAD, 300, 216);
}
@@ -1290,9 +1420,9 @@ draw_numeric_input(const char *buf)
int focused = FALSE;
uint16_t xsim = 0b0010010000000000;
+ uint16_t fg = DEFAULT_MENU_TEXT_COLOR;
+ uint16_t bg = config.menu_normal_color;
for (i = 0, x = 64; i < 10 && buf[i]; i++, xsim<<=1) {
- uint16_t fg = DEFAULT_MENU_TEXT_COLOR;
- uint16_t bg = config.menu_normal_color;
int c = buf[i];
if (c == '.')
c = KP_PERIOD;
@@ -1310,16 +1440,27 @@ draw_numeric_input(const char *buf)
ili9341_set_foreground(fg);
ili9341_set_background(bg);
if (c >= 0) // c is number
- ili9341_drawfont(c, x, 240-NUM_INPUT_HEIGHT+4);
+ ili9341_drawfont(c, x, LCD_HEIGHT-NUM_INPUT_HEIGHT+4);
else if (focused) // c not number, but focused
- ili9341_drawfont(0, x, 240-NUM_INPUT_HEIGHT+4);
+ ili9341_drawfont(0, x, LCD_HEIGHT-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);
+ ili9341_fill(x, LCD_HEIGHT-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);
+// ili9341_fill(x, LCD_HEIGHT-NUM_INPUT_HEIGHT+4, NUM_FONT_GET_WIDTH+2+8, NUM_FONT_GET_WIDTH+2+8, config.menu_normal_color);
+ ili9341_fill(x, LCD_HEIGHT-NUM_INPUT_HEIGHT+4, LCD_WIDTH-64, NUM_FONT_GET_WIDTH+2+8, config.menu_normal_color);
+ if (buf[0] == 0 && kp_help_text != NULL) {
+ ili9341_set_foreground(fg);
+ ili9341_set_background(bg);
+ const char *l1,*l2;
+ if (menu_is_multiline(kp_help_text, &l1, &l2)) {
+ ili9341_drawstring_7x13(l1, 64+NUM_FONT_GET_WIDTH+2, LCD_HEIGHT-NUM_INPUT_HEIGHT+1);
+ ili9341_drawstring_7x13(l2, 64+NUM_FONT_GET_WIDTH+2, LCD_HEIGHT-NUM_INPUT_HEIGHT/2 + 1);
+ } else
+ ili9341_drawstring_7x13(kp_help_text, 64+NUM_FONT_GET_WIDTH+2, LCD_HEIGHT-(FONT_GET_HEIGHT+NUM_INPUT_HEIGHT)/2);
+ }
}
static int
@@ -1333,6 +1474,7 @@ menu_is_multiline(const char *label, const char **l1, const char **l2)
return TRUE;
}
+#ifdef __VNA__
static void
menu_item_modify_attribute(const menuitem_t *menu, int item,
uint16_t *fg, uint16_t *bg)
@@ -1407,36 +1549,106 @@ menu_item_modify_attribute(const menuitem_t *menu, int item,
}
}
}
+#endif
+
+#ifndef __VNA__
+extern void menu_item_modify_attribute(
+ const menuitem_t *menu, int item, uint16_t *fg, uint16_t *bg);
+#endif
static void
draw_menu_buttons(const menuitem_t *menu)
{
int i = 0;
- for (i = 0; i < 7; i++) {
+ char text[30];
+ int y = 0;
+ for (i = 0; i < 8; i++) {
const char *l1, *l2;
- if (menu[i].type == MT_NONE)
+ if ((menu[i].type & MT_LOW) && !MODE_LOW(setting.mode)) //not applicable to mode
+ continue;
+ if (MT_MASK(menu[i].type) == MT_NONE)
break;
- if (menu[i].type == MT_BLANK)
+ if (MT_MASK(menu[i].type) == MT_BLANK)
continue;
- int y = MENU_BUTTON_HEIGHT*i;
- uint16_t bg = config.menu_normal_color;
- uint16_t fg = DEFAULT_MENU_TEXT_COLOR;
+ uint16_t bg;
+ uint16_t fg;
+ if (MT_MASK(menu[i].type) == MT_TITLE) {
+ fg = config.menu_normal_color;
+ bg = DEFAULT_MENU_TEXT_COLOR;
+ } else {
+ bg = config.menu_normal_color;
+ 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-MENU_BUTTON_WIDTH, y, MENU_BUTTON_WIDTH, MENU_BUTTON_HEIGHT-2, bg);
-
- menu_item_modify_attribute(menu, i, &fg, &bg);
+
+ uint16_t old_bg = bg;
+ int active_button_width;
+ int active_button_start;
+ menu_item_modify_attribute(menu, i, &fg, &bg); // before plot_printf to create status text
+ if (menu[i].type & MT_FORM) {
+ active_button_start = LCD_WIDTH - MENU_FORM_WIDTH;
+ active_button_width = MENU_FORM_WIDTH - 30; // Shorten at the right
+ if (MT_MASK(menu[i].type) == MT_KEYPAD) { // Only keypad retrieves value
+ keypad_mode = menu[i].data;
+ fetch_numeric_target();
+ }
+ plot_printf(text, sizeof text, menu[i].label, uistat.text);
+ }
+ else {
+ active_button_width = MENU_BUTTON_WIDTH;
+ active_button_start = LCD_WIDTH - MENU_BUTTON_WIDTH;
+ }
+ ili9341_fill(active_button_start, y, active_button_width, MENU_BUTTON_HEIGHT-4, old_bg); // Set button to unmodified background color
+#if 0
+ // 3D button accent
+ int bw = LCD_WIDTH;
+
+ if (MT_MASK(menu[i].type) != MT_TITLE) {
+ ili9341_fill(bw-active_button_width, y, 2, MENU_BUTTON_HEIGHT-4, LIGHT_GREY); // Set button to unmodified background color
+ ili9341_fill(bw-active_button_width, y, active_button_width, 2, LIGHT_GREY); // Set button to unmodified background color
+ ili9341_fill(bw-2, y, 2, MENU_BUTTON_HEIGHT-4, DARK_GREY); // Set button to unmodified background color
+ ili9341_fill(bw-active_button_width, y+MENU_BUTTON_HEIGHT-4, active_button_width, 2, DARK_GREY); // Set button to unmodified background color
+ }
+#endif
+
ili9341_set_foreground(fg);
ili9341_set_background(bg);
- if (menu_is_multiline(menu[i].label, &l1, &l2)) {
- 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);
+ if (menu[i].type & MT_FORM) {
+ ili9341_fill(active_button_start+2, y+2, active_button_width-4, FONT_GET_HEIGHT*2+8, bg);
+ ili9341_drawstring_size(text, active_button_start+6, y+6, 2);
+#ifdef __ICONS__
+ if (menu[i].type & MT_ICON) {
+ blit16BitWidthBitmap(LCD_HEIGHT,y+6,16,16,&left_icons[((menu[i].data >>4)&0xf)*16]);
+ blit16BitWidthBitmap(256,y+6,16,16,&right_icons[((menu[i].data >>0)&0xf)*16]);
+ }
+#endif
} else {
- 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);
+ if (menu_is_multiline(menu[i].label, &l1, &l2)) {
+#define BIG_BUTTON_FONT 1
+#ifdef BIG_BUTTON_FONT
+#undef FONT_HEIGHT
+#define FONT_HEIGHT 13
+ ili9341_fill(active_button_start+1, y+1, active_button_width-2, 13+13 -2, bg);
+ ili9341_drawstring_7x13(l1, active_button_start+2, y+1);
+ ili9341_drawstring_7x13(l2, active_button_start+2, y+1+13-1);
+#else
+ ili9341_fill(active_button_start+3, y+5, active_button_width-6, 2+FONT_GET_HEIGHT+1+FONT_GET_HEIGHT+2, bg);
+ ili9341_drawstring(l1, active_button_start+5, y+7);
+ ili9341_drawstring(l2, active_button_start+5, y+7+FONT_GET_HEIGHT+1);
+#endif
+ } else {
+#ifdef BIG_BUTTON_FONT
+ ili9341_fill(active_button_start+1, y+1, active_button_width-2, 13+13 -2, bg);
+ ili9341_drawstring_7x13(menu[i].label, active_button_start+2, y+6);
+#else
+ ili9341_fill(active_button_start+3, y+8, active_button_width-6, 2+FONT_GET_HEIGHT+2, bg);
+ ili9341_drawstring(menu[i].label, active_button_start+5, y+10);
+#endif
+ }
}
+ y += MENU_BUTTON_HEIGHT;
}
}
@@ -1456,20 +1668,31 @@ menu_apply_touch(void)
int touch_x, touch_y;
const menuitem_t *menu = menu_stack[menu_current_level];
int i;
-
+ int y = 0;
touch_position(&touch_x, &touch_y);
- for (i = 0; i < 7; i++) {
- if (menu[i].type == MT_NONE)
+ for (i = 0; i < 8; i++) {
+ if ((menu[i].type & MT_LOW) && !MODE_LOW(setting.mode)) //not applicable to mode
+ continue;
+ if (MT_MASK(menu[i].type) == MT_NONE)
break;
- if (menu[i].type == MT_BLANK)
+ if (MT_MASK(menu[i].type == MT_BLANK) || MT_MASK(menu[i].type) == MT_TITLE) {
+ y += MENU_BUTTON_HEIGHT;
continue;
- int y = MENU_BUTTON_HEIGHT*i;
- if (y < touch_y && touch_y < y+MENU_BUTTON_HEIGHT && 320-MENU_BUTTON_WIDTH < touch_x) {
+ }
+ int active_button_width;
+ if (menu[i].type & MT_FORM)
+ active_button_width = MENU_FORM_WIDTH;
+ else
+ active_button_width = MENU_BUTTON_WIDTH;
+
+ if (y < touch_y && touch_y < y+MENU_BUTTON_HEIGHT && LCD_WIDTH-active_button_width < touch_x) {
menu_select_touch(i);
return;
}
+ y += MENU_BUTTON_HEIGHT;
}
-
+ if (menu_is_form(menu))
+ return;
touch_wait_release();
ui_mode_normal();
}
@@ -1483,13 +1706,18 @@ draw_menu(void)
static void
erase_menu_buttons(void)
{
- ili9341_fill(320-MENU_BUTTON_WIDTH, 0, MENU_BUTTON_WIDTH, MENU_BUTTON_HEIGHT*7, DEFAULT_BG_COLOR);
+// ili9341_fill(area_width, 0, LCD_WIDTH - area_width, area_height, DEFAULT_BG_COLOR);
+ if (current_menu_is_form())
+ ili9341_fill(5*5, 0,LCD_WIDTH-5*5, MENU_BUTTON_HEIGHT*8, DEFAULT_BG_COLOR);
+ else
+ ili9341_fill(LCD_WIDTH-MENU_BUTTON_WIDTH, 0, MENU_BUTTON_WIDTH, MENU_BUTTON_HEIGHT*8, DEFAULT_BG_COLOR);
+ draw_frequencies();
}
static void
erase_numeric_input(void)
{
- ili9341_fill(0, 240-NUM_INPUT_HEIGHT, 320, NUM_INPUT_HEIGHT, DEFAULT_BG_COLOR);
+ ili9341_fill(0, LCD_HEIGHT-NUM_INPUT_HEIGHT, LCD_WIDTH, NUM_INPUT_HEIGHT, DEFAULT_BG_COLOR);
}
static void
@@ -1505,6 +1733,7 @@ leave_ui_mode()
}
}
+#ifdef __VNA__
static void
fetch_numeric_target(void)
{
@@ -1551,6 +1780,7 @@ fetch_numeric_target(void)
// uistat.previous_value = uistat.value;
}
+
static void
set_numeric_value(void)
{
@@ -1584,16 +1814,17 @@ set_numeric_value(void)
break;
}
}
+#endif
static void
draw_numeric_area(void)
{
char buf[10];
- plot_printf(buf, sizeof buf, "%9d", uistat.value);
+ plot_printf(buf, sizeof buf, "%9d", ((int32_t)uistat.value));
draw_numeric_input(buf);
}
-static void
+void
ui_mode_menu(void)
{
if (ui_mode == UI_MENU)
@@ -1619,7 +1850,7 @@ ui_mode_numeric(int _keypad_mode)
keypad_mode = _keypad_mode;
ui_mode = UI_NUMERIC;
area_width = AREA_WIDTH_NORMAL;
- area_height = 240-NUM_INPUT_HEIGHT;//AREA_HEIGHT_NORMAL - 32;
+ area_height = LCD_HEIGHT-NUM_INPUT_HEIGHT;//AREA_HEIGHT_NORMAL - 32;
draw_numeric_area_frame();
fetch_numeric_target();
@@ -1629,7 +1860,7 @@ ui_mode_numeric(int _keypad_mode)
static void
ui_mode_keypad(int _keypad_mode)
{
- if (ui_mode == UI_KEYPAD)
+ if (ui_mode == UI_KEYPAD && keypad_mode == _keypad_mode )
return;
// keypads array
@@ -1643,13 +1874,14 @@ ui_mode_keypad(int _keypad_mode)
ui_mode = UI_KEYPAD;
area_width = AREA_WIDTH_NORMAL - MENU_BUTTON_WIDTH;
area_height = HEIGHT - 32;
- draw_menu();
+ if (!current_menu_is_form())
+ draw_menu();
draw_keypad();
draw_numeric_area_frame();
draw_numeric_input("");
}
-static void
+void
ui_mode_normal(void)
{
if (ui_mode == UI_NORMAL)
@@ -1664,18 +1896,29 @@ ui_mode_normal(void)
static void
lever_move_marker(int status)
{
+ int step = 1;
+ int count = 0;
do {
if (active_marker >= 0 && markers[active_marker].enabled) {
if ((status & EVT_DOWN) && markers[active_marker].index > 0) {
- markers[active_marker].index--;
+ markers[active_marker].index -= step;
+ if (markers[active_marker].index < 0)
+ markers[active_marker].index = 0 ;
markers[active_marker].frequency = frequencies[markers[active_marker].index];
redraw_marker(active_marker);
}
if ((status & EVT_UP) && markers[active_marker].index < sweep_points-1) {
- markers[active_marker].index++;
+ markers[active_marker].index += step;
+ if (markers[active_marker].index > POINTS_COUNT-1)
+ markers[active_marker].index = POINTS_COUNT-1 ;
markers[active_marker].frequency = frequencies[markers[active_marker].index];
redraw_marker(active_marker);
}
+ count++;
+ if (count > 10) {
+ step *= 2;
+ count = 0;
+ }
}
status = btn_wait_release();
} while (status != 0);
@@ -1745,7 +1988,7 @@ lever_move(int status, int mode)
}
#define STEPRATIO 0.2
-
+#ifdef __VNA__
static void
lever_edelay(int status)
{
@@ -1760,7 +2003,7 @@ lever_edelay(int status)
}
set_electrical_delay(value);
}
-
+#endif
static void
ui_process_normal(void)
{
@@ -1781,9 +2024,11 @@ ui_process_normal(void)
else
lever_zoom_span(status);
break;
+#ifdef __VNA__
case LM_EDELAY:
lever_edelay(status);
break;
+#endif
}
}
}
@@ -1795,20 +2040,30 @@ ui_process_menu(void)
int status = btn_check();
if (status != 0) {
if (status & EVT_BUTTON_SINGLE_CLICK) {
+ if (selection == -1) {
+ selection = 0;
+ goto activate;
+ }
menu_invoke(selection);
} else {
do {
if (status & EVT_UP) {
// close menu if next item is sentinel
+ while ((menu_stack[menu_current_level][selection+1].type & MT_LOW) && !MODE_LOW(setting.mode))
+ selection++;
if (menu_stack[menu_current_level][selection+1].type == MT_NONE)
goto menuclose;
- selection++;
+ if (!(menu_stack[menu_current_level][selection+1].type == (MT_FORM | MT_NONE)))
+ selection++;
}
if (status & EVT_DOWN) {
- if (selection == 0)
- goto menuclose;
- selection--;
+ while ((menu_stack[menu_current_level][selection+1].type & MT_LOW) && !MODE_LOW(setting.mode))
+ selection--;
+ if (! ( selection == 0 && menu_stack[menu_current_level][0].type & MT_FORM))
+ selection--;
}
+activate:
+ ensure_selection();
draw_menu();
status = btn_wait_release();
} while (status != 0);
@@ -1824,17 +2079,25 @@ static int
keypad_click(int key)
{
int c = keypads[key].c;
- if ((c >= KP_X1 && c <= KP_G) || c == KP_N || c == KP_P) {
- int32_t scale = 1;
+ if ((c >= KP_X1 && c <= KP_G) || c == KP_m || c == KP_u || c == KP_n) {
+ float scale = 1.0;
if (c >= KP_X1 && c <= KP_G) {
int n = c - KP_X1;
while (n-- > 0)
- scale *= 1000;
- } else if (c == KP_N) {
- scale *= 1000;
+ scale *= 1000.0;
+ } else if (c == KP_m) {
+ scale /= 1000.0;
+ } else if (c == KP_u) {
+ scale /= 1000000.0;
+ } else if (c == KP_n) {
+ scale /= 1000000000.0;
}
/* numeric input done */
double value = my_atof(kp_buf) * scale;
+#if 1
+ uistat.value = value;
+ set_numeric_value();
+#else
switch (keypad_mode) {
case KM_START:
set_sweep_frequency(ST_START, value);
@@ -1867,10 +2130,16 @@ keypad_click(int key)
set_trace_scale(uistat.current_trace, value * 1e-12); // pico second
break;
}
-
+#endif
return KP_DONE;
} else if (c <= 9 && kp_index < NUMINPUT_LEN) {
kp_buf[kp_index++] = '0' + c;
+ } else if (c>=KP_1) {
+ kp_buf[kp_index++] = keypad_scale_text[c-KP_1][0];
+ if (c >=KP_10)
+ kp_buf[kp_index++] = '0';
+ if (c >=KP_100)
+ kp_buf[kp_index++] = '0';
} else if (c == KP_PERIOD && kp_index < NUMINPUT_LEN) {
// check period in former input
int j;
@@ -1935,7 +2204,7 @@ numeric_apply_touch(void)
return;
}
- if (touch_y > 240-40) {
+ if (touch_y > LCD_HEIGHT-40) {
int n = 9 - (touch_x - 64) / 20;
uistat.digit = n;
uistat.digit_mode = TRUE;
@@ -2056,10 +2325,16 @@ ui_process_keypad(void)
break;
}
}
-
+ kp_help_text = NULL;
redraw_frame();
- request_to_redraw_grid();
- ui_mode_normal();
+ if (current_menu_is_form()) {
+ ui_mode_menu(); //Reactivate menu after keypad
+ selection = -1;
+ ensure_selection();
+ } else {
+ ui_mode_normal();
+ request_to_redraw_grid();
+ }
//redraw_all();
touch_start_watchdog();
}
@@ -2153,11 +2428,50 @@ touch_lever_mode_select(void)
return TRUE;
}
if (touch_y < 25) {
+#ifdef __VNA__
if (touch_x < FREQUENCIES_XPOS2 && get_electrical_delay() != 0.0) {
select_lever_mode(LM_EDELAY);
} else {
+#endif
select_lever_mode(LM_MARKER);
+#ifdef __VNA__
+ }
+#endif
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int
+touch_marker_select(void)
+{
+ int selected_marker = 0;
+ int touch_x, touch_y;
+ touch_position(&touch_x, &touch_y);
+ if (current_menu_is_form() || touch_x > LCD_WIDTH-MENU_BUTTON_WIDTH || touch_x < 25 || touch_y > 30)
+ return FALSE;
+ if (touch_y > 15)
+ selected_marker = 2;
+ selected_marker += (touch_x >150 ? 1 : 0);
+ for (int i = 0; i < MARKERS_MAX; i++) {
+ if (markers[i].enabled) {
+ if (selected_marker == 0) {
+ active_marker = i;
+ break;
+ }
+ selected_marker --;
}
+ }
+ if (touch_y < 25) {
+#ifdef __VNA__
+ if (touch_x < FREQUENCIES_XPOS2 && get_electrical_delay() != 0.0) {
+ select_lever_mode(LM_EDELAY);
+ } else {
+#endif
+ select_lever_mode(LM_MARKER);
+#ifdef __VNA__
+ }
+#endif
return TRUE;
}
return FALSE;
@@ -2176,14 +2490,18 @@ void ui_process_touch(void)
// Try drag marker
if (touch_pickup_marker())
break;
+ if (touch_marker_select())
+ 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();
selection = -1; // hide keyboard mode selection
+ ensure_selection();
ui_mode_menu();
break;
case UI_MENU:
@@ -2198,11 +2516,20 @@ void ui_process_touch(void)
touch_start_watchdog();
}
+static int previous_button_state = 0;
+
void
ui_process(void)
{
- if (operation_requested&OP_LEVER)
+ int button_state = READ_PORT() & BUTTON_MASK;
+ if (ui_mode == UI_NORMAL && current_menu_is_form()) { // Force into menu mode
+ selection = -1; // hide keyboard mode selection
+ ui_mode_menu();
+ }
+ if (operation_requested&OP_LEVER || previous_button_state != button_state) {
ui_process_lever();
+ previous_button_state = button_state;
+ }
if (operation_requested&OP_TOUCH)
ui_process_touch();
operation_requested = OP_NONE;
@@ -2214,14 +2541,19 @@ static void extcb1(EXTDriver *extp, expchannel_t channel)
(void)extp;
(void)channel;
operation_requested|=OP_LEVER;
- //cur_button = READ_PORT() & BUTTON_MASK;
+ // cur_button = READ_PORT() & BUTTON_MASK;
}
static const EXTConfig extcfg = {
{
{EXT_CH_MODE_DISABLED, NULL},
+#ifdef __ULTRA_SA__
+ {EXT_CH_MODE_DISABLED, NULL},
+ {EXT_CH_MODE_DISABLED, NULL},
+#else
{EXT_CH_MODE_RISING_EDGE | EXT_CH_MODE_AUTOSTART | EXT_MODE_GPIOA, extcb1},
{EXT_CH_MODE_RISING_EDGE | EXT_CH_MODE_AUTOSTART | EXT_MODE_GPIOA, extcb1},
+#endif
{EXT_CH_MODE_RISING_EDGE | EXT_CH_MODE_AUTOSTART | EXT_MODE_GPIOA, extcb1},
{EXT_CH_MODE_DISABLED, NULL},
{EXT_CH_MODE_DISABLED, NULL},
@@ -2279,8 +2611,8 @@ ui_init()
/*
* Activates the EXT driver 1.
*/
- extStart(&EXTD1, &extcfg);
+ extStart(&EXTD1, &extcfg);
#if 1
gptStart(&GPTD3, &gpt3cfg);
gptPolledDelay(&GPTD3, 10); /* Small delay.*/
@@ -2290,3 +2622,20 @@ ui_init()
touch_start_watchdog();
}
+
+void wait_user(void)
+{
+ adc_stop();
+ touch_wait_release();
+#if 0
+ operation_requested = OP_NONE;
+ while (true) {
+ if (operation_requested & OP_TOUCH)
+ break;
+ if (operation_requested & OP_LEVER)
+ break;
+ }
+#endif
+ touch_start_watchdog();
+}
+
diff --git a/ui_sa.c b/ui_sa.c
new file mode 100644
index 0000000..20e3e5d
--- /dev/null
+++ b/ui_sa.c
@@ -0,0 +1,1906 @@
+void markmap_all_markers(void);
+static void menu_marker_modify_cb(int item, uint8_t data);
+extern const menuitem_t menu_marker_modify[];
+void set_sweep_frequency(int type, uint32_t frequency);
+uint32_t get_sweep_frequency(int type);
+void clearDisplay(void);
+
+void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
+ const uint16_t *bitmap);
+
+
+const uint16_t left_icons [] =
+{
+#define I_EMPTY 0*16
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0001,
+ 0x0001,
+ 0x0001,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0001,
+ 0x0001,
+ 0x0001,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+#define I_HIGH_INPUT 1*16
+ /* +-----------------+
+ | |
+ | ** |
+ | *** |
+ | ************ |
+ | *** |
+ | ** |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ +-----------------+ */
+ 0x0000,
+ 0x0000,
+ 0x0060,
+ 0x0039,
+ 0x0fff,
+ 0x0039,
+ 0x0060,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0001,
+ 0x0001,
+ 0x0001,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+
+#define I_LOW_INPUT 2*16
+ /* +-----------------+
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | |
+ | ** |
+ | **** |
+ | ************ |
+ | **** |
+ | ** |
+ | |
+ +-----------------+ */
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0001,
+ 0x0001,
+ 0x0001,
+ 0x0000,
+ 0x0000,
+ 0x0000,
+ 0x0060,
+ 0x0039,
+ 0x0fff,
+ 0x0039,
+ 0x0060,
+ 0x0000,
+ 0x0000,
+
+#define I_LOW_OUTPUT 3*16
+
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000001,
+ 0b0000000000000001,
+ 0b0000000000000001,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000110000000,
+ 0b0000011100000001,
+ 0b0000111111111111,
+ 0b0000011100000001,
+ 0b0000000110000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+
+#define I_HIGH_OUTPUT 4*16
+
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000110000000,
+ 0b0000011100000001,
+ 0b0000111111111111,
+ 0b0000011100000001,
+ 0b0000000110000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000001,
+ 0b0000000000000001,
+ 0b0000000000000001,
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+
+#define I_CONNECT 5*16
+
+ 0b0000000000000000,
+ 0b0000000000000000,
+ 0b0000000000110000,
+ 0b0000000000111101,
+ 0b0000001111111111,
+ 0b0000010000111101,
+ 0b0000100000110000,
+ 0b0001000000000000,
+ 0b0001000000000000,
+ 0b0000100000110000,
+ 0b0000010000111101,
+ 0b0000001111111111,
+ 0b0000000000111101,
+ 0b0000000000110000,
+ 0b0000000000000000,
+ 0b0000000000000000,
+
+};
+
+const uint16_t right_icons [] =
+{
+#define I_SA 0
+ /* Character 0 (0x00):
+ width 16
+ +-----------------+
+ | |
+ | *************** |
+ | * * |
+ |** * |
+ | * * * |
+ | * * * |
+ | * * * * |
+ | * * * * |
+ | * * * * * |
+ | * * * * * * |
+ | * * * * * * * |
+ | * * * * * * * |
+ |** *********** * |
+ | * * |
+ | *************** |
+ | |
+ +-----------------+ */
+ 0x0000,
+ 0x7fff,
+ 0x4001,
+ 0xc001,
+ 0xc001,
+ 0xc001,
+ 0x4801,
+ 0x4801,
+ 0x4a89,
+ 0x4aa9,
+ 0xcaa9,
+ 0xdffd,
+ 0xc001,
+ 0x4001,
+ 0x7fff,
+ 0x0000,
+
+#define I_GEN 1
+ /* Character 0 (0x00):
+ width 16
+ +-----------------+
+ | |
+ | *************** |
+ | * * |
+ |** * |
+ | * ***** ** * |
+ | * * * * * |
+ | * * * * * |
+ | * * * * * |
+ | * * * * * |
+ | * * * * * |
+ | * * * * * |
+ | * ** ***** * |
+ |** * |
+ | * * |
+ | *************** |
+ | |
+ +-----------------+ */
+ 0x0000,
+ 0x7fff,
+ 0x4001,
+ 0xc001,
+ 0xcf8d,
+ 0xc889,
+ 0x4889,
+ 0x4889,
+ 0x4889,
+ 0x4889,
+ 0xc889,
+ 0xd8f9,
+ 0xc001,
+ 0x4001,
+ 0x7fff,
+ 0x0000,
+
+#define I_CONFIG 2
+
+ 0b0000000000000000,
+ 0b0111111111111111,
+ 0b0100000000000001,
+ 0b1100000010000001,
+ 0b1100001111000001,
+ 0b1100011110001001,
+ 0b0100011100011101,
+ 0b0100011110111001,
+ 0b0100001111111001,
+ 0b0100011111110001,
+ 0b1100111110000001,
+ 0b1101111100000001,
+ 0b1100111000000001,
+ 0b0100000000000001,
+ 0b0111111111111111,
+ 0b0000000000000000,
+
+#define I_SINUS 3
+
+ 0b0000000000000000,
+ 0b0111111111111111, // 1
+ 0b0100000000000001, // 2
+ 0b1100000000000001, // 3
+ 0b1100000000110001, // 4
+ 0b1100000001001001, // 5
+ 0b0100000010000101, // 6
+ 0b0101000010000101, // 7
+ 0b0101000010000101, // 8
+ 0b0101000010000001, // 9
+ 0b1100100100000001, //10
+ 0b1100011000000001, //11
+ 0b1100000000000001, //12
+ 0b0100000000000001, //13
+ 0b0111111111111111, //14
+ 0b0000000000000000,
+};
+
+enum {
+ KM_START=1, KM_STOP, KM_CENTER, KM_SPAN, KM_CW, KM_REFLEVEL, KM_SCALE, KM_ATTENUATION,
+ KM_ACTUALPOWER, KM_IF, KM_SAMPLETIME, KM_DRIVE, KM_LOWOUTLEVEL, KM_DECAY, KM_NOISE,
+ KM_10MHZ, KM_REPEAT, KM_OFFSET, KM_TRIGGER, KM_LEVELSWEEP, KM_SWEEP_TIME,
+};
+
+
+
+#define KP_X(x) (48*(x) + 2 + (LCD_WIDTH-BUTTON_WIDTH-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 KP_PLUSMINUS 19
+#define KP_KEYPAD 20
+#define KP_m 21
+#define KP_u 22
+#define KP_n 23
+
+#define KP_1 32
+#define KP_2 33
+#define KP_5 34
+#define KP_10 35
+#define KP_20 36
+#define KP_50 37
+#define KP_100 38
+#define KP_200 39
+#define KP_500 40
+
+
+typedef struct {
+ uint8_t x:4;
+ uint8_t y:4;
+ int8_t c;
+} keypads_t;
+
+static const keypads_t *keypads;
+
+static uint8_t keypads_last_index;
+
+// 7 8 9 G
+// 4 5 6 M
+// 1 2 3 k
+// 0 . < x
+
+static const keypads_t keypads_freq[] = {
+ { 1, 3, KP_PERIOD },
+ { 0, 3, 0 },
+ { 0, 2, 1 },
+ { 1, 2, 2 },
+ { 2, 2, 3 },
+ { 0, 1, 4 },
+ { 1, 1, 5 },
+ { 2, 1, 6 },
+ { 0, 0, 7 },
+ { 1, 0, 8 },
+ { 2, 0, 9 },
+ { 3, 0, KP_G },
+ { 3, 1, KP_M },
+ { 3, 2, KP_K },
+ { 3, 3, KP_X1 },
+ { 2, 3, KP_BS },
+ { 0, 0, -1 }
+};
+
+// 7 8 9
+// 4 5 6
+// 1 2 3
+// 0 . < x
+
+static const keypads_t keypads_positive[] = {
+ { 1, 3, KP_PERIOD },
+ { 0, 3, 0 },
+ { 0, 2, 1 },
+ { 1, 2, 2 },
+ { 2, 2, 3 },
+ { 0, 1, 4 },
+ { 1, 1, 5 },
+ { 2, 1, 6 },
+ { 0, 0, 7 },
+ { 1, 0, 8 },
+ { 2, 0, 9 },
+ { 3, 3, KP_X1 },
+ { 2, 3, KP_BS },
+ { 0, 0, -1 }
+};
+
+// 100 200 500 n
+// 10 20 50 u
+// 1 2 5 m
+// 0 . < x
+
+static const keypads_t keypads_pos_unit[] = {
+ { 1, 3, KP_PERIOD },
+ { 0, 3, 0 },
+ { 0, 2, KP_1 },
+ { 1, 2, KP_2 },
+ { 2, 2, KP_5 },
+ { 0, 1, KP_10 },
+ { 1, 1, KP_20 },
+ { 2, 1, KP_50 },
+ { 0, 0, KP_100 },
+ { 1, 0, KP_200 },
+ { 2, 0, KP_500 },
+ { 3, 0, KP_n },
+ { 3, 1, KP_u },
+ { 3, 2, KP_m },
+ { 3, 3, KP_X1 },
+ { 2, 3, KP_BS },
+ { 0, 0, -1 }
+};
+
+// 7 8 9 m
+// 4 5 6 u
+// 1 2 3 -
+// 0 . < x
+
+static const keypads_t keypads_plusmin_unit[] = {
+ { 1, 3, KP_PERIOD },
+ { 0, 3, 0 },
+ { 0, 2, 1 },
+ { 1, 2, 2 },
+ { 2, 2, 3 },
+ { 0, 1, 4 },
+ { 1, 1, 5 },
+ { 2, 1, 6 },
+ { 0, 0, 7 },
+ { 1, 0, 8 },
+ { 2, 0, 9 },
+ { 3, 0, KP_u},
+ { 3, 1, KP_m},
+ { 3, 2, KP_MINUS },
+ { 3, 3, KP_X1 },
+ { 2, 3, KP_BS },
+ { 0, 0, -1 }
+};
+// 7 8 9
+// 4 5 6
+// 1 2 3 -
+// 0 . < x
+
+static const keypads_t keypads_plusmin[] = {
+ { 1, 3, KP_PERIOD },
+ { 0, 3, 0 },
+ { 0, 2, 1 },
+ { 1, 2, 2 },
+ { 2, 2, 3 },
+ { 0, 1, 4 },
+ { 1, 1, 5 },
+ { 2, 1, 6 },
+ { 0, 0, 7 },
+ { 1, 0, 8 },
+ { 2, 0, 9 },
+ { 3, 0, KP_u},
+ { 3, 1, KP_m},
+ { 3, 2, KP_MINUS },
+ { 3, 3, KP_X1 },
+ { 2, 3, KP_BS },
+ { 0, 0, -1 }
+};
+
+// 7 8 9
+// 4 5 6
+// 1 2 3 m
+// 0 . < x
+static const keypads_t keypads_time[] = {
+ { 1, 3, KP_PERIOD },
+ { 0, 3, 0 },
+ { 0, 2, 1 },
+ { 1, 2, 2 },
+ { 2, 2, 3 },
+ { 0, 1, 4 },
+ { 1, 1, 5 },
+ { 2, 1, 6 },
+ { 0, 0, 7 },
+ { 1, 0, 8 },
+ { 2, 0, 9 },
+// { 3, 0, KP_n},
+// { 3, 1, KP_u},
+ { 3, 2, KP_m },
+ { 3, 3, KP_X1 },
+ { 2, 3, KP_BS },
+ { 0, 0, -1 }
+};
+
+static const keypads_t * const keypads_mode_tbl[] = {
+ NULL, // never used
+ keypads_freq, // start
+ keypads_freq, // stop
+ keypads_freq, // center
+ keypads_freq, // span
+ keypads_freq, // cw freq
+ keypads_plusmin_unit, // reflevel
+ keypads_pos_unit, // scale
+ keypads_positive, // attenuation
+ keypads_plusmin_unit, // actual power
+ keypads_freq, // IF
+ keypads_positive, // sample delay
+ keypads_positive, // drive
+ keypads_plusmin, // KM_LOWOUTLEVEL
+ keypads_positive, // KM_DECAY
+ keypads_positive, // KM_NOISE
+ keypads_plusmin, // KM_10MHz
+ keypads_positive, // KM_REPEA
+ keypads_plusmin, // KM_OFFSET
+ keypads_plusmin_unit, // KM_TRIGGER
+ keypads_plusmin, // KM_LEVELSWEEP
+ keypads_time, // KM_SWEEP_TIME
+};
+
+#ifdef __VNA__
+static const char * const keypad_mode_label[] = {
+ "START", "STOP", "CENTER", "SPAN", "CW FREQ", "SCALE", "REFPOS", "EDELAY", "VELOCITY%", "DELAY"
+};
+#endif
+#ifdef __SA__
+static const char * const keypad_mode_label[] = {
+ "error", "START", "STOP", "CENTER", "SPAN", "FREQ", "\2REF\0LEVEL", "SCALE", // 0-7
+ "\2ATTENUATE\0 0-31dB", "\2ACTUAL\0POWER", "IF", "\2SAMPLE\0DELAY", "DRIVE", "LEVEL", "SCANS", "LEVEL", // 8-15
+ "OFFSET" , "\2SAMPLE\0REPEAT", "OFFSET", "\2TRIGGER\0LEVEL", "\2LEVEL\0SWEEP", "\2SWEEP\0SECONDS"// 16-
+};
+#endif
+
+
+// ===[MENU CALLBACKS]=========================================================
+
+
+int generator_enabled = false;
+
+extern const menuitem_t menu_lowoutputmode[];
+extern const menuitem_t menu_highoutputmode[];
+extern const menuitem_t menu_modulation[];
+extern const menuitem_t menu_top[];
+extern const menuitem_t menu_tophigh[];
+extern const menuitem_t menu_topultra[];
+
+ void menu_mode_cb(int item, uint8_t data)
+{
+ (void)data;
+ set_mode(item);
+// draw_cal_status();
+ switch (item) {
+ case 0:
+// if (setting.mode != M_LOW)
+// set_mode(M_LOW);
+ menu_move_back();
+ ui_mode_normal();
+ break;
+ case 1:
+// if (setting.mode != M_HIGH)
+// set_mode(M_HIGH);
+ menu_move_back();
+ ui_mode_normal();
+ break;
+ case 2:
+ menu_push_submenu(menu_lowoutputmode);
+ break;
+ case 3:
+ menu_push_submenu(menu_highoutputmode);
+ break;
+#ifdef __ULTRA__
+ case 7:
+ menu_push_submenu(menu_topultra);
+ break;
+#endif
+ }
+ redraw_request |= REDRAW_CAL_STATUS;
+}
+
+void menu_load_preset_cb(int item, uint8_t data)
+{
+ (void)item;
+ if (caldata_recall(data) == -1) {
+ if (data == 0)
+ reset_settings(setting.mode); // Restore all defaults
+ else {
+ draw_menu();
+ return;
+ }
+ }
+ menu_move_back();
+ ui_mode_normal();
+}
+
+void menu_store_preset_cb(int item, uint8_t data)
+{
+ (void)item;
+ if (data == 100) {
+ reset_settings(M_LOW); // Restore all defaults in Low mode
+ // setting.mode = -1;
+ data = 0;
+ }
+ caldata_save(data);
+ menu_move_back();
+ ui_mode_normal();
+}
+
+
+extern int dirty;
+void menu_autosettings_cb(int item, uint8_t data)
+{
+ (void)item;
+ (void)data;
+ reset_settings(setting.mode);
+
+ active_marker = 0;
+ for (int i = 1; i= 0 && item < MARKERS_MAX) {
+ markers[item].enabled = true;
+ active_marker_select(item);
+ menu_push_submenu(menu_marker_modify);
+ redraw_marker(active_marker);
+ draw_menu();
+ }
+}
+
+static void menu_marker_modify_cb(int item, uint8_t data)
+{
+ (void)item;
+ if (markers[active_marker].enabled == M_ENABLED)
+ {
+ if (data == M_DELETE) {
+ markers[active_marker].enabled = false;
+ menu_move_back();
+// ui_mode_normal();
+// return;
+ } else if (data == M_NORMAL) {
+ markers[active_marker].mtype = M_NORMAL;
+ } else if (data == M_REFERENCE) {
+ for (int i = 0; i 1) {
+ mark = true;
+ }
+#ifdef __ULTRA__
+ } else if (MT_MASK(menu[item].type) == MT_CALLBACK && menu == menu_harmonic) {
+ if (data == setting.harmonic)
+ mark = true;
+#endif
+ } else if (MT_MASK(menu[item].type) == MT_CALLBACK && menu == menu_settings2) {
+ int v=0;
+ switch(data) {
+ case 1: v = setting.agc; break;
+ case 2: v = setting.lna; break;
+ case 3: v = setting.tracking; break;
+ case 4: v = setting.below_IF; break;
+ }
+ if (S_IS_AUTO(v))
+ m_auto = true;
+ else if (v == S_ON)
+ mark = true;
+ } else if (menu == menu_marker_modify && active_marker >= 0 && markers[active_marker].enabled == M_ENABLED) {
+ if (data & markers[active_marker].mtype)
+ mark = true;
+ else if (item < 5 && data==markers[active_marker].mtype) // This catches the M_NORMAL case
+ mark = true;
+ } else if (menu == menu_marker_search) {
+ if (item == 4 && markers[active_marker].mtype & M_TRACKING)
+ mark = true;
+ } else if (menu == menu_marker_sel || menu == menu_marker_select) {
+ if (item < 4 && markers[item].enabled)
+ mark = true;
+ else if (item == 4 && uistat.marker_delta)
+ mark = true;
+ else if (item == 5 && uistat.marker_noise)
+ mark = true;
+ else if (item == 6 && uistat.marker_tracking)
+ mark = true;
+ } else if (menu == menu_reflevel) {
+ if ((item == 0 && setting.auto_reflevel) || (item == 1 && !setting.auto_reflevel))
+ mark = true;
+ } else if (menu == menu_atten) {
+ if ((item == 0 && setting.auto_attenuation ) || (item == 1 && !setting.auto_attenuation))
+ mark = true;
+ }
+ if (m_auto) {
+ *bg = LIGHT_GREY;
+ *fg = config.menu_normal_color;
+ } else if (mark) {
+ *bg = DEFAULT_MENU_TEXT_COLOR;
+ *fg = config.menu_normal_color;
+ }
+ if (ui_mode == UI_MENU && menu_is_form(menu)) {
+ // if (item == 0)
+ // redraw_frame();
+ if (item <= 1) {
+ area_width = 0;
+ }
+ }else{
+ area_width = AREA_WIDTH_NORMAL - MENU_BUTTON_WIDTH;
+ }
+}
+
+static void fetch_numeric_target(void)
+{
+ switch (keypad_mode) {
+ case KM_START:
+ uistat.value = get_sweep_frequency(ST_START);
+ plot_printf(uistat.text, sizeof uistat.text, "%3.3fMHz", uistat.value / 1000000.0);
+ break;
+ case KM_STOP:
+ uistat.value = get_sweep_frequency(ST_STOP);
+ plot_printf(uistat.text, sizeof uistat.text, "%3.3fMHz", uistat.value / 1000000.0);
+ break;
+ case KM_CENTER:
+ uistat.value = get_sweep_frequency(ST_CENTER);
+ plot_printf(uistat.text, sizeof uistat.text, "%3.3fMHz", uistat.value / 1000000.0);
+ break;
+ case KM_SPAN:
+ uistat.value = get_sweep_frequency(ST_SPAN);
+ plot_printf(uistat.text, sizeof uistat.text, "%3.3fMHz", uistat.value / 1000000.0);
+ break;
+ case KM_CW:
+ uistat.value = get_sweep_frequency(ST_CW);
+ plot_printf(uistat.text, sizeof uistat.text, "%3.3fMHz", uistat.value / 1000000.0);
+ break;
+ case KM_SCALE:
+ uistat.value = setting.scale;
+ plot_printf(uistat.text, sizeof uistat.text, "%f/", uistat.value);
+ break;
+ case KM_REFLEVEL:
+ uistat.value = setting.reflevel;
+ plot_printf(uistat.text, sizeof uistat.text, "%f", uistat.value);
+ break;
+ case KM_ATTENUATION:
+ uistat.value = get_attenuation();
+ plot_printf(uistat.text, sizeof uistat.text, "%ddB", ((int32_t)uistat.value));
+ break;
+ case KM_ACTUALPOWER:
+ uistat.value = get_level_offset();
+ plot_printf(uistat.text, sizeof uistat.text, "%ddB", ((int32_t)uistat.value));
+ break;
+ case KM_IF:
+ uistat.value = setting.frequency_IF;
+ plot_printf(uistat.text, sizeof uistat.text, "%3.3fMHz", uistat.value / 1000000.0);
+ break;
+ case KM_SAMPLETIME:
+ uistat.value = setting.step_delay;
+ plot_printf(uistat.text, sizeof uistat.text, "%3duS", ((int32_t)uistat.value));
+ break;
+ case KM_REPEAT:
+ uistat.value = setting.repeat;
+ plot_printf(uistat.text, sizeof uistat.text, "%2d", ((int32_t)uistat.value));
+ break;
+ case KM_DRIVE:
+ uistat.value = setting.drive;
+ plot_printf(uistat.text, sizeof uistat.text, "%3ddB", ((int32_t)uistat.value));
+ break;
+ case KM_LOWOUTLEVEL:
+ uistat.value = get_attenuation(); // compensation for dB offset during low output mode
+ plot_printf(uistat.text, sizeof uistat.text, "%ddB", ((int32_t)uistat.value));
+ break;
+ case KM_DECAY:
+ uistat.value = setting.decay;
+ plot_printf(uistat.text, sizeof uistat.text, "%3d", ((int32_t)uistat.value));
+ break;
+ case KM_NOISE:
+ uistat.value = setting.noise;
+ plot_printf(uistat.text, sizeof uistat.text, "%3d", ((int32_t)uistat.value));
+ break;
+ case KM_10MHZ:
+ uistat.value = setting_frequency_10mhz;
+ plot_printf(uistat.text, sizeof uistat.text, "%3.6fMHz", uistat.value / 1000000.0);
+ break;
+ case KM_OFFSET:
+ uistat.value = setting.offset;
+ plot_printf(uistat.text, sizeof uistat.text, "%.1fdB", uistat.value);
+ break;
+ case KM_LEVELSWEEP:
+ uistat.value = setting.level_sweep;
+ plot_printf(uistat.text, sizeof uistat.text, "%.1fdB", uistat.value);
+ break;
+ case KM_SWEEP_TIME:
+ if (setting.sweep_time < calc_min_sweep_time())
+ uistat.value = calc_min_sweep_time();
+ else
+ uistat.value = setting.sweep_time;
+ uistat.value /= 1000.0;
+ plot_printf(uistat.text, sizeof uistat.text, "%.3FS", uistat.value);
+ break;
+ case KM_TRIGGER:
+ uistat.value = setting.trigger_level;
+ plot_printf(uistat.text, sizeof uistat.text, "%.1fdB", uistat.value);
+ break;
+
+ }
+
+ {
+ uint32_t x = uistat.value;
+ int n = 0;
+ for (; x >= 10 && n < 9; n++)
+ x /= 10;
+ uistat.digit = n;
+ }
+// uistat.previous_value = uistat.value;
+}
+
+static void
+set_numeric_value(void)
+{
+ switch (keypad_mode) {
+ case KM_START:
+ set_sweep_frequency(ST_START, uistat.value);
+ break;
+ case KM_STOP:
+ set_sweep_frequency(ST_STOP, uistat.value);
+ break;
+ case KM_CENTER:
+ set_sweep_frequency(ST_CENTER, uistat.value);
+ break;
+ case KM_SPAN:
+ setting.modulation = MO_NONE;
+ set_sweep_frequency(ST_SPAN, uistat.value);
+ break;
+ case KM_CW:
+ set_sweep_frequency(ST_CW, uistat.value);
+ break;
+ case KM_SCALE:
+ user_set_scale(uistat.value);
+ break;
+ case KM_REFLEVEL:
+ user_set_reflevel(uistat.value);
+ break;
+ case KM_ATTENUATION:
+ setting.auto_attenuation = false;
+ set_attenuation(uistat.value);
+ break;
+ case KM_ACTUALPOWER:
+ set_actual_power(uistat.value);
+ config_save();
+ break;
+ case KM_IF:
+ setting.auto_IF = false;
+ set_IF(uistat.value);
+// config_save();
+ break;
+ case KM_SAMPLETIME:
+ set_step_delay(uistat.value);
+ break;
+ case KM_REPEAT:
+ set_repeat(uistat.value);
+ break;
+ case KM_DRIVE:
+ set_drive(uistat.value);
+ break;
+ case KM_LOWOUTLEVEL:
+ set_level(uistat.value);
+ break;
+ case KM_DECAY:
+ set_decay(uistat.value);
+ break;
+ case KM_NOISE:
+ set_noise(uistat.value);
+ break;
+ case KM_10MHZ:
+ if (uistat.value < 9000000) {
+ set_10mhz(setting_frequency_10mhz + uistat.value);
+ } else
+ set_10mhz(uistat.value);
+ dirty = true;
+ break;
+ case KM_OFFSET:
+ set_offset(uistat.value);
+ break;
+ case KM_LEVELSWEEP:
+ setting.modulation = MO_NONE;
+ set_level_sweep(uistat.value);
+ break;
+ case KM_SWEEP_TIME:
+ set_sweep_time(uistat.value*1000.0);
+ update_grid();
+ break;
+ case KM_TRIGGER:
+ if (setting.trigger == T_AUTO )
+ set_trigger(T_NORMAL);
+ set_trigger_level(to_dBm(uistat.value));
+ redraw_request |= REDRAW_CAL_STATUS | REDRAW_AREA;
+ completed = true;
+
+ break;
+ }
+}