diff --git a/Makefile b/Makefile index bec51b8..7fdcd84 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 = -O2 -fno-inline-small-functions -ggdb -fomit-frame-pointer -falign-functions=16 --specs=nano.specs -fstack-usage + USE_OPT = -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). @@ -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 # C++ sources that can be compiled in ARM or THUMB mode depending on the global # setting. diff --git a/NANOVNA_STM32_F072/board.h b/NANOVNA_STM32_F072/board.h index c64cf75..1a43c50 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" +#define BOARD_VERSION 0 /* * Board frequencies. */ @@ -47,11 +47,12 @@ /* on-board */ -#define GPIOA_BUTTON 0 +#define GPIOA_PE_SEL 0 #define GPIOA_LEVER1 1 #define GPIOA_LEVER2 2 #define GPIOA_PUSH 3 -#define GPIOA_DAC2 5 +#define GPIOA_RX_SEL 4 +#define GPIOA_LO_SEL 5 #define GPIOA_XP 6 #define GPIOA_YP 7 #define GPIOA_MCO 8 @@ -74,9 +75,9 @@ #define GPIOB_I2C1_SDA 9 #define GPIOB_SD_GP2 10 #define GPIOB_SD_CS 11 -#define GPIOB_I2S2_WCLK 12 -#define GPIOB_I2S2_BCLK 13 -#define GPIOB_I2S2_MOSI 15 +#define GPIOB_SPI2_CLK 12 +#define GPIOB_SPI2_SDO 13 +#define GPIOB_SPI2_SDI 15 #define GPIOC_LED 13 @@ -115,23 +116,23 @@ * PA13 - SWDIO (alternate 0). * PA14 - SWCLK (alternate 0). */ -#define VAL_GPIOA_MODER (PIN_MODE_INPUT(0U) | \ +#define VAL_GPIOA_MODER (PIN_MODE_OUTPUT(GPIOA_PE_SEL) | \ PIN_MODE_INPUT(1U) | \ PIN_MODE_INPUT(2U) | \ PIN_MODE_INPUT(3U) | \ - PIN_MODE_INPUT(4U) | \ - PIN_MODE_ANALOG(GPIOA_DAC2) | \ + PIN_MODE_OUTPUT(GPIOA_RX_SEL) | \ + PIN_MODE_OUTPUT(GPIOA_LO_SEL) | \ 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)) -#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(0U) | \ +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PE_SEL) | \ PIN_OTYPE_PUSHPULL(1U) | \ PIN_OTYPE_PUSHPULL(2U) | \ PIN_OTYPE_PUSHPULL(3U) | \ @@ -147,44 +148,44 @@ PIN_OTYPE_PUSHPULL(GPIOA_JTMS) | \ PIN_OTYPE_PUSHPULL(GPIOA_JTCK) | \ PIN_OTYPE_PUSHPULL(GPIOA_LCD_RESET)) -#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_2M(0) | \ +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_100M(GPIOA_PE_SEL) | \ 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(GPIOA_PE_SEL) | \ 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(GPIOA_PE_SEL) | \ 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) | \ @@ -195,7 +196,7 @@ PIN_ODR_HIGH(GPIOA_JTMS) | \ PIN_ODR_HIGH(GPIOA_JTCK) | \ PIN_ODR_HIGH(GPIOA_LCD_RESET)) -#define VAL_GPIOA_AFRL (PIN_AFIO_AF(0, 0) | \ +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PE_SEL, 0) | \ PIN_AFIO_AF(1, 0) | \ PIN_AFIO_AF(2, 0) | \ PIN_AFIO_AF(3, 0) | \ @@ -238,10 +239,10 @@ PIN_MODE_ALTERNATE(GPIOB_I2C1_SDA) | \ PIN_MODE_OUTPUT(10) | \ PIN_MODE_OUTPUT(11) | \ - PIN_MODE_ALTERNATE(GPIOB_I2S2_WCLK) | \ - PIN_MODE_ALTERNATE(GPIOB_I2S2_BCLK) | \ + PIN_MODE_OUTPUT(GPIOB_SPI2_CLK) | \ + PIN_MODE_INPUT(GPIOB_SPI2_SDO) | \ PIN_MODE_ALTERNATE(14) | \ - PIN_MODE_ALTERNATE(GPIOB_I2S2_MOSI)) + PIN_MODE_OUTPUT(GPIOB_SPI2_SDI)) #define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(0) | \ PIN_OTYPE_PUSHPULL(1) | \ PIN_OTYPE_PUSHPULL(2) | \ @@ -254,10 +255,10 @@ PIN_OTYPE_PUSHPULL(GPIOB_I2C1_SDA) | \ PIN_OTYPE_PUSHPULL(10) | \ PIN_OTYPE_PUSHPULL(11) | \ - PIN_OTYPE_PUSHPULL(GPIOB_I2S2_WCLK) | \ - PIN_OTYPE_PUSHPULL(GPIOB_I2S2_BCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_CLK) | \ + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_SDO) | \ PIN_OTYPE_PUSHPULL(14) | \ - PIN_OTYPE_PUSHPULL(GPIOB_I2S2_MOSI)) + PIN_OTYPE_PUSHPULL(GPIOB_SPI2_SDI)) #define VAL_GPIOB_OSPEEDR (PIN_PUPDR_FLOATING(GPIOB_XN) | \ PIN_PUPDR_FLOATING(GPIOB_YN) | \ PIN_OSPEED_100M(2) | \ @@ -270,10 +271,10 @@ PIN_OSPEED_100M(GPIOB_I2C1_SDA) | \ PIN_OSPEED_100M(10) | \ PIN_OSPEED_100M(11) | \ - PIN_OSPEED_100M(GPIOB_I2S2_WCLK) | \ - PIN_OSPEED_100M(GPIOB_I2S2_BCLK) | \ + PIN_OSPEED_100M(GPIOB_SPI2_CLK) | \ + PIN_OSPEED_100M(GPIOB_SPI2_SDO) | \ PIN_OSPEED_100M(14) | \ - PIN_OSPEED_100M(GPIOB_I2S2_MOSI)) + PIN_OSPEED_100M(GPIOB_SPI2_SDI)) #define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(0) | \ PIN_PUPDR_PULLUP(1) | \ PIN_PUPDR_PULLUP(2) | \ @@ -286,10 +287,10 @@ PIN_PUPDR_PULLUP(GPIOB_I2C1_SDA) | \ PIN_PUPDR_PULLUP(10) | \ PIN_PUPDR_PULLUP(11) | \ - PIN_PUPDR_PULLUP(GPIOB_I2S2_WCLK) | \ - PIN_PUPDR_PULLUP(GPIOB_I2S2_BCLK) | \ + PIN_PUPDR_PULLUP(GPIOB_SPI2_CLK) | \ + PIN_PUPDR_PULLUP(GPIOB_SPI2_SDO) | \ PIN_PUPDR_PULLUP(14) | \ - PIN_PUPDR_PULLUP(GPIOB_I2S2_MOSI)) + PIN_PUPDR_PULLUP(GPIOB_SPI2_SDI)) #define VAL_GPIOB_ODR (PIN_ODR_HIGH(0) | \ PIN_ODR_HIGH(1) | \ PIN_ODR_HIGH(2) | \ @@ -302,10 +303,10 @@ PIN_ODR_HIGH(GPIOB_I2C1_SDA) | \ PIN_ODR_HIGH(10) | \ PIN_ODR_HIGH(11) | \ - PIN_ODR_HIGH(GPIOB_I2S2_WCLK) | \ - PIN_ODR_HIGH(GPIOB_I2S2_BCLK) | \ + PIN_ODR_HIGH(GPIOB_SPI2_CLK) | \ + PIN_ODR_HIGH(GPIOB_SPI2_SDO) | \ PIN_ODR_HIGH(14) | \ - PIN_ODR_HIGH(GPIOB_I2S2_MOSI)) + PIN_ODR_HIGH(GPIOB_SPI2_SDI)) #define VAL_GPIOB_AFRL (PIN_AFIO_AF(0, 0) | \ PIN_AFIO_AF(1, 0) | \ PIN_AFIO_AF(2, 0) | \ @@ -318,10 +319,10 @@ PIN_AFIO_AF(GPIOB_I2C1_SDA, 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(GPIOB_SPI2_CLK, 0) | \ + PIN_AFIO_AF(GPIOB_SPI2_SDO, 0) | \ PIN_AFIO_AF(14, 0) | \ - PIN_AFIO_AF(GPIOB_I2S2_MOSI, 0)) + PIN_AFIO_AF(GPIOB_SPI2_SDI, 0)) /* * GPIOC setup: * @@ -743,6 +744,7 @@ PIN_AFIO_AF(14, 0) | \ PIN_AFIO_AF(15, 0)) + #if !defined(_FROM_ASM_) #ifdef __cplusplus extern "C" { diff --git a/dsp.c b/dsp.c deleted file mode 100644 index 6e9f607..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 } -}; - -int32_t acc_samp_s; -int32_t acc_samp_c; -int32_t acc_ref_s; -int32_t 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/halconf.h b/halconf.h index 38341a0..1450b9f 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 /** diff --git a/main.c b/main.c index fff210d..d25530c 100644 --- a/main.c +++ b/main.c @@ -21,14 +21,25 @@ #include "ch.h" #include "hal.h" #include "usbcfg.h" +#ifdef __VNA__ #include "si5351.h" +#endif #include "nanovna.h" +#ifdef __VNA__ #include "fft.h" +#endif #include #include #include +extern uint32_t minFreq; +extern uint32_t maxFreq; +uint32_t frequencyStart; +uint32_t frequencyStop; +int32_t frequencyExtra; +#define START_MIN minFreq +#define STOP_MAX maxFreq /* * Shell settings */ @@ -69,13 +80,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); +#endif static void update_frequencies(void); static void set_frequencies(uint32_t start, uint32_t stop, uint16_t points); static bool sweep(bool break_on_operation); +#ifdef __VNA__ static void transform_domain(void); #define DRIVE_STRENGTH_AUTO (-1) @@ -85,14 +98,15 @@ 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, - "2016-2020 Copyright @edy555", - "Licensed under GPL. See: https://github.com/ttrftech/NanoVNA", + "2016-2020 Copyright @Erik Kaashoek", + "Licensed under GPL. See: https://github.com/erikkaashoek/tinySA", "Version: " VERSION, "Build Time: " __DATE__ " - " __TIME__, "Kernel: " CH_KERNEL_VERSION, @@ -103,7 +117,7 @@ const char *info_about[]={ 0 // sentinel }; -static THD_WORKING_AREA(waThread1, 640); +static THD_WORKING_AREA(waThread1, 700); static THD_FUNCTION(Thread1, arg) { (void)arg; @@ -129,7 +143,9 @@ static THD_FUNCTION(Thread1, arg) // Process collected data, calculate trace coordinates and plot only if scan // 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; @@ -166,6 +182,7 @@ toggle_sweep(void) sweep_mode ^= SWEEP_ENABLE; } +#ifdef __VNA__ static float bessel0(float x) { @@ -261,9 +278,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 +305,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 +335,7 @@ VNA_SHELL_FUNCTION(cmd_reset) ; } +#ifdef __VNA__ const int8_t gain_table[] = { 0, // 0 ~ 300MHz 40, // 300 ~ 600MHz @@ -341,9 +361,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 +374,8 @@ int set_frequency(uint32_t freq) } delay += si5351_set_frequency(freq, ds); return delay; +#endif + return 1; } // Use macro, std isdigit more big @@ -467,7 +492,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 +501,7 @@ VNA_SHELL_FUNCTION(cmd_offset) } si5351_set_frequency_offset(my_atoi(argv[0])); } +#endif VNA_SHELL_FUNCTION(cmd_freq) { @@ -490,16 +516,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 +556,7 @@ VNA_SHELL_FUNCTION(cmd_dac) dacPutChannelX(&DACD2, 0, value); } +#ifdef __VNA__ VNA_SHELL_FUNCTION(cmd_threshold) { uint32_t value; @@ -539,6 +568,7 @@ VNA_SHELL_FUNCTION(cmd_threshold) value = my_atoui(argv[0]); config.harmonic_freq_threshold = value; } +#endif VNA_SHELL_FUNCTION(cmd_saveconfig) { @@ -565,6 +595,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]; @@ -587,7 +618,9 @@ int16_t dump_selection = 0; volatile int16_t wait_count = 0; float measured[2][POINTS_COUNT][2]; - +#endif +measurement_t measured; +#ifdef __VNA__ #ifdef ENABLED_DUMP static void duplicate_buffer_to_dump(int16_t *p) @@ -637,25 +670,21 @@ 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: + if (sel >= 0 || sel <= MAX_DATA) { + for (i = 0; i < sweep_points; i++) + shell_printf("%f %f\r\n", measured[sel][i], 0.0); + return; + } shell_printf("usage: data [array]\r\n"); } @@ -718,7 +747,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) @@ -742,19 +771,22 @@ 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, + .level_offset = 0 }; properties_t current_props; @@ -762,14 +794,13 @@ 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 } + { 1, M_REFERENCE, 30, 0 }, { 0, M_DELTA, 40, 0 }, { 0, M_DELTA, 60, 0 }, { 0, M_DELTA, 80, 0 } }; // Load propeties default settings @@ -777,21 +808,29 @@ 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._frequency0 = 0; // start = 0Hz + current_props._frequency1 = 350000000; // end = 350MHz + current_props._frequency_IF= 433900000, + current_props._sweep_points = POINTS_COUNT; + #ifdef VNA__ current_props._cal_status = 0; //This data not loaded by default //current_props._frequencies[POINTS_COUNT]; //current_props._cal_data[5][POINTS_COUNT][2]; //============================================= current_props._electrical_delay = 0.0; +#endif memcpy(current_props._trace, def_trace, sizeof(def_trace)); memcpy(current_props._markers, def_markers, sizeof(def_markers)); +#ifdef __VNA__ current_props._velocity_factor = 0.7; +#endif current_props._active_marker = 0; +#ifdef __VNA__ current_props._domain_mode = 0; current_props._marker_smith_format = MS_RLC; +#endif //Checksum add on caldata_save //current_props.checksum = 0; } @@ -805,9 +844,13 @@ ensure_edit_config(void) //memcpy(¤t_props, active_props, sizeof(config_t)); active_props = ¤t_props; // move to uncal state +#ifdef __VNA__ 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(); @@ -855,6 +898,7 @@ bool sweep(bool break_on_operation) palSetPad(GPIOC, GPIOC_LED); return true; } +#endif VNA_SHELL_FUNCTION(cmd_scan) { @@ -881,8 +925,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) @@ -891,8 +937,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 %f ", measured[0][i]); + if (mask & 4) shell_printf("%f %f ", measured[1][i]); + if (mask & 8) shell_printf("%f %f ", measured[2][i]); shell_printf("\r\n"); } } @@ -947,6 +994,7 @@ 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; + update_rbw(frequencies[1] - frequencies[0]); } static void @@ -968,7 +1016,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) @@ -1032,8 +1082,10 @@ set_sweep_frequency(int type, uint32_t freq) break; } update_frequencies(); +#ifdef __VNA__ if (cal_auto_interpolate && cal_applied) cal_interpolate(lastsaveid); +#endif } uint32_t @@ -1091,7 +1143,7 @@ usage: "\tsweep {%s} {freq(Hz)}\r\n", sweep_cmd); } - +#ifdef __VNA__ static void eterm_set(int term, float re, float im) { @@ -1508,13 +1560,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 }, @@ -1525,12 +1579,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; @@ -1666,6 +1725,7 @@ usage: } +#ifdef __VNA__ void set_electrical_delay(float picoseconds) { if (electrical_delay != picoseconds) { @@ -1690,6 +1750,7 @@ VNA_SHELL_FUNCTION(cmd_edelay) set_electrical_delay(my_atof(argv[0])); } } +#endif VNA_SHELL_FUNCTION(cmd_marker) @@ -1775,6 +1836,7 @@ VNA_SHELL_FUNCTION(cmd_frequencies) } } +#ifdef __VNA__ static void set_domain_mode(int mode) // accept DOMAIN_FREQ or DOMAIN_TIME { @@ -1839,6 +1901,7 @@ VNA_SHELL_FUNCTION(cmd_transform) usage: shell_printf("usage: transform {%s} [...]\r\n", cmd_transform_list); } +#endif VNA_SHELL_FUNCTION(cmd_test) { @@ -1896,6 +1959,7 @@ VNA_SHELL_FUNCTION(cmd_test) } } +#ifdef __VNA__ VNA_SHELL_FUNCTION(cmd_gain) { int rvalue; @@ -1956,6 +2020,7 @@ VNA_SHELL_FUNCTION(cmd_stat) // extern int awd_count; // shell_printf("awd: %d\r\n", awd_count); } +#endif #ifndef VERSION #define VERSION "unknown" @@ -2079,6 +2144,161 @@ VNA_SHELL_FUNCTION(cmd_threads) } #endif + +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_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_x) +{ + int rvalue; + int lvalue = 0; + if (argc != 1 && argc != 2) { + shell_printf("usage: x {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_i) +{ + int rvalue; + SI4432_Init(); + shell_printf("SI4432 init done\r\n"); + if (argc == 1) { + rvalue = xtoi(argv[0]); + SetRX(rvalue); + SetMode(rvalue); + shell_printf("SI4432 mode %d set\r\n", rvalue); + } +} +VNA_SHELL_FUNCTION(cmd_o) +{ + (void) argc; + int32_t value = my_atoi(argv[0]); + if (VFO == 0) + frequency_IF = value; + setFreq(VFO, value); +} + +VNA_SHELL_FUNCTION(cmd_a) +{ + (void)argc; + int32_t value = my_atoi(argv[0]); + frequencyStart = value; +} + +VNA_SHELL_FUNCTION(cmd_b) +{ + (void)argc; + 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; + extraVFO = my_atoi(argv[0]); + if (extraVFO == -1) + extraVFO = false; + else + extraVFO = true; + + if (argc >1) + frequencyExtra = my_atoi(argv[1]); +} + +VNA_SHELL_FUNCTION(cmd_s) +{ + (void)argc; + points = my_atoi(argv[0]); +} + +VNA_SHELL_FUNCTION(cmd_m) +{ + (void)argc; + (void)argv; + pause_sweep(); + int32_t f_step = (frequencyStop-frequencyStart)/ points; + palClearPad(GPIOC, GPIOC_LED); // disable led and wait for voltage stabilization + update_rbw(f_step); + chThdSleepMilliseconds(10); + streamPut(shell_stream, '{'); + for (int i = 0; i>8) & 0xFF)); + // enable led + } + streamPut(shell_stream, '}'); + palSetPad(GPIOC, GPIOC_LED); +} + +VNA_SHELL_FUNCTION(cmd_p) +{ + (void)argc; + int p = my_atoi(argv[0]); + int a = my_atoi(argv[1]); + if (p==5) + SetAttenuation(-a); +// if (p==6) +// SetMode(a); +} + +VNA_SHELL_FUNCTION(cmd_w) +{ + (void)argc; + int p = my_atoi(argv[0]); + SetRBW(p); +} //============================================================================= VNA_SHELL_FUNCTION(cmd_help); @@ -2097,7 +2317,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 @@ -2109,11 +2331,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}, @@ -2122,19 +2346,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}, @@ -2142,6 +2372,18 @@ static const VNAShellCommand commands[] = #ifdef ENABLE_COLOR_COMMAND {"color" , cmd_color , 0}, #endif + { "x", cmd_x, 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 }, #ifdef ENABLE_THREADS_COMMAND {"threads" , cmd_threads , 0}, #endif @@ -2269,6 +2511,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)) @@ -2296,7 +2539,7 @@ static const I2CConfig i2ccfg = { .cr1 = 0, // CR1 register initialization. .cr2 = 0 // CR2 register initialization. }; - +#endif static DACConfig dac1cfg1 = { //init: 2047U, init: 1922U, @@ -2315,8 +2558,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)); @@ -2342,19 +2587,23 @@ int main(void) /* restore config */ config_recall(); + /* 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 */ @@ -2363,7 +2612,8 @@ int main(void) i2sObjectInit(&I2SD2); i2sStart(&I2SD2, &i2sconfig); i2sStartExchange(&I2SD2); - +#endif + area_height = AREA_HEIGHT_NORMAL; ui_init(); //Initialize graph plotting plot_init(); diff --git a/mcuconf.h b/mcuconf.h index a1da287..e04096c 100644 --- a/mcuconf.h +++ b/mcuconf.h @@ -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 d553f38..1334f7c 100644 --- a/nanovna.h +++ b/nanovna.h @@ -22,10 +22,29 @@ // Need enable HAL_USE_SPI in halconf.h #define __USE_DISPLAY_DMA__ +#define __SA__ +//#define __SIMULATION__ +//#define __PIPELINE__ +#define __SCROLL__ /* * main.c */ +#ifdef __SA__ +#define POINTS_COUNT 290 +#define MARKER_COUNT 4 + +#define TRACE_COUNT 3 +#define TRACE_ACTUAL 2 +#define TRACE_STORED 1 +#define TRACE_TEMP 0 +#define stored_t measured[TRACE_STORED] +#define actual_t measured[TRACE_ACTUAL] +#define temp_t measured[TRACE_TEMP] +typedef float measurement_t[3][POINTS_COUNT]; +extern measurement_t measured; +#endif +#ifdef __VNA__ // Minimum frequency set #define START_MIN 50000 // Maximum frequency set @@ -81,7 +100,7 @@ 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 @@ -91,15 +110,24 @@ void set_sweep_frequency(int type, uint32_t frequency); uint32_t get_sweep_frequency(int type); double my_atof(const char *p); +int shell_printf(const char *fmt, ...); void toggle_sweep(void); void load_default_properties(void); +extern float perform(bool b, int i, int32_t f, int e); +enum { + AV_OFF, AV_MIN, AV_MAX, AV_2, AV_4, AV_8 +}; +enum { + M_LOW, M_HIGH, M_GENLOW, M_GENHIGH, +}; #define SWEEP_ENABLE 0x01 #define SWEEP_ONCE 0x02 extern int8_t sweep_mode; extern const char *info_about[]; +#ifdef __VNA__ /* * dsp.c */ @@ -121,7 +149,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 +160,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 25 +#define OFFSETY 0 +#define BUTTON_WIDTH 66 +#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 9 #define FREQUENCIES_XPOS1 OFFSETX #define FREQUENCIES_XPOS2 200 @@ -155,7 +196,7 @@ extern void tlv320aic3204_select(int channel); #define GRIDY (HEIGHT / NGRIDY) // -#define CELLOFFSETX 5 +#define CELLOFFSETX 0 #define AREA_WIDTH_NORMAL (CELLOFFSETX + WIDTH + 1 + 4) #define AREA_HEIGHT_NORMAL ( HEIGHT + 1) @@ -190,7 +231,7 @@ extern const uint16_t numfont16x22[]; #define S_OHM "\036" // trace -#define TRACES_MAX 4 +#define TRACES_MAX 3 #define MAX_TRACE_TYPE 12 enum trace_type { @@ -231,13 +272,17 @@ 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 level_offset; + uint8_t _reserved[24]; uint32_t checksum; } config_t; extern config_t config; +#define settingLevelOffset config.level_offset void set_trace_type(int t, int type); void set_trace_channel(int t, int channel); @@ -247,20 +292,26 @@ float get_trace_scale(int t); float get_trace_refpos(int t); const char *get_trace_typename(int t); +#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_REFERENCE, M_NORMAL, M_DELTA +}; -#define MARKERS_MAX 4 - -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 +323,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); @@ -306,7 +357,7 @@ extern volatile uint8_t redraw_request; #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 DEFAULT_FG_COLOR RGB565(255,255,255) #define DEFAULT_BG_COLOR RGB565( 0, 0, 0) @@ -314,13 +365,16 @@ extern volatile uint8_t redraw_request; #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; @@ -349,6 +403,8 @@ void show_logo(void); /* * flash.c */ + +#if 0 #define SAVEAREA_MAX 5 // Begin addr 0x08018000 #define SAVE_CONFIG_AREA_SIZE 0x00008000 @@ -360,26 +416,45 @@ void show_logo(void); #define SAVE_PROP_CONFIG_2_ADDR 0x0801b800 #define SAVE_PROP_CONFIG_3_ADDR 0x0801d000 #define SAVE_PROP_CONFIG_4_ADDR 0x0801e800 - +#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 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 typedef struct properties { uint32_t magic; uint32_t _frequency0; uint32_t _frequency1; uint16_t _sweep_points; +#ifdef __VNA__ uint16_t _cal_status; +#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__ uint8_t _domain_mode; /* 0bxxxxxffm : where ff: TD_FUNC m: DOMAIN_MODE */ uint8_t _marker_smith_format; - uint8_t _reserved[50]; +#endif + uint8_t _reserved[2]; uint32_t checksum; } properties_t; @@ -394,26 +469,34 @@ extern properties_t current_props; #define frequency0 current_props._frequency0 #define frequency1 current_props._frequency1 #define sweep_points current_props._sweep_points +#ifdef __VNA__ #define cal_status current_props._cal_status +#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 - +#endif #define trace current_props._trace #define markers current_props._markers #define active_marker current_props._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 +#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) - +#ifdef __VNA__ int caldata_save(int id); int caldata_recall(int id); const properties_t *caldata_ref(int id); - +#endif int config_save(void); int config_recall(void); @@ -446,7 +529,7 @@ 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 + int32_t value; // for editing at numeric input area // uint32_t previous_value; uint8_t lever_mode; uint8_t marker_delta; @@ -484,6 +567,23 @@ 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 settingAttenuate; +extern int settingPowerCal; +extern int stepDelay; +extern int settingSpeed; +extern int settingMode; +void update_rbw(uint32_t delta_f); + +#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); +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(); @@ -491,4 +591,12 @@ int plot_printf(char *str, int, const char *fmt, ...); // Macros for convert define value to string #define STR1(x) #x #define define_to_STR(x) STR1(x) + +// sa_core.c +int GetRBW(void); +int GetStorage(void); +int GetSubtractStorage(void); +int get_waterfall(void); + + /*EOF*/ diff --git a/plot.c b/plot.c index 01b1e85..325cd7d 100644 --- a/plot.c +++ b/plot.c @@ -25,22 +25,29 @@ #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 m, int n, int w, int h); +static 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" @@ -58,6 +65,20 @@ typedef uint16_t map_t; typedef uint32_t map_t; #endif +uint16_t marker_color[3] = +{ + RGBHEX(0xFFFFFF), + RGBHEX(0x0000FF), + RGBHEX(0x00FF00) +}; + +char marker_letter[3] = +{ + 'R', + 'N', + 'D' +}; + map_t markmap[2][MAX_MARKMAP_Y]; uint8_t current_mappage = 0; @@ -107,6 +128,7 @@ void update_grid(void) redraw_request |= REDRAW_FREQUENCY; } +#ifdef __VNA__ static inline int circle_inout(int x, int y, int r) { @@ -339,7 +361,7 @@ smith_grid3(int x, int y) return 0; } #endif - +#endif #if 0 static int rectangular_grid(int x, int y) @@ -424,9 +446,10 @@ draw_on_strut(int v0, int d, int color) static float logmag(const float *v) { - return log10f(v[0]*v[0] + v[1]*v[1]) * 10; + return v[0]; // raw data is in logmag*10 format } +#ifdef __VNA_ /* * calculate phase[-2:2] of coefficient */ @@ -529,13 +552,14 @@ 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 *coeff = &array[i]; float refpos = NGRIDY - get_trace_refpos(t); float v = refpos; float scale = 1 / get_trace_scale(t); @@ -543,7 +567,8 @@ trace_into_index(int t, int i, float array[POINTS_COUNT][2]) case TRC_LOGMAG: v-= logmag(coeff) * scale; break; - case TRC_PHASE: +#ifdef __VNA__ + case TRC_PHASE: v-= phase(coeff) * scale; break; case TRC_DELAY: @@ -572,15 +597,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 +652,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 +767,43 @@ trace_get_value_string_delta(int t, char *buf, int len, float array[POINTS_COUNT } plot_printf(buf, len, format, v); } +#endif +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]; + buf2[0]=' '; + uint32_t dfreq = 0; + float rlevel = 0; + if (mtype == M_DELTA) { + if (ri > i) { + dfreq = frequencies[ri] - frequencies[i]; + buf2[0] = '-'; + } else { + dfreq = frequencies[i] - frequencies[ri]; + buf2[0] = '+'; + } + rlevel = coeff[ri]; + } else { + dfreq = frequencies[i]; + } + frequency_string(&buf2[1], sizeof(buf2) -1, dfreq); + v = logmag(&coeff[i]); + if (v == -INFINITY) + plot_printf(buf, len, "-INF"); + else + plot_printf(buf, len, " %s %.2f", buf2, v - rlevel); +} +#ifdef __VNA__ static int trace_get_info(int t, char *buf, int len) { @@ -773,6 +838,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) @@ -1038,7 +1104,7 @@ markmap_marker(int marker) } } -static void +void markmap_all_markers(void) { int i; @@ -1170,7 +1236,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 +1324,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 +1348,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 @@ -1335,7 +1403,8 @@ draw_cell(int m, int n) if (n == 0) cell_draw_marker_info(x0, y0); #endif -// PULSE; + cell_draw_test_info(m, n, w, h); + // PULSE; // Draw reference position (<10 system ticks for all screen calls) for (t = 0; t < TRACES_MAX; t++) { if (!trace[t].enabled) @@ -1385,6 +1454,51 @@ draw_all_cells(bool flush_markmap) // clear map for next plotting clear_markmap(); } +#ifdef __SCROLL__ + if (waterfall) { + for (m = 226; m >= HEIGHT; m -= 1) { // Scroll down + uint16_t *buf = &spi_buffer[0]; + ili9341_read_memory(5*5, m, area_width, 1, area_width, buf); + ili9341_bulk(5*5,m+1, area_width,1); + } + for (int i=0; i 255) k = 255; + volatile 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 + spi_buffer[i] = RGB565(r,g,b); + } + ili9341_bulk(5*5,HEIGHT, 290,1); + } +#endif } void @@ -1464,7 +1578,7 @@ cell_drawchar(uint8_t ch, int x, int y) return ch_size; } -static void +void cell_drawstring(char *str, int x, int y) { if (y <= -FONT_GET_HEIGHT || y >= CELLHEIGHT) @@ -1476,6 +1590,7 @@ cell_drawstring(char *str, int x, int y) } } +#ifdef __VNA__ static void cell_draw_marker_info(int x0, int y0) { @@ -1601,13 +1716,93 @@ 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 (!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; + int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0; + int ypos = 1 + (j/2)*(FONT_GET_HEIGHT+1) - y0; + int k = 0; + if (i == active_marker) + buf[k++] = '\033'; // Right arrow (?) + else + buf[k++] = ' '; + buf[k++] = i+'1'; + buf[k++] = marker_letter[markers[i].mtype]; + buf[k++] = 0; + ili9341_set_foreground(marker_color[markers[i].mtype]); + cell_drawstring(buf, xpos, ypos); + trace_get_value_string( + t, buf, sizeof buf, + idx, measured[trace[t].channel], frequencies, sweep_points, ridx, markers[i].mtype); +// cell_drawstring_7x13(w, h, buf, xpos+2*7, ypos, config.trace_color[t]); + cell_drawstring(buf, xpos+2*7, ypos); + j++; + } + } +} +static 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.%03dMHz", + (int)(freq / 1000000), + (int)((freq / 1000) % 1000)); + } +#endif +} + void draw_frequencies(void) { char buf1[32]; char buf2[32]; buf2[0] = 0; +#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)); } else if (FREQ_IS_STARTSTOP()) { @@ -1617,10 +1812,12 @@ 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); @@ -1631,7 +1828,7 @@ draw_frequencies(void) ili9341_drawstring(buf1, FREQUENCIES_XPOS1, FREQUENCIES_YPOS); ili9341_drawstring(buf2, FREQUENCIES_XPOS2, FREQUENCIES_YPOS); } - +#ifdef __VNA__ void draw_cal_status(void) { @@ -1660,7 +1857,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 +1889,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 +1908,25 @@ redraw_frame(void) draw_cal_status(); } +int get_waterfall(void) +{ + return(waterfall); +} + +void +toggle_waterfall(void) +{ + if (!waterfall) { + _height = HEIGHT_SCROLL; + waterfall = true; + fullscreen = false; + } else { + _height = HEIGHT_NOSCROLL; + waterfall = false; + fullscreen = true; + } + request_to_redraw_grid(); +} void plot_init(void) { diff --git a/sa_core.c b/sa_core.c new file mode 100644 index 0000000..e5d66d8 --- /dev/null +++ b/sa_core.c @@ -0,0 +1,1180 @@ +// --------------------------------------------------- + +#include "SI4432.h" // comment out for simulation + +#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 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])/rbw/1000))) + +float LEVEL(uint32_t i, uint32_t f, int v) +{ + float dv; + float df = fabs((float)f - (float)i); + if (df < rbw*1000) + dv = df/(rbw*1000); + else + dv = 1 + 50*(df - rbw*1000)/(rbw*1000); + return (v - dv - settingAttenuate); +} + +float Simulated_SI4432_RSSI(uint32_t i, int s) +{ + SI4432_Sel = s; + float v = -100 + log10(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 +//--------------------- Frequency control ----------------------- + +int dirty = true; +int scandirty = true; + +//---------------- menu system ----------------------- + +int settingAttenuate = 0; +int settingGenerate = 0; +int settingBandwidth = 0; + +//int settingLevelOffset = 0; + +int settingRefer = 1; +int refferFreq[] = {30000000, 15000000, 10000000, 4000000, 3000000, 2000000, 1000000}; +int settingSpur = 0; +int settingAverage = 0; +int settingShowStorage = 0; +int settingSubtractStorage = 0; +int settingMode = 0; +int settingDrive=0; // 0-3 , 3=+20dBm +int settingAGC = true; +int settingLNA = false; +int extraVFO = false; + +uint32_t minFreq = 0; +uint32_t maxFreq = 350000000; + +void set_refer_output(int v) +{ + settingRefer = v; + dirty = true; +} + +int get_refer_output(void) +{ + return(settingRefer); +} + +void SetGenerate(int g) +{ + settingGenerate = g; + dirty = true; +} + +int GetMode(void) +{ + return(settingMode); +} + +void SetMode(int m) +{ + settingMode = m; + switch(m) { + case M_LOW: + case M_GENLOW: + minFreq = 0; + maxFreq = 520000000; + set_sweep_frequency(ST_START, (int32_t) 0); + set_sweep_frequency(ST_STOP, (int32_t) 300000000); + break; + case M_HIGH: + case M_GENHIGH: + minFreq = 260000000; + maxFreq = 960000000; + set_sweep_frequency(ST_START, (int32_t) 300000000); + set_sweep_frequency(ST_STOP, (int32_t) 960000000); + break; + } + dirty = true; +} + + +void SetAttenuation(int a) +{ + settingAttenuate = a; + dirty = true; +} + +void SetStorage(void) +{ + for (int i=0; i -150) { + tft.fillRect(oX+100, 0, 100, 8-1, DISPLAY_BLACK); + tft.setCursor(oX + 100,0); // Start at top-left corner + tft.setTextColor(DISPLAY_WHITE); // Draw white text + tft.print("Max="); + tft.print((int)((peakLevel/ 2.0 - settingAttenuate) - 120.0)+settingLevelOffset); + tft.print("dB, "); + tft.print(peakFreq/ 1000000.0); + tft.print("MHz"); + } + + if (old_settingAverage != settingAverage || abs(old_settingSpur) != abs(settingSpur)) { + int x = tft.width() - 60; + tft.fillRect( x, 0, 60, oY-2, DISPLAY_BLACK); + tft.setTextColor(DISPLAY_WHITE); // Draw white text + if (settingAverage) { + tft.setCursor( x,0); // Start at top-left corner + tft.print("AVR:"); + tft.print(averageText[settingAverage]); + } + if (settingSpur) { + tft.setCursor(x,8); // Start at top-left corner + tft.print("SPUR:"); + tft.print("ON"); + } + old_settingAverage = settingAverage; + old_settingSpur = settingSpur; + } + + + + /* + for (int i=0; i= Y_GRID * dY) f = Y_GRID * dY-1; + if (f < 0) f = 0; + double f2 = ((actual_t[i+1] / 2.0 - settingAttenuate) - 120.0) + settingLevelOffset; + f2 = (f2 - settingMin) * Y_GRID * dY / delta; + if (f2 >= Y_GRID * dY) f2 = Y_GRID * dY-1; + if (f2 < 0) f2 = 0; + int x = i; + int Y1 = Y_GRID * dY - 1 - (int)f; + int Y2 = Y_GRID * dY - 1 - (int)f2; + tft.drawLine(x+oX, oY+Y1, x+oX+1, oY+Y2, DISPLAY_YELLOW); +// tft.drawLine(x+oX, oY+Y1+1, x+oX+1, oY+Y2, DISPLAY_YELLOW); + } + + + */ + sendDisplay(); +} + +void DisplayPoint(unsigned char *data, int i, int color) +{ + if (i == 0) + return; + int x = i-1; + int delta=settingMax - settingMin; + double f = ((data[x] / 2.0 - settingAttenuate) - 120.0) + settingLevelOffset; + f = (f - settingMin) * Y_GRID * dY / delta; + if (f >= Y_GRID * dY) f = Y_GRID * dY-1; + if (f < 0) f = 0; + double f2 = ((data[x+1] / 2.0 - settingAttenuate) - 120.0) + settingLevelOffset; + f2 = (f2 - settingMin) * Y_GRID * dY / delta; + if (f2 >= Y_GRID * dY) f2 = Y_GRID * dY-1; + if (f2 < 0) f2 = 0; + int Y1 = Y_GRID * dY - 1 - (int)f; + int Y2 = Y_GRID * dY - 1 - (int)f2; + DrawDirty(x,min(Y2,Y1)); + DrawDirty(x+1,min(Y2,Y1)); + tft.drawLine(x+oX, oY+Y1, x+oX+1, oY+Y2, color); + // tft.drawLine(x+oX, oY+Y1+1, x+oX+1, oY+Y2, DISPLAY_YELLOW); + sendDisplay(); +} + +void DisplayPeakData(void) +{ + double f = ((((float)actual_t[peakIndex]) / 2.0 - settingAttenuate) - 120.0) + settingLevelOffset; + int delta=settingMax - settingMin; + f = (f - settingMin) * Y_GRID * dY / delta; + if (f >= Y_GRID * dY) f = Y_GRID * dY-1; + if (f < 0) f = 0; + int Y1 = Y_GRID * dY - 1 - (int)f; + tft.setCursor(oX+peakIndex+5,oY+Y1); // Start at top-left corner + tft.setTextColor(DISPLAY_WHITE); // Draw white text + tft.print(peakFreq/ 1000000.0); + tft.setCursor(oX+peakIndex+5,oY+Y1+8); // Start at top-left corner + tft.print((int)((peakLevel/ 2.0 - settingAttenuate) - 120.0)+settingLevelOffset); + tft.print("dB"); + for (int x=peakIndex+5;x=0) { + SI4432_Sel = V; +#ifdef USE_SI4463 + if (SI4432_Sel == 2) { + freq = freq - 433000000; + freq = freq / 10000; //convert to 10kHz channel starting with 433MHz + // Serial.print("Set frequency Si4463 = "); + // Serial.println(freq); + Si446x_RX ((uint8_t)freq); + } + else +#endif + SI4432_Set_Frequency(freq); + } +} + +void SetSwitchTransmit(void) { + SI4432_Write_Byte(0x0b, 0x1f);// Set switch to transmit + SI4432_Write_Byte(0x0c, 0x1d); +} + +void SetSwitchReceive(void) { + SI4432_Write_Byte(0x0b, 0x1d);// Set switch to receive + SI4432_Write_Byte(0x0c, 0x1f); +} + +void SetAGCLNA(void) { + unsigned char v = 0x40; + if (settingAGC) v |= 0x20; + if (settingLNA) v |= 0x10; + SI4432_Write_Byte(0x69, v); +} + +void SetRX(int m) +{ +switch(m) { +case M_LOW: // Mixed into 0 + SI4432_Sel = 0; + SI4432_Receive(); + SetSwitchReceive(); + SetAGCLNA(); + + SI4432_Sel = 1; + SetSwitchReceive(); +// SI4432_Receive(); For noise testing only + SI4432_Transmit(settingDrive); + // SI4432_SetReference(settingRefer); + break; +case M_HIGH: // Direct into 1 + // SI4432_SetReference(-1); // Stop reference output + SI4432_Sel = 0; // both as receiver to avoid spurs + SetSwitchReceive(); + SI4432_Receive(); + + SI4432_Sel = 1; + SI4432_Receive(); + SetSwitchReceive(); + SetAGCLNA(); + + break; +case M_GENLOW: // Mixed output from 0 + SI4432_Sel = 0; + SetSwitchTransmit(); + SI4432_Transmit(settingDrive); + + SI4432_Sel = 1; + SetSwitchReceive(); + SI4432_Transmit(settingDrive); + + break; +case M_GENHIGH: // Direct output from 1 + SI4432_Sel = 0; + SI4432_Receive(); + SetSwitchReceive(); + + SI4432_Sel = 1; + SetSwitchTransmit(); + SI4432_Transmit(settingDrive); + + break; + } +} + +void update_rbw(uint32_t delta_f) +{ + vbw = (delta_f)/1000.0; + rbw = settingBandwidth; +// float old_rbw = rbw; + if (rbw == 0) + rbw = 2*vbw; + if (rbw < 2.6) + rbw = 2.6; + if (rbw > 600) + rbw = 600; + SI4432_Sel = (settingMode & 1); + rbw = SI4432_SET_RBW(rbw); + vbwSteps = ((int)(2 * vbw / rbw)); + if (vbwSteps < 1) + vbwSteps = 1; + dirty = true; +} + +float perform(bool break_on_operation, int i, int32_t f, int extraV) +{ + long local_IF = ((settingMode & 1) == 0?frequency_IF + (int)(rbw < 300.0?settingSpur * 1000 * rbw :0):0); + if (i == 0) { + if (settingSpeed == 0){ + if (rbw < 10.0) + stepDelay = 2500; + else if (rbw <30.0) + stepDelay = 2000; + else if (rbw <100.0) + stepDelay = 1000; + else + stepDelay = 500; + } else + stepDelay = settingSpeed; + +// setupSA(); + + int p = settingAttenuate * 2; + PE4302_Write_Byte(p); + SetRX(settingMode); + SI4432_SetReference(settingRefer); + temppeakLevel = -150; + setFreq (0, local_IF); + if (dirty) { + scandirty = true; + dirty = false; + } + } + volatile int subSteps = ((int)(2 * vbw / rbw)); + float RSSI = -150.0; + int t = 0; + do { + int lf = (uint32_t)(f + (int)(t * 500 * rbw)); + if (extraV) + setFreq (0, local_IF + lf - refferFreq[settingRefer]); // Offset so fundamental of reffer is visible + setFreq (1, local_IF + lf); + float subRSSI = SI4432_RSSI(lf, (settingMode & 1))+settingLevelOffset+settingAttenuate; + if (RSSI < subRSSI) + RSSI = subRSSI; + t++; + if (operation_requested && break_on_operation) + subSteps = 0; // abort + } while (subSteps-- > 0); + return(RSSI); +#if 0 + temp_t[i] = RSSI; + if (settingSubtractStorage) { + RSSI = RSSI - stored_t[i] ; + } + if (scandirty || settingAverage == AV_OFF) + actual_t[i] = RSSI; + else { + switch(settingAverage) { + case AV_MIN: if (actual_t[i] > RSSI) actual_t[i] = RSSI; break; + case AV_MAX: if (actual_t[i] < RSSI) actual_t[i] = RSSI; break; + case AV_2: actual_t[i] = (actual_t[i] + RSSI) / 2.0; break; + case AV_4: actual_t[i] = (actual_t[i]*3 + RSSI) / 4.0; break; + case AV_8: actual_t[i] = (actual_t[i]*7 + RSSI) / 8.0; break; + } + } + if (frequencies[i] > 1000000) { + if (temppeakLevel < actual_t[i]) { + temppeakIndex = i; + temppeakLevel = actual_t[i]; + } + } + if (temp_t[i] == 0) { + SI4432_Init(); + } + if (i == POINTS_COUNT -1) { + if (scandirty) { + scandirty = false; + } + peakIndex = temppeakIndex; + peakLevel = actual_t[peakIndex]; + peakFreq = frequencies[peakIndex]; + settingSpur = -settingSpur; + int peak_marker = 0; + markers[peak_marker].enabled = true; + markers[peak_marker].index = peakIndex; + markers[peak_marker].frequency = frequencies[markers[peak_marker].index]; +// redraw_marker(peak_marker, FALSE); + + + } +#endif +} + +// main loop for measurement +static bool sweep(bool break_on_operation) +{ + float RSSI; + palClearPad(GPIOC, GPIOC_LED); + for (int i = 0; i < sweep_points; i++) { +again: + RSSI = perform(break_on_operation, i, frequencies[i], extraVFO); + if (settingSpur == 1) + temp_t[i] = RSSI; + else + { + if (settingSpur == -1) + RSSI = ( RSSI < temp_t[i] ? RSSI : temp_t[i]); + temp_t[i] = RSSI; + if (settingSubtractStorage) { + RSSI = RSSI - stored_t[i] ; + } + // stored_t[i] = (SI4432_Read_Byte(0x69) & 0x0f) * 3.0 - 90.0; // Display the AGC value in thestored trace + if (scandirty || settingAverage == AV_OFF) + actual_t[i] = RSSI; + else { + switch(settingAverage) { + case AV_MIN: if (actual_t[i] > RSSI) actual_t[i] = RSSI; break; + case AV_MAX: if (actual_t[i] < RSSI) actual_t[i] = RSSI; break; + case AV_2: actual_t[i] = (actual_t[i] + RSSI) / 2.0; break; + case AV_4: actual_t[i] = (actual_t[i]*3 + RSSI) / 4.0; break; + case AV_8: actual_t[i] = (actual_t[i]*7 + RSSI) / 8.0; break; + } + } + if (frequencies[i] > 1000000) { + if (temppeakLevel < actual_t[i]) { + temppeakIndex = i; + temppeakLevel = actual_t[i]; + } + } + } + if (i == sweep_points -1) { + if (settingSpur == 1) { + settingSpur = -1; + i = 0; + goto again; + } + if (scandirty) { + scandirty = false; + } + peakIndex = temppeakIndex; + peakLevel = actual_t[peakIndex]; + peakFreq = frequencies[peakIndex]; + settingSpur = -settingSpur; + int peak_marker = 0; + markers[peak_marker].enabled = true; + markers[peak_marker].index = peakIndex; + markers[peak_marker].frequency = frequencies[markers[peak_marker].index]; + // redraw_marker(peak_marker, FALSE); + + + } + // back to toplevel to handle ui operation + if (operation_requested && break_on_operation) + return false; + } + palSetPad(GPIOC, GPIOC_LED); + return true; +} + + +#if 0 +void PeakSearch() +{ +#define PEAKSTACK 4 +#define PEAKDISTANCE 10 + int level = 0; + int searchLeft[PEAKSTACK]; + int peakIndex[PEAKSTACK]; + int peak_marker = 0; + searchLeft[level] = true; + peakIndex[level] = markers[peak_marker].index; + level++; + searchLeft[level] = true; + int peakFrom; + int peakTo; + while (peak_marker < 4){ + if (searchLeft[level]) + { + int fromLevel = level; + while (fromLevel > 0 && searchLeft[fromLevel]) + fromLevel-- + if(fromLevel == 0) { + peakFrom = PEAKDISTANCE; + } else { + peakFrom = peakIndex[fromLevel] + PEAKDISTANCE; + } + peakTo = peakIndex[level] - PEAKDISTANCE; + } else { + int toLevel = level; + while (toLevel > 0 && !searchLeft[toLevel]) + toLevel-- + if(toLevel == 0) { + peakTo = POINTS_COUNT - 1 - PEAKDISTANCE; + } else { + peakTo = peakIndex[fromLevel] - PEAKDISTANCE; + } + peakFrom = peakIndex[level] + PEAKDISTANCE; + } + float peakMax = actual_t[peakFrom]; + int peakIndex = peakFrom; + for (int i = peakFrom; i < peakTo; i++) { + if (peakMax < actual_t[i]) { + peakMax = actual_t[i]; + peakIndex = i; + } + } + + + peakIndex = temppeakIndex; + peakLevel = actual_t[peakIndex]; + peakFreq = frequencies[peakIndex]; + settingSpur = -settingSpur; + int peak_marker = 0; + markers[peak_marker].enabled = true; + markers[peak_marker].index = peakIndex; + markers[peak_marker].frequency = frequencies[markers[peak_marker].index]; +// redraw_marker(peak_marker, FALSE); + + +} + +} +#endif + +char *averageText[] = { "OFF", "MIN", "MAX", "2", "4", "8"}; +char *dBText[] = { "1dB/", "2dB/", "5dB/", "10dB/", "20dB/"}; +int refMHz[] = { 30, 15, 10, 4, 3, 2, 1 }; + +void draw_cal_status(void) +{ +#define BLEN 10 + char buf[BLEN]; +#define YSTEP 8 + int x = 0; + int y = OFFSETY; + unsigned int color; + +#define XSTEP 40 + +// if (!sweep_enabled) +// perform(true, 0, frequencies[0], false); + + ili9341_fill(x, y, OFFSETX, HEIGHT, 0x0000); + ili9341_set_background(DEFAULT_BG_COLOR); + + int yMax = (NGRIDY - get_trace_refpos(0)) * get_trace_scale(0); + plot_printf(buf, BLEN, "%ddB", yMax); + buf[5]=0; + ili9341_set_foreground(DEFAULT_FG_COLOR); + ili9341_drawstring(buf, x, y); + + y += YSTEP*2; + plot_printf(buf, BLEN, "%ddB/",(int)get_trace_scale(0)); + ili9341_drawstring(buf, x, y); + + if (settingAttenuate) { + ili9341_set_foreground(BRIGHT_COLOR_GREEN); + y += YSTEP*2; + ili9341_drawstring("Attn:", x, y); + + y += YSTEP; + plot_printf(buf, BLEN, "-%ddB", settingAttenuate); + buf[5]=0; + ili9341_drawstring(buf, x, y); + } + + if (settingAverage>0) { + ili9341_set_foreground(BRIGHT_COLOR_BLUE); + y += YSTEP*2; + ili9341_drawstring("Aver:", x, y); + + y += YSTEP; + plot_printf(buf, BLEN, "%s",averageText[settingAverage]); + buf[5]=0; + ili9341_drawstring(buf, x, y); + } + + if (settingSpur) { + ili9341_set_foreground(BRIGHT_COLOR_BLUE); + y += YSTEP*2; + ili9341_drawstring("Spur:", x, y); + + y += YSTEP; + plot_printf(buf, BLEN, "ON"); + ili9341_drawstring(buf, x, y); + } + + if (settingBandwidth) + color = BRIGHT_COLOR_GREEN; + else + color = DEFAULT_FG_COLOR; + ili9341_set_foreground(color); + + y += YSTEP*2; + ili9341_drawstring("RBW:", x, y); + + y += YSTEP; + plot_printf(buf, BLEN, "%dkHz", (int)rbw); + buf[5]=0; + ili9341_drawstring(buf, x, y); + + ili9341_set_foreground(DEFAULT_FG_COLOR); + y += YSTEP*2; + ili9341_drawstring("VBW:", x, y); + + y += YSTEP; + plot_printf(buf, BLEN, "%dkHz",(int)vbw); + buf[5]=0; + ili9341_drawstring(buf, x, y); + + y += YSTEP*2; + ili9341_drawstring("Scan:", x, y); + + y += YSTEP; + int32_t t = (int)((2* vbwSteps * sweep_points * ( stepDelay / 100) )) /10 * (settingSpur ? 2 : 1); // in mS + if (t>1000) + plot_printf(buf, BLEN, "%dS",(t+500)/1000); + else + plot_printf(buf, BLEN, "%dmS",t); + + buf[5]=0; + ili9341_drawstring(buf, x, y); + + + if (settingRefer >= 0) { + ili9341_set_foreground(BRIGHT_COLOR_RED); + y += YSTEP*2; + ili9341_drawstring("Ref:", x, y); + + y += YSTEP; + plot_printf(buf, BLEN, "%dMHz",refMHz[settingRefer]); + buf[5]=0; + ili9341_drawstring(buf, x, y); + } + + y = HEIGHT-7 + OFFSETY; + plot_printf(buf, BLEN, "%ddB", (int)(yMax - get_trace_scale(0) * NGRIDY)); + buf[5]=0; + ili9341_set_foreground(DEFAULT_FG_COLOR); + ili9341_drawstring(buf, x, y); + +} + +// -------------------- Self testing ------------------------------------------------- + +enum { + TC_SIGNAL, TC_BELOW, TC_ABOVE, TC_FLAT +}; + +enum { + TP_SILENT, TP_10MHZ, TP_10MHZEXTRA, TP_30MHZ +}; + +#define TEST_COUNT 7 + +static const struct { + int kind; + int setup; + uint32_t center; // In MHz + int span; // In MHz + float pass; + int width; + float stop; +} test_case [TEST_COUNT] = +{// Condition Preparation Center Span Pass Width Stop + {TC_SIGNAL, TP_10MHZ, 10, 7, -30, 30, -85 }, + {TC_SIGNAL, TP_10MHZ, 20, 7, -50, 30, -90 }, + {TC_SIGNAL, TP_10MHZ, 30, 7, -40, 30, -90 }, + {TC_BELOW, TP_SILENT, 200, 100, -80, 0, 0}, + {TC_SIGNAL, TP_10MHZEXTRA, 10, 8, -30, 50, -80 }, + {TC_FLAT, TP_10MHZEXTRA, 10, 4, -35, 20, -80}, + {TC_SIGNAL, TP_30MHZ, 360, 18, -70, 20, -100 }, +}; + +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 void test_acquire(int i) +{ + pause_sweep(); + if (test_case[i].center < 300) + settingMode = 0; + else + settingMode = 1; + + set_sweep_frequency(ST_CENTER, (int32_t)test_case[i].center * 1000000); + set_sweep_frequency(ST_SPAN, (int32_t)test_case[i].span * 1000000); + 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_draw_test_info(int m, int n, int w, int h) +{ +#define INFO_SPACING 13 + char buf[35]; + if (!show_test_info) + return; + for (int i = -1; i < TEST_COUNT+1; i++) { + int xpos = 25; + int ypos = 40+i*INFO_SPACING; + xpos -= m * CELLWIDTH -CELLOFFSETX; + ypos -= n * CELLHEIGHT; + unsigned int color = RGBHEX(0xFFFFFF); + if (i == -1) { + plot_printf(buf, sizeof buf, "Self test status:"); + } else if (i == TEST_COUNT) { + if (test_wait) + plot_printf(buf, sizeof buf, "Touch screen to continue"); + else + buf[0] = 0; + } else { + plot_printf(buf, sizeof 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); + } + cell_drawstring(buf, xpos, ypos, color); + } +} + +#define fabs(X) ((X)<0?-(X):(X)) + +int validate_peak_within(int i, float margin) +{ + if (fabs(peakLevel-test_case[i].pass) > margin) + return false; + return(test_case[i].center * 1000000 - 100000 < peakFreq && peakFreq < test_case[i].center * 1000000 + 100000 ); +} + +int validate_peak_below(int i, float margin) { + return(test_case[i].pass - peakLevel > margin); +} + +int validate_below(void) { + int status = TS_PASS; + for (int j = 0; j < POINTS_COUNT; j++) { + if (actual_t[j] > stored_t[j] - 5) + status = TS_CRITICAL; + else if (actual_t[j] > stored_t[j]) { + status = TS_FAIL; + break; + } + } + return(status); +} + +int validate_flatness(int i) { + volatile int j; + for (j = peakIndex; j < POINTS_COUNT; j++) { + if (actual_t[j] < peakLevel - 3) // Search right -3dB + break; + } + if (j - peakIndex < test_case[i].width) + return(TS_FAIL); + for (j = peakIndex; j > 0; j--) { + if (actual_t[j] < peakLevel - 3) // Search left -3dB + break; + } + if (peakIndex - j < test_case[i].width) + return(TS_FAIL); + return(TS_PASS); +} + +int validate_above(void) { + int status = TS_PASS; + for (int j = 0; j < POINTS_COUNT; j++) { + if (actual_t[j] < stored_t[j] + 5) + status = TS_CRITICAL; + else if (actual_t[j] < stored_t[j]) { + status = TS_FAIL; + break; + } + } + return(status); +} + + +void test_validate(int i) +{ + if (test_case[i].kind == TC_SIGNAL) { // Validate signal + if (validate_peak_within(i, 5.0)) // Validate Peak + test_status[i] = TS_PASS; + else if (validate_peak_within(i, 10.0)) + test_status[i] = TS_CRITICAL; + else + test_status[i] = TS_FAIL; + if (test_status[i] != TS_PASS) + test_fail_cause[i] = "Peak "; + if (test_status[i] == TS_PASS) { // Validate noise floor + for (int j = 0; j < POINTS_COUNT/2 - test_case[i].width; j++) { + if (actual_t[j] > test_case[i].stop - 5) + test_status[i] = TS_CRITICAL; + else if (actual_t[j] > test_case[i].stop) { + test_status[i] = TS_FAIL; + break; + } + } + for (int j = POINTS_COUNT/2 + test_case[i].width; j < POINTS_COUNT; j++) { + if (actual_t[j] > test_case[i].stop - 5) + test_status[i] = TS_CRITICAL; + else if (actual_t[j] > test_case[i].stop) { + test_status[i] = TS_FAIL; + break; + } + } + if (test_status[i] != TS_PASS) + test_fail_cause[i] = "Stopband "; + } + + } else if (test_case[i].kind == TC_ABOVE) { // Validate signal above curve + for (int j = 0; j < POINTS_COUNT; j++) { + if (actual_t[j] < test_case[i].pass + 5) + test_status[i] = TS_CRITICAL; + else if (actual_t[j] < test_case[i].pass) { + test_status[i] = TS_FAIL; + break; + } + } + if (test_status[i] != TS_PASS) + test_fail_cause[i] = "Above "; + + } else if (test_case[i].kind == TC_BELOW) { // Validate signal below curve + if (validate_peak_below(i, 10.0)) + test_status[i] = TS_PASS; + else if (validate_peak_below(i, 5.0)) + test_status[i] = TS_CRITICAL; + else + test_status[i] = TS_FAIL; + if (test_status[i] != TS_PASS) + test_fail_cause[i] = "Above "; + } else if (test_case[i].kind == TC_FLAT) { // Validate passband flatness + test_status[i] = validate_flatness(i); + if (test_status[i] != TS_PASS) + test_fail_cause[i] = "Passband "; + } + + // Report status + + if (test_status[i] != TS_PASS || i == TEST_COUNT - 1) + test_wait = true; + draw_all(TRUE); + resume_sweep(); +} + +extern void menu_autosettings_cb(int item); +extern void touch_wait_release(void); + +void self_test(void) +{ + menu_autosettings_cb(0); + for (int i=0; i < TEST_COUNT; i++) { // All test cases waiting + test_status[i] = TS_WAITING; + test_fail_cause[i] = ""; + } + show_test_info = TRUE; + for (int i=0; i < TEST_COUNT; i++) { + extraVFO = false; //Default test setup + switch(test_case[i].setup) { // Prepare test conditions + case TP_SILENT: // No input signal + set_refer_output(-1); + for (int j = 0; j < POINTS_COUNT; j++) + stored_t[j] = test_case[i].pass; + break; + case TP_10MHZEXTRA: // Swept receiver + extraVFO = true; //Sweep BPF + // Fall through intended!!!!!! + case TP_10MHZ: // 10MHz input + common: + set_refer_output(2); + int j; + for (j = 0; j < POINTS_COUNT/2 - test_case[i].width; j++) + stored_t[j] = test_case[i].stop; + for (j = POINTS_COUNT/2 + test_case[i].width; j < POINTS_COUNT; j++) + stored_t[j] = test_case[i].stop; + for (j = POINTS_COUNT/2 - test_case[i].width; j < POINTS_COUNT/2 + test_case[i].width; j++) + stored_t[j] = test_case[i].pass; + break; + case TP_30MHZ: + set_refer_output(0); + goto common; + } + trace[TRACE_STORED].enabled = true; + set_trace_refpos(0, NGRIDY - (test_case[i].pass + 30) / get_trace_scale(0)); + set_trace_refpos(1, NGRIDY - (test_case[i].pass + 30) / get_trace_scale(0)); + set_trace_refpos(2, NGRIDY - (test_case[i].pass + 30) / get_trace_scale(0)); + draw_cal_status(); + test_acquire(i); // Acquire test + test_validate(i); // Validate test + chThdSleepMilliseconds(2000); + if (test_status[i] != TS_PASS) { + touch_wait_release(); + } + } + touch_wait_release(); + // chThdSleepMilliseconds(2000); + show_test_info = FALSE; + trace[TRACE_STORED].enabled = false; + set_trace_refpos(0, NGRIDY - (-10) / get_trace_scale(0)); + set_trace_refpos(1, NGRIDY - (-10) / get_trace_scale(0)); + set_trace_refpos(2, NGRIDY - (-10) / get_trace_scale(0)); + set_refer_output(0); + settingMode = 0; + draw_cal_status(); + + menu_autosettings_cb(0); +} diff --git a/si4432.c b/si4432.c new file mode 100644 index 0000000..6efbd8f --- /dev/null +++ b/si4432.c @@ -0,0 +1,371 @@ +/* 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 "si4432.h" + +#define CS_SI0_HIGH palSetPad(GPIOA, GPIOA_RX_SEL) +#define CS_SI1_HIGH palSetPad(GPIOA, GPIOA_LO_SEL) +#define CS_PE_HIGH palSetPad(GPIOA, GPIOA_PE_SEL) + +#define CS_SI0_LOW palClearPad(GPIOA, GPIOA_RX_SEL) +#define CS_SI1_LOW palClearPad(GPIOA, GPIOA_LO_SEL) +#define CS_PE_LOW palClearPad(GPIOA, GPIOA_PE_SEL) + +#define SPI2_CLK_HIGH palSetPad(GPIOB, GPIOB_SPI2_CLK) +#define SPI2_CLK_LOW palClearPad(GPIOB, GPIOB_SPI2_CLK) + +#define SPI2_SDI_HIGH palSetPad(GPIOB, GPIOB_SPI2_SDI) +#define SPI2_SDI_LOW palClearPad(GPIOB, GPIOB_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= 480000000) { + hbsel = 1; + Freq = Freq / 2; + } else { + hbsel = 0; + } + int sbsel = 1; + int N = Freq / 10000000; + Carrier = ( 4 * ( Freq - N * 10000000 )) / 625; + int Freq_Band = ( N - 24 ) | ( hbsel << 5 ) | ( sbsel << 6 ); +#if 1 + 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 +} + +int stepDelay = 1500; +int settingSpeed = 0; + +float SI4432_RSSI(uint32_t i, int s) +{ + int RSSI_RAW; + // SEE DATASHEET PAGE 61 +#ifdef USE_SI4463 + if (SI4432_Sel == 2) { + RSSI_RAW = Si446x_getRSSI(); + } else +#endif + SI4432_Sel = s; + chThdSleepMicroseconds(stepDelay); + RSSI_RAW = (unsigned char)SI4432_Read_Byte( 0x26 ) ; + if (settingMode < 2 && RSSI_RAW == 0) + SI4432_Init(); + float dBm = 0.5 * RSSI_RAW - 120.0 ; +#ifdef __SIMULATION__ + dBm = Simulated_SI4432_RSSI(i,s); +#endif + // Serial.println(dBm,2); + return dBm ; +} + + +void SI4432_Sub_Init() +{ + SI4432_Reset(); + 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_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_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_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() +{ + + +//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(433700000); + 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(443700000); + 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; +} + +extern void shiftOut(uint8_t val); + +void PE4302_Write_Byte(unsigned char DATA ) +{ + SPI2_CLK_LOW; + shiftOut(DATA); + CS_PE_HIGH; + CS_PE_LOW; +} + +#endif diff --git a/si4432.h b/si4432.h new file mode 100644 index 0000000..8b2774e --- /dev/null +++ b/si4432.h @@ -0,0 +1,22 @@ +#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); + +#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 391af98..a75838b 100644 --- a/ui.c +++ b/ui.c @@ -52,7 +52,7 @@ uistat_t uistat = { #define BIT_DOWN1 1 #define READ_PORT() palReadPort(GPIOA) -#define BUTTON_MASK 0b1111 +#define BUTTON_MASK 0b1110 static uint16_t last_button = 0b0000; static uint32_t last_button_down_ticks; @@ -67,9 +67,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 @@ -120,6 +122,7 @@ 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); @@ -287,7 +290,7 @@ 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) @@ -435,6 +438,7 @@ enum { typedef void (*menuaction_cb_t)(int item, uint8_t data); +#ifdef __VNA__ static void menu_calop_cb(int item, uint8_t data) { @@ -630,7 +634,6 @@ menu_transform_filter_cb(int item, uint8_t data) domain_mode = (domain_mode & ~TD_FUNC) | data; ui_mode_normal(); } - static void choose_active_marker(void) { @@ -647,9 +650,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(); @@ -685,6 +690,7 @@ menu_stimulus_cb(int item, uint8_t data) break; } } +#endif static uint32_t get_marker_frequency(int marker) @@ -730,6 +736,7 @@ menu_marker_op_cb(int item, uint8_t data) } } break; +#ifdef __VNA__ case 4: /* MARKERS->EDELAY */ { if (uistat.current_trace == -1) @@ -739,6 +746,7 @@ menu_marker_op_cb(int item, uint8_t data) set_electrical_delay(electrical_delay + (v / 1e-12)); } break; +#endif } ui_mode_normal(); draw_cal_status(); @@ -775,7 +783,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) { @@ -784,6 +792,7 @@ menu_marker_smith_cb(int item, uint8_t data) redraw_marker(active_marker); draw_menu(); } +#endif static void active_marker_select(int item) @@ -830,7 +839,7 @@ menu_marker_sel_cb(int item, uint8_t data) 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 }, @@ -1035,6 +1044,9 @@ const menuitem_t menu_top[] = { { MT_SUBMENU, 0, "CONFIG", menu_config }, { MT_NONE, 0, NULL, NULL } // sentinel }; +#endif + +#include "ui_sa.c" #define MENU_STACK_DEPTH_MAX 4 const menuitem_t *menu_stack[MENU_STACK_DEPTH_MAX] = { @@ -1127,7 +1139,7 @@ menu_invoke(int item) // Key x, y position (0 - 15) on screen #define KP_GET_X(posx) ((posx)*KP_WIDTH + (320-64-KP_WIDTH*4)) #define KP_GET_Y(posy) ((posy)*KP_HEIGHT + 12 ) - +#ifdef __VNA__ // Key names #define KP_0 0 #define KP_1 1 @@ -1233,6 +1245,7 @@ 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 void draw_keypad(void) @@ -1315,6 +1328,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) @@ -1384,6 +1398,12 @@ 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) @@ -1482,6 +1502,7 @@ leave_ui_mode() } } +#ifdef __VNA__ static void fetch_numeric_target(void) { @@ -1528,6 +1549,7 @@ fetch_numeric_target(void) // uistat.previous_value = uistat.value; } + static void set_numeric_value(void) { @@ -1561,6 +1583,7 @@ set_numeric_value(void) break; } } +#endif static void draw_numeric_area(void) @@ -1722,7 +1745,7 @@ lever_move(int status, int mode) } #define STEPRATIO 0.2 - +#ifdef __VNA__ static void lever_edelay(int status) { @@ -1737,7 +1760,7 @@ lever_edelay(int status) } set_electrical_delay(value); } - +#endif static void ui_process_normal(void) { @@ -1758,9 +1781,11 @@ ui_process_normal(void) else lever_zoom_span(status); break; +#ifdef __VNA__ case LM_EDELAY: lever_edelay(status); break; +#endif } } } @@ -1812,6 +1837,10 @@ keypad_click(int key) } /* numeric input done */ double value = my_atof(kp_buf) * scale; +#if 1 + uistat.value = (int)value; + set_numeric_value(); +#else switch (keypad_mode) { case KM_START: set_sweep_frequency(ST_START, value); @@ -1844,7 +1873,7 @@ 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; @@ -2130,11 +2159,15 @@ 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; @@ -2191,7 +2224,7 @@ 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 = { diff --git a/ui_sa.c b/ui_sa.c new file mode 100644 index 0000000..d6adfd3 --- /dev/null +++ b/ui_sa.c @@ -0,0 +1,826 @@ + +void markmap_all_markers(void); +static void menu_marker_type_cb(int item, uint8_t data); + +void set_sweep_frequency(int type, uint32_t frequency); +uint32_t get_sweep_frequency(int type); +void clearDisplay(void); +//void ui_process_touch(void); +void SetPowerGrid(int); +void SetRefLevel(int); +void set_refer_output(int); +int get_refer_output(void); +void SetAttenuation(int); +void SetPowerLevel(int); +void SetGenerate(int); +void SetRBW(int); +void SetSpur(int); +int GetSpur(void); +void SetAverage(int); +int GetAverage(void); +void SetStorage(void); +void SetClearStorage(void); +void SetSubtractStorage(void); +void toggle_waterfall(void); +void SetMode(int); +int GetMode(void); +void AllDirty(void); +void MenuDirty(void); +void redrawHisto(void); +void self_test(void); +extern int32_t frequencyExtra; +extern int extraVFO; +extern int settingDrive; +extern int settingLNA; +extern int settingAGC; +extern int settingSpeed; +extern int stepDelay; + +enum { + KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_CW, KM_REFPOS, KM_SCALE, KM_ATTENUATION, KM_ACTUALPOWER, KM_IF, KM_SAMPLETIME, KM_DRIVE +}; + + +#define KP_X(x) (48*(x) + 2 + (320-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_N 21 +#define KP_P 22 + + +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; + + +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 } +}; + +static const keypads_t keypads_scale[] = { + { 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 } +}; + +static const keypads_t keypads_level[] = { + { 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, 2, KP_MINUS }, + { 3, 3, KP_X1 }, + { 2, 3, KP_BS }, + { 0, 0, -1 } +}; + + +static const keypads_t * const keypads_mode_tbl[] = { + keypads_freq, // start + keypads_freq, // stop + keypads_freq, // center + keypads_freq, // span + keypads_freq, // cw freq + keypads_level, // refpos + keypads_scale, // scale + keypads_scale, // attenuation + keypads_level, // actual power + keypads_freq, // IF + keypads_level, // sample time + keypads_scale, // drive +}; + +#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[] = { + "START", "STOP", "CENTER", "SPAN", "CW FREQ", "REFPOS", "SCALE", "ATTENUATION", "ACTUALPOWER", "IF", "SAMPLE TIME", "DRIVE" +}; +#endif + + +// ===[MENU CALLBACKS]========================================================= + + +int generator_enabled = false; + +static void menu_mode_cb(int item, uint8_t data) +{ + (void)data; + switch (item) { + case 4: // Change reference output + break; + default: + SetMode(item); + menu_move_back(); + ui_mode_normal(); + draw_cal_status(); + break; + } + +} + +extern int dirty; +void menu_autosettings_cb(int item, uint8_t data) +{ + (void)item; + (void)data; + SetMode(M_LOW); +// set_sweep_frequency(ST_START, (int32_t) 0); +// set_sweep_frequency(ST_STOP, (int32_t) 300000000); + + int value = 10; // 10dB/ + set_trace_scale(0, value); + set_trace_scale(1, value); + set_trace_scale(2, value); + + value = -10; // Top at -10dB + set_trace_refpos(0, - value / get_trace_scale(0) + NGRIDY); + set_trace_refpos(1, - value / get_trace_scale(0) + NGRIDY); + set_trace_refpos(2, - value / get_trace_scale(0) + NGRIDY); + + active_marker = 0; + menu_marker_type_cb(M_REFERENCE,M_REFERENCE); + + set_refer_output(1); + SetAttenuation(0); + SetPowerLevel(100); // Reset + SetRBW(0); + dirty = true; + menu_move_back(); + ui_mode_normal(); + draw_cal_status(); +} + +static void menu_config_cb(int item, uint8_t data) +{ + (void)data; + switch (item) { + case 0: + touch_cal_exec(); + redraw_frame(); + request_to_redraw_grid(); + draw_menu(); + break; + case 1: + touch_draw_test(); + redraw_frame(); + request_to_redraw_grid(); + draw_menu(); + break; + case 2: + menu_move_back(); + ui_mode_normal(); + self_test(); + break; + case 3: + show_version(); + redraw_frame(); + request_to_redraw_grid(); + draw_menu(); + } +} + +static void menu_dfu_cb(int item, uint8_t data) +{ + (void)data; + switch (item) { + case 0: + enter_dfu(); + } +} + +int menu_refer_value[]={-1,0,1,2,3,4,5,6}; +static void menu_refer_cb(int item, uint8_t data) +{ + (void)data; +//Serial.println(item); + set_refer_output(menu_refer_value[item]); + menu_move_back(); + ui_mode_normal(); + draw_cal_status(); +} + +static void menu_refer_cb2(int item, uint8_t data) +{ + (void)data; +//Serial.println(item); + set_refer_output(menu_refer_value[item+5]); + menu_move_back(); + ui_mode_normal(); + draw_cal_status(); +} + +static void menu_spur_cb(int item, uint8_t data) +{ + (void)data; + (void)item; + if (GetSpur()) + SetSpur(0); + else + SetSpur(1); // must be 0 or 1 !!!! + menu_move_back(); + ui_mode_normal(); + draw_cal_status(); +} + +static void menu_storage_cb(int item, uint8_t data) +{ + (void)data; + switch(item) { + case 0: + SetStorage(); + break; + case 1: + SetClearStorage(); + break; + case 2: + SetSubtractStorage(); + break; + case 3: + toggle_waterfall(); + break; + } + menu_move_back(); + ui_mode_normal(); + draw_cal_status(); +} + +static void menu_average_cb(int item, uint8_t data) +{ + (void)data; + SetAverage(item); + menu_move_back(); + ui_mode_normal(); + draw_cal_status(); +} + +static void menu_marker_type_cb(int item, uint8_t data) +{ + (void)data; + if (markers[active_marker].enabled) + { + if (item == M_REFERENCE) { + for (int i = 0; i= 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: + set_sweep_frequency(ST_SPAN, uistat.value); + break; + case KM_CW: + set_sweep_frequency(ST_CW, uistat.value); + break; + case KM_SCALE: + set_trace_scale(0, uistat.value / 1000.0); + set_trace_scale(1, uistat.value / 1000.0); + set_trace_scale(2, uistat.value / 1000.0); + break; + case KM_REFPOS: + set_trace_refpos(0, NGRIDY - uistat.value / get_trace_scale(0)); + set_trace_refpos(1, NGRIDY - uistat.value / get_trace_scale(0)); + set_trace_refpos(2, NGRIDY - uistat.value / get_trace_scale(0)); + break; + case KM_ATTENUATION: + SetAttenuation(uistat.value); + break; + case KM_ACTUALPOWER: + SetPowerLevel(uistat.value); + config_save(); + break; + case KM_IF: + frequency_IF = uistat.value; + config_save(); + break; + case KM_SAMPLETIME: + settingSpeed = uistat.value; + break; + case KM_DRIVE: + settingDrive = uistat.value; + break; + } +}