Compare commits

..

70 commits

Author SHA1 Message Date
TT d02db797a7
Merge pull request #144 from czietz/window_loss
Compensate IFFT window / zero-padding loss in TD
2020-11-12 06:02:21 +09:00
Christian Zietz 4d64ef6e48 Compensate IFFT window / zero-padding loss in TD
Depending on the chosen window and mode, the magnitude of the
impulse response in time-domain previously was to low. This can
be explained by looking at the signal processing. For example,
in bandpass mode with normal window, it applies a 101 point Kaiser
window (shape factor 6) and zero-pads to do a 256 point IFFT.
Therefore, the loss is 20*log10(256/sum(kaiser(101,6))) ≈ 14.2 dB.

This change compensates the signal processing losses in bandpass
and lowpass impulse mode depending on the window type, which makes
the time-domain results similar to other VNAs.
2020-10-25 13:34:19 +01:00
TT bc1b57c3f0 feat: add format quality factor 2020-06-20 08:08:21 +09:00
TT 64de4d5d87 fix: add wait in dump command 2020-06-16 08:22:18 +09:00
TT e57292ea01 doc: add ssci to README.md 2020-06-12 05:50:55 +09:00
TT fb57511f9a view: change R+Xj to R+jX in menu label of smith value format 2020-05-16 10:48:50 +09:00
TT 56b0d3ad8a env: insert wait after switching to dfu 2020-05-14 07:20:29 +09:00
TT ba7d358d35 fix: force disable tracking on marker search left/right op 2020-05-14 07:18:59 +09:00
TT d7c7d8faeb feat: add bandwidth command 2020-05-14 07:05:43 +09:00
TT fe7a1ac4de fix: keep freq mode in each save slot 2020-05-14 06:53:52 +09:00
TT 5a10105b1a Merge branch 'bandwidth' 2020-03-21 21:19:53 +09:00
TT 1656342eeb feat: add bandwidth setting of detector 2020-03-21 21:03:08 +09:00
TT 0d407577f8 style: uniform code style and untabify 2020-03-21 09:33:33 +09:00
TT a4821604a5
Merge pull request #126 from DiSlord/master
Fix screen artifacts, change start/stop or center/span mode set, remove Mutex use
2020-03-21 09:22:06 +09:00
DiSlord 597c2c2958 Better solutiom of prev fixes (reload si5351 settings on sweep begin) 2020-03-15 16:02:22 +03:00
DiSlord 23c765b719 Fix very strange bug, on band 2
!!!!! Don`t understand why si5351 non stable on band 2 then change from band 3
It fixed if set before sweep one frequency from band 1 (for example 50MHz)
Possibly problem in tlv320aic3204_set_gain, call only si5351_set_frequency_with_offset not work

Little faster call command from shell

Fix interpolation if points < POINTS_COUNT
2020-03-15 14:14:52 +03:00
DiSlord 3eb8a4cfe9 Fix interpolation range if sweep_points!=source calibration points count
use sweep_points exept POINTS_COUNT on marker search and so

Now possible change sweep_points in process (for faster sweep)
2020-03-14 21:23:02 +03:00
DiSlord fdb3886b0f Move define to str macro in nanovna.h (it allow output define valuer in error messages) 2020-03-14 16:50:35 +03:00
DiSlord 45dfd7d970 Fix sweep if points < maximum (mot sweep if frequency[i] == 0)
Fix my tupo in extended scan command (not correctly parse point count)
2020-03-14 16:48:36 +03:00
DiSlord 8a11eaa764 Extend scan command, now in have additional input variable (optional), allow more faster get measured data
usage: scan {start(Hz)} {stop(Hz)} [points] [outmask]
[outmask] - optional, allow output measured data, its a mask (allow dec, hex, bin, oct)
0b001 - output frequency
0b010 - output CH0 data
0b100 - output CH1 data
Example:
'scan 1000000 5000000 101 0b111' - output data in format: freq ch0[0] ch0[1] ch1[0] ch1[1]
'scan 1000000 5000000 101 0b101' - output data in format: freq ch1[0] ch1[1]
'scan 1000000 5000000 101 0x7'   - output data as 0b111
2020-03-14 16:05:26 +03:00
DiSlord ec81a01226 Not use float in vbat measure (faster, less size), yes get little error (but less then 1mV) 2020-03-14 15:21:26 +03:00
DiSlord 922b66abdb Move offset variable to si5351.c (better use it as independent library)
Define and move constants in nanovna.h, and use it
Fix command 'marker' - display marker freq (not current freq)
2020-03-14 15:18:14 +03:00
DiSlord 88617a31fe In ili9341.c remove tabs, add palette mode blit function
In plot.c prepare for 8bit/pixel mode (test, allow increase cell buffer size by use 4 or 8bit/pixel mode, but not need for now)
main.c little change wait execute shell command in sweep thread
2020-03-13 22:42:28 +03:00
DiSlord 8bdb650212 Implement color command, allow change color settings in config (enabled bu default ENABLE_COLOR_COMMAND)
Usage: usage: color {id} {rgb24}
- Grid color: id = -3
- Menu bg color: id = -2
- Selected menu: id = -1
- Trace 1-4: id = 0..3
Color in hex RGB format (but possible any type input, dec, hex, bin. oct)
2020-03-12 21:43:35 +03:00
DiSlord 6f25d0d43f Remove Mutex use (CH_CFG_USE_MUTEXES = FALSE), now all Mutex depend functions run in sweep thread
It allow:
- reduce shell thread stack size
- more compact code
- fix some hardcoded scan command code, allow write better scan version
- run calibrate (not depend from pause sweep flag)

Rewrite uint32_t my_atoui(const char *p), now its allow read:
hex 0xaAbBcC1122
dec 12345678
bin 0b00011100
oct 0o12345678

Add some comments
2020-03-12 19:53:58 +03:00
DiSlord 51b5cce016 Fix Random jitters at band 1 and band change on some freq ranges
Improve frequency stability on band change (100 MHz, 150MHz, 300 MHz, 450MHz)

Restore freq cache in CW mode
2020-03-11 20:11:46 +03:00
DiSlord 10ae59e786 Little cleanup 2020-03-09 23:57:03 +03:00
DiSlord 3714e05395 Fix artifacts after marker move
(For faster screen update on marker move, all old area update info invalidate after use draw_all_cells(TRUE) on page switch)
Force redraw all cells after end marker move
2020-03-09 22:47:35 +03:00
DiSlord eebb625b9d Always update marker info 2020-03-09 22:28:05 +03:00
DiSlord 04fb661b1a Add flag in config for sweep mode
#define FREQ_MODE_START_STOP    0x0
#define FREQ_MODE_CENTER_SPAN   0x1
Now sweep mode not defined from frequency0 > frequency1 or frequency0 < frequency1
frequency0 always < frequency1

All freq must get by use get_sweep_frequency(mode)

Revert Select CH0 reflect channel before set freq, add additional delay on 0 sweep point
2020-03-09 18:24:31 +03:00
DiSlord f9074149bb Size fixes, use define exept const, typdef index_t for indexes 2020-03-09 16:18:29 +03:00
DiSlord 19121b3371 Auto determine mark_map mask size from MAX_MARKMAP_X on compilation (up to MAX_MARKMAP_X = 32) 2020-03-09 14:40:17 +03:00
DiSlord 2d273a5548 Fix typo 2020-03-09 14:22:59 +03:00
DiSlord a19722cdc3 Reduce last patch fix size (use pointers) 2020-03-09 14:08:06 +03:00
DiSlord 90407d5730 Fix screen artifacts:
In mark_cells_from_index(void) mark all rectangle (in most cases this not decrease render speed, and more fast in calculation, and no errors)
2020-03-09 13:12:01 +03:00
DiSlord 5cf86ee1a6 Revert dsp changes, need more research 2020-03-09 10:28:33 +03:00
DiSlord a2d90a5e91 Try not lost data on dsp (Less noise on small signals)
Use int64_t acc for values
Use double on calculation

Not cache freq on si5351_set_frequency_with_offset (to fast change in rare cases on cw mode, and process wrong DSP block) as i write before need change DSP delay tactic
2020-03-09 01:25:46 +03:00
DiSlord 77b5d0bcc8 Select CH0 reflect channel before set freq (in some rare cases dsp started but CH not ready)
Little code optimization
Add commented 600kHz I2C bus timings (work, give x1.5 speed, but need change DSP ready timings not by wait_count, need use chVTGetSystemTimeX() its better)
2020-03-08 22:48:36 +03:00
TT c40d78d80f env: clean Makefile 2020-03-08 20:03:54 +09:00
TT 608482a970 env: add debug conf for vscode 2020-03-08 19:56:37 +09:00
TT ba5bf9c1ad fix: board definition 2020-03-08 19:55:57 +09:00
TT 6befd57bc1 fix: segv in sample command 2020-03-08 19:37:26 +09:00
TT 7c2e4364e6
Merge pull request #125 from DiSlord/master
Speedup and fix Si5351 clock generator
2020-03-08 19:33:13 +09:00
DiSlord 45f04420cb Implement info command, move info_about[] to main.c
Command enabled by default: ENABLE_INFO_COMMAND
This feature not increase flash size
2020-03-08 08:32:38 +03:00
DiSlord fc6e090595 Add vbat_offset to config
Implement vbat_offset command (if defined ENABLE_VBAT_OFFSET_COMMAND)
Reduce code size
2020-03-07 23:37:39 +03:00
DiSlord bb7127fdd0 Remove variable, use speep_mode flag 2020-03-07 22:21:02 +03:00
DiSlord e896f32803 Replace function wait_dsp(delay) by definition:
DSP_START(delay)
//================================================
// Place some code thats need execute while delay
//================================================
DSP_WAIT_READY

Fix Band table description

Add power stabilization delay on sweep start
2020-03-07 20:57:43 +03:00
DiSlord 12d53738bc Revert some changes:
Start/stop generation feature (unstable on segment scan from CPU)
 Calibration on paused sweep (need more stack, need find better solution)
 Variable use optimization
2020-03-07 17:19:43 +03:00
DiSlord a43b6e3acc si5351.c and si5351.h
Cleanup and optimize  code
Add comments, fix definitions
Fix rounding errors
Fix band 1 stability

mcuconf.h
Set I2C bus clock to SYSCLK (more fast)
Apply 400kHz bus I2C clock timings for 8MHz and 48Mhz clock

main.c
Remove and reset some variables
Add separate sweep for calibration (allow calibrate if sweep paused)

Increase main thread stack (need for run calibrate, possibly need execute some commands in sweep threads for reduce stack usage)
2020-03-07 14:54:51 +03:00
DiSlord b77e1d6680 Big work around si5351 generator
Improve sweep speed about 60%
Stop generation on pause sweep
Remove all hack for si5351
Reduce code size
Fix integer overflow on big freq values

Additional
Change I2C

Others:
 move marker_tracking variable to ui config
 move some definition to correct place
 reduce tlv320aic3204 code size
 Speedup marker move from lever (BUTTON_REPEAT_TICKS = 625)

Need test stability
2020-03-05 22:36:44 +03:00
TT f1cc60e99e feat: add lever mode for electrical delay 2020-03-01 09:29:28 +09:00
TT f6b28c2c14
Merge pull request #121 from DiSlord/master
Fix crash on trace command, reduce flash usage by 8k, up to 2x faster screen render
2020-03-01 09:19:28 +09:00
TT 18c5ca9157 feat: add lever operation of electrical delay 2020-03-01 08:50:46 +09:00
TT 7f5948c4b8 chore: add scope name onto struct and enum 2020-03-01 08:18:12 +09:00
DiSlord 153585ff1f Move more address constants to nanovna.h 2020-02-28 23:52:01 +03:00
DiSlord ccb3693516 Huge reduce flash usage (about 5k), remove cal_data and _frequencies properties from data section
Use void loadDefaultProps() for load default properties (default loaded also on error load from flash)
Move some constants to nanovna.h
2020-02-28 23:15:38 +03:00
DiSlord cc3370c962 si5351.c
Remove unused function from header
Set static calls for functions (less size)
Set static constants (less size)
2020-02-28 18:57:18 +03:00
DiSlord a164a5765a Disable HAL_USE_RTC usage (need for cmd_time)
Add ENABLE_TIME_COMMAND for enable cmd_time if need

Fix incorrect data on run cmd_scan cmd_data if Tansform enabled on NanoVNA (remove transform_domain() from sweep, add in front of plot_into_index in sweep thread)
Remove pause/run in reload (not need, command run vs CMD_WAIT_MUTEX flag)
2020-02-28 18:52:25 +03:00
DiSlord 0116c529ea Restore sweep stack size as 640 2020-02-28 00:50:12 +03:00
DiSlord cb587d05a4 Makefile:
Remove compile
 #include $(CHIBIOS)/test/rt/test.mk
 #include $(CHIBIOS)/os/various/shell/shell.mk

Shell not used, test not used
2020-02-27 22:11:32 +03:00
DiSlord 95b3f6f7d0 Disable ChibiOS option CH_CFG_USE_MUTEXES_RECURSIVE
All calls chMtxLock - chMtxUnlock not recursive
2020-02-27 21:21:54 +03:00
DiSlord 17734f257d Disable unused ChibiOS options:
CH_CFG_USE_WAITEXIT (used only is Shell run as thread)
CH_CFG_USE_EVENTS (NanoVNA not use events)
CH_CFG_USE_EVENTS_TIMEOUT (NanoVNA not use events)

Implement stack use check in "threads" command, now free stack space show in table as "stk free" in hex
Check stack usage by sweep, and main threads (seems all ok, but add 64 bytes to sweep)

Replace some const values to defined
2020-02-27 20:53:45 +03:00
DiSlord d386b0823c Write clearScreen and use it in code
More hard coded values fixes
2020-02-26 23:55:06 +03:00
DiSlord b7934745ca Restore main thread stack size (stack usage code optimization give good result)
Decrease sweep thread stack size from 640 to 512 (also stack usage code optimization give good result)
Little change 16x22 font

ui.c
Use definition for some hard coded values
Fix button "Correction" not reset after use "reset"
Define menu button and input num size

#define MENU_BUTTON_WIDTH  60
#define MENU_BUTTON_HEIGHT 30
#define NUM_INPUT_HEIGHT   30

Reduce button height from 32 to 30 pixels (fix in stimulus menu "<back" button overwrite by input num field)
Little code change
2020-02-26 23:30:50 +03:00
DiSlord a4e9b7a139
Merge branch 'master' into master 2020-02-25 06:35:06 +03:00
TT 48ff4893d3 feat: force putting trailing zeros on float value 2020-02-25 08:41:22 +09:00
DiSlord d2431f0cdc Increase screen render (in some cases up to 2x speedup), decrease stack usage (code size less on 1500 bytes)
Write simple profiling definitions
 START_PROFILE
 STOP_PROFILE
Use it for detect sys tick amount and output to screen

main.c
 Reduce VNA_SHELL_MAX_LENGTH to 48, and made shell_line as static (reduce stack usage)
 Remove BaseSequentialStream *chp from command calls (use static shell_stream), it reduce code size and stack usage
 Use VNA_SHELL_FUNCTION definition for all commands
 Remove chMtxLock(&mutex);chMtxUnlock(&mutex); from commands, and define command flag for use it in calls
 Apply default scale from trace_info on trace change
 Led blink outside from main sweep cycle (better look, and less noise)
 Some size fixes

chprintf.c
 Implement small memory stream object, only put function and plot_printf(char *str, int size, const char *fmt, ...)
 Use it in all code (little increase speed, and huge decrease size)

 Restore USE_EXCEPTIONS_STACKSIZE = 0x180 (possible not need, but not good tested)

plot.c
 Made huge screen render profile (add some comments)
 Not use cell clipping on draw cell data (use constants increase speed, decrease stack usage (not need put it to stack))
 Clip cell if need only on screen flush
 Use new plot_printf, remove chsnprintf usage

Apply code style
============================================================================================================
Interesting fact
Usage memset(spi_buffer, DEFAULT_BG_COLOR, (h*CELLWIDTH)*sizeof(uint16_t)); dramatically decrease render speed
possibly it fill buffer by 8 bit data, so slow
Usage
  uint32_t *p = (uint32_t *)spi_buffer;
  while (count--) {
    p[0] = DEFAULT_BG_COLOR|(DEFAULT_BG_COLOR<<16);
    p[1] = DEFAULT_BG_COLOR|(DEFAULT_BG_COLOR<<16);
    p[2] = DEFAULT_BG_COLOR|(DEFAULT_BG_COLOR<<16);
    p[3] = DEFAULT_BG_COLOR|(DEFAULT_BG_COLOR<<16);
    p+=4;
  }
gives x10 speed perfomance

Draw polar and smit grid very slow (but i don`t know how increase it except use bitmaps, but it need about 5-8k flash size and file prepare)
On long lines render slow down, but clipping use more calculation, and not give good result
Need made stack usage check
2020-02-24 22:47:52 +03:00
DiSlord 5ee23be06f Add definition of spi_buffer size
Add check cell and spi_buffer size
2020-02-23 17:13:52 +03:00
DiSlord c92987c52e Fix default trace refpos set (use NGRIDY value) 2020-02-23 15:58:12 +03:00
DiSlord 1177d87498 Increase main thread stack size (if used as shell, if run some commands get stack limit, example "trace 0 x" command)
Decrease interrupt stack size

