diff --git a/chconf.h b/chconf.h index deb0f9e..d4f1b6b 100644 --- a/chconf.h +++ b/chconf.h @@ -147,7 +147,7 @@ * * @note The default is @p TRUE. */ -#define CH_CFG_USE_REGISTRY TRUE +#define CH_CFG_USE_REGISTRY FALSE /** * @brief Threads synchronization APIs. diff --git a/main.c b/main.c index ff52df4..0cfed2f 100644 --- a/main.c +++ b/main.c @@ -61,8 +61,6 @@ static volatile vna_shellcmd_t shell_function = 0; //#define ENABLED_DUMP // Allow get threads debug info //#define ENABLE_THREADS_COMMAND -// RTC time not used -//#define ENABLE_TIME_COMMAND // Enable vbat_offset command, allow change battery voltage correction in config #define ENABLE_VBAT_OFFSET_COMMAND // Info about NanoVNA, need fore soft @@ -337,8 +335,8 @@ static const uint8_t gain_table[][2] = { { 0, 0 }, // 1st: 0 ~ 300MHz { 50, 50 }, // 2nd: 300 ~ 900MHz { 75, 75 }, // 3th: 900 ~ 1500MHz - { 85, 85 }, // 4th: 1500 ~ 1800MHz - { 95, 95 }, // 5th: 2100 ~ 2400MHz + { 85, 85 }, // 4th: 1500 ~ 2100MHz + { 95, 95 }, // 5th: 2100 ~ 2700MHz }; #define DELAY_GAIN_CHANGE 4 @@ -515,17 +513,32 @@ VNA_SHELL_FUNCTION(cmd_power) // set_frequency(frequency); } -#ifdef ENABLE_TIME_COMMAND -#if HAL_USE_RTC == FALSE -#error "Error cmd_time require define HAL_USE_RTC = TRUE in halconf.h" -#endif +#ifdef __USE_RTC__ VNA_SHELL_FUNCTION(cmd_time) { - RTCDateTime timespec; (void)argc; (void)argv; - rtcGetTime(&RTCD1, ×pec); - shell_printf("%d/%d/%d %d\r\n", timespec.year+1980, timespec.month, timespec.day, timespec.millisecond); + uint32_t dt_buf[2]; + dt_buf[0] = rtc_get_tr_bcd(); // TR should be read first for sync + dt_buf[1] = rtc_get_dr_bcd(); // DR should be read second + static const uint8_t idx_to_time[] = {6,5,4,2, 1, 0}; + static const char time_cmd[] = "y|m|d|h|min|sec"; + // 0 1 2 4 5 6 + // time[] ={sec, min, hr, 0, day, month, year, 0} + uint8_t *time = (uint8_t*)dt_buf; + + if (argc!=2) goto usage; + int idx = get_str_index(argv[0], time_cmd); + uint32_t val = my_atoui(argv[1]); + if (idx < 0 || val > 99) + goto usage; + // Write byte value in struct + time[idx_to_time[idx]] = ((val/10)<<4)|(val%10); // value in bcd format + rtc_set_time(dt_buf[1], dt_buf[0]); + return; +usage: + shell_printf("20%02X/%02X/%02X %02X:%02X:%02X\r\n", time[6], time[5], time[4], time[2], time[1], time[0]); + shell_printf("usage: time [%s] 0-99\r\n", time_cmd); } #endif @@ -2269,7 +2282,7 @@ static const VNAShellCommand commands[] = {"freq" , cmd_freq , CMD_WAIT_MUTEX}, {"offset" , cmd_offset , CMD_WAIT_MUTEX}, {"bandwidth" , cmd_bandwidth , 0}, -#ifdef ENABLE_TIME_COMMAND +#ifdef __USE_RTC__ {"time" , cmd_time , 0}, #endif {"dac" , cmd_dac , 0}, @@ -2486,6 +2499,10 @@ int main(void) { halInit(); chSysInit(); +#ifdef __USE_RTC__ + rtc_init(); // Initialize RTC library +#endif + #ifdef USE_VARIABLE_OFFSET generate_DSP_Table(FREQUENCY_OFFSET); #endif diff --git a/mcuconf.h b/mcuconf.h index a1da287..8c8842a 100644 --- a/mcuconf.h +++ b/mcuconf.h @@ -42,9 +42,7 @@ #define STM32_HSI_ENABLED TRUE #define STM32_HSI14_ENABLED TRUE #define STM32_HSI48_ENABLED TRUE -#define STM32_LSI_ENABLED TRUE #define STM32_HSE_ENABLED FALSE -#define STM32_LSE_ENABLED FALSE #define STM32_SW STM32_SW_PLL #define STM32_PLLSRC STM32_PLLSRC_HSI_DIV2 #define STM32_PREDIV_VALUE 1 @@ -61,7 +59,27 @@ //#define STM32_I2C1SW STM32_I2C1SW_HSI #define STM32_I2C1SW STM32_I2C1SW_SYSCLK #define STM32_USART1SW STM32_USART1SW_PCLK + +/* + * RTC driver system settings for stm32f303 + */ + +#ifndef VNA_USE_LSE +// Use 40kHz LSI +#define STM32_LSE_ENABLED FALSE +#define STM32_LSI_ENABLED TRUE #define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTC_PRESA_VALUE 40 +#define STM32_RTC_PRESS_VALUE 1000 +#else +// Use 32768Hz LSE +#define STM32_LSE_ENABLED TRUE +#define STM32_LSI_ENABLED FALSE +#define STM32_RTCSEL STM32_RTCSEL_LSE +#define STM32_RTC_PRESA_VALUE 32 +#define STM32_RTC_PRESS_VALUE 1024 +#define STM32_LSEDRV (3 << 3) +#endif /* * ADC driver system settings. diff --git a/nanovna.h b/nanovna.h index 7222bcf..a86f5a9 100644 --- a/nanovna.h +++ b/nanovna.h @@ -21,6 +21,8 @@ // Need enable HAL_USE_SPI in halconf.h #define __USE_DISPLAY_DMA__ +// Add RTC clock support +//#define __USE_RTC__ /* * main.c @@ -405,6 +407,37 @@ void ili9341_line(int x0, int y0, int x1, int y1); void show_version(void); void show_logo(void); +/* + * rtc.c + */ +#ifdef __USE_RTC__ +#define RTC_START_YEAR 2000 + +#define RTC_DR_YEAR(dr) (((dr)>>16)&0xFF) +#define RTC_DR_MONTH(dr) (((dr)>> 8)&0xFF) +#define RTC_DR_DAY(dr) (((dr)>> 0)&0xFF) + +#define RTC_TR_HOUR(dr) (((tr)>>16)&0xFF) +#define RTC_TR_MIN(dr) (((tr)>> 8)&0xFF) +#define RTC_TR_SEC(dr) (((tr)>> 0)&0xFF) + +// Init RTC +void rtc_init(void); +// Then read time and date TR should read first, after DR !!! +// Get RTC time as bcd structure in 0x00HHMMSS +#define rtc_get_tr_bcd() (RTC->TR & 0x007F7F7F) +// Get RTC date as bcd structure in 0x00YYMMDD (remove day of week information!!!!) +#define rtc_get_dr_bcd() (RTC->DR & 0x00FF1F3F) +// read TR as 0x00HHMMSS in bin (TR should be read first for sync) +uint32_t rtc_get_tr_bin(void); +// read DR as 0x00YYMMDD in bin (DR should be read second) +uint32_t rtc_get_dr_bin(void); +// Read time in FAT filesystem format +uint32_t rtc_get_FAT(void); +// Write date and time (need in bcd format!!!) +void rtc_set_time(uint32_t dr, uint32_t tr); +#endif + /* * flash.c */ diff --git a/rtc.c b/rtc.c new file mode 100644 index 0000000..13e33dc --- /dev/null +++ b/rtc.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014-2020, Dmitry (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 "ch.h" +#include "hal.h" +#include "nanovna.h" + +#ifdef __USE_RTC__ + +// Compact STM32 RTC time library +#if HAL_USE_RTC == TRUE +#error "Error VNA use self RTC lib, define HAL_USE_RTC = FALSE in halconf.h" +#endif + +// Get RTC time as binary structure in 0x00HHMMSS +uint32_t rtc_get_tr_bin(void){ + uint32_t tr = RTC->TR; + uint32_t v = (tr&0x0F0F0F) + ((tr&0x707070)>>1) + ((tr&0x707070)>>3); + return v; +} + +// Get RTC time as binary structure in 0x00YYMMDD +uint32_t rtc_get_dr_bin(void){ + uint32_t dr = RTC->DR; + uint32_t v = (dr&0x000F0F0F) + ((dr&0x00F01030)>>1) + ((dr&0x00F01030)>>3); + return v;// | ((dr&0xE000)<<15); // day of week at end +} + +uint32_t rtc_get_FAT(void) { + uint32_t fattime; + uint32_t tr = rtc_get_tr_bin(); + uint32_t dr = rtc_get_dr_bin(); + fattime = ((tr>> 0)&0xFF) >> 1U; // Seconds / 2 + fattime |= ((tr>> 8)&0xFF) << 5U; // Minutes + fattime |= ((tr>>16)&0xFF) << 11U; // Hour + fattime |= ((dr>> 0)&0xFF) << 16U; // Day + fattime |= ((dr>> 8)&0xFF) << 21U; // Month + fattime |= (((dr>>16)&0xFF) + RTC_START_YEAR - 1980) << 25U; // Local year begin from 2000, fat from 1980 + return fattime; +} + +void rtc_set_time(uint32_t dr, uint32_t tr) { + // Beginning of configuration procedure. + RTC->ISR |= RTC_ISR_INIT; + while ((RTC->ISR & RTC_ISR_INITF) == 0) + ; + // Writing the registers. + RTC->TR = tr; + RTC->DR = dr; + RTC->ISR &= ~RTC_ISR_INIT; +} + +#define RTC_PRER(a, s) ((((a) - 1) << 16) | ((s) - 1)) + +// Initiate RTC clock, LSE or LSI generators initiate by ChibiOS !!! +void rtc_init(void){ + // Disable write protection. + RTC->WPR = 0xCA; + RTC->WPR = 0x53; + // If calendar has not been initialized yet then proceed with the initial setup. + if (!(RTC->ISR & RTC_ISR_INITS)) { + // Beginning of configuration procedure. + RTC->ISR |= RTC_ISR_INIT; + while ((RTC->ISR & RTC_ISR_INITF) == 0) + ; + RTC->CR = 0; + RTC->ISR = RTC_ISR_INIT; // Clearing all but RTC_ISR_INIT. + RTC->PRER = RTC_PRER(STM32_RTC_PRESA_VALUE, STM32_RTC_PRESS_VALUE); + RTC->PRER = RTC_PRER(STM32_RTC_PRESA_VALUE, STM32_RTC_PRESS_VALUE); + RTC->ISR &= ~RTC_ISR_INIT; + } + else + RTC->ISR &= ~RTC_ISR_RSF; +#if 0 + // ChibiOS init BDCR by self!! + // For add auto select RTC source need rewrite it + // see hal_lld_backup_domain_init() in hal_lld.c for every CPU + // Default RTC clock is LSE, but it possible not launch if no quartz installed + uint32_t rtc_drv = STM32_RTCSEL_LSI; + uint32_t rtc_prer = RTC_PRER(40, 1000); + + // If LSE off try launch it + if ((RCC->BDCR & RCC_BDCR_LSEON) == 0){ + // Try start LSE + RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON; + uint32_t count = 65535; + do{ + if (RCC->BDCR & RCC_BDCR_LSERDY) break; + }while (--count);// Waits until LSE is stable. or count == 0 + } + // Check, if LSE ready, then prepare it data + if (RCC->BDCR & RCC_BDCR_LSERDY){ + rtc_drv = STM32_RTCSEL_LSE; + rtc_prer = RTC_PRER(32, 1024); + } else{ + // Try start LSI + RCC->CSR |= RCC_CSR_LSION; + while ((RCC->CSR & RCC_CSR_LSIRDY) == 0) + ; + } + + PWR->CR |= PWR_CR_DBP; + // If the backup domain hasn't been initialized yet then proceed with initialization or source different + if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0 || (RCC->BDCR & STM32_RTCSEL_MASK)!=rtc_drv) { + // Backup domain reset. + RCC->BDCR = RCC_BDCR_BDRST; + RCC->BDCR = 0; + // Selects clock source. + RCC->BDCR |= rtc_drv; + // Disable write protection. + RTC->WPR = 0xCA; + RTC->WPR = 0x53; + // Beginning of configuration procedure. + RTC->ISR |= RTC_ISR_INIT; + while ((RTC->ISR & RTC_ISR_INITF) == 0) + ; + // Prescaler value loaded in registers. + RTC->CR = 0; + RTC->ISR = RTC_ISR_INIT; // Clearing all but RTC_ISR_INIT. + RTC->PRER = rtc_prer; + RTC->PRER = rtc_prer; + // Finalizing of configuration procedure. + RTC->ISR &= ~RTC_ISR_INIT; + RCC->BDCR |= RCC_BDCR_RTCEN; // RTC clock enabled. + } +#endif +} +#endif diff --git a/ui.c b/ui.c index 7e3336d..a5514c9 100644 --- a/ui.c +++ b/ui.c @@ -41,10 +41,10 @@ uistat_t uistat = { #define EVT_DOWN 0x20 #define EVT_REPEAT 0x40 -#define BUTTON_DOWN_LONG_TICKS 5000 /* 1sec */ -#define BUTTON_DOUBLE_TICKS 2500 /* 500ms */ -#define BUTTON_REPEAT_TICKS 200 /* 40ms */ -#define BUTTON_DEBOUNCE_TICKS 100 /* 20ms */ +#define BUTTON_DOWN_LONG_TICKS 5000 /* 500ms */ +#define BUTTON_DOUBLE_TICKS 2500 /* 250ms */ +#define BUTTON_REPEAT_TICKS 200 /* 20ms */ +#define BUTTON_DEBOUNCE_TICKS 400 /* 40ms */ /* lever switch assignment */ #define BIT_UP1 3 @@ -155,10 +155,11 @@ static int btn_wait_release(void) systime_t ticks = chVTGetSystemTimeX(); systime_t dt = ticks - last_button_down_ticks; // Debounce input - if (dt < BUTTON_DEBOUNCE_TICKS){ - chThdSleepMilliseconds(10); - continue; - } +// if (dt < BUTTON_DEBOUNCE_TICKS){ +// chThdSleepMilliseconds(10); +// continue; +// } + chThdSleepMilliseconds(1); uint16_t cur_button = READ_PORT() & BUTTON_MASK; uint16_t changed = last_button ^ cur_button; if (dt >= BUTTON_DOWN_LONG_TICKS && (cur_button & (1<>=1; y+=5;} while (shift&1); - ili9341_drawstring(info_about[i++], x, y+=5); + ili9341_drawstring(info_about[i++], x, y+=FONT_STR_HEIGHT+3-5); } + // Update battery and time + y+=3*FONT_STR_HEIGHT; + uint16_t cnt = 0; while (true) { if (touch_check() == EVT_TOUCH_PRESSED) break; if (btn_check() & EVT_BUTTON_SINGLE_CLICK) break; + chThdSleepMilliseconds(40); + if ((cnt++)&0x07) continue; // Not update time so fast + +#ifdef __USE_RTC__ + char buffer[32]; + uint32_t tr = rtc_get_tr_bin(); // TR read first + uint32_t dr = rtc_get_dr_bin(); // DR read second + plot_printf(buffer, sizeof(buffer), "Time: 20%02d/%02d/%02d %02d:%02d:%02d", + RTC_DR_YEAR(dr), + RTC_DR_MONTH(dr), + RTC_DR_DAY(dr), + RTC_TR_HOUR(dr), + RTC_TR_MIN(dr), + RTC_TR_SEC(dr)); + ili9341_drawstring(buffer, x, y); +#endif +// uint32_t vbat = adc_vbat_read(); +// plot_printf(buffer, sizeof(buffer), "Battery: %d.%03dV", vbat/1000, vbat%1000); +// ili9341_drawstring(buffer, x, y + FONT_STR_HEIGHT + 2); } touch_start_watchdog(); @@ -1447,12 +1471,12 @@ draw_menu_buttons(const menuitem_t *menu) ili9341_set_foreground(fg); ili9341_set_background(bg); if (menu_is_multiline(menu[i].label, &l1, &l2)) { - ili9341_fill(LCD_WIDTH-MENU_BUTTON_WIDTH+3, y+5, MENU_BUTTON_WIDTH-6, 2+FONT_GET_HEIGHT+1+FONT_GET_HEIGHT+2, bg); - ili9341_drawstring(l1, LCD_WIDTH-MENU_BUTTON_WIDTH+5, y+7); - ili9341_drawstring(l2, LCD_WIDTH-MENU_BUTTON_WIDTH+5, y+7+FONT_GET_HEIGHT+1); + ili9341_fill(LCD_WIDTH-MENU_BUTTON_WIDTH+3, y+MENU_BUTTON_HEIGHT/2-FONT_GET_HEIGHT-3, MENU_BUTTON_WIDTH-6, 2+FONT_GET_HEIGHT+1+FONT_GET_HEIGHT+2, bg); + ili9341_drawstring(l1, LCD_WIDTH-MENU_BUTTON_WIDTH+5, y+MENU_BUTTON_HEIGHT/2-FONT_GET_HEIGHT-1); + ili9341_drawstring(l2, LCD_WIDTH-MENU_BUTTON_WIDTH+5, y+MENU_BUTTON_HEIGHT/2); } else { - ili9341_fill(LCD_WIDTH-MENU_BUTTON_WIDTH+3, y+8, MENU_BUTTON_WIDTH-6, 2+FONT_GET_HEIGHT+2, bg); - ili9341_drawstring(menu[i].label, LCD_WIDTH-MENU_BUTTON_WIDTH+5, y+10); + ili9341_fill(LCD_WIDTH-MENU_BUTTON_WIDTH+3, y+(MENU_BUTTON_HEIGHT-FONT_GET_HEIGHT-6)/2, MENU_BUTTON_WIDTH-6, 2+FONT_GET_HEIGHT+2, bg); + ili9341_drawstring(menu[i].label, LCD_WIDTH-MENU_BUTTON_WIDTH+5, y+(MENU_BUTTON_HEIGHT-FONT_GET_HEIGHT-6)/2+2); } } }