2016-08-16 11:56:10 +02: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/>.
*
*/
/** library to control multiple software USARTs (code)
* @ file usart_soft . c
* @ author King Kévin < kingkevin @ cuvoodoo . info >
* @ date 2016
* @ note peripherals used : GPIO @ ref usart_soft_gpio , timer @ ref usart_soft_timer
*/
/* standard libraries */
# include <stdint.h> // standard integer types
# include <stdlib.h> // general utilities
/* STM32 (including CM3) libraries */
# include <libopencm3/stm32/rcc.h> // real-time control clock library
# include <libopencm3/stm32/gpio.h> // general purpose input output library
# include <libopencm3/stm32/timer.h> // timer library
# include <libopencm3/cm3/nvic.h> // interrupt handler
# include "usart_soft.h" // software USART library API
# include "global.h" // common methods
/** @defgroup usart_soft_gpio GPIO used for the software USART ports
2016-08-19 21:59:22 +02:00
* @ note up to 4 pins supported , comment if unused
2016-08-16 11:56:10 +02:00
* @ {
*/
2016-08-19 21:59:22 +02:00
# define USART_SOFT_RX_PORT0 A
# define USART_SOFT_RX_PIN0 0
# define USART_SOFT_RX_PORT1 A
# define USART_SOFT_RX_PIN1 0
# define USART_SOFT_RX_PORT2 A
# define USART_SOFT_RX_PIN2 0
# define USART_SOFT_RX_PORT3 A
# define USART_SOFT_RX_PIN3 0
# define USART_SOFT_TX_PORT0 A
# define USART_SOFT_TX_PIN0 0
# define USART_SOFT_TX_PORT1 A
# define USART_SOFT_TX_PIN1 0
# define USART_SOFT_TX_PORT2 A
# define USART_SOFT_TX_PIN2 0
# define USART_SOFT_TX_PORT3 A
# define USART_SOFT_TX_PIN3 0
2016-08-16 11:56:10 +02:00
/** @} */
2016-08-19 21:59:22 +02:00
/** @defgroup usart_soft_config USART configurations (2400-115200 bps)
2016-08-18 10:45:36 +02:00
* @ note this implementation is designed for 8 bits , no parity , any stop configuration since this is the most common case
2016-08-16 11:56:10 +02:00
* @ {
*/
2016-08-19 21:59:22 +02:00
# define USART_SOFT_RX_BAUDRATE0 0
# define USART_SOFT_RX_BAUDRATE1 0
# define USART_SOFT_RX_BAUDRATE2 0
# define USART_SOFT_RX_BAUDRATE3 0
# define USART_SOFT_TX_BAUDRATE0 0
# define USART_SOFT_TX_BAUDRATE1 0
# define USART_SOFT_TX_BAUDRATE2 0
# define USART_SOFT_TX_BAUDRATE3 0
2016-08-16 11:56:10 +02:00
/** @} */
/** @defgroup usart_soft_timer timer used to same USART signals
* @ {
*/
2016-08-19 21:59:22 +02:00
# if (defined(USART_SOFT_RX_PORT0) && defined(USART_SOFT_RX_PIN0)) || (defined(USART_SOFT_RX_PORT1) && defined(USART_SOFT_RX_PIN1)) || (defined(USART_SOFT_RX_PORT2) && defined(USART_SOFT_RX_PIN2)) || (defined(USART_SOFT_RX_PORT3) && defined(USART_SOFT_RX_PIN0))
# define USART_SOFT_RX_TIMER 3 /**< timer peripheral for receive signals */
# endif
# if (defined(USART_SOFT_TX_PORT0) && defined(USART_SOFT_TX_PIN0)) || (defined(USART_SOFT_TX_PORT1) && defined(USART_SOFT_TX_PIN1)) || (defined(USART_SOFT_TX_PORT2) && defined(USART_SOFT_TX_PIN2)) || (defined(USART_SOFT_TX_PORT3) && defined(USART_SOFT_TX_PIN0))
# define USART_SOFT_TX_TIMER 4 /**< timer peripheral for transmit signals */
# endif
/** @} */
/** @defgroup usart_soft_state
* @ {
*/
# if (defined(USART_SOFT_RX_PORT0) && defined(USART_SOFT_RX_PIN0))
volatile bool rx0_state = 0 ; /**< state of the GPIO */
volatile uint8_t rx0_bit = 0 ; /**< next bit to receive */
# endif
2016-08-16 11:56:10 +02:00
/** @} */
2016-08-18 10:45:36 +02:00
bool usart_soft_setup ( void )
2016-08-16 11:56:10 +02:00
{
2016-08-18 10:45:36 +02:00
// verify configuration
2016-08-19 21:59:22 +02:00
# if (defined(USART_SOFT_RX_BAUDRATE0) && ((USART_SOFT_RX_BAUDRATE0<2400) || (USART_SOFT_RX_BAUDRATE0>115200)))
return false ;
# endif
# if (defined(USART_SOFT_RX_BAUDRATE1) && ((USART_SOFT_RX_BAUDRATE1<2400) || (USART_SOFT_RX_BAUDRATE1>115200)))
return false ;
# endif
# if (defined(USART_SOFT_RX_BAUDRATE2) && ((USART_SOFT_RX_BAUDRATE2<2400) || (USART_SOFT_RX_BAUDRATE2>115200)))
return false ;
# endif
# if (defined(USART_SOFT_RX_BAUDRATE3) && ((USART_SOFT_RX_BAUDRATE3<2400) || (USART_SOFT_RX_BAUDRATE3>115200)))
return false ;
# endif
# if (defined(USART_SOFT_TX_BAUDRATE0) && ((USART_SOFT_TX_BAUDRATE0<2400) || (USART_SOFT_TX_BAUDRATE0>115200)))
return false ;
# endif
# if (defined(USART_SOFT_TX_BAUDRATE1) && ((USART_SOFT_TX_BAUDRATE1<2400) || (USART_SOFT_TX_BAUDRATE1>115200)))
2016-08-18 10:45:36 +02:00
return false ;
2016-08-19 21:59:22 +02:00
# endif
# if (defined(USART_SOFT_TX_BAUDRATE2) && ((USART_SOFT_TX_BAUDRATE2<2400) || (USART_SOFT_TX_BAUDRATE2>115200)))
2016-08-18 10:45:36 +02:00
return false ;
2016-08-19 21:59:22 +02:00
# endif
# if (defined(USART_SOFT_TX_BAUDRATE3) && ((USART_SOFT_TX_BAUDRATE3<2400) || (USART_SOFT_TX_BAUDRATE3>115200)))
return false ;
# endif
2016-08-18 10:45:36 +02:00
2016-08-16 11:56:10 +02:00
// setup GPIOs
2016-08-19 21:59:22 +02:00
# if defined(USART_SOFT_RX_PORT0) && defined(USART_SOFT_RX_PIN0)
rcc_periph_clock_enable ( RCC_GPIO ( USART_SOFT_RX_PORT0 ) ) ; // enable clock for GPIO peripheral
gpio_set_mode ( GPIO ( USART_SOFT_RX_PORT0 ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_PULL_UPDOWN , GPIO ( USART_SOFT_RX_PIN0 ) ) ; // setup GPIO pin USART receive
gpio_set ( GPIO ( USART_SOFT_RX_PORT0 ) , GPIO ( USART_SOFT_RX_PIN0 ) ) ; // pull up to avoid noise when not connected
rx0_state = gpio_get ( GPIO ( USART_SOFT_RX_PORT0 ) , GPIO ( USART_SOFT_RX_PIN0 ) ) ; // save state of GPIO
rx0_bit = 0 ; // reset bits received
# endif
# if defined(USART_SOFT_RX_PORT1) && defined(USART_SOFT_RX_PIN1)
rcc_periph_clock_enable ( RCC_GPIO ( USART_SOFT_RX_PORT1 ) ) ; // enable clock for GPIO peripheral
gpio_set_mode ( GPIO ( USART_SOFT_RX_PORT1 ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_PULL_UPDOWN , GPIO ( USART_SOFT_RX_PIN1 ) ) ; // setup GPIO pin USART receive
gpio_set ( GPIO ( USART_SOFT_RX_PORT1 ) , GPIO ( USART_SOFT_RX_PIN1 ) ) ; // pull up to avoid noise when not connected
# endif
# if defined(USART_SOFT_RX_PORT2) && defined(USART_SOFT_RX_PIN2)
rcc_periph_clock_enable ( RCC_GPIO ( USART_SOFT_RX_PORT2 ) ) ; // enable clock for GPIO peripheral
gpio_set_mode ( GPIO ( USART_SOFT_RX_PORT2 ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_PULL_UPDOWN , GPIO ( USART_SOFT_RX_PIN2 ) ) ; // setup GPIO pin USART receive
gpio_set ( GPIO ( USART_SOFT_RX_PORT2 ) , GPIO ( USART_SOFT_RX_PIN2 ) ) ; // pull up to avoid noise when not connected
# endif
# if defined(USART_SOFT_RX_PORT3) && defined(USART_SOFT_RX_PIN3)
rcc_periph_clock_enable ( RCC_GPIO ( USART_SOFT_RX_PORT3 ) ) ; // enable clock for GPIO peripheral
gpio_set_mode ( GPIO ( USART_SOFT_RX_PORT3 ) , GPIO_MODE_INPUT , GPIO_CNF_INPUT_PULL_UPDOWN , GPIO ( USART_SOFT_RX_PIN3 ) ) ; // setup GPIO pin USART receive
gpio_set ( GPIO ( USART_SOFT_RX_PORT3 ) , GPIO ( USART_SOFT_RX_PIN3 ) ) ; // pull up to avoid noise when not connected
# endif
# if defined(USART_SOFT_TX_PORT0) && defined(USART_SOFT_TX_PIN0)
rcc_periph_clock_enable ( RCC_GPIO ( USART_SOFT_TX_PORT0 ) ) ; // enable clock for GPIO peripheral
gpio_set_mode ( GPIO ( USART_SOFT_TX_PORT0 ) , GPIO_MODE_OUTPUT_2_MHZ , GPIO_CNF_OUTPUT_PUSHPULL , GPIO ( USART_SOFT_TX_PIN0 ) ) ;
# endif
# if defined(USART_SOFT_TX_PORT1) && defined(USART_SOFT_TX_PIN1)
rcc_periph_clock_enable ( RCC_GPIO ( USART_SOFT_TX_PORT1 ) ) ; // enable clock for GPIO peripheral
gpio_set_mode ( GPIO ( USART_SOFT_TX_PORT1 ) , GPIO_MODE_OUTPUT_2_MHZ , GPIO_CNF_OUTPUT_PUSHPULL , GPIO ( USART_SOFT_TX_PIN1 ) ) ;
# endif
# if defined(USART_SOFT_TX_PORT2) && defined(USART_SOFT_TX_PIN2)
rcc_periph_clock_enable ( RCC_GPIO ( USART_SOFT_TX_PORT2 ) ) ; // enable clock for GPIO peripheral
gpio_set_mode ( GPIO ( USART_SOFT_TX_PORT2 ) , GPIO_MODE_OUTPUT_2_MHZ , GPIO_CNF_OUTPUT_PUSHPULL , GPIO ( USART_SOFT_TX_PIN2 ) ) ;
# endif
# if defined(USART_SOFT_TX_PORT3) && defined(USART_SOFT_TX_PIN3)
rcc_periph_clock_enable ( RCC_GPIO ( USART_SOFT_TX_PORT3 ) ) ; // enable clock for GPIO peripheral
gpio_set_mode ( GPIO ( USART_SOFT_TX_PORT3 ) , GPIO_MODE_OUTPUT_2_MHZ , GPIO_CNF_OUTPUT_PUSHPULL , GPIO ( USART_SOFT_TX_PIN3 ) ) ;
# endif
2016-08-18 10:45:36 +02:00
// setup timer
2016-08-19 21:59:22 +02:00
# if defined(USART_SOFT_RX_TIMER)
rcc_periph_clock_enable ( RCC_TIM ( USART_SOFT_RX_TIMER ) ) ; // enable clock for timer peripheral
timer_reset ( TIM ( USART_SOFT_RX_TIMER ) ) ; // reset timer state
timer_set_mode ( TIM ( USART_SOFT_RX_TIMER ) , TIM_CR1_CKD_CK_INT , TIM_CR1_CMS_EDGE , TIM_CR1_DIR_UP ) ; // set timer mode, use undivided timer clock, edge alignment (simple count), and count up
timer_set_prescaler ( TIM ( USART_SOFT_RX_TIMER ) , 0 ) ; // prescaler to be able to sample 2400-115200 bps (72MHz/2^16=1099<2400bps)
nvic_enable_irq ( NVIC_TIM_IRQ ( USART_SOFT_RX_TIMER ) ) ; // allow interrupt for timer
# endif
# if defined(USART_SOFT_TX_TIMER)
rcc_periph_clock_enable ( RCC_TIM ( USART_SOFT_TX_TIMER ) ) ; // enable clock for timer peripheral
timer_reset ( TIM ( USART_SOFT_TX_TIMER ) ) ; // reset timer state
timer_set_mode ( TIM ( USART_SOFT_TX_TIMER ) , TIM_CR1_CKD_CK_INT , TIM_CR1_CMS_EDGE , TIM_CR1_DIR_UP ) ; // set timer mode, use undivided timer clock, edge alignment (simple count), and count up
timer_set_prescaler ( TIM ( USART_SOFT_TX_TIMER ) , 0 ) ; // prescaler to be able to sample 2400-115200 bps (72MHz/2^16=1099<2400bps)
nvic_enable_irq ( NVIC_TIM_IRQ ( USART_SOFT_TX_TIMER ) ) ; // allow interrupt for timer
# endif
2016-08-18 10:45:36 +02:00
return true ; // setup completed
}
2016-08-19 21:59:22 +02:00
# if defined(USART_SOFT_RX_TIMER)
2016-08-18 10:45:36 +02:00
void TIM_ISR ( USART_SOFT_RX_TIMER ) ( void )
{
2016-08-16 11:56:10 +02:00
}
2016-08-19 21:59:22 +02:00
# endif
# if defined(USART_SOFT_TX_TIMER)
void TIM_ISR ( USART_SOFT_TX_TIMER ) ( void )
{
}
# endif
/** central function handling receive signal activity */
static void rx_activity ( void )
{
}
# if (defined(USART_SOFT_RX_PORT0) && defined(USART_SOFT_RX_PIN0) && USART_SOFT_RX_PIN0==0) || (defined(USART_SOFT_RX_PORT1) && defined(USART_SOFT_RX_PIN1) && USART_SOFT_RX_PIN1==0) || (defined(USART_SOFT_RX_PORT2) && defined(USART_SOFT_RX_PIN2) && USART_SOFT_RX_PIN2==0) || (defined(USART_SOFT_RX_PORT3) && defined(USART_SOFT_RX_PIN3) && USART_SOFT_RX_PIN3==0)
void exti0_isr ( void )
{
rx_activity ( ) ;
}
# endif
# if (defined(USART_SOFT_RX_PORT0) && defined(USART_SOFT_RX_PIN0) && USART_SOFT_RX_PIN0==1) || (defined(USART_SOFT_RX_PORT1) && defined(USART_SOFT_RX_PIN1) && USART_SOFT_RX_PIN1==1) || (defined(USART_SOFT_RX_PORT2) && defined(USART_SOFT_RX_PIN2) && USART_SOFT_RX_PIN2==1) || (defined(USART_SOFT_RX_PORT3) && defined(USART_SOFT_RX_PIN3) && USART_SOFT_RX_PIN3==1)
void exti1_isr ( void )
{
rx_activity ( ) ;
}
# endif
# if (defined(USART_SOFT_RX_PORT0) && defined(USART_SOFT_RX_PIN0) && USART_SOFT_RX_PIN0==2) || (defined(USART_SOFT_RX_PORT1) && defined(USART_SOFT_RX_PIN1) && USART_SOFT_RX_PIN1==2) || (defined(USART_SOFT_RX_PORT2) && defined(USART_SOFT_RX_PIN2) && USART_SOFT_RX_PIN2==2) || (defined(USART_SOFT_RX_PORT3) && defined(USART_SOFT_RX_PIN3) && USART_SOFT_RX_PIN3==2)
void exti2_isr ( void )
{
rx_activity ( ) ;
}
# endif
# if (defined(USART_SOFT_RX_PORT0) && defined(USART_SOFT_RX_PIN0) && USART_SOFT_RX_PIN0==3) || (defined(USART_SOFT_RX_PORT1) && defined(USART_SOFT_RX_PIN1) && USART_SOFT_RX_PIN1==3) || (defined(USART_SOFT_RX_PORT2) && defined(USART_SOFT_RX_PIN2) && USART_SOFT_RX_PIN2==3) || (defined(USART_SOFT_RX_PORT3) && defined(USART_SOFT_RX_PIN3) && USART_SOFT_RX_PIN3==3)
void exti3_isr ( void )
{
rx_activity ( ) ;
}
# endif
# if (defined(USART_SOFT_RX_PORT0) && defined(USART_SOFT_RX_PIN0) && USART_SOFT_RX_PIN0==4) || (defined(USART_SOFT_RX_PORT1) && defined(USART_SOFT_RX_PIN1) && USART_SOFT_RX_PIN1==4) || (defined(USART_SOFT_RX_PORT2) && defined(USART_SOFT_RX_PIN2) && USART_SOFT_RX_PIN2==4) || (defined(USART_SOFT_RX_PORT3) && defined(USART_SOFT_RX_PIN3) && USART_SOFT_RX_PIN3==4)
void exti4_isr ( void )
{
rx_activity ( ) ;
}
# endif
# if (defined(USART_SOFT_RX_PORT0) && defined(USART_SOFT_RX_PIN0) && (USART_SOFT_RX_PIN0==5 || USART_SOFT_RX_PIN0==6 || USART_SOFT_RX_PIN0==7 || USART_SOFT_RX_PIN0==8 || USART_SOFT_RX_PIN0==9)) || (defined(USART_SOFT_RX_PORT1) && defined(USART_SOFT_RX_PIN1) && (USART_SOFT_RX_PIN1==5 || USART_SOFT_RX_PIN1==6 || USART_SOFT_RX_PIN1==7 || USART_SOFT_RX_PIN1==8 || USART_SOFT_RX_PIN1==9)) || (defined(USART_SOFT_RX_PORT2) && defined(USART_SOFT_RX_PIN2) && (USART_SOFT_RX_PIN2==5 || USART_SOFT_RX_PIN2==6 || USART_SOFT_RX_PIN2==7 || USART_SOFT_RX_PIN2==8 || USART_SOFT_RX_PIN2==9)) || (defined(USART_SOFT_RX_PORT3) && defined(USART_SOFT_RX_PIN3) && (USART_SOFT_RX_PIN3==5 || USART_SOFT_RX_PIN3==6 || USART_SOFT_RX_PIN3==7 || USART_SOFT_RX_PIN3==8 || USART_SOFT_RX_PIN3==9))
void exti9_5_isr ( void )
{
rx_activity ( ) ;
}
# endif
# if (defined(USART_SOFT_RX_PORT0) && defined(USART_SOFT_RX_PIN0) && (USART_SOFT_RX_PIN0==10 || USART_SOFT_RX_PIN0==11 || USART_SOFT_RX_PIN0==12 || USART_SOFT_RX_PIN0==13 || USART_SOFT_RX_PIN0==14 || USART_SOFT_RX_PIN0==15)) || (defined(USART_SOFT_RX_PORT1) && defined(USART_SOFT_RX_PIN1) && (USART_SOFT_RX_PIN1==10 || USART_SOFT_RX_PIN1==11 || USART_SOFT_RX_PIN1==12 || USART_SOFT_RX_PIN1==13 || USART_SOFT_RX_PIN1==14 || USART_SOFT_RX_PIN1==15)) || (defined(USART_SOFT_RX_PORT2) && defined(USART_SOFT_RX_PIN2) && (USART_SOFT_RX_PIN2==10 || USART_SOFT_RX_PIN2==11 || USART_SOFT_RX_PIN2==12 || USART_SOFT_RX_PIN2==13 || USART_SOFT_RX_PIN2==14 || USART_SOFT_RX_PIN2==15)) || (defined(USART_SOFT_RX_PORT3) && defined(USART_SOFT_RX_PIN3) && (USART_SOFT_RX_PIN3==10 || USART_SOFT_RX_PIN3==11 || USART_SOFT_RX_PIN3==12 || USART_SOFT_RX_PIN3==13 || USART_SOFT_RX_PIN3==14 || USART_SOFT_RX_PIN3==15))
void exti15_10_isr ( void )
{
rx_activity ( ) ;
}
# endif