142 lines
6.1 KiB
C
142 lines
6.1 KiB
C
/* 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/cm3/nvic.h> // interrupt definitions
|
|
#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 "usart_enhanced.h" // utilities for USART enhancements
|
|
#include "busvoodoo_global.h" // BusVoodoo definitions
|
|
#include "busvoodoo_oled.h" // OLED utilities
|
|
#include "busvoodoo_uart_generic.h" // generic UART mode
|
|
#include "busvoodoo_uart.h" // own definitions
|
|
|
|
/** @defgroup busvoodoo_uart USART peripheral used for UART communication
|
|
* @{
|
|
*/
|
|
#define BUSVOODOO_UART_USART 3 /**< USART peripheral */
|
|
/** @} */
|
|
|
|
#define BUSVOODOO_UART_RX_TIMER 2 /**< timer ID to capture RX edges */
|
|
#define BUSVOODOO_UART_RX_CHANNEL 4 /**< channel ID used as input capture to capture RX edges */
|
|
|
|
/** UART specific methods that will be called by the generic methods */
|
|
static const struct busvoodoo_uart_generic_specific_t busvoodoo_uart_generic_uart = {
|
|
.usart = USART(BUSVOODOO_UART_USART),
|
|
.usart_rcc = RCC_USART(BUSVOODOO_UART_USART),
|
|
.usart_rst = RST_USART(BUSVOODOO_UART_USART),
|
|
.multidrive = true,
|
|
.tx_port = USART_TX_PORT(BUSVOODOO_UART_USART),
|
|
.tx_pin = USART_TX_PIN(BUSVOODOO_UART_USART),
|
|
.tx_rcc = RCC_USART_PORT(BUSVOODOO_UART_USART),
|
|
.tx_pre = NULL,
|
|
.tx_post = NULL,
|
|
.rx_port = USART_RX_PORT(BUSVOODOO_UART_USART),
|
|
.rx_pin = USART_RX_PIN(BUSVOODOO_UART_USART),
|
|
.rx_rcc = RCC_USART_PORT(BUSVOODOO_UART_USART),
|
|
.rx_pre = NULL,
|
|
.rx_post = NULL,
|
|
.hwflowctl = true,
|
|
.rts_port = USART_RTS_PORT(BUSVOODOO_UART_USART),
|
|
.rts_pin = USART_RTS_PIN(BUSVOODOO_UART_USART),
|
|
.rts_rcc = RCC_USART_PORT(BUSVOODOO_UART_USART),
|
|
.cts_port = USART_CTS_PORT(BUSVOODOO_UART_USART),
|
|
.cts_pin = USART_CTS_PIN(BUSVOODOO_UART_USART),
|
|
.cts_rcc = RCC_USART_PORT(BUSVOODOO_UART_USART),
|
|
.timer = TIM(BUSVOODOO_UART_RX_TIMER),
|
|
.timer_rcc = RCC_TIM(BUSVOODOO_UART_RX_TIMER),
|
|
.timer_port = TIM_CH_PORT(BUSVOODOO_UART_RX_TIMER, BUSVOODOO_UART_RX_CHANNEL),
|
|
.timer_port_rcc = RCC_TIM_CH(BUSVOODOO_UART_RX_TIMER, BUSVOODOO_UART_RX_CHANNEL),
|
|
.timer_pin = TIM_CH_PIN(BUSVOODOO_UART_RX_TIMER, BUSVOODOO_UART_RX_CHANNEL),
|
|
.timer_ic = TIM_IC(BUSVOODOO_UART_RX_CHANNEL),
|
|
.timer_ic_in_ti = TIM_IC_IN_TI(BUSVOODOO_UART_RX_CHANNEL),
|
|
.timer_sr_ccif = TIM_SR_CCIF(BUSVOODOO_UART_RX_CHANNEL),
|
|
.timer_sr_ccof = TIM_SR_CCOF(BUSVOODOO_UART_RX_CHANNEL),
|
|
.timer_ccr = &TIM_CCR(BUSVOODOO_UART_RX_TIMER, BUSVOODOO_UART_RX_CHANNEL),
|
|
.timer_dier_ccie = TIM_DIER_CCIE(BUSVOODOO_UART_RX_CHANNEL),
|
|
.timer_nvic_irq = NVIC_TIM_IRQ(BUSVOODOO_UART_RX_TIMER),
|
|
};
|
|
|
|
/** 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_generic_configure(&busvoodoo_uart_generic_uart); // provide the UART specific information
|
|
}
|
|
complete = busvoodoo_uart_generic_setup(prefix, line); // configure underlying generic UART
|
|
if (complete) { // generic configuration finished
|
|
busvoodoo_led_blue_off(); // disable blue LED because there is no activity
|
|
gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, AFIO_MAPR_TIM2_REMAP_PARTIAL_REMAP2); // remap timer 2 channel 4 to RX to be able to measure the edge timing
|
|
*prefix = "UART"; // display mode
|
|
busvoodoo_oled_text_left(*prefix); // set mode title on OLED display
|
|
const char* pinout_io[10] = {"GND", "5V", "3V3", "LV", "Rx", "Tx", "RTS", "CTS", NULL, NULL}; // UART mode pinout
|
|
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
|
|
}
|
|
if (busvoodoo_full) {
|
|
const char* pinout_rscan[5] = {"HV", NULL, NULL, NULL, NULL}; // HiZ mode RS/CAN pinout
|
|
for (uint8_t i=0; i<LENGTH(pinout_rscan) && i<LENGTH(busvoodoo_global_pinout_rscan); i++) {
|
|
busvoodoo_global_pinout_rscan[i] = pinout_rscan[i]; // set pin names
|
|
}
|
|
}
|
|
busvoodoo_oled_text_pinout((const char**)pinout_io, true); // set pinout on display
|
|
busvoodoo_oled_update(); // update display to show text and pinout
|
|
}
|
|
return complete;
|
|
}
|
|
|
|
/** exit UART mode
|
|
*/
|
|
static void busvoodoo_uart_exit(void)
|
|
{
|
|
busvoodoo_uart_generic_exit(); // exiting the underlying generic UART does everything we need
|
|
// disable timer 2 remapping set during configuration
|
|
uint32_t remap = AFIO_MAPR; // get the remap setting
|
|
remap &= ~AFIO_MAPR_SWJ_MASK; // mask the SWJ setting since they are read only
|
|
remap &= ~AFIO_MAPR_TIM2_REMAP_FULL_REMAP; // clear the timer 2 remap
|
|
gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, remap); // disable timer 2 remapping set during configuration
|
|
}
|
|
|
|
const struct busvoodoo_mode_t busvoodoo_uart_mode = {
|
|
.name = "uart",
|
|
.description = "Universal Asynchronous Receiver-Transmitter",
|
|
.full_only = false,
|
|
.setup = &busvoodoo_uart_setup,
|
|
.commands = busvoodoo_uart_generic_commands,
|
|
.commands_nb = busvoodoo_uart_generic_commands_nb,
|
|
.exit = &busvoodoo_uart_exit,
|
|
};
|