Use __ROR instruction in flash.c for checksum rotate
Fix erase background for frequencies string in plot.c

Implement getStringIndex function for parse string arguments, now Usage show correct information about used arg, and more easy use strings definitions
Example:
 Need check if string "on"  in avaible arguments list "load|open|short|thru|isoln|done|on|off|reset|data|in"
 getStringIndex("on", "load|open|short|thru|isoln|done|on|off|reset|data|in") return 6
 If not found return -1
Not need use if (strcmp() == ...) else ....
This usage save some amount of size
2020-02-23 15:45:37 +03:00
25 changed files with 6291 additions and 5759 deletions

156
.clang-format Normal file
View file

@ -0,0 +1,156 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 90
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: true
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseTab: Never
...

31
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,31 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "OpenOCD-Debug",
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"executable": "build/ch.elf",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f0x.cfg"
],
"cwd": "${workspaceRoot}",
"svdFile": "STM32F0x2.svd",
"device": "stm32f0x",
"preLaunchTask": "build",
},
{
"name": "STLink-Debug",
"type": "cortex-debug",
"request": "launch",
"servertype": "stutil",
"executable": "build/ch.elf",
"cwd": "${workspaceRoot}",
"svdFile": "STM32F0x2.svd",
"device": "stm32f0x",
"preLaunchTask": "build",
}
]
}

View file

@ -1,3 +1,4 @@
{
"C_Cpp.errorSquiggles": "Disabled"
"C_Cpp.errorSquiggles": "Disabled",
"cpplint.filters": ["-build/include_subdir", "-build/include_order", "-readability/casting", "-whitespace/comments"]
}

12
.vscode/tasks.json vendored
View file

@ -2,19 +2,19 @@
"version": "2.0.0",
"tasks": [
{
"label": "make",
"label": "build",
"type": "shell",
"command": "make",
"group": "build"
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "flash",
"type": "shell",
"command": "make dfu flash",
"group": {
"kind": "build",
"isDefault": true
}
"group": "build"
}
]
}

View file

@ -11,6 +11,7 @@
#define FONT_GET_DATA(ch) (&x5x7_bits[ch*7])
#define FONT_GET_WIDTH(ch) (8-x5x7_bits[ch*7]&7)
#define FONT_MAX_WIDTH 7
#define FONT_GET_HEIGHT 7
#define CHAR5x7_WIDTH_1px 0x07

View file

@ -81,6 +81,10 @@ endif
# Project, sources and paths
#
# Dvice node to flash
DEVICE = /dev/cu.usbmodem401
#DEVICE = /dev/ttyACM0
# Define project name here
PROJECT = ch
@ -100,9 +104,9 @@ include $(CHIBIOS)/os/hal/osal/rt/osal.mk
include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
# Other files (optional).
include $(CHIBIOS)/test/rt/test.mk
#include $(CHIBIOS)/test/rt/test.mk
include $(CHIBIOS)/os/hal/lib/streams/streams.mk
include $(CHIBIOS)/os/various/shell/shell.mk
#include $(CHIBIOS)/os/various/shell/shell.mk
# Define linker script file here
#LDSCRIPT= $(STARTUPLD)/STM32F072xB.ld
@ -118,12 +122,9 @@ CSRC = $(STARTUPSRC) \
$(PLATFORMSRC) \
$(BOARDSRC) \
$(STREAMSSRC) \
$(SHELLSRC) \
usbcfg.c \
main.c si5351.c tlv320aic3204.c dsp.c plot.c ui.c ili9341.c numfont20x22.c Font5x7.c flash.c adc.c
# $(TESTSRC) \
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CPPSRC =
@ -153,8 +154,7 @@ ASMSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
INCDIR = $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
$(HALINC) $(PLATFORMINC) $(BOARDINC) \
$(STREAMSINC) $(SHELLINC)
# $(TESTINC)
$(STREAMSINC)
#
# Project, sources and paths
@ -176,7 +176,7 @@ CPPC = $(TRGT)g++
LD = $(TRGT)gcc
#LD = $(TRGT)g++
CP = $(TRGT)objcopy
AS = $(TRGT)gcc -x assembler-with-cpp
AS = $(TRGT)gcc -x assembler-with-cpp -ggdb
AR = $(TRGT)ar
OD = $(TRGT)objdump
SZ = $(TRGT)size
@ -229,9 +229,4 @@ flash: build/ch.bin
dfu-util -d 0483:df11 -a 0 -s 0x08000000:leave -D build/ch.bin
dfu:
-@printf "reset dfu\r" >/dev/cu.usbmodem401
TAGS: Makefile
@etags *.[ch] NANOVNA_STM32_F072/*.[ch] $(shell find ChibiOS/os/hal/ports/STM32/STM32F0xx ChibiOS/os -name \*.\[ch\] -print)
@ls -l TAGS
-printf "reset dfu\r" >$(DEVICE) && sleep 1

View file

@ -17,10 +17,6 @@
#ifndef _BOARD_H_
#define _BOARD_H_
/*
* Setup for the Strawberry Linux STbee
*/
/*
* Board identifier.
*/
@ -130,8 +126,8 @@
PIN_MODE_ALTERNATE(GPIOA_MCO) | \
PIN_MODE_INPUT(9U) | \
PIN_MODE_OUTPUT(GPIOA_USB_DISC) | \
PIN_MODE_INPUT(GPIOA_USB_DM) | \
PIN_MODE_INPUT(GPIOA_USB_DP) | \
PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \
PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \
PIN_MODE_ALTERNATE(GPIOA_JTMS) | \
PIN_MODE_ALTERNATE(GPIOA_JTCK) | \
PIN_MODE_OUTPUT(GPIOA_LCD_RESET))
@ -161,7 +157,7 @@
PIN_OSPEED_2M(7) | \
PIN_OSPEED_100M(GPIOA_MCO) | \
PIN_OSPEED_100M(9) | \
PIN_OSPEED_100M(10) | \
PIN_OSPEED_100M(GPIOA_USB_DISC) | \
PIN_OSPEED_100M(GPIOA_USB_DM) | \
PIN_OSPEED_100M(GPIOA_USB_DP) | \
PIN_OSPEED_100M(GPIOA_JTMS) | \
@ -177,7 +173,7 @@
PIN_PUPDR_FLOATING(7) | \
PIN_PUPDR_PULLUP(GPIOA_MCO) | \
PIN_PUPDR_PULLUP(9) | \
PIN_PUPDR_PULLUP(GPIOA_USB_DISC) | \
PIN_PUPDR_FLOATING(GPIOA_USB_DISC) | \
PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \
PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \
PIN_PUPDR_PULLDOWN(GPIOA_JTMS) | \

