Add compact RTC library (only 500 bytes for all, default RTC lib req ~ 2kB)

For enable use external (LSE) clock generator need un comment in Makefile
#UDEFS+= -DVNA_USE_LSE
By default use internal (LSI) clock generator, but it stop then VNA power off
For enable use external (LSE) clock generator, need install 32.768kHz clock quartz on PC14 and PC15 pins, it allow clock run while power off

For enable use RTC in code uncomment in nanovna.h
#define __USE_RTC__
This enable command 'time'
usage: time [y|m|d|h|min|sec] 0-99
Example set 2020 year run 'time y 20'

Add show current time in version screen
Better use font size constants for all screen size
pull/130/head
DiSlord 6 years ago
parent 3491ba2fbe
commit a8f36a4c5d

@ -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.

@ -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, &timespec);
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

@ -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.

@ -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
*/

145
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

58
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<<BIT_PUSH)))
@ -362,23 +363,46 @@ touch_position(int *x, int *y)
void
show_version(void)
{
int x = 5, y = 5, i = 0;
int x = 5, y = 5, i = 1;
adc_stop();
ili9341_set_foreground(DEFAULT_FG_COLOR);
ili9341_set_background(DEFAULT_BG_COLOR);
ili9341_clear_screen();
uint16_t shift = 0b0000010000111110;
ili9341_drawstring_size(info_about[i++], x , y, 4);
uint16_t shift = 0b000100000;
ili9341_drawstring_size(BOARD_NAME, x , y, 3);
y+=FONT_GET_HEIGHT*3+3-5;
while (info_about[i]) {
do {shift>>=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);
}
}
}

Loading…
Cancel
Save

Powered by TurnKey Linux.