2019-02-20 19:14:08 +01:00
/** STM32F1 BusVoodoo application
2020-02-17 18:08:17 +01:00
* @ file
2016-08-14 21:02:38 +02:00
* @ author King Kévin < kingkevin @ cuvoodoo . info >
2020-06-06 14:35:55 +02:00
* @ copyright SPDX - License - Identifier : GPL - 3.0 - or - later
2020-02-17 18:08:17 +01:00
* @ date 2016 - 2020
2016-08-14 21:02:38 +02:00
*/
2016-01-17 14:54:54 +01:00
/* standard libraries */
# include <stdint.h> // standard integer types
2016-08-14 21:02:38 +02:00
# include <string.h> // string utilities
2016-01-17 14:54:54 +01:00
/* STM32 (including CM3) libraries */
2016-01-18 16:23:35 +01:00
# include <libopencmsis/core_cm3.h> // Cortex M3 utilities
2016-10-23 17:42:27 +02:00
# include <libopencm3/stm32/gpio.h> // general purpose input output library
# include <libopencm3/stm32/rcc.h> // real-time control clock library
2019-02-20 19:14:08 +01:00
# include <libopencm3/stm32/dbgmcu.h> // debug utilities
2016-08-14 21:02:38 +02:00
# include <libopencm3/stm32/rtc.h> // real time clock utilities
2016-10-23 17:42:27 +02:00
# include <libopencm3/stm32/iwdg.h> // independent watchdog utilities
2016-01-17 14:54:54 +01:00
/* own libraries */
2016-01-28 21:21:50 +01:00
# include "global.h" // board definitions
2017-04-03 13:32:45 +02:00
# include "print.h" // printing utilities
2016-01-18 16:23:35 +01:00
# include "usb_cdcacm.h" // USB CDC ACM utilities
2018-04-06 17:37:17 +02:00
# include "terminal.h" // handle the terminal interface
# include "menu.h" // menu utilities
2019-02-20 19:14:08 +01:00
# include "busvoodoo_global.h" // BusVoodoo definitions
# include "busvoodoo_hiz.h" // BusVoodoo HiZ mode
# include "busvoodoo_uart.h" // BusVoodoo UART mode
# include "busvoodoo_i2c.h" // BusVoodoo I2C mode
# include "busvoodoo_spi.h" // BusVoodoo SPI mode
# include "busvoodoo_onewire.h" // BusVoodoo 1-wire mode
2021-03-30 17:41:35 +02:00
# if BUSVOODOO_HARDWARE_VERSION != 2
2020-03-09 13:09:01 +01:00
# include "uart.h" // USART utilities
# include "busvoodoo_oled.h" // OLED utilities
2019-02-20 19:14:08 +01:00
# include "busvoodoo_rs232.h" // BusVoodoo RS-232 mode
# include "busvoodoo_rs485.h" // BusVoodoo RS-485/422 mode
# include "busvoodoo_sdio.h" // BusVoodoo SDIO mode
2020-03-09 13:09:01 +01:00
# endif
2016-01-17 14:54:54 +01:00
2020-02-02 21:19:03 +01:00
/** watchdog period in ms */
# define WATCHDOG_PERIOD 10000
2019-06-18 17:43:43 +02:00
/** set to 0 if the RTC is reset when the board is powered on, only indicates the uptime
* set to 1 if VBAT can keep the RTC running when the board is unpowered , indicating the date and time
*/
2020-02-02 21:19:03 +01:00
# define RTC_DATE_TIME 0
/** number of RTC ticks per second
* @ note use integer divider of oscillator to keep second precision
*/
# define RTC_TICKS_SECOND 4
2019-06-18 17:43:43 +02:00
2019-02-20 19:14:08 +01:00
/** all supported BusVoodoo modes */
static const struct busvoodoo_mode_t * busvoodoo_modes [ ] = {
& busvoodoo_hiz_mode ,
& busvoodoo_uart_mode ,
& busvoodoo_i2c_mode ,
& busvoodoo_spi_mode ,
& busvoodoo_onewire_mode ,
2021-03-30 17:41:35 +02:00
# if BUSVOODOO_HARDWARE_VERSION != 2
2019-02-20 19:14:08 +01:00
& busvoodoo_rs232_mode ,
& busvoodoo_rs485_mode ,
& busvoodoo_sdio_mode ,
2020-03-09 13:09:01 +01:00
# endif
2019-02-20 19:14:08 +01:00
} ;
/** current BusVoodoo mode */
static struct busvoodoo_mode_t const * busvoodoo_mode = NULL ;
/** is mode setup complete */
static bool busvoodoo_mode_complete = false ;
2017-04-03 13:32:45 +02:00
size_t putc ( char c )
2016-01-17 14:54:54 +01:00
{
2017-04-03 13:32:45 +02:00
size_t length = 0 ; // number of characters printed
2018-04-06 17:37:17 +02:00
static char last_c = 0 ; // to remember on which character we last sent
if ( ' \n ' = = c ) { // send carriage return (CR) + line feed (LF) newline for each LF
if ( ' \r ' ! = last_c ) { // CR has not already been sent
2020-03-09 13:09:01 +01:00
# if BUSVOODOO_HARDWARE_VERSION != 2
2018-02-18 15:18:42 +01:00
uart_putchar_nonblocking ( ' \r ' ) ; // send CR over USART
2020-03-09 13:09:01 +01:00
# endif
2017-04-19 16:24:07 +02:00
usb_cdcacm_putchar ( ' \r ' ) ; // send CR over USB
2018-04-06 17:37:17 +02:00
length + + ; // remember we printed 1 character
2016-01-17 14:54:54 +01:00
}
}
2020-03-09 13:09:01 +01:00
# if BUSVOODOO_HARDWARE_VERSION != 2
2018-04-06 17:37:17 +02:00
uart_putchar_nonblocking ( c ) ; // send byte over USART
2020-03-09 13:09:01 +01:00
# endif
2018-04-06 17:37:17 +02:00
usb_cdcacm_putchar ( c ) ; // send byte over USB
length + + ; // remember we printed 1 character
last_c = c ; // remember last character
2019-03-26 19:27:40 +01:00
return length ; // return number of characters printed
2016-01-17 14:54:54 +01:00
}
2019-02-20 19:14:08 +01:00
/** switch BusVoddoo mode
* @ param [ in ] mode mode to switch to
2018-04-06 17:37:17 +02:00
*/
2019-02-20 19:14:08 +01:00
static void switch_mode ( const struct busvoodoo_mode_t * mode )
{
if ( busvoodoo_mode ) {
( * busvoodoo_mode - > exit ) ( ) ; // exit current mode
}
busvoodoo_leds_off ( ) ; // switch off LEDs
busvoodoo_safe_state ( ) ; // return to safe state
// reset pinout
2020-03-09 15:20:28 +01:00
for ( uint8_t i = 0 ; i < LENGTH ( busvoodoo_global_pinout_io ) ; i + + ) {
2019-02-20 19:14:08 +01:00
busvoodoo_global_pinout_io [ i ] = NULL ;
}
2020-03-09 13:09:01 +01:00
# if BUSVOODOO_HARDWARE_VERSION != 2
2020-03-09 15:20:28 +01:00
for ( uint8_t i = 0 ; i < LENGTH ( busvoodoo_global_pinout_rscan ) ; i + + ) {
2020-03-09 13:09:01 +01:00
busvoodoo_global_pinout_rscan [ i ] = NULL ;
}
2019-02-20 19:14:08 +01:00
busvoodoo_oled_clear ( ) ; // clear OLED display buffer
busvoodoo_oled_update ( ) ; // update OLED display
2020-03-09 13:09:01 +01:00
# endif
2020-03-09 15:20:28 +01:00
if ( NULL = = mode ) { // no mode provided
2019-02-20 19:14:08 +01:00
busvoodoo_mode = & busvoodoo_hiz_mode ; // use default mode
} else { // mode provided
busvoodoo_mode = mode ; // set provided mode a current mode
}
busvoodoo_mode_complete = ( * busvoodoo_mode - > setup ) ( & terminal_prefix , NULL ) ; // start setup
terminal_send ( 0 ) ; // update the terminal prompt
}
2018-04-06 17:37:17 +02:00
2019-02-20 19:14:08 +01:00
/** command to show help
2018-04-06 17:37:17 +02:00
* @ param [ in ] argument no argument required
*/
2019-02-20 19:14:08 +01:00
static void command_help ( void * argument ) ;
/** command to select mode
* @ param [ in ] argument mode to select
2018-04-06 17:37:17 +02:00
*/
2019-02-20 19:14:08 +01:00
static void command_mode ( void * argument ) ;
/** command to quit current BusVoodoo mode
* @ param [ in ] argument no argument required
2019-06-18 17:43:43 +02:00
*/
2019-02-20 19:14:08 +01:00
static void command_quit ( void * argument ) ;
/** command to reset board
2018-04-06 17:37:17 +02:00
* @ param [ in ] argument no argument required
*/
static void command_reset ( void * argument ) ;
2019-02-20 19:14:08 +01:00
/** command to reboot into bootloader
2018-04-06 17:37:17 +02:00
* @ param [ in ] argument no argument required
*/
/** list of all supported commands */
static const struct menu_command_t menu_commands [ ] = {
{
2019-02-20 19:14:08 +01:00
. shortcut = ' m ' ,
. name = " mode " ,
. command_description = " select mode " ,
. argument = MENU_ARGUMENT_STRING ,
. argument_description = " [mode] " ,
. command_handler = & command_mode ,
2018-04-06 17:37:17 +02:00
} ,
{
2019-02-20 19:14:08 +01:00
. shortcut = ' q ' ,
. name = " quit " ,
. command_description = " quit current mode " ,
2018-04-06 17:37:17 +02:00
. argument = MENU_ARGUMENT_NONE ,
. argument_description = NULL ,
2019-02-20 19:14:08 +01:00
. command_handler = & command_quit ,
2018-04-06 17:37:17 +02:00
} ,
2019-06-18 17:43:43 +02:00
{
2019-02-20 19:14:08 +01:00
. shortcut = ' R ' ,
2018-04-06 17:37:17 +02:00
. name = " reset " ,
. command_description = " reset board " ,
. argument = MENU_ARGUMENT_NONE ,
. argument_description = NULL ,
. command_handler = & command_reset ,
} ,
{
2019-02-20 19:14:08 +01:00
. shortcut = ' h ' ,
. name = " help " ,
. command_description = " display help " ,
2018-04-06 17:37:17 +02:00
. argument = MENU_ARGUMENT_NONE ,
. argument_description = NULL ,
2019-02-20 19:14:08 +01:00
. command_handler = & command_help ,
2018-04-06 17:37:17 +02:00
} ,
} ;
static void command_help ( void * argument )
{
( void ) argument ; // we won't use the argument
printf ( " available commands: \n " ) ;
menu_print_commands ( menu_commands , LENGTH ( menu_commands ) ) ; // print global commands
2019-02-20 19:14:08 +01:00
menu_print_commands ( busvoodoo_global_commands , busvoodoo_global_commands_nb ) ; // print BusVoodoo global commands
2020-03-09 13:09:01 +01:00
# if BUSVOODOO_HARDWARE_VERSION != 2
2019-02-20 19:14:08 +01:00
if ( busvoodoo_full ) {
menu_print_commands ( busvoodoo_global_full_commands , busvoodoo_global_full_commands_nb ) ; // print BusVoodoo global commands
}
2020-03-09 13:09:01 +01:00
# endif
2019-02-20 19:14:08 +01:00
if ( ! busvoodoo_mode - > full_only | | busvoodoo_full ) {
menu_print_commands ( busvoodoo_mode - > commands , busvoodoo_mode - > commands_nb ) ; // print BusVoodoo mode commands
}
2018-04-06 17:37:17 +02:00
}
2019-02-20 19:14:08 +01:00
static void command_mode ( void * argument )
2019-06-18 17:43:43 +02:00
{
2020-03-09 15:20:28 +01:00
if ( NULL = = argument | | 0 = = strlen ( argument ) ) { // no mode provided: list all modes
2019-02-20 19:14:08 +01:00
printf ( " available modes: \n " ) ;
2020-03-09 15:20:28 +01:00
for ( uint8_t i = 0 ; i < LENGTH ( busvoodoo_modes ) ; i + + ) { // go through all modes
2019-02-20 19:14:08 +01:00
if ( ! busvoodoo_modes [ i ] - > full_only | | busvoodoo_full ) {
printf ( " %s \t %s \n " , busvoodoo_modes [ i ] - > name , busvoodoo_modes [ i ] - > description ) ; // display mode information
}
2019-06-18 17:43:43 +02:00
}
2019-02-20 19:14:08 +01:00
} else { // mode provided
bool mode_found = false ; // to know if we found the matching mode
2020-03-09 15:20:28 +01:00
for ( uint8_t i = 0 ; i < LENGTH ( busvoodoo_modes ) ; i + + ) { // go through all modes
if ( 0 = = strcmp ( argument , busvoodoo_modes [ i ] - > name ) ) { // check for corresponding mode
2019-02-20 19:14:08 +01:00
if ( ! busvoodoo_mode - > full_only | | busvoodoo_full ) {
switch_mode ( busvoodoo_modes [ i ] ) ; // switch to mode
} else {
printf ( " mode only available for BusVoodoo full \n " ) ;
}
mode_found = true ; // remember we found the mode
break ; // stop searching for mode
}
}
if ( ! mode_found ) {
printf ( " unknown mode: %s \n " , argument ) ;
2019-06-18 17:43:43 +02:00
}
}
}
2019-02-20 19:14:08 +01:00
static void command_quit ( void * argument )
2018-04-06 17:37:17 +02:00
{
( void ) argument ; // we won't use the argument
2019-02-20 19:14:08 +01:00
switch_mode ( NULL ) ; // switch do default mode
2018-04-06 17:37:17 +02:00
}
2019-02-20 19:14:08 +01:00
static void command_reset ( void * argument )
2018-04-06 17:37:17 +02:00
{
( void ) argument ; // we won't use the argument
2019-02-20 19:14:08 +01:00
scb_reset_system ( ) ; // reset device
2018-04-06 17:37:17 +02:00
while ( true ) ; // wait for the reset to happen
}
2016-01-17 14:54:54 +01:00
2016-08-14 21:02:38 +02:00
/** process user command
* @ param [ in ] str user command string ( \ 0 ended )
*/
static void process_command ( char * str )
2016-01-17 14:54:54 +01:00
{
2018-04-06 17:37:17 +02:00
// ensure actions are available
2019-06-18 17:44:50 +02:00
if ( NULL = = menu_commands | | 0 = = LENGTH ( menu_commands ) ) {
2018-04-06 17:37:17 +02:00
return ;
2016-08-14 21:02:38 +02:00
}
2019-02-20 19:14:08 +01:00
// handle user input
2020-03-09 15:20:28 +01:00
if ( NULL = = busvoodoo_mode ) { // no mode set
2019-02-20 19:14:08 +01:00
switch_mode ( NULL ) ; // set default mode
2018-04-06 17:37:17 +02:00
}
2019-02-20 19:14:08 +01:00
if ( ! busvoodoo_mode_complete ) { // mode setup is not complete
busvoodoo_mode_complete = ( * busvoodoo_mode - > setup ) ( & terminal_prefix , str ) ; // continue setup
terminal_send ( 0 ) ; // update the terminal prompt
} else { // mode setup is complete
// don't handle empty lines
2020-03-09 15:20:28 +01:00
if ( ! str | | 0 = = strlen ( str ) ) {
2019-02-20 19:14:08 +01:00
return ;
}
bool command_handled = false ;
if ( ! busvoodoo_mode - > full_only | | busvoodoo_full ) {
command_handled = menu_handle_command ( str , busvoodoo_mode - > commands , busvoodoo_mode - > commands_nb ) ; // try if the mode can handle this command
}
2020-03-09 13:09:01 +01:00
# if BUSVOODOO_HARDWARE_VERSION != 2
2019-02-20 19:14:08 +01:00
if ( ! command_handled & & busvoodoo_full ) {
command_handled = menu_handle_command ( str , busvoodoo_global_full_commands , busvoodoo_global_full_commands_nb ) ; // try if full BusVoodoo can handle this command
}
2020-03-09 13:09:01 +01:00
# endif
2019-02-20 19:14:08 +01:00
if ( ! command_handled ) {
command_handled = menu_handle_command ( str , busvoodoo_global_commands , busvoodoo_global_commands_nb ) ; // try if the base BusVoodoo can handle this command
}
if ( ! command_handled ) {
command_handled = menu_handle_command ( str , menu_commands , LENGTH ( menu_commands ) ) ; // try if this is not a global command
}
if ( ! command_handled ) {
printf ( " command not recognized. enter help to list commands \n " ) ;
}
2016-08-14 21:02:38 +02:00
}
2016-01-17 14:54:54 +01:00
}
2016-08-14 21:02:38 +02:00
/** program entry point
* this is the firmware function started by the micro - controller
*/
2016-10-23 17:42:27 +02:00
void main ( void ) ;
void main ( void )
2018-04-06 17:37:17 +02:00
{
2016-01-29 00:24:49 +01:00
rcc_clock_setup_in_hse_8mhz_out_72mhz ( ) ; // use 8 MHz high speed external clock to generate 72 MHz internal clock
2016-08-14 21:02:38 +02:00
2016-10-23 17:42:27 +02:00
# if DEBUG
2017-01-30 09:44:51 +01:00
// enable functionalities for easier debug
2016-10-23 17:42:27 +02:00
DBGMCU_CR | = DBGMCU_CR_IWDG_STOP ; // stop independent watchdog counter when code is halted
DBGMCU_CR | = DBGMCU_CR_WWDG_STOP ; // stop window watchdog counter when code is halted
DBGMCU_CR | = DBGMCU_CR_STANDBY ; // allow debug also in standby mode (keep digital part and clock powered)
DBGMCU_CR | = DBGMCU_CR_STOP ; // allow debug also in stop mode (keep clock powered)
DBGMCU_CR | = DBGMCU_CR_SLEEP ; // allow debug also in sleep mode (keep clock powered)
2017-02-06 17:40:28 +01:00
# else
2017-01-30 09:44:51 +01:00
// setup watchdog to reset in case we get stuck (i.e. when an error occurred)
iwdg_set_period_ms ( WATCHDOG_PERIOD ) ; // set independent watchdog period
iwdg_start ( ) ; // start independent watchdog
2016-10-23 17:42:27 +02:00
# endif
2019-02-20 19:14:08 +01:00
// setup board
2017-04-03 13:32:45 +02:00
board_setup ( ) ; // setup board
2020-03-09 13:09:01 +01:00
# if BUSVOODOO_HARDWARE_VERSION != 2
2018-02-18 15:18:42 +01:00
uart_setup ( ) ; // setup USART (for printing)
2020-03-09 13:09:01 +01:00
# endif
2019-02-20 19:14:08 +01:00
busvoodoo_setup ( ) ; // setup BusVoodoo board
2017-04-19 16:26:40 +02:00
usb_cdcacm_setup ( ) ; // setup USB CDC ACM (for printing)
2020-03-09 13:08:13 +01:00
puts ( " \n welcome to \x1b [32mBus \x1b [35mVoodoo \x1b [0m \n " ) ; // print welcome message
2016-01-29 00:24:49 +01:00
2019-12-21 19:26:27 +01:00
# if DEBUG
// show reset cause
if ( RCC_CSR & ( RCC_CSR_LPWRRSTF | RCC_CSR_WWDGRSTF | RCC_CSR_IWDGRSTF | RCC_CSR_SFTRSTF | RCC_CSR_PORRSTF | RCC_CSR_PINRSTF ) ) {
puts ( " reset cause(s): " ) ;
if ( RCC_CSR & RCC_CSR_LPWRRSTF ) {
puts ( " low-power " ) ;
}
if ( RCC_CSR & RCC_CSR_WWDGRSTF ) {
puts ( " window-watchdog " ) ;
}
if ( RCC_CSR & RCC_CSR_IWDGRSTF ) {
puts ( " independent-watchdog " ) ;
}
if ( RCC_CSR & RCC_CSR_SFTRSTF ) {
puts ( " software " ) ;
}
if ( RCC_CSR & RCC_CSR_PORRSTF ) {
puts ( " POR/PDR " ) ;
}
if ( RCC_CSR & RCC_CSR_PINRSTF ) {
puts ( " pin " ) ;
}
putc ( ' \n ' ) ;
RCC_CSR | = RCC_CSR_RMVF ; // clear reset flags
}
# endif
2017-01-30 09:44:51 +01:00
2020-03-10 00:04:31 +01:00
# if BUSVOODOO_HARDWARE_VERSION == 2
// on the STLINK/V2 PB7 is pulled high, while on the BusVoodoo dongle it is floating
# define BUSVOODOO_STLINK_PIN PB7
gpio_clear ( GPIO_PORT ( BUSVOODOO_STLINK_PIN ) , GPIO_PIN ( BUSVOODOO_STLINK_PIN ) ) ;
gpio_set_mode ( GPIO_PORT ( BUSVOODOO_STLINK_PIN ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_PULL_UPDOWN , GPIO_PIN ( BUSVOODOO_STLINK_PIN ) ) ;
sleep_ms ( 100 ) ; // wait for voltage to settle
if ( gpio_get ( GPIO_PORT ( BUSVOODOO_STLINK_PIN ) , GPIO_PIN ( BUSVOODOO_STLINK_PIN ) ) ) {
while ( true ) {
puts ( " solder the micro-controller on a BusVoodoo dongle \n " ) ;
iwdg_reset ( ) ; // kick the dog
sleep_ms ( 1000 ) ;
}
}
# endif
2016-08-14 21:02:38 +02:00
// setup RTC
2020-02-02 21:19:03 +01:00
rtc_auto_awake ( RCC_HSE , 8000000 / 128 / RTC_TICKS_SECOND - 1 ) ; // use High Speed External oscillator (8 MHz / 128) as RTC clock (VBAT can't be used to keep the RTC running)
2016-08-14 21:02:38 +02:00
rtc_interrupt_enable ( RTC_SEC ) ; // enable RTC interrupt on "seconds"
nvic_enable_irq ( NVIC_RTC_IRQ ) ; // allow the RTC to interrupt
2018-04-06 17:37:17 +02:00
// setup terminal
2019-02-20 19:14:08 +01:00
terminal_prefix = " BV " ; // set default prefix
2018-04-06 17:37:17 +02:00
terminal_process = & process_command ; // set central function to process commands
terminal_setup ( ) ; // start terminal
2016-10-23 17:42:27 +02:00
2020-03-09 13:09:01 +01:00
# if BUSVOODOO_HARDWARE_VERSION != 2
2019-02-20 19:14:08 +01:00
// setup OLED display
sleep_ms ( 10 ) ; // wait a bit until the display is ready
busvoodoo_oled_setup ( ) ; // setup OLED display
// display version
busvoodoo_oled_clear ( ) ;
busvoodoo_oled_text_left ( " BusVoodoo " ) ;
char str [ 20 ] ;
snprintf ( str , sizeof ( str ) , " fl: %s " , busvoodoo_full ? " full " : " light " ) ;
busvoodoo_oled_text_pos ( 1 , 16 + ( fonts [ FONT_KING10 ] . height + 2 ) * 1 , FONT_KING10 , str ) ;
snprintf ( str , sizeof ( str ) , " hw: %c " , busvoodoo_version ) ;
busvoodoo_oled_text_pos ( 1 , 16 + ( fonts [ FONT_KING10 ] . height + 2 ) * 2 , FONT_KING10 , str ) ;
snprintf ( str , sizeof ( str ) , " fw: %04u-%02u-%02u \n " , BUILD_YEAR , BUILD_MONTH , BUILD_DAY ) ;
busvoodoo_oled_text_pos ( 1 , 16 + ( fonts [ FONT_KING10 ] . height + 2 ) * 3 , FONT_KING10 , str ) ;
snprintf ( str , sizeof ( str ) , " bus.cuvoodoo.info " ) ;
busvoodoo_oled_text_pos ( ( 127 - ( ( fonts [ FONT_KING8 ] . width + 1 ) * strlen ( str ) ) ) / 2 , 63 , FONT_KING8 , str ) ;
busvoodoo_oled_update ( ) ;
sleep_ms ( 1000 ) ;
busvoodoo_oled_clear ( ) ;
2020-03-09 13:09:01 +01:00
# endif
2019-02-20 19:14:08 +01:00
// setup default mode
switch_mode ( NULL ) ;
// main loop
2016-02-18 10:39:08 +01:00
bool action = false ; // if an action has been performed don't go to sleep
button_flag = false ; // reset button flag
2016-01-29 00:24:49 +01:00
while ( true ) { // infinite loop
2016-10-23 17:42:27 +02:00
iwdg_reset ( ) ; // kick the dog
2019-02-20 19:14:08 +01:00
while ( user_input_available ) { // user input received
action = true ; // action has been performed
char c = user_input_get ( ) ; // get user input
2020-03-09 15:20:28 +01:00
if ( 0x04 = = c ) { // CTRL+D is used to quit the mode
2019-02-20 19:14:08 +01:00
printf ( " quit \n " ) ; // acknowledge quitting
command_quit ( NULL ) ; // quit current mode
} else {
terminal_send ( c ) ; // send received character to terminal
2020-02-02 21:19:03 +01:00
}
2016-08-14 21:02:38 +02:00
}
if ( action ) { // go to sleep if nothing had to be done, else recheck for activity
2016-02-18 10:39:08 +01:00
action = false ;
} else {
__WFI ( ) ; // go to sleep
}
2016-10-23 17:42:27 +02:00
} // main loop
2016-01-17 14:54:54 +01:00
}
2016-01-29 11:25:30 +01:00
2016-08-14 21:02:38 +02:00
/** @brief interrupt service routine called when tick passed on RTC */
void rtc_isr ( void )
{
rtc_clear_flag ( RTC_SEC ) ; // clear flag
}