View file

@ -89,7 +89,7 @@ There are seveal numbers of great companion PC tools from third-party.
## Documentation
* [NanoVNA User Guide](https://cho45.github.io/NanoVNA-manual/) [(google translate)](https://translate.google.com/translate?sl=ja&tl=en&u=https%3A%2F%2Fcho45.github.io%2FNanoVNA-manual%2F) by cho45
* [NanoVNA User Guide(ja)](https://cho45.github.io/NanoVNA-manual/) by cho45. [(en:google translate)](https://translate.google.com/translate?sl=ja&tl=en&u=https%3A%2F%2Fcho45.github.io%2FNanoVNA-manual%2F)
## Reference
@ -105,6 +105,7 @@ Hardware design material is disclosed to prevent bad quality clone. Please let m
## Authorized Distributor
* [Nooelec](https://www.nooelec.com/store/nanovna-bundle.html)
* Switch Science(ja) [NanoVNA-H](https://www.switch-science.com/catalog/6405/) [NanoVNA-H4](https://www.switch-science.com/catalog/6406/)
## Credit

106
adc.c
View file

@ -28,80 +28,82 @@
#define ADC_SMPR_SMP_239P5 7U /**< @brief 252 cycles conversion time. */
#define ADC_CFGR1_RES_12BIT (0U << 3U)
#define VNA_ADC ADC1
void adc_init(void)
{
rccEnableADC1(FALSE);
/* Ensure flag states */
ADC1->IER = 0;
VNA_ADC->IER = 0;
/* Calibration procedure.*/
ADC->CCR = 0;
if (ADC1->CR & ADC_CR_ADEN) {
ADC1->CR |= ~ADC_CR_ADDIS; /* Disable ADC */
if (VNA_ADC->CR & ADC_CR_ADEN) {
VNA_ADC->CR |= ~ADC_CR_ADDIS; /* Disable ADC */
}
while (ADC1->CR & ADC_CR_ADEN)
while (VNA_ADC->CR & ADC_CR_ADEN)
;
ADC1->CFGR1 &= ~ADC_CFGR1_DMAEN;
ADC1->CR |= ADC_CR_ADCAL;
while (ADC1->CR & ADC_CR_ADCAL)
VNA_ADC->CFGR1 &= ~ADC_CFGR1_DMAEN;
VNA_ADC->CR |= ADC_CR_ADCAL;
while (VNA_ADC->CR & ADC_CR_ADCAL)
;
if (ADC1->ISR & ADC_ISR_ADRDY) {
ADC1->ISR |= ADC_ISR_ADRDY; /* clear ADRDY */
if (VNA_ADC->ISR & ADC_ISR_ADRDY) {
VNA_ADC->ISR |= ADC_ISR_ADRDY; /* clear ADRDY */
}
/* Enable ADC */
ADC1->CR |= ADC_CR_ADEN;
while (!(ADC1->ISR & ADC_ISR_ADRDY))
VNA_ADC->CR |= ADC_CR_ADEN;
while (!(VNA_ADC->ISR & ADC_ISR_ADRDY))
;
}
uint16_t adc_single_read(ADC_TypeDef *adc, uint32_t chsel)
uint16_t adc_single_read(uint32_t chsel)
{
/* ADC setup */
adc->ISR = adc->ISR;
adc->IER = 0;
adc->TR = ADC_TR(0, 0);
adc->SMPR = ADC_SMPR_SMP_239P5;
adc->CFGR1 = ADC_CFGR1_RES_12BIT;
adc->CHSELR = chsel;
VNA_ADC->ISR = VNA_ADC->ISR;
VNA_ADC->IER = 0;
VNA_ADC->TR = ADC_TR(0, 0);
VNA_ADC->SMPR = ADC_SMPR_SMP_239P5;
VNA_ADC->CFGR1 = ADC_CFGR1_RES_12BIT;
VNA_ADC->CHSELR = chsel;
/* ADC conversion start.*/
adc->CR |= ADC_CR_ADSTART;
VNA_ADC->CR |= ADC_CR_ADSTART;
while (adc->CR & ADC_CR_ADSTART)
while (VNA_ADC->CR & ADC_CR_ADSTART)
;
return adc->DR;
return VNA_ADC->DR;
}
int16_t adc_vbat_read(ADC_TypeDef *adc)
int16_t adc_vbat_read(void)
{
// 13.9 Temperature sensor and internal reference voltage
// VREFINT_CAL calibrated on 3.3V, need get value in mV
#define ADC_FULL_SCALE 3300
#define VBAT_DIODE_VF 500
#define VREFINT_CAL (*((uint16_t*)0x1FFFF7BA))
float vbat = 0;
float vrefint = 0;
adc_stop();
ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_VBATEN;
// VREFINT == ADC_IN17
vrefint = adc_single_read(adc, ADC_CHSELR_CHSEL17);
uint32_t vrefint = adc_single_read(ADC_CHSELR_CHSEL17);
// VBAT == ADC_IN18
// VBATEN enables resiter devider circuit. It consume vbat power.
vbat = adc_single_read(adc, ADC_CHSELR_CHSEL18);
uint32_t vbat = adc_single_read(ADC_CHSELR_CHSEL18);
ADC->CCR &= ~(ADC_CCR_VREFEN | ADC_CCR_VBATEN);
uint16_t vbat_raw = (ADC_FULL_SCALE * VREFINT_CAL * vbat * 2 / (vrefint * ((1<<12)-1)));
touch_start_watchdog();
// vbat_raw = (3300 * 2 * vbat / 4095) * (VREFINT_CAL / vrefint)
// uint16_t vbat_raw = (ADC_FULL_SCALE * VREFINT_CAL * (float)vbat * 2 / (vrefint * ((1<<12)-1)));
// For speed divide not on 4095, divide on 4096, get little error, but no matter
uint16_t vbat_raw = ((ADC_FULL_SCALE * 2 * vbat)>>12) * VREFINT_CAL / vrefint;
if (vbat_raw < 100) {
// maybe D2 is not installed
return -1;
}
return vbat_raw + VBAT_DIODE_VF;
return vbat_raw + config.vbat_offset;
}
void adc_start_analog_watchdogd(ADC_TypeDef *adc, uint32_t chsel)
void adc_start_analog_watchdogd(uint32_t chsel)
{
uint32_t cfgr1;
@ -111,38 +113,38 @@ void adc_start_analog_watchdogd(ADC_TypeDef *adc, uint32_t chsel)
/* ADC setup, if it is defined a callback for the analog watch dog then it
is enabled.*/
adc->ISR = adc->ISR;
adc->IER = ADC_IER_AWDIE;
adc->TR = ADC_TR(0, TOUCH_THRESHOLD);
adc->SMPR = ADC_SMPR_SMP_1P5;
adc->CHSELR = chsel;
VNA_ADC->ISR = VNA_ADC->ISR;
VNA_ADC->IER = ADC_IER_AWDIE;
VNA_ADC->TR = ADC_TR(0, TOUCH_THRESHOLD);
VNA_ADC->SMPR = ADC_SMPR_SMP_1P5;
VNA_ADC->CHSELR = chsel;
/* ADC configuration and start.*/
adc->CFGR1 = cfgr1;
VNA_ADC->CFGR1 = cfgr1;
/* ADC conversion start.*/
adc->CR |= ADC_CR_ADSTART;
VNA_ADC->CR |= ADC_CR_ADSTART;
}
void adc_stop(ADC_TypeDef *adc)
void adc_stop(void)
{
if (adc->CR & ADC_CR_ADEN) {
if (adc->CR & ADC_CR_ADSTART) {
adc->CR |= ADC_CR_ADSTP;
while (adc->CR & ADC_CR_ADSTP)
if (VNA_ADC->CR & ADC_CR_ADEN) {
if (VNA_ADC->CR & ADC_CR_ADSTART) {
VNA_ADC->CR |= ADC_CR_ADSTP;
while (VNA_ADC->CR & ADC_CR_ADSTP)
;
}
/* adc->CR |= ADC_CR_ADDIS;
while (adc->CR & ADC_CR_ADDIS)
/* VNA_ADC->CR |= ADC_CR_ADDIS;
while (VNA_ADC->CR & ADC_CR_ADDIS)
;*/
}
}
void adc_interrupt(ADC_TypeDef *adc)
void adc_interrupt(void)
{
uint32_t isr = adc->ISR;
adc->ISR = isr;
uint32_t isr = VNA_ADC->ISR;
VNA_ADC->ISR = isr;
if (isr & ADC_ISR_OVR) {
/* ADC overflow condition, this could happen only if the DMA is unable
@ -159,7 +161,7 @@ OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER)
{
OSAL_IRQ_PROLOGUE();
adc_interrupt(ADC1);
adc_interrupt();
OSAL_IRQ_EPILOGUE();
}

View file

@ -156,7 +156,7 @@
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_WAITEXIT TRUE
#define CH_CFG_USE_WAITEXIT FALSE
/**
* @brief Semaphores APIs.
@ -183,7 +183,7 @@
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_MUTEXES TRUE
#define CH_CFG_USE_MUTEXES FALSE
/**
* @brief Enables recursive behavior on mutexes.
@ -193,7 +193,7 @@
* @note The default is @p FALSE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#define CH_CFG_USE_MUTEXES_RECURSIVE TRUE
#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
/**
* @brief Conditional Variables APIs.
@ -221,7 +221,7 @@
*
* @note The default is @p TRUE.
*/
#define CH_CFG_USE_EVENTS TRUE
#define CH_CFG_USE_EVENTS FALSE
/**
* @brief Events Flags APIs with timeout.
@ -231,7 +231,7 @@
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_EVENTS.
*/
#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
#define CH_CFG_USE_EVENTS_TIMEOUT FALSE
/**
* @brief Synchronous Messages APIs.

View file

@ -29,13 +29,16 @@
#include "hal.h"
#include "chprintf.h"
#include "memstreams.h"
//#include "memstreams.h"
#include <math.h>
// Enable [flags], support:
// ' ' Prepends a space for positive signed-numeric types. positive = ' ', negative = '-'. This flag is ignored if the + flag exists.
//#define CHPRINTF_USE_SPACE_FLAG
// Force putting trailing zeros on float value
#define CHPRINTF_FORCE_TRAILING_ZEROS
#define MAX_FILLER 11
#define FLOAT_PRECISION 9
@ -53,7 +56,6 @@ static char smallPrefix[]= { 'm', 0x1d, 'n', 'p', 'f', 'a', 'z', 'y',
#pragma pack(pop)
//86066 5116 11456 102622 190de build/ch.elf
static char *long_to_string_with_divisor(char *p,
uint32_t num,
uint32_t radix,
@ -81,7 +83,9 @@ static char *long_to_string_with_divisor(char *p,
#define FREQ_NO_SPACE 2
#define FREQ_PREFIX_SPACE 4
static char *ulong_freq(char *p, uint32_t freq, uint32_t precision){
static char *
ulong_freq(char *p, uint32_t freq, uint32_t precision)
{
uint8_t flag = FREQ_PSET;
if (precision == 0)
flag|=FREQ_PREFIX_SPACE;
@ -106,16 +110,22 @@ static char *ulong_freq(char *p, uint32_t freq, uint32_t precision){
freq += freq >> 1;
freq += freq >> 4;
freq += freq >> 8;
freq+=freq>>16; // freq = 858993459*freq/1073741824 = freq * 0,799999999813735485076904296875
freq += freq >> 16; // freq = 858993459*freq/1073741824 = freq *
// 0,799999999813735485076904296875
freq >>= 3; // freq/=8; freq = freq * 0,09999999997671693563461303710938
c -= freq * 10; // freq*10 = (freq*4+freq)*2 = ((freq<<2)+freq)<<1
while (c>=10) {freq++;c-=10;}
while (c >= 10) {
freq++;
c -= 10;
}
#endif
*--q = c + '0';
if (freq==0)
break;
if (freq == 0) break;
// Add spaces, calculate prefix
if (format&1) {*--q = ' '; s++;}
if (format & 1) {
*--q = ' ';
s++;
}
format >>= 1;
} while (1);
s = bigPrefix[s];
@ -136,8 +146,7 @@ static char *ulong_freq(char *p, uint32_t freq, uint32_t precision){
if (flag & FREQ_PSET) {
c = '.';
flag &= ~FREQ_PSET;
}
else if (flag&FREQ_NO_SPACE)
} else if (flag & FREQ_NO_SPACE)
c = *q++;
}
*p++ = c;
@ -161,12 +170,14 @@ static char *ftoa(char *p, float num, uint32_t precision) {
// Fix rounding error if get
if (k>=multi){k-=multi;l++;}
p = long_to_string_with_divisor(p, l, 10, 0);
if (precision && k){
if (precision) {
*p++ = '.';
p=long_to_string_with_divisor(p, k, 10, precision);
#ifndef CHPRINTF_FORCE_TRAILING_ZEROS
// remove zeros at end
while (p[-1]=='0') p--;
if (p[-1]=='.') p--;
#endif
}
return p;
}
@ -462,6 +473,7 @@ unsigned_common:/*
*
* @api
*/
#if 0
int chprintf(BaseSequentialStream *chp, const char *fmt, ...) {
va_list ap;
int formatted_bytes;
@ -472,7 +484,7 @@ int chprintf(BaseSequentialStream *chp, const char *fmt, ...) {
return formatted_bytes;
}
#endif
/**
* @brief System formatted output function.
* @details This function implements a minimal @p vprintf()-like functionality
@ -501,6 +513,7 @@ int chprintf(BaseSequentialStream *chp, const char *fmt, ...) {
*
* @api
*/
#if 0
int chsnprintf(char *str, size_t size, const char *fmt, ...) {
va_list ap;
MemoryStream ms;
@ -530,5 +543,52 @@ int chsnprintf(char *str, size_t size, const char *fmt, ...) {
/* Return number of bytes that would have been written.*/
return retval;
}
#endif
//
// Small memory stream object, only put function
//
struct printStreamVMT {
_base_sequential_stream_methods
};
typedef struct {
const struct printStreamVMT *vmt;
uint8_t *buffer;
uint16_t size;
} printStream;
static msg_t put(void *ip, uint8_t b) {
printStream *ps = ip;
if (ps->size > 1){
*(ps->buffer++) = b;
ps->size--;
}
return MSG_OK;
}
static const struct printStreamVMT vmt = {NULL, NULL, put, NULL};
void printObjectInit(printStream *ps, int size, uint8_t *buffer){
ps->vmt = &vmt;
ps->buffer = buffer;
ps->size = size;
}
// Simple print in buffer function
int plot_printf(char *str, int size, const char *fmt, ...) {
va_list ap;
printStream ps;
int retval;
if (size <= 0) return 0;
// Init small memory stream for print
printObjectInit(&ps, size, (uint8_t *)str);
// Performing the print operation using the common code.
va_start(ap, fmt);
retval = chvprintf((BaseSequentialStream *)(void *)&ps, fmt, ap);
va_end(ap);
*(ps.buffer)=0;
if (retval > size-1) retval = size-1;
// Return number of bytes that would have been written.
return retval;
}
/** @} */

16
dsp.c
View file

@ -41,10 +41,10 @@ const int16_t sincos_tbl[48][2] = {
{-24636, -21605 }, {-32698, -2143 }, {-27246, 18205 }, {-10533, 31029 }
};
int32_t acc_samp_s;
int32_t acc_samp_c;
int32_t acc_ref_s;
int32_t acc_ref_c;
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)
@ -79,10 +79,10 @@ dsp_process(int16_t *capture, size_t length)
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;
acc_samp_s += samp_s;
acc_samp_c += samp_c;
acc_ref_s += ref_s;
acc_ref_c += ref_c;
}
void

4
fft.h
View file

@ -68,8 +68,8 @@ static void fft256(float array[][2], const uint8_t dir) {
uint16_t j, k;
for (j = i, k = 0; j < i + halfsize; j++, k += tablestep) {
uint16_t l = j + halfsize;
float tpre = array[l][real] * cos(2 * M_PI * k / 256) + array[l][imag] * sin(2 * M_PI * k / 256);
float tpim = -array[l][real] * sin(2 * M_PI * k / 256) + array[l][imag] * cos(2 * M_PI * k / 256);
float tpre = array[l][real] * cos(2 * VNA_PI * k / 256) + array[l][imag] * sin(2 * VNA_PI * k / 256);
float tpim = -array[l][real] * sin(2 * VNA_PI * k / 256) + array[l][imag] * cos(2 * VNA_PI * k / 256);
array[l][real] = array[j][real] - tpre;
array[l][imag] = array[j][imag] - tpim;
array[j][real] += tpre;

32
flash.c
View file

@ -64,8 +64,6 @@ void flash_unlock(void)
FLASH->KEYR = 0xCDEF89AB;
}
#define rotate(x) (((x)<<1) | ((x)&(1<<31)?1:0))
static uint32_t
checksum(const void *start, size_t len)
{
@ -73,14 +71,14 @@ checksum(const void *start, size_t len)
uint32_t *tail = (uint32_t*)(start + len);
uint32_t value = 0;
while (p < tail)
value = rotate(value) + *p++;
value = __ROR(value, 31) + *p++;
return value;
}
#define FLASH_PAGESIZE 0x800
const uint32_t save_config_area = 0x08018000;
const uint32_t save_config_area = SAVE_CONFIG_ADDR;
int
config_save(void)
@ -122,14 +120,15 @@ config_recall(void)
return 0;
}
#define SAVEAREA_MAX 5
const uint32_t saveareas[] =
{ 0x08018800, 0x0801a000, 0x0801b800, 0x0801d000, 0x0801e800 };
const uint32_t saveareas[SAVEAREA_MAX] = {
SAVE_PROP_CONFIG_0_ADDR,
SAVE_PROP_CONFIG_1_ADDR,
SAVE_PROP_CONFIG_2_ADDR,
SAVE_PROP_CONFIG_3_ADDR,
SAVE_PROP_CONFIG_4_ADDR };
int16_t lastsaveid = 0;
int
caldata_save(int id)
{
@ -142,7 +141,8 @@ caldata_save(int id)
dst = (uint16_t*)saveareas[id];
current_props.magic = CONFIG_MAGIC;
current_props.checksum = checksum(&current_props, sizeof current_props - sizeof current_props.checksum);
current_props.checksum = checksum(
&current_props, sizeof current_props - sizeof current_props.checksum);
flash_unlock();
@ -174,15 +174,15 @@ caldata_recall(int id)
void *dst = &current_props;
if (id < 0 || id >= SAVEAREA_MAX)
return -1;
goto load_default;
// point to saved area on the flash memory
src = (properties_t*)saveareas[id];
if (src->magic != CONFIG_MAGIC)
return -1;
goto load_default;
if (checksum(src, sizeof *src - sizeof src->checksum) != src->checksum)
return -1;
goto load_default;
/* active configuration points to save data on flash memory */
active_props = src;
@ -190,8 +190,10 @@ caldata_recall(int id)
/* duplicated saved data onto sram to be able to modify marker/trace */
memcpy(dst, src, sizeof(properties_t));
return 0;
load_default:
load_default_properties();
return -1;
}
const properties_t *
@ -209,7 +211,7 @@ caldata_ref(int id)
return src;
}
const uint32_t save_config_prop_area_size = 0x8000;
const uint32_t save_config_prop_area_size = SAVE_CONFIG_AREA_SIZE;
void
clear_all_config_prop_data(void)

View file

@ -118,7 +118,7 @@
* @brief Enables the RTC subsystem.
*/
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC TRUE
#define HAL_USE_RTC FALSE
#endif
/**

105
ili9341.c
View file

@ -21,10 +21,10 @@
#include "hal.h"
#include "nanovna.h"
uint16_t spi_buffer[2048];
uint16_t spi_buffer[SPI_BUFFER_SIZE];
// Default foreground & background colors
uint16_t foreground_color=DEFAULT_FG_COLOR;
uint16_t background_color=DEFAULT_BG_COLOR;
uint16_t foreground_color = 0;
uint16_t background_color = 0;
// Display width and height definition
#define ILI9341_WIDTH 320
@ -129,7 +129,8 @@ uint16_t background_color=DEFAULT_BG_COLOR;
#define DISPLAY_ROTATION_270 (ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR)
#define DISPLAY_ROTATION_90 (ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR)
#define DISPLAY_ROTATION_0 (ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR)
#define DISPLAY_ROTATION_180 (ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR)
#define DISPLAY_ROTATION_180 (ILI9341_MADCTL_MX | ILI9341_MADCTL_MY \
| ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR)
//
// Pin macros
@ -179,14 +180,17 @@ uint16_t background_color=DEFAULT_BG_COLOR;
#define SPI_READ_DATA SPI1->DR
#ifdef __USE_DISPLAY_DMA__
static const stm32_dma_stream_t *dmatx = STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM);
static uint32_t txdmamode = STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) // Select SPI1 Tx DMA
static const stm32_dma_stream_t *dmatx =
STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM);
static uint32_t txdmamode =
STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) // Select SPI1 Tx DMA
| STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) // Set priority
| STM32_DMA_CR_DIR_M2P // Memory to Spi
| STM32_DMA_CR_DMEIE //
| STM32_DMA_CR_TEIE;
static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) {
static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags)
{
(void)spip;
(void)flags;
}
@ -199,12 +203,14 @@ static uint32_t rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_CHANNEL)
| STM32_DMA_CR_DMEIE
| STM32_DMA_CR_TEIE;
static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) {
static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags)
{
(void)spip;
(void)flags;
}
static void dmaStreamFlush(uint32_t len){
static void dmaStreamFlush(uint32_t len)
{
while (len) {
// DMA data transfer limited by 65535
uint16_t tx_size = len > 65535 ? 65535 : len;
@ -251,11 +257,13 @@ static void __attribute__ ((noinline)) send_command(uint8_t cmd, uint8_t len, co
DC_CMD;
SPI_WRITE_8BIT(cmd);
// Need wait transfer complete and set data bit
while (SPI_IS_BUSY);
while (SPI_IS_BUSY)
;
// Send command data (if need)
DC_DATA;
while (len-- > 0) {
while (SPI_TX_IS_NOT_EMPTY);
while (SPI_TX_IS_NOT_EMPTY)
;
SPI_WRITE_8BIT(*data++);
}
//CS_HIGH;
@ -352,7 +360,8 @@ void ili9341_fill(int x, int y, int w, int h, int color)
send_command(ILI9341_MEMORY_WRITE, 0, NULL);
int32_t len = w * h;
while (len-- > 0) {
while (SPI_TX_IS_NOT_EMPTY);
while (SPI_TX_IS_NOT_EMPTY)
;
SPI_WRITE_16BIT(color);
}
}
@ -369,7 +378,8 @@ void ili9341_bulk(int x, int y, int w, int h)
send_command(ILI9341_MEMORY_WRITE, 0, NULL);
int32_t len = w * h;
while (len-- > 0) {
while (SPI_TX_IS_NOT_EMPTY);
while (SPI_TX_IS_NOT_EMPTY)
;
SPI_WRITE_16BIT(*buf++);
}
}
@ -425,6 +435,25 @@ void ili9341_fill(int x, int y, int w, int h, int color)
dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD);
dmaStreamFlush(w * h);
}
void ili9341_bulk_8bit(int x, int y, int w, int h, uint16_t *palette)
{
uint32_t xx = __REV16(x | ((x + w - 1) << 16));
uint32_t yy = __REV16(y | ((y + h - 1) << 16));
send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx);
send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t *)&yy);
send_command(ILI9341_MEMORY_WRITE, 0, NULL);
uint8_t *buf = (uint8_t *)spi_buffer;
int32_t len = w * h;
while (len-- > 0) {
uint16_t color = palette[*buf++];
while (SPI_TX_IS_NOT_EMPTY)
;
SPI_WRITE_16BIT(color);
}
}
// Copy spi_buffer to region
void ili9341_bulk(int x, int y, int w, int h)
{
@ -436,7 +465,8 @@ void ili9341_bulk(int x, int y, int w, int h)
// Init Tx DMA mem->spi, set size, mode (spi and mem data size is 16 bit)
dmaStreamSetMemory0(dmatx, spi_buffer);
dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_MINC);
dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD |
STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_MINC);
dmaStreamFlush(w * h);
}
@ -453,12 +483,12 @@ void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out)
send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t *)&yy);
send_command(ILI9341_MEMORY_READ, 0, NULL);
// Skip SPI rx buffer
while (SPI_RX_IS_NOT_EMPTY)
(void) SPI_READ_DATA;
while (SPI_RX_IS_NOT_EMPTY) (void)SPI_READ_DATA;
// Init Rx DMA buffer, size, mode (spi and mem data size is 8 bit)
dmaStreamSetMemory0(dmarx, rgbbuf);
dmaStreamSetTransactionSize(dmarx, data_size);
dmaStreamSetMode(dmarx, rxdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_MINC);
dmaStreamSetMode(dmarx, rxdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
STM32_DMA_CR_MINC);
// Init dummy Tx DMA (for rx clock), size, mode (spi and mem data size is 8 bit)
dmaStreamSetMemory0(dmatx, &dummy_tx);
dmaStreamSetTransactionSize(dmatx, data_size);
@ -487,15 +517,31 @@ void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out)
}
#endif
void setForegroundColor(uint16_t fg) {foreground_color = fg;}
void setBackgroundColor(uint16_t bg) {background_color = bg;}
void ili9341_clear_screen(void)
{
ili9341_fill(0, 0, ILI9341_WIDTH, ILI9341_HEIGHT, background_color);
}
void ili9341_setRotation(uint8_t r) {
// static const uint8_t rotation_const[]={DISPLAY_ROTATION_0, DISPLAY_ROTATION_90, DISPLAY_ROTATION_180, DISPLAY_ROTATION_270};
void ili9341_set_foreground(uint16_t fg)
{
foreground_color = fg;
}
void ili9341_set_background(uint16_t bg)
{
background_color = bg;
}
void ili9341_set_rotation(uint8_t r)
{
// static const uint8_t rotation_const[]={DISPLAY_ROTATION_0, DISPLAY_ROTATION_90,
// DISPLAY_ROTATION_180, DISPLAY_ROTATION_270};
send_command(ILI9341_MEMORY_ACCESS_CONTROL, 1, &r);
}
void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *bitmap){
void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
const uint8_t *bitmap)
{
uint16_t *buf = spi_buffer;
for (uint16_t c = 0; c < height; c++) {
uint8_t bits = *bitmap++;
@ -507,7 +553,9 @@ void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height
ili9341_bulk(x, y, width, height);
}
void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *bitmap){
static void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
const uint16_t *bitmap)
{
uint16_t *buf = spi_buffer;
for (uint16_t c = 0; c < height; c++) {
uint16_t bits = *bitmap++;
@ -535,10 +583,11 @@ void ili9341_drawstring(const char *str, int x, int y)
}
}
void ili9341_drawstringV(const char *str, int x, int y){
ili9341_setRotation(DISPLAY_ROTATION_270);
void ili9341_drawstringV(const char *str, int x, int y)
{
ili9341_set_rotation(DISPLAY_ROTATION_270);
ili9341_drawstring(str, ILI9341_HEIGHT-y, x);
ili9341_setRotation(DISPLAY_ROTATION_0);
ili9341_set_rotation(DISPLAY_ROTATION_0);
}
int ili9341_drawchar_size(uint8_t ch, int x, int y, uint8_t size)
@ -560,7 +609,8 @@ int ili9341_drawchar_size(uint8_t ch, int x, int y, uint8_t size)
void ili9341_drawfont(uint8_t ch, int x, int y)
{
blit16BitWidthBitmap(x, y, NUM_FONT_GET_WIDTH, NUM_FONT_GET_HEIGHT, NUM_FONT_GET_DATA(ch));
blit16BitWidthBitmap(x, y, NUM_FONT_GET_WIDTH, NUM_FONT_GET_HEIGHT,
NUM_FONT_GET_DATA(ch));
}
void ili9341_drawstring_size(const char *str, int x, int y, uint8_t size)
@ -580,6 +630,7 @@ static void ili9341_pixel(int x, int y, uint16_t color)
#endif
#define SWAP(x, y) { int z = x; x = y; y = z; }
void ili9341_line(int x0, int y0, int x1, int y1)
{
#if 0

1454
main.c

File diff suppressed because it is too large Load diff

View file

@ -58,7 +58,8 @@
#define STM32_ADCSW STM32_ADCSW_HSI14
#define STM32_USBSW STM32_USBSW_HSI48
#define STM32_CECSW STM32_CECSW_HSI
#define STM32_I2C1SW STM32_I2C1SW_HSI
//#define STM32_I2C1SW STM32_I2C1SW_HSI
#define STM32_I2C1SW STM32_I2C1SW_SYSCLK
#define STM32_USART1SW STM32_USART1SW_PCLK
#define STM32_RTCSEL STM32_RTCSEL_LSI

150
nanovna.h
View file

@ -26,6 +26,17 @@
* main.c
*/
// Minimum frequency set
#define START_MIN 50000
// Maximum frequency set
#define STOP_MAX 2700000000U
// Frequency offset (sin_cos table in dsp.c generated for this offset, if change need create new table)
#define FREQUENCY_OFFSET 5000
// Speed of light const
#define SPEED_OF_LIGHT 299792458
// pi const
#define VNA_PI 3.14159265358979323846
#define POINTS_COUNT 101
extern float measured[2][POINTS_COUNT][2];
@ -71,8 +82,9 @@ extern float measured[2][POINTS_COUNT][2];
void cal_collect(int type);
void cal_done(void);
enum {
ST_START, ST_STOP, ST_CENTER, ST_SPAN, ST_CW
#define MAX_FREQ_TYPE 5
enum stimulus_type {
ST_START=0, ST_STOP, ST_CENTER, ST_SPAN, ST_CW
};
void set_sweep_frequency(int type, uint32_t frequency);
@ -81,17 +93,12 @@ uint32_t get_sweep_frequency(int type);
double my_atof(const char *p);
void toggle_sweep(void);
void load_default_properties(void);
extern int8_t sweep_enabled;
/*
* ui.c
*/
extern void ui_init(void);
extern void ui_process(void);
enum { OP_NONE = 0, OP_LEVER, OP_TOUCH, OP_FREQCHANGE };
extern uint8_t operation_requested;
#define SWEEP_ENABLE 0x01
#define SWEEP_ONCE 0x02
extern int8_t sweep_mode;
extern const char *info_about[];
/*
* dsp.c
@ -115,9 +122,6 @@ void calculate_gamma(float *gamma);
void fetch_amplitude(float *gamma);
void fetch_amplitude_ref(float *gamma);
int si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength);
/*
* tlv320aic3204.c
*/
@ -144,7 +148,7 @@ extern void tlv320aic3204_select(int channel);
#define FREQUENCIES_XPOS1 OFFSETX
#define FREQUENCIES_XPOS2 200
#define FREQUENCIES_YPOS (HEIGHT+1)
#define FREQUENCIES_YPOS (240-7)
// GRIDX calculated depends from frequency span
//#define GRIDY 29
@ -167,6 +171,7 @@ extern int16_t area_height;
extern const uint8_t x5x7_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
#define FONT_GET_HEIGHT 7
extern const uint16_t numfont16x22[];
@ -187,11 +192,12 @@ extern const uint16_t numfont16x22[];
#define TRACES_MAX 4
enum {
TRC_LOGMAG, TRC_PHASE, TRC_DELAY, TRC_SMITH, TRC_POLAR, TRC_LINEAR, TRC_SWR, TRC_REAL, TRC_IMAG, TRC_R, TRC_X, TRC_OFF
#define MAX_TRACE_TYPE 12
enum trace_type {
TRC_LOGMAG=0, TRC_PHASE, TRC_DELAY, TRC_SMITH, TRC_POLAR, TRC_LINEAR, TRC_SWR, TRC_REAL, TRC_IMAG, TRC_R, TRC_X, TRC_Q, TRC_OFF
};
// Mask for define rectangular plot
#define RECTANGULAR_GRID_MASK ((1<<TRC_LOGMAG)|(1<<TRC_PHASE)|(1<<TRC_DELAY)|(1<<TRC_LINEAR)|(1<<TRC_SWR)|(1<<TRC_REAL)|(1<<TRC_IMAG)|(1<<TRC_R)|(1<<TRC_X))
#define RECTANGULAR_GRID_MASK ((1<<TRC_LOGMAG)|(1<<TRC_PHASE)|(1<<TRC_DELAY)|(1<<TRC_LINEAR)|(1<<TRC_SWR)|(1<<TRC_REAL)|(1<<TRC_IMAG)|(1<<TRC_R)|(1<<TRC_X)|(1<<TRC_Q))
// LOGMAG: SCALE, REFPOS, REFVAL
// PHASE: SCALE, REFPOS, REFVAL
@ -203,7 +209,7 @@ enum {
// Electrical Delay
// Phase
typedef struct {
typedef struct trace {
uint8_t enabled;
uint8_t type;
uint8_t channel;
@ -212,7 +218,11 @@ typedef struct {
float refpos;
} trace_t;
typedef struct {
#define FREQ_MODE_START_STOP 0x0
#define FREQ_MODE_CENTER_SPAN 0x1
#define FREQ_MODE_DOTTED_GRID 0x2
typedef struct config {
int32_t magic;
uint16_t dac_value;
uint16_t grid_color;
@ -220,17 +230,14 @@ typedef struct {
uint16_t menu_active_color;
uint16_t trace_color[TRACES_MAX];
int16_t touch_cal[4];
int8_t default_loadcal;
uint32_t harmonic_freq_threshold;
uint8_t _reserved[24];
uint16_t vbat_offset;
uint8_t _reserved[22];
uint32_t checksum;
} config_t;
extern config_t config;
//extern trace_t trace[TRACES_MAX];
void set_trace_type(int t, int type);
void set_trace_channel(int t, int channel);
void set_trace_scale(int t, float scale);
@ -238,7 +245,6 @@ 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);
void draw_battery_status(void);
void set_electrical_delay(float picoseconds);
float get_electrical_delay(void);
@ -248,7 +254,7 @@ float groupdelay_from_array(int i, float array[POINTS_COUNT][2]);
#define MARKERS_MAX 4
typedef struct {
typedef struct marker {
int8_t enabled;
int16_t index;
uint32_t frequency;
@ -264,7 +270,7 @@ void redraw_frame(void);
//void redraw_all(void);
void request_to_draw_cells_behind_menu(void);
void request_to_draw_cells_behind_numeric_input(void);
void redraw_marker(int marker, int update_info);
void redraw_marker(int marker);
void plot_into_index(float measured[2][POINTS_COUNT][2]);
void force_set_markmap(void);
void draw_frequencies(void);
@ -281,14 +287,14 @@ int marker_search(void);
int marker_search_left(int from);
int marker_search_right(int from);
extern uint16_t redraw_request;
// _request flag for update screen
#define REDRAW_CELLS (1<<0)
#define REDRAW_FREQUENCY (1<<1)
#define REDRAW_CAL_STATUS (1<<2)
#define REDRAW_MARKER (1<<3)
extern int16_t vbat;
#define REDRAW_BATTERY (1<<4)
#define REDRAW_AREA (1<<5)
extern volatile uint8_t redraw_request;
/*
* ili9341.c
@ -298,6 +304,9 @@ extern int16_t vbat;
#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 DEFAULT_FG_COLOR RGB565(255,255,255)
#define DEFAULT_BG_COLOR RGB565( 0, 0, 0)
#define DEFAULT_GRID_COLOR RGB565(128,128,128)
@ -315,17 +324,16 @@ extern int16_t vbat;
extern uint16_t foreground_color;
extern uint16_t background_color;
extern uint16_t spi_buffer[2048];
extern uint16_t spi_buffer[SPI_BUFFER_SIZE];
void ili9341_init(void);
//void ili9341_setRotation(uint8_t r);
void ili9341_test(int mode);
void ili9341_bulk(int x, int y, int w, int h);
void ili9341_fill(int x, int y, int w, int h, int color);
void setForegroundColor(uint16_t fg);
void setBackgroundColor(uint16_t fg);
void ili9341_set_foreground(uint16_t fg);
void ili9341_set_background(uint16_t fg);
void ili9341_clear_screen(void);
void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *bitmap);
void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *bitmap);
void ili9341_drawchar(uint8_t ch, int x, int y);
void ili9341_drawstring(const char *str, int x, int y);
void ili9341_drawstringV(const char *str, int x, int y);
@ -341,8 +349,18 @@ void show_logo(void);
* flash.c
*/
#define SAVEAREA_MAX 5
// Begin addr 0x08018000
#define SAVE_CONFIG_AREA_SIZE 0x00008000
// config save area
#define SAVE_CONFIG_ADDR 0x08018000
// properties_t save area
#define SAVE_PROP_CONFIG_0_ADDR 0x08018800
#define SAVE_PROP_CONFIG_1_ADDR 0x0801a000
#define SAVE_PROP_CONFIG_2_ADDR 0x0801b800
#define SAVE_PROP_CONFIG_3_ADDR 0x0801d000
#define SAVE_PROP_CONFIG_4_ADDR 0x0801e800
typedef struct {
typedef struct properties {
uint32_t magic;
uint32_t _frequency0;
uint32_t _frequency1;
@ -360,7 +378,9 @@ typedef struct {
int8_t _active_marker;
uint8_t _domain_mode; /* 0bxxxxxffm : where ff: TD_FUNC m: DOMAIN_MODE */
uint8_t _marker_smith_format;
uint8_t _reserved[50];
uint8_t _bandwidth;
int8_t _freq_mode;
uint8_t _reserved[49];
uint32_t checksum;
} properties_t;
@ -386,14 +406,12 @@ extern properties_t current_props;
#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
#define freq_mode current_props._freq_mode
#define FREQ_IS_STARTSTOP() (frequency0 < frequency1)
#define FREQ_IS_CENTERSPAN() (frequency0 > frequency1)
#define FREQ_IS_STARTSTOP() (!(freq_mode & FREQ_MODE_CENTER_SPAN))
#define FREQ_IS_CENTERSPAN() (freq_mode & FREQ_MODE_CENTER_SPAN)
#define FREQ_IS_CW() (frequency0 == frequency1)
#define FREQ_START() (frequency0)
#define FREQ_STOP() (frequency1)
#define FREQ_CENTER() (frequency0/2 + frequency1/2)
#define FREQ_SPAN() (frequency0 - frequency1)
int caldata_save(int id);
int caldata_recall(int id);
@ -407,29 +425,38 @@ void clear_all_config_prop_data(void);
/*
* ui.c
*/
extern void ui_init(void);
extern void ui_process(void);
// Irq operation process set
#define OP_NONE 0x00
#define OP_LEVER 0x01
#define OP_TOUCH 0x02
//#define OP_FREQCHANGE 0x04
extern volatile uint8_t operation_requested;
// lever_mode
enum {
LM_MARKER, LM_SEARCH, LM_CENTER, LM_SPAN
enum lever_mode {
LM_MARKER, LM_SEARCH, LM_CENTER, LM_SPAN, LM_EDELAY
};
// marker smith value format
enum {
enum marker_smithvalue {
MS_LIN, MS_LOG, MS_REIM, MS_RX, MS_RLC
};
typedef struct {
typedef struct uistat {
int8_t digit; /* 0~5 */
int8_t digit_mode;
int8_t current_trace; /* 0..3 */
uint32_t value; // for editing at numeric input area
uint32_t previous_value;
// uint32_t previous_value;
uint8_t lever_mode;
bool marker_delta;
uint8_t marker_delta;
uint8_t marker_tracking;
} uistat_t;
extern uistat_t uistat;
void ui_init(void);
void ui_show(void);
void ui_hide(void);
@ -449,15 +476,22 @@ void enter_dfu(void);
*/
void adc_init(void);
uint16_t adc_single_read(ADC_TypeDef *adc, uint32_t chsel);
void adc_start_analog_watchdogd(ADC_TypeDef *adc, uint32_t chsel);
void adc_stop(ADC_TypeDef *adc);
void adc_interrupt(ADC_TypeDef *adc);
int16_t adc_vbat_read(ADC_TypeDef *adc);
uint16_t adc_single_read(uint32_t chsel);
void adc_start_analog_watchdogd(uint32_t chsel);
void adc_stop(void);
void adc_interrupt(void);
int16_t adc_vbat_read(void);
/*
* misclinous
*/
int plot_printf(char *str, int, const char *fmt, ...);
#define PULSE do { palClearPad(GPIOC, GPIOC_LED); palSetPad(GPIOC, GPIOC_LED);} while(0)
// Speed profile definition
#define START_PROFILE systime_t time = chVTGetSystemTimeX();
#define STOP_PROFILE {char string_buf[12];plot_printf(string_buf, sizeof string_buf, "T:%06d", chVTGetSystemTimeX() - time);ili9341_drawstringV(string_buf, 1, 60);}
// Macros for convert define value to string
#define STR1(x) #x
#define define_to_STR(x) STR1(x)
/*EOF*/

View file

@ -98,8 +98,8 @@ const uint16_t numfont16x22[] = {
0b0111111111111110,
0b0111110000111110,
0b1111100000011111,
0b1111000000011111,
0b1111000000011111,
0b1111000000001111,
0b1111000000001111,
0b0000000000011110,
0b0000000000111110,
0b0000000111111100,
@ -305,7 +305,7 @@ const uint16_t numfont16x22[] = {
0b0000000000001111,
0b0000000000011111,
0b0000000000111111,
0b0000000000111111,
0b0000000001111111,
0b0000000000001111,
0b0000000000001111,
0b0000000000001111,
@ -381,10 +381,10 @@ const uint16_t numfont16x22[] = {
0b1111000000000000,
0b1111000000000000,
0b1111000000000000,
0b1111000000000000,
0b1111000001111111,
0b1111000001111111,
0b1111000001111111,
0b1111000000111111,
0b1111000000111111,
0b1111000000111111,
0b1111000000000111,
0b1111000000001111,
0b1111100000011111,
0b0111110000111111,
@ -553,4 +553,3 @@ const uint16_t numfont16x22[] = {
0b1111000000000000,
0b1111000000000000,
};

789
plot.c

File diff suppressed because it is too large Load diff

592
si5351.c
View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com
* Modified by DiSlord dislordlive@gmail.com
* All rights reserved.
*
* This is free software; you can redistribute it and/or modify
@ -21,40 +22,100 @@
#include "nanovna.h"
#include "si5351.h"
#define SI5351_I2C_ADDR (0x60<<1)
// Enable cache for SI5351 CLKX_CONTROL register, little speedup exchange
#define USE_CLK_CONTROL_CACHE TRUE
static void
si5351_write(uint8_t reg, uint8_t dat)
// 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)
{
int addr = SI5351_I2C_ADDR>>1;
uint8_t buf[] = { reg, dat };
i2cAcquireBus(&I2CD1);
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, 2, NULL, 0, 1000);
i2cReleaseBus(&I2CD1);
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)
{
int addr = SI5351_I2C_ADDR>>1;
i2cAcquireBus(&I2CD1);
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000);
(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, &reg, 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_26_PLL_A, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
9, SI5351_REG_PLL_A, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
9, SI5351_REG_PLL_B, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
// RESET PLL
2, SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B,
2, SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B | 0x0C, //
// setup multisynth (832MHz / 104 = 8MHz, 104/2-2=50)
9, SI5351_REG_58_MULTISYNTH2, /*P3*/0, 1, /*P1*/0, 50, 0, /*P2|P3*/0, 0, 0,
2, SI5351_REG_18_CLK2_CONTROL, SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_INPUT_MULTISYNTH_N | SI5351_CLK_INTEGER_MODE,
2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0,
#endif
2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, ~(SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN),
0 // sentinel
};
@ -69,230 +130,211 @@ si5351_init(void)
}
}
void si5351_disable_output(void)
{
uint8_t reg[4];
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff);
reg[0] = SI5351_REG_16_CLK0_CONTROL;
reg[1] = SI5351_CLK_POWERDOWN;
reg[2] = SI5351_CLK_POWERDOWN;
reg[3] = SI5351_CLK_POWERDOWN;
si5351_bulk_write(reg, 4);
}
void si5351_enable_output(void)
{
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0x00);
}
void si5351_reset_pll(void)
{
//si5351_write(SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B);
si5351_write(SI5351_REG_177_PLL_RESET, 0xAC);
}
void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */
uint8_t mult,
uint32_t num,
uint32_t denom)
{
/* Get the appropriate starting point for the PLL registers */
const uint8_t pllreg_base[] = {
SI5351_REG_26_PLL_A,
SI5351_REG_34_PLL_B
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
};
uint32_t P1;
uint32_t P2;
uint32_t P3;
/* Feedback Multisynth Divider Equation
* where: a = mult, b = num and c = denom
* P1 register is an 18-bit value using following formula:
* P1[17:0] = 128 * mult + floor(128*(num/denom)) - 512
* P2 register is a 20-bit value using the following formula:
* P2[19:0] = 128 * num - denom * floor(128*(num/denom))
* P3 register is a 20-bit value using the following formula:
* P3[19:0] = denom
*/
/* Set the main PLL config registers */
if (num == 0)
{
/* Integer mode */
P1 = 128 * mult - 512;
P2 = 0;
P3 = 1;
}
else
{
/* Fractional mode */
//P1 = (uint32_t)(128 * mult + floor(128 * ((float)num/(float)denom)) - 512);
P1 = 128 * mult + ((128 * num) / denom) - 512;
//P2 = (uint32_t)(128 * num - denom * floor(128 * ((float)num/(float)denom)));
P2 = 128 * num - denom * ((128 * num) / denom);
P3 = denom;
}
/* The datasheet is a nightmare of typos and inconsistencies here! */
uint8_t reg[9];
reg[0] = pllreg_base[pll];
reg[1] = (P3 & 0x0000FF00) >> 8;
reg[2] = (P3 & 0x000000FF);
reg[3] = (P1 & 0x00030000) >> 16;
reg[4] = (P1 & 0x0000FF00) >> 8;
reg[5] = (P1 & 0x000000FF);
reg[6] = ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16);
reg[7] = (P2 & 0x0000FF00) >> 8;
reg[8] = (P2 & 0x000000FF);
si5351_bulk_write(reg, 9);
}
void
si5351_setupMultisynth(uint8_t output,
uint8_t pllSource,
uint32_t div, // 4,6,8, 8+ ~ 900
uint32_t num,
uint32_t denom,
uint32_t rdiv, // SI5351_R_DIV_1~128
uint8_t drive_strength)
{
/* Get the appropriate starting point for the PLL registers */
const uint8_t msreg_base[] = {
static const uint8_t msreg_base[] = {
SI5351_REG_42_MULTISYNTH0,
SI5351_REG_50_MULTISYNTH1,
SI5351_REG_58_MULTISYNTH2,
};
const uint8_t clkctrl[] = {
static const uint8_t clkctrl[] = {
SI5351_REG_16_CLK0_CONTROL,
SI5351_REG_17_CLK1_CONTROL,
SI5351_REG_18_CLK2_CONTROL
};
uint8_t dat;
uint32_t P1;
uint32_t P2;
uint32_t P3;
uint32_t div4 = 0;
// 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 + floor(128*(b/c)) - 512
* P1[17:0] = 128 * a + int((128*b)/c) - 512
* P2 register is a 20-bit value using the following formula:
* P2[19:0] = 128 * b - c * floor(128*(b/c))
* P2[19:0] = (128 * b) % c
* P3 register is a 20-bit value using the following formula:
* P3[19:0] = c
*/
/* Set the main PLL config registers */
if (div == 4) {
div4 = SI5351_DIVBY4;
P1 = P2 = 0;
P3 = 1;
} else if (num == 0) {
/* Integer mode */
P1 = 128 * div - 512;
P2 = 0;
P3 = 1;
} else {
/* Fractional mode */
P1 = 128 * div + ((128 * num) / denom) - 512;
P2 = 128 * num - denom * ((128 * num) / denom);
uint32_t P1 = 0;
uint32_t P2 = 0;
uint32_t P3 = 1;
if (div == 4)
rdiv|= SI5351_DIVBY4;
else {
num<<=7;
div<<=7;
P1 = div - 512; // Integer mode
if (num) { // Fractional mode
P1+= num / denom;
P2 = num % denom;
P3 = denom;
}
}
/* Set the MSx config registers */
uint8_t reg[9];
reg[0] = msreg_base[output];
reg[1] = (P3 & 0x0000FF00) >> 8;
reg[2] = (P3 & 0x000000FF);
reg[3] = ((P1 & 0x00030000) >> 16) | div4 | rdiv;
reg[4] = (P1 & 0x0000FF00) >> 8;
reg[5] = (P1 & 0x000000FF);
reg[6] = ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16);
reg[7] = (P2 & 0x0000FF00) >> 8;
reg[8] = (P2 & 0x000000FF);
reg[0] = msreg_base[channel]; // SI5351_REG_42_MULTISYNTH0, SI5351_REG_50_MULTISYNTH1, SI5351_REG_58_MULTISYNTH2
reg[1] = (P3 & 0x0FF00)>>8; // MSx_P3[15: 8]
reg[2] = (P3 & 0x000FF); // MSx_P3[ 7: 0]
reg[3] = ((P1 & 0x30000)>>16)| rdiv; // Rx_DIV[2:0] | MSx_DIVBY4[1:0] | MSx_P1[17:16]
reg[4] = (P1 & 0x0FF00)>> 8; // MSx_P1[15: 8]
reg[5] = (P1 & 0x000FF); // MSx_P1[ 7: 0]
reg[6] = ((P3 & 0xF0000)>>12)|((P2 & 0xF0000)>>16); // MSx_P3[19:16] | MSx_P2[19:16]
reg[7] = (P2 & 0x0FF00)>>8; // MSx_P2[15: 8]
reg[8] = (P2 & 0x000FF); // MSx_P2[ 7: 0]
si5351_bulk_write(reg, 9);
/* Configure the clk control and enable the output */
dat = drive_strength | SI5351_CLK_INPUT_MULTISYNTH_N;
if (pllSource == SI5351_PLL_B)
dat |= SI5351_CLK_PLL_SELECT_B;
uint8_t dat = chctrl | SI5351_CLK_INPUT_MULTISYNTH_N;
if (num == 0)
dat |= SI5351_CLK_INTEGER_MODE;
si5351_write(clkctrl[output], dat);
#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
}
#define XTALFREQ 26000000L
#define PLL_N 32
#define PLLFREQ (XTALFREQ * PLL_N)
void
si5351_set_frequency_fixedpll(int channel, int pll, uint32_t pllfreq, uint32_t freq,
int rdiv, uint8_t drive_strength, int mul)
// Find better approximate values for n/d
#define MAX_DENOMINATOR ((1 << 20) - 1)
static inline void approximate_fraction(uint32_t *n, uint32_t *d)
{
int denom = freq;
int div = (pllfreq * mul) / denom; // range: 8 ~ 1800
int num = (pllfreq * mul) - denom * div;
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
int max_denominator = (1 << 20) - 1;
if (denom > max_denominator) {
int p0 = 0, q0 = 1, p1 = 1, q1 = 0;
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) {
int a = num / denom;
int q2 = q0 + a*q1;
if (q2 > max_denominator)
uint32_t a = num / denom;
uint32_t b = num % denom;
uint32_t q2 = q0 + a*q1;
if (q2 > MAX_DENOMINATOR)
break;
int p2 = p0 + a*p1;
uint32_t p2 = p0 + a*p1;
p0 = p1; q0 = q1; p1 = p2; q1 = q2;
int new_denom = num - a * denom;
num = denom; denom = new_denom;
num = denom; denom = b;
}
*n = p1;
*d = q1;
}
num = p1;
denom = q1;
}
si5351_setupMultisynth(channel, pll, div, num, denom, rdiv, drive_strength);
}
void
si5351_set_frequency_fixeddiv(int channel, int pll, uint32_t freq, int div,
uint8_t drive_strength, int mul)
// Setup Multisynth divider for get correct output freq if fixed PLL = pllfreq
static void
si5351_set_frequency_fixedpll(uint8_t channel, uint64_t pllfreq, uint32_t freq, uint32_t rdiv, uint8_t chctrl)
{
int denom = XTALFREQ * mul;
int64_t pllfreq = (int64_t)freq * div;
int multi = pllfreq / denom;
int num = pllfreq - denom * multi;
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
int max_denominator = (1 << 20) - 1;
if (denom > max_denominator) {
int p0 = 0, q0 = 1, p1 = 1, q1 = 0;
while (denom != 0) {
int a = num / denom;
int q2 = q0 + a*q1;
if (q2 > max_denominator)
break;
int p2 = p0 + a*p1;
p0 = p1; q0 = q1; p1 = p2; q1 = q2;
int new_denom = num - a * denom;
num = denom; denom = new_denom;
}
num = p1;
denom = q1;
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);
}
si5351_setupPLL(pll, multi, num, denom);
si5351_setupMultisynth(channel, pll, div, 0, 1, SI5351_R_DIV_1, drive_strength);
// 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);
}
/*
* 1~100MHz fixed PLL 900MHz, fractional divider
* 100~150MHz fractional PLL 600-900MHz, fixed divider 6
* 150~200MHz fractional PLL 600-900MHz, fixed divider 4
*/
void
si5351_set_frequency(int channel, int freq, uint8_t drive_strength)
si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength)
{
if (freq <= 100000000) {
si5351_setupPLL(SI5351_PLL_B, 32, 0, 1);
@ -303,29 +345,61 @@ si5351_set_frequency(int channel, int freq, uint8_t drive_strength)
si5351_set_frequency_fixeddiv(channel, SI5351_PLL_B, freq, 4, drive_strength, 1);
}
}
int current_band = -1;
#define DELAY_NORMAL 3
#define DELAY_BANDCHANGE 1
#define DELAY_LOWBAND 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
*/
#define CLK2_FREQUENCY 8000000L
int
si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength)
si5351_set_frequency(uint32_t freq, uint8_t drive_strength)
{
int band;
uint8_t band;
int delay = DELAY_NORMAL;
uint32_t ofreq = freq + offset;
if (freq == current_freq)
return delay;
else if (current_freq > freq) // Reset band on sweep begin (if set range 150-600, fix error then 600 MHz band 2 or 3 go back)
current_band = 0;
current_freq = freq;
uint32_t ofreq = freq + current_offset;
uint32_t mul = 1, omul = 1;
uint32_t rdiv = SI5351_R_DIV_1;
uint32_t fdiv;
// Fix possible incorrect input
drive_strength&=SI5351_CLK_DRIVE_STRENGTH_MASK;
if (freq >= config.harmonic_freq_threshold * 7U) {
mul = 9;
omul = 11;
@ -338,84 +412,62 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng
} else if (freq >= config.harmonic_freq_threshold) {
mul = 3;
omul = 5;
}
if ((freq / mul) < 100000000U) {
band = 0;
} else if ((freq / mul) < 150000000U) {
band = 1;
} else {
band = 2;
}
if (freq <= 500000U) {
} else if (freq <= 500000U) {
rdiv = SI5351_R_DIV_64;
freq<<= 6;
ofreq<<= 6;
} else if (freq <= 4000000U) {
rdiv = SI5351_R_DIV_8;
freq<<= 3;
ofreq<<= 3;
}
#if 1
if (current_band != band)
si5351_disable_output();
#endif
band = si5351_get_band(freq / mul);
switch (band) {
case 0:
// fractional divider mode. only PLL A is used.
if (current_band == 1 || current_band == 2)
si5351_setupPLL(SI5351_PLL_A, 32, 0, 1);
// Set PLL twice on changing from band 2
if (current_band == 2)
si5351_setupPLL(SI5351_PLL_A, 32, 0, 1);
if (rdiv == SI5351_R_DIV_8) {
freq *= 8;
ofreq *= 8;
} else if (rdiv == SI5351_R_DIV_64) {
freq *= 64;
ofreq *= 64;
}
si5351_set_frequency_fixedpll(0, SI5351_PLL_A, PLLFREQ, ofreq,
rdiv, drive_strength, omul);
si5351_set_frequency_fixedpll(1, SI5351_PLL_A, PLLFREQ, freq,
rdiv, drive_strength, mul);
//if (current_band != 0)
si5351_set_frequency_fixedpll(2, SI5351_PLL_A, PLLFREQ, CLK2_FREQUENCY,
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1);
break;
case 1:
// Set PLL twice on changing from band 2
if (current_band == 2) {
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul);
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul);
// 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;
}
// div by 6 mode. both PLL A and B are dedicated for CLK0, CLK1
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul);
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul);
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq / mul * 6, CLK2_FREQUENCY,
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1);
// 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:
// div by 4 mode. both PLL A and B are dedicated for CLK0, CLK1
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 4, drive_strength, omul);
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 4, drive_strength, mul);
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq / mul * 4, CLK2_FREQUENCY,
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1);
break;
}
case 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_reset_pll();
#if 1
si5351_enable_output();
#endif
delay += DELAY_BANDCHANGE;
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;
}
if (band == 0)
delay += DELAY_LOWBAND;
// 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;
}

View file

@ -17,12 +17,39 @@
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#define SI5351_PLL_A 0
#define SI5351_PLL_B 1
#define SI5351_MULTISYNTH_DIV_4 4
#define SI5351_MULTISYNTH_DIV_6 6
#define SI5351_MULTISYNTH_DIV_8 8
#define SI5351_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)
@ -31,35 +58,6 @@
#define SI5351_R_DIV_32 (5<<4)
#define SI5351_R_DIV_64 (6<<4)
#define SI5351_R_DIV_128 (7<<4)
#define SI5351_DIVBY4 (3<<2)
#define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3
#define SI5351_REG_16_CLK0_CONTROL 16
#define SI5351_REG_17_CLK1_CONTROL 17
#define SI5351_REG_18_CLK2_CONTROL 18
#define SI5351_REG_26_PLL_A 26
#define SI5351_REG_34_PLL_B 34
#define SI5351_REG_42_MULTISYNTH0 42
#define SI5351_REG_50_MULTISYNTH1 50
#define SI5351_REG_58_MULTISYNTH2 58
#define SI5351_CLK_POWERDOWN (1<<7)
#define SI5351_CLK_INTEGER_MODE (1<<6)
#define SI5351_CLK_PLL_SELECT_B (1<<5)
#define SI5351_CLK_INVERT (1<<4)
#define SI5351_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_177_PLL_RESET 177
#define SI5351_PLL_RESET_B (1<<7)
@ -70,20 +68,10 @@
#define SI5351_CRYSTAL_LOAD_8PF (2<<6)
#define SI5351_CRYSTAL_LOAD_10PF (3<<6)
#define SI5351_CRYSTAL_FREQ_25MHZ 25000000
void si5351_init(void);
void si5351_disable_output(void);
void si5351_enable_output(void);
void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */
uint8_t mult,
uint32_t num,
uint32_t denom);
void si5351_setupMultisynth(uint8_t output,
uint8_t pllSource,
uint32_t div,
uint32_t num,
uint32_t denom,
uint32_t rdiv,
uint8_t drive_strength);
void si5351_set_frequency(int channel, int freq, uint8_t drive_strength);
void si5351_set_frequency_offset(int32_t offset);
int si5351_set_frequency(uint32_t freq, uint8_t drive_strength);
uint32_t si5351_get_frequency(void);

View file

@ -25,74 +25,78 @@
#define wait_ms(ms) chThdSleepMilliseconds(ms)
static const uint8_t conf_data_pll[] = {
// len, ( reg, data ),
2, 0x00, 0x00, /* Initialize to Page 0 */
2, 0x01, 0x01, /* Initialize the device through software reset */
2, 0x04, 0x43, /* PLL Clock High, MCLK, PLL */
static const uint8_t conf_data[] = {
// reg, data,
// PLL clock config
0x00, 0x00, /* Initialize to Page 0 */
0x01, 0x01, /* Initialize the device through software reset */
0x04, 0x43, /* PLL Clock High, MCLK, PLL */
#ifdef REFCLK_8000KHZ
/* 8.000MHz*10.7520 = 86.016MHz, 86.016MHz/(2*7*128) = 48kHz */
2, 0x05, 0x91, /* Power up PLL, P=1,R=1 */
2, 0x06, 0x0a, /* J=10 */
2, 0x07, 29, /* D=7520 = (29<<8) + 96 */
2, 0x08, 96,
0x05, 0x91, /* Power up PLL, P=1,R=1 */
0x06, 0x0a, /* J=10 */
0x07, 29, /* D=7520 = (29<<8) + 96 */
0x08, 96,
#endif
0 // sentinel
// Clock config, default fs=48kHz
0x0b, 0x82, /* Power up the NDAC divider with value 2 */
0x0c, 0x87, /* Power up the MDAC divider with value 7 */
0x0d, 0x00, /* Program the OSR of DAC to 128 */
0x0e, 0x80,
0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */
//0x3c, 25, /* Set the DAC Mode to PRB_P25 */
0x1b, 0x0c, /* Set the BCLK,WCLK as output */
0x1e, 0x80 + 28, /* Enable the BCLKN divider with value 28 */
0x25, 0xee, /* DAC power up */
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 */
};
// default fs=48kHz
static const uint8_t conf_data_clk[] = {
2, 0x0b, 0x82, /* Power up the NDAC divider with value 2 */
2, 0x0c, 0x87, /* Power up the MDAC divider with value 7 */
2, 0x0d, 0x00, /* Program the OSR of DAC to 128 */
2, 0x0e, 0x80,
2, 0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */
//2, 0x3c, 25, /* Set the DAC Mode to PRB_P25 */
2, 0x1b, 0x0c, /* Set the BCLK,WCLK as output */
2, 0x1e, 0x80 + 28, /* Enable the BCLKN divider with value 28 */
2, 0x25, 0xee, /* DAC power up */
2, 0x12, 0x82, /* Power up the NADC divider with value 2 */
2, 0x13, 0x87, /* Power up the MADC divider with value 7 */
2, 0x14, 0x80, /* Program the OSR of ADC to 128 */
2, 0x3d, 0x01, /* Select ADC PRB_R1 */
0 // sentinel
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_routing[] = {
2, 0x00, 0x01, /* Select Page 1 */
2, 0x01, 0x08, /* Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO*/
2, 0x02, 0x01, /* Enable Master Analog Power Control */
2, 0x7b, 0x01, /* Set the REF charging time to 40ms */
2, 0x14, 0x25, /* HP soft stepping settings for optimal pop performance at power up Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling capacitor. Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound. */
2, 0x0a, 0x33, /* Set the Input Common Mode to 0.9V and Output Common Mode for Headphone to 1.65V */
2, 0x3d, 0x00, /* Select ADC PTM_R4 */
2, 0x47, 0x32, /* Set MicPGA startup delay to 3.1ms */
2, 0x7b, 0x01, /* Set the REF charging time to 40ms */
2, 0x34, 0x10, /* Route IN2L to LEFT_P with 10K */
2, 0x36, 0x10, /* Route IN2R to LEFT_N with 10K */
2, 0x37, 0x04, /* Route IN3R to RIGHT_P with 10K */
2, 0x39, 0x04, /* Route IN3L to RIGHT_N with 10K */
2, 0x3b, 0, /* Unmute Left MICPGA, Gain selection of 32dB to make channel gain 0dB */
2, 0x3c, 0, /* Unmute Right MICPGA, Gain selection of 32dB to make channel gain 0dB */
0 // sentinel
static const uint8_t conf_data_ch3_select[] = {
// reg, data,
0x00, 0x01, /* Select Page 1 */
0x37, 0x04, /* Route IN3R to RIGHT_P with input impedance of 10K */
0x39, 0x04, /* Route IN3L to RIGHT_N with input impedance of 10K */
};
const uint8_t conf_data_unmute[] = {
2, 0x00, 0x00, /* Select Page 0 */
2, 0x51, 0xc0, /* Power up Left and Right ADC Channels */
2, 0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */
0 // sentinel
static const uint8_t conf_data_ch1_select[] = {
// reg, data,
0x00, 0x01, /* Select Page 1 */
0x37, 0x40, /* Route IN1R to RIGHT_P with input impedance of 10K */
0x39, 0x10, /* Route IN1L to RIGHT_N with input impedance of 10K */
};
static void
static inline void
tlv320aic3204_bulk_write(const uint8_t *buf, int len)
{
int addr = AIC3204_ADDR;
i2cAcquireBus(&I2CD1);
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000);
i2cReleaseBus(&I2CD1);
(void)i2cMasterTransmitTimeout(&I2CD1, AIC3204_ADDR, buf, len, NULL, 0, 1000);
}
#if 0
@ -109,49 +113,32 @@ tlv320aic3204_read(uint8_t d0)
#endif
static void
tlv320aic3204_config(const uint8_t *data)
tlv320aic3204_config(const uint8_t *data, int len)
{
const uint8_t *p = data;
while (*p) {
uint8_t len = *p++;
tlv320aic3204_bulk_write(p, len);
p += len;
}
i2cAcquireBus(&I2CD1);
for (; len--; data += 2)
tlv320aic3204_bulk_write(data, 2);
i2cReleaseBus(&I2CD1);
}
void tlv320aic3204_init(void)
{
tlv320aic3204_config(conf_data_pll);
tlv320aic3204_config(conf_data_clk);
tlv320aic3204_config(conf_data_routing);
tlv320aic3204_config(conf_data, sizeof(conf_data)/2);
wait_ms(40);
tlv320aic3204_config(conf_data_unmute);
tlv320aic3204_config(conf_data_unmute, sizeof(conf_data_unmute)/2);
}
void tlv320aic3204_select(int channel)
{
const uint8_t ch3[] = {
2, 0x00, 0x01, /* Select Page 1 */
2, 0x37, 0x04, /* Route IN3R to RIGHT_P with input impedance of 10K */
2, 0x39, 0x04, /* Route IN3L to RIGHT_N with input impedance of 10K */
0 // sentinel
};
const uint8_t ch1[] = {
2, 0x00, 0x01, /* Select Page 1 */
2, 0x37, 0x40, /* Route IN1R to RIGHT_P with input impedance of 10K */
2, 0x39, 0x10, /* Route IN1L to RIGHT_N with input impedance of 10K */
0 // sentinel
};
tlv320aic3204_config(channel ? ch1 : ch3);
tlv320aic3204_config(channel ? conf_data_ch1_select : conf_data_ch3_select, sizeof(conf_data_ch3_select)/2);
}
void tlv320aic3204_set_gain(int lgain, int rgain)
{
uint8_t data[] = {
2, 0x00, 0x01, /* Select Page 1 */
2, 0x3b, lgain, /* Unmute Left MICPGA, set gain */
2, 0x3c, rgain, /* Unmute Right MICPGA, set gain */
0 // sentinel
0x00, 0x01, /* Select Page 1 */
0x3b, lgain, /* Unmute Left MICPGA, set gain */
0x3c, rgain, /* Unmute Right MICPGA, set gain */
};
tlv320aic3204_config(data);
tlv320aic3204_config(data, sizeof(data)/2);
}

442
ui.c

File diff suppressed because it is too large Load diff