2018-01-24 16:36:19 +01:00
/* This program 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 of the License , or
* ( at your option ) any later version .
*
* This program 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 this program . If not , see < http : //www.gnu.org/licenses/>.
*
*/
/** BusVoodoo UART mode (code)
* @ file busvoodoo_uart . c
* @ author King Kévin < kingkevin @ cuvoodoo . info >
* @ date 2018
* @ note peripherals used : USART @ ref busvoodoo_uart
*/
/* standard libraries */
# include <stdint.h> // standard integer types
# include <stdlib.h> // standard utilities
# include <string.h> // string utilities
/* STM32 (including CM3) libraries */
# include <libopencm3/stm32/gpio.h> // general purpose input output library
# include <libopencm3/stm32/rcc.h> // real-time control clock library
# include <libopencm3/stm32/usart.h> // USART utilities
/* own libraries */
# include "global.h" // board definitions
# include "print.h" // printing utilities
# include "menu.h" // menu definitions
# include "busvoodoo_global.h" // BusVoodoo definitions
2018-02-06 12:33:00 +01:00
# include "busvoodoo_oled.h" // OLED utilities
2018-01-24 16:36:19 +01:00
# include "busvoodoo_uart.h" // own definitions
/** @defgroup busvoodoo_uart USART peripheral used for UART communication
* @ {
*/
# define BUSVOODOO_USART_ID 3 /**< USART peripheral */
/** @} */
/** mode setup stage */
static enum busvoodoo_uart_setting_t {
BUSVOODOO_UART_SETTING_NONE ,
BUSVOODOO_UART_SETTING_BAUDRATE ,
BUSVOODOO_UART_SETTING_DATABITS ,
BUSVOODOO_UART_SETTING_PARITY ,
BUSVOODOO_UART_SETTING_STOPBITS ,
2018-03-22 13:53:05 +01:00
BUSVOODOO_UART_SETTING_HWFLOWCTL ,
2018-01-24 16:36:19 +01:00
BUSVOODOO_UART_SETTING_DRIVE ,
BUSVOODOO_UART_SETTING_DONE ,
2018-03-22 13:53:05 +01:00
} busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_NONE ; /**< current mode setup stage */
2018-01-24 16:36:19 +01:00
/** UART baud rate (in bps) */
2018-03-15 18:55:52 +01:00
static uint32_t busvoodoo_uart_baudrate = 115200 ;
2018-01-24 16:36:19 +01:00
/** UART data bits */
2018-03-15 18:55:52 +01:00
static uint8_t busvoodoo_uart_databits = 8 ;
2018-01-24 16:36:19 +01:00
/** UART parity setting */
2018-03-22 13:53:05 +01:00
static uint32_t busvoodoo_uart_parity = USART_PARITY_NONE ;
/** UART stop bits setting */
static uint32_t busvoodoo_uart_stopbits = USART_STOPBITS_1 ;
/** UART hardware flow control setting (true = with hardware flow control, false = without hardware flow control */
static bool busvoodoo_uart_hwflowctl = false ;
/** pin drive mode (true = push-pull, false = open-drain) */
static bool busvoodoo_uart_drive = true ;
/** if embedded pull-up resistors are used */
static bool busvoodoo_uart_pullup = false ;
2018-01-24 16:36:19 +01:00
/** setup UART mode
* @ param [ out ] prefix terminal prompt prefix
* @ param [ in ] line terminal prompt line to configure mode
* @ return if setup is complete
*/
static bool busvoodoo_uart_setup ( char * * prefix , const char * line )
{
bool complete = false ; // is the setup complete
if ( NULL = = line ) { // first call
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_NONE ; // re-start configuration
}
switch ( busvoodoo_uart_setting ) {
case BUSVOODOO_UART_SETTING_NONE :
2018-03-15 18:55:52 +01:00
snprintf ( busvoodoo_global_string , LENGTH ( busvoodoo_global_string ) , " baud rate in bps (1-2000000) [%u] " , busvoodoo_uart_baudrate ) ;
* prefix = busvoodoo_global_string ; // ask for baud rate
2018-01-24 16:36:19 +01:00
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_BAUDRATE ;
break ;
case BUSVOODOO_UART_SETTING_BAUDRATE :
if ( NULL = = line | | 0 = = strlen ( line ) ) { // use default setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_DATABITS ; // go to next setting
} else { // setting provided
uint32_t baudrate = atoi ( line ) ; // parse setting
2018-03-15 18:55:52 +01:00
if ( baudrate > 0 & & baudrate < = 2000000 ) { // check setting
2018-01-24 16:36:19 +01:00
busvoodoo_uart_baudrate = baudrate ; // remember setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_DATABITS ; // go to next setting
}
}
if ( BUSVOODOO_UART_SETTING_DATABITS = = busvoodoo_uart_setting ) { // if next setting
2018-03-15 18:55:52 +01:00
snprintf ( busvoodoo_global_string , LENGTH ( busvoodoo_global_string ) , " data bits (8-9) [%u] " , busvoodoo_uart_databits ) ; // prepare next setting
* prefix = busvoodoo_global_string ; // display next setting
2018-01-24 16:36:19 +01:00
}
break ;
case BUSVOODOO_UART_SETTING_DATABITS :
if ( NULL = = line | | 0 = = strlen ( line ) ) { // use default setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_PARITY ; // go to next setting
} else { // setting provided
uint8_t databits = atoi ( line ) ; // parse setting
if ( 8 = = databits | | 9 = = databits ) { // check setting
busvoodoo_uart_databits = databits ; // remember setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_PARITY ; // go to next setting
}
}
if ( BUSVOODOO_UART_SETTING_PARITY = = busvoodoo_uart_setting ) { // if next setting
2018-03-22 13:53:05 +01:00
printf ( " 1) none \n " ) ;
printf ( " 2) even \n " ) ;
printf ( " 3) odd \n " ) ;
snprintf ( busvoodoo_global_string , LENGTH ( busvoodoo_global_string ) , " parity (1,2,3) [%c] " , USART_PARITY_NONE = = busvoodoo_uart_parity ? ' 1 ' : ( USART_PARITY_EVEN = = busvoodoo_uart_parity ? ' 2 ' : ' 3 ' ) ) ; // prepare next setting
2018-03-15 18:55:52 +01:00
* prefix = busvoodoo_global_string ; // display next setting
2018-01-24 16:36:19 +01:00
}
break ;
case BUSVOODOO_UART_SETTING_PARITY :
if ( NULL = = line | | 0 = = strlen ( line ) ) { // use default setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_STOPBITS ; // go to next setting
2018-03-22 13:53:05 +01:00
} else if ( 1 = = strlen ( line ) ) { // setting provided
if ( ' 1 ' = = line [ 0 ] ) { // no parity
busvoodoo_uart_parity = USART_PARITY_NONE ;
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_STOPBITS ; // go to next setting
} else if ( ' 2 ' = = line [ 0 ] ) { // even parity
busvoodoo_uart_parity = USART_PARITY_EVEN ;
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_STOPBITS ; // go to next setting
} else if ( ' 3 ' = = line [ 0 ] ) { // odd parity
busvoodoo_uart_parity = USART_PARITY_ODD ;
2018-01-24 16:36:19 +01:00
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_STOPBITS ; // go to next setting
}
}
if ( BUSVOODOO_UART_SETTING_STOPBITS = = busvoodoo_uart_setting ) { // if next setting
2018-03-22 13:53:05 +01:00
printf ( " 1) 0.5 \n " ) ;
printf ( " 2) 1 \n " ) ;
printf ( " 3) 1.5 \n " ) ;
printf ( " 4) 2 \n " ) ;
snprintf ( busvoodoo_global_string , LENGTH ( busvoodoo_global_string ) , " stop bits (1,2,3,4) [%s] " , USART_STOPBITS_0_5 = = busvoodoo_uart_stopbits ? " 0.5 " : ( USART_STOPBITS_1 = = busvoodoo_uart_stopbits ? " 1 " : ( USART_STOPBITS_1_5 = = busvoodoo_uart_stopbits ? " 1.5 " : " 2.0 " ) ) ) ; // prepare next setting
2018-03-15 18:55:52 +01:00
* prefix = busvoodoo_global_string ; // display next setting
2018-01-24 16:36:19 +01:00
}
break ;
case BUSVOODOO_UART_SETTING_STOPBITS :
2018-03-22 13:53:05 +01:00
if ( NULL = = line | | 0 = = strlen ( line ) ) { // use default setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_HWFLOWCTL ; // go to next setting
} else if ( 1 = = strlen ( line ) ) { // setting provided
if ( ' 1 ' = = line [ 0 ] ) { // 0.5 stop bits
busvoodoo_uart_stopbits = USART_STOPBITS_0_5 ; // remember setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_HWFLOWCTL ; // go to next setting
} else if ( ' 2 ' = = line [ 0 ] ) { // 1 stop bits
busvoodoo_uart_stopbits = USART_STOPBITS_1 ; // remember setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_HWFLOWCTL ; // go to next setting
} else if ( ' 3 ' = = line [ 0 ] ) { // 1.5 stop bits
busvoodoo_uart_stopbits = USART_STOPBITS_1_5 ; // remember setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_HWFLOWCTL ; // go to next setting
} else if ( ' 4 ' = = line [ 0 ] ) { // 2 stop bits
busvoodoo_uart_stopbits = USART_STOPBITS_2 ; // remember setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_HWFLOWCTL ; // go to next setting
}
}
if ( BUSVOODOO_UART_SETTING_HWFLOWCTL = = busvoodoo_uart_setting ) { // if next setting
printf ( " 1) no flow control \n " ) ;
printf ( " 2) RTS/CTS hardware flow control \n " ) ;
snprintf ( busvoodoo_global_string , LENGTH ( busvoodoo_global_string ) , " flow control (1,2) [%c] " , busvoodoo_uart_hwflowctl ? ' 2 ' : ' 1 ' ) ; // prepare next setting
* prefix = busvoodoo_global_string ; // display next setting
}
break ;
case BUSVOODOO_UART_SETTING_HWFLOWCTL :
2018-01-24 16:36:19 +01:00
if ( NULL = = line | | 0 = = strlen ( line ) ) { // use default setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_DRIVE ; // go to next setting
2018-03-22 13:53:05 +01:00
} else if ( 1 = = strlen ( line ) ) { // setting provided
if ( ' 1 ' = = line [ 0 ] | | ' 2 ' = = line [ 0 ] ) { // setting provided
busvoodoo_uart_hwflowctl = ( ' 2 ' = = line [ 0 ] ) ; // remember setting
2018-01-24 16:36:19 +01:00
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_DRIVE ; // go to next setting
}
}
if ( BUSVOODOO_UART_SETTING_DRIVE = = busvoodoo_uart_setting ) { // if next setting
2018-03-22 13:53:05 +01:00
printf ( " 1) push-pull (3.3V) \n " ) ;
printf ( " 2) open-drain, with embedded pull-up resistors (2kO) \n " ) ;
printf ( " 3) open-drain, with external pull-up resistors \n " ) ;
snprintf ( busvoodoo_global_string , LENGTH ( busvoodoo_global_string ) , " drive mode (1,2,3) [%c] " , busvoodoo_uart_drive ? ' 1 ' : ( busvoodoo_uart_pullup ? ' 2 ' : ' 3 ' ) ) ; // show drive mode
2018-03-15 18:55:52 +01:00
* prefix = busvoodoo_global_string ; // display next setting
2018-01-24 16:36:19 +01:00
}
break ;
case BUSVOODOO_UART_SETTING_DRIVE :
if ( NULL = = line | | 0 = = strlen ( line ) ) { // use default setting
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_DONE ; // go to next setting
2018-03-22 13:53:05 +01:00
} else if ( 1 = = strlen ( line ) ) { // setting provided
uint8_t drive = atoi ( line ) ; // parse setting
if ( 1 = = drive | | 2 = = drive | | 3 = = drive ) { // check setting
busvoodoo_uart_drive = ( 1 = = drive ) ; // remember setting
busvoodoo_uart_pullup = ( 2 = = drive ) ; // remember setting
2018-01-24 16:36:19 +01:00
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_DONE ; // go to next setting
}
}
if ( BUSVOODOO_UART_SETTING_DONE = = busvoodoo_uart_setting ) { // we have all settings, configure UART
2018-03-15 18:55:52 +01:00
rcc_periph_clock_enable ( RCC_AFIO ) ; // enable clock for USART alternate function
2018-03-22 13:53:05 +01:00
rcc_periph_clock_enable ( RCC_USART ( BUSVOODOO_USART_ID ) ) ; // enable clock for USART peripheral
2018-01-24 16:36:19 +01:00
usart_set_baudrate ( USART ( BUSVOODOO_USART_ID ) , busvoodoo_uart_baudrate ) ; // set baud rate
usart_set_databits ( USART ( BUSVOODOO_USART_ID ) , busvoodoo_uart_databits ) ; // set data bits
2018-03-22 13:53:05 +01:00
usart_set_parity ( USART ( BUSVOODOO_USART_ID ) , busvoodoo_uart_parity ) ; // set parity
usart_set_stopbits ( USART ( BUSVOODOO_USART_ID ) , busvoodoo_uart_stopbits ) ; // set stop bits
if ( busvoodoo_uart_hwflowctl ) {
usart_set_flow_control ( USART ( BUSVOODOO_USART_ID ) , USART_FLOWCONTROL_RTS_CTS ) ; // set RTS/CTS flow control
} else {
usart_set_flow_control ( USART ( BUSVOODOO_USART_ID ) , USART_FLOWCONTROL_NONE ) ; // set no flow control
2018-01-24 16:36:19 +01:00
}
usart_set_mode ( USART ( BUSVOODOO_USART_ID ) , USART_MODE_TX_RX ) ; // full-duplex communication
2018-03-22 13:53:05 +01:00
rcc_periph_clock_enable ( RCC_USART_PORT ( BUSVOODOO_USART_ID ) ) ; // enable clock for USART GPIO peripheral
if ( busvoodoo_uart_drive ) { // use push-pull drive mode
gpio_set_mode ( USART_TX_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_OUTPUT_10_MHZ , GPIO_CNF_OUTPUT_ALTFN_PUSHPULL , USART_TX_PIN ( BUSVOODOO_USART_ID ) ) ; // setup GPIO pin USART transmit
gpio_set ( USART_RX_PORT ( BUSVOODOO_USART_ID ) , USART_RX_PIN ( BUSVOODOO_USART_ID ) ) ; // pull up to avoid noise when not connected
gpio_set_mode ( USART_RX_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_PULL_UPDOWN , USART_RX_PIN ( BUSVOODOO_USART_ID ) ) ; // setup GPIO pin USART receive
if ( busvoodoo_uart_hwflowctl ) { // use open drain drive mode
gpio_set_mode ( USART_RTS_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_OUTPUT_10_MHZ , GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN , USART_RTS_PIN ( BUSVOODOO_USART_ID ) ) ; // setup GPIO pin USART transmit
gpio_set ( USART_CTS_PORT ( BUSVOODOO_USART_ID ) , USART_CTS_PIN ( BUSVOODOO_USART_ID ) ) ; // pull up to block transmission unless requested
gpio_set_mode ( USART_CTS_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_PULL_UPDOWN , USART_CTS_PIN ( BUSVOODOO_USART_ID ) ) ; // setup GPIO pin USART receive
}
} else {
gpio_set_mode ( USART_TX_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_OUTPUT_10_MHZ , GPIO_CNF_OUTPUT_ALTFN_PUSHPULL , USART_TX_PIN ( BUSVOODOO_USART_ID ) ) ; // setup GPIO pin USART transmit
gpio_set_mode ( USART_RX_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_FLOAT , USART_RX_PIN ( BUSVOODOO_USART_ID ) ) ; // setup GPIO pin USART receive
if ( busvoodoo_uart_hwflowctl ) {
gpio_set_mode ( USART_RTS_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_OUTPUT_10_MHZ , GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN , USART_RTS_PIN ( BUSVOODOO_USART_ID ) ) ; // setup GPIO pin USART transmit
gpio_set_mode ( USART_CTS_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_FLOAT , USART_CTS_PIN ( BUSVOODOO_USART_ID ) ) ; // setup GPIO pin USART receive
}
}
if ( ! busvoodoo_uart_drive & & busvoodoo_uart_pullup ) { // enable embedded pull-ups if used
busvoodoo_embedded_pullup ( true ) ; // set embedded pull-ups
printf ( " use LV to set pull-up voltage \n " ) ;
2018-01-24 16:36:19 +01:00
}
usart_enable ( USART ( BUSVOODOO_USART_ID ) ) ; // enable USART
2018-01-24 21:29:22 +01:00
led_off ( ) ; // disable LED because there is no activity
2018-01-24 16:36:19 +01:00
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_NONE ; // restart settings next time
* prefix = " UART " ; // display mode
2018-03-22 13:53:05 +01:00
busvoodoo_oled_text_left ( * prefix ) ; // set mode title on OLED display
char * pinout_io [ 10 ] = { " GND " , " 5V " , " 3V3 " , " LV " , " Rx " , " Tx " , NULL , NULL , NULL , NULL } ; // UART mode pinout
if ( busvoodoo_uart_hwflowctl ) { // hardware flow control is used
pinout_io [ 6 ] = " RTS " ; // update pin name
pinout_io [ 7 ] = " CTS " ; // update pin name
}
2018-02-06 17:35:14 +01:00
for ( uint8_t i = 0 ; i < LENGTH ( pinout_io ) & & i < LENGTH ( busvoodoo_global_pinout_io ) ; i + + ) {
busvoodoo_global_pinout_io [ i ] = pinout_io [ i ] ; // set pin names
}
2018-03-22 13:53:05 +01:00
busvoodoo_oled_text_pinout ( ( const char * * ) pinout_io , true ) ; // set pinout on display
2018-02-06 12:33:00 +01:00
busvoodoo_oled_update ( ) ; // update display to show text and pinout
complete = true ; // configuration is complete
2018-01-24 16:36:19 +01:00
}
break ;
default : // unknown case
busvoodoo_uart_setting = BUSVOODOO_UART_SETTING_NONE ; // restart settings next time
break ;
}
return complete ;
}
/** exit UART mode
*/
static void busvoodoo_uart_exit ( void )
{
usart_disable ( USART ( BUSVOODOO_USART_ID ) ) ; // disable USART
2018-03-22 13:53:05 +01:00
rcc_periph_clock_disable ( RCC_USART ( BUSVOODOO_USART_ID ) ) ; // disable domain clock
gpio_set_mode ( USART_TX_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_FLOAT , USART_TX_PIN ( BUSVOODOO_USART_ID ) ) ; // set pin back to floating input
gpio_set_mode ( USART_RX_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_FLOAT , USART_RX_PIN ( BUSVOODOO_USART_ID ) ) ; // set pin back to floating input
gpio_set_mode ( USART_RTS_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_FLOAT , USART_RTS_PIN ( BUSVOODOO_USART_ID ) ) ; // set pin back to floating input
gpio_set_mode ( USART_CTS_PORT ( BUSVOODOO_USART_ID ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_FLOAT , USART_CTS_PIN ( BUSVOODOO_USART_ID ) ) ; // set pin back to floating input
2018-01-24 16:36:19 +01:00
busvoodoo_embedded_pullup ( false ) ; // disable embedded pull-ups
}
// command handlers
2018-03-22 13:53:05 +01:00
/** command to transmit a string
* @ param [ in ] argument string to transmit ( CR + LF when none provided )
2018-01-24 16:36:19 +01:00
*/
static void busvoodoo_uart_command_transmit ( void * argument )
{
if ( NULL = = argument | | 0 = = strlen ( argument ) ) { // nothing to transmit
2018-03-22 13:53:05 +01:00
argument = " \r \n " ; // transmit CR+LF
}
printf ( " press any key to exit \n " ) ;
for ( uint16_t i = 0 ; ( ( char * ) ( argument ) ) [ i ] & & ! user_input_available ; i + + ) {
while ( ( 0 = = ( USART_SR ( USART ( BUSVOODOO_USART_ID ) ) & USART_SR_TXE ) & & ! user_input_available ) ) ; // wait for transmit buffer to be empty
if ( USART_SR ( USART ( BUSVOODOO_USART_ID ) ) & USART_SR_TXE ) { // we can send a character
printf ( " %c " , ( ( char * ) ( argument ) ) [ i ] ) ; // echo character to transmit
busvoodoo_led_red_pulse ( BUSVOODOO_LED_PULSE ) ; // pulse red LED to show transmission
usart_send ( USART ( BUSVOODOO_USART_ID ) , ( ( char * ) ( argument ) ) [ i ] ) ; // transmit character
}
}
if ( user_input_available ) { // user interrupted flow
user_input_get ( ) ; // discard user input
2018-01-24 16:36:19 +01:00
}
2018-03-22 13:53:05 +01:00
if ( strcmp ( argument , " \r \n " ) ) {
printf ( " \n " ) ;
2018-01-24 16:36:19 +01:00
}
}
/** command to receive data
2018-03-22 15:05:09 +01:00
* @ param [ in ] argument in which format to display
2018-01-24 16:36:19 +01:00
*/
static void busvoodoo_uart_command_receive ( void * argument )
{
2018-03-22 15:05:09 +01:00
bool display_hex = false ; // display in hex
bool display_bin = false ; // display in bin
if ( NULL ! = argument & & strlen ( argument ) > 0 ) {
if ( 0 = = strcmp ( argument , " h " ) | | 0 = = strcmp ( argument , " hex " ) ) { // user wants hexadecimal display
display_hex = true ; // remember to display in hexadecimal
} else if ( 0 = = strcmp ( argument , " b " ) | | 0 = = strcmp ( argument , " bin " ) ) { // user wants binary display
display_bin = true ; // remember to display in binary
} else {
printf ( " malformed argument \n " ) ;
return ;
}
}
2018-01-25 11:31:27 +01:00
printf ( " press any key to exit \n " ) ;
while ( ! user_input_available ) { // check for user input to exit
if ( ( USART_SR ( USART ( BUSVOODOO_USART_ID ) ) & USART_SR_RXNE ) ) { // verify if data has been received
2018-03-22 15:05:09 +01:00
uint16_t c = usart_recv ( USART ( BUSVOODOO_USART_ID ) ) ; // receive character
2018-03-22 13:53:05 +01:00
busvoodoo_led_blue_pulse ( BUSVOODOO_LED_PULSE ) ; // enable blue LED to show reception
2018-03-22 15:05:09 +01:00
// remove unused bits (ignore parity bit)
if ( USART_PARITY_NONE = = busvoodoo_uart_parity ) { // no parity bit in frame
if ( 8 = = busvoodoo_uart_databits ) { // 8-bit frame
c & = 0xff ;
} else { // 9-bit frame
c & = 0x1ff ;
}
} else { // MSb is parity bit
if ( 8 = = busvoodoo_uart_databits ) { // 8-bit frame
c & = 0x7f ;
} else { // 9-bit frame
c & = 0xff ;
}
}
if ( display_hex ) { // display data in hex
if ( ( USART_PARITY_NONE = = busvoodoo_uart_parity ) & & 9 = = busvoodoo_uart_databits ) { // case where the final data is 9 bits long
printf ( " %03x " , c ) ;
} else {
printf ( " %02x " , c ) ;
}
} else if ( display_bin ) { // display data in binary
if ( USART_PARITY_NONE = = busvoodoo_uart_parity ) {
if ( 8 = = busvoodoo_uart_databits ) { // 8-bit frame
printf ( " %08b " , c ) ;
} else { // 9-bit frame
printf ( " %09b " , c ) ;
}
} else { // one bit is a parity bit
if ( 8 = = busvoodoo_uart_databits ) { // 8-bit frame
printf ( " %07b " , c ) ;
} else { // 9-bit frame
printf ( " %08b " , c ) ;
}
}
} else { // display in ASCII
printf ( " %c " , c ) ; // print received character
}
2018-01-25 11:31:27 +01:00
}
2018-01-24 16:36:19 +01:00
}
2018-01-25 11:31:27 +01:00
user_input_get ( ) ; // discard user input
printf ( " \n " ) ; // get to next line
}
/** command to transmit and receive data
* @ param [ in ] argument no argument required
*/
static void busvoodoo_uart_command_transceive ( void * argument )
{
( void ) argument ; // we won't use the argument
printf ( " press 5 times escape to exit \n " ) ;
char last_c = 0 ; // last user character received
uint8_t esc_count = 0 ; // number of times escape has press received
2018-03-22 14:30:50 +01:00
while ( true ) { // check for escape sequence
2018-01-25 11:31:27 +01:00
if ( user_input_available ) { // check if user wants to transmit something
char c = user_input_get ( ) ; // get user input
if ( 0x1b = = c ) { // user pressed escape
if ( 0x1b ! = last_c ) { // this is the first escape press
esc_count = 0 ;
}
esc_count + + ; // increment escape count
}
2018-02-06 11:56:18 +01:00
last_c = c ; // remember key press
2018-03-22 14:30:50 +01:00
if ( esc_count < 5 ) { // check for escape sequence
while ( ( 0 = = ( USART_SR ( USART ( BUSVOODOO_USART_ID ) ) & USART_SR_TXE ) & & ! user_input_available ) ) ; // wait for transmit buffer to be empty
if ( USART_SR ( USART ( BUSVOODOO_USART_ID ) ) & USART_SR_TXE ) { // we can send a character
usart_send_blocking ( USART ( BUSVOODOO_USART_ID ) , c ) ; // send user character
busvoodoo_led_red_pulse ( BUSVOODOO_LED_PULSE ) ; // enable red LED to show transmission
}
} else { // user wants to exit
break ; // exit infinite loop
}
2018-01-25 11:31:27 +01:00
}
if ( ( USART_SR ( USART ( BUSVOODOO_USART_ID ) ) & USART_SR_RXNE ) ) { // verify if data has been received
char c = usart_recv ( USART ( BUSVOODOO_USART_ID ) ) ; // receive character
2018-03-22 13:53:05 +01:00
busvoodoo_led_blue_pulse ( BUSVOODOO_LED_PULSE ) ; // enable blue LED to show reception
2018-01-25 11:31:27 +01:00
printf ( " %c " , c ) ; // print received character
}
}
printf ( " \n " ) ; // get to next line
2018-01-24 16:36:19 +01:00
}
2018-03-22 13:53:05 +01:00
/** UART menu commands */
2018-01-24 16:36:19 +01:00
static const struct menu_command_t busvoodoo_uart_commands [ ] = {
{
' r ' ,
" receive " ,
2018-03-22 15:05:09 +01:00
" show incoming data [in hexadecimal or binary] " ,
MENU_ARGUMENT_STRING ,
" [hex|bin] " ,
2018-01-24 16:36:19 +01:00
& busvoodoo_uart_command_receive ,
} ,
{
' t ' ,
" transmit " ,
2018-03-22 13:53:05 +01:00
" transmit ASCII text (empty for CR+LF) " ,
2018-01-24 16:36:19 +01:00
MENU_ARGUMENT_STRING ,
2018-03-22 13:53:05 +01:00
" [text] " ,
2018-01-24 16:36:19 +01:00
& busvoodoo_uart_command_transmit ,
} ,
2018-01-25 11:31:27 +01:00
{
' x ' ,
" transceive " ,
" transmit and receive data " ,
MENU_ARGUMENT_NONE ,
NULL ,
& busvoodoo_uart_command_transceive ,
} ,
2018-01-24 16:36:19 +01:00
} ;
struct busvoodoo_mode_t busvoodoo_uart_mode = {
" uart " ,
" Universal Asynchronous Receiver-Transmitter " ,
& busvoodoo_uart_setup ,
busvoodoo_uart_commands ,
LENGTH ( busvoodoo_uart_commands ) ,
& busvoodoo_uart_exit ,
} ;