busvoodoo_rs485.c
Go to the documentation of this file.
/* 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/>.
*
*/
/* 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 utilities
#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
#include "busvoodoo_oled.h" // OLED utilities
#include "busvoodoo_uart_generic.h" // generic UART mode
#include "busvoodoo_rs485.h" // own definitions
#define BUSVOODOO_RS485_USART 2
static void busvoodoo_rs485_drive_enable(void)
{
gpio_set(GPIO(BUSVOODOO_RS485_DE_PORT), GPIO(BUSVOODOO_RS485_DE_PIN)); // set high to enable RS-485 transceiver driver
}
static void busvoodoo_rs485_drive_disable(void)
{
gpio_clear(GPIO(BUSVOODOO_RS485_DE_PORT), GPIO(BUSVOODOO_RS485_DE_PIN)); // set low to disable RS-485 transceiver driver
}
static void busvoodoo_rs485_receive_enable(void)
{
gpio_clear(GPIO(BUSVOODOO_RS485_RE_PORT), GPIO(BUSVOODOO_RS485_RE_PIN)); // set high to low enable RS-485 transceiver receiver
}
static void busvoodoo_rs485_receive_disable(void)
{
gpio_set(GPIO(BUSVOODOO_RS485_RE_PORT), GPIO(BUSVOODOO_RS485_RE_PIN)); // set high to disable RS-485 transceiver receiver
}
#define BUSVOODOO_RS485_RX_TIMER 2
#define BUSVOODOO_RS485_RX_CHANNEL 4
static const struct busvoodoo_uart_generic_specific_t busvoodoo_uart_generic_rs485 = {
.usart = USART(BUSVOODOO_RS485_USART),
.usart_rcc = RCC_USART(BUSVOODOO_RS485_USART),
.usart_rst = RST_USART(BUSVOODOO_RS485_USART),
.multidrive = false,
.tx_port = USART_TX_PORT(BUSVOODOO_RS485_USART),
.tx_pin = USART_TX_PIN(BUSVOODOO_RS485_USART),
.tx_rcc = RCC_USART_PORT(BUSVOODOO_RS485_USART),
.tx_pre = &busvoodoo_rs485_drive_enable,
.tx_post = &busvoodoo_rs485_drive_disable,
.rx_port = USART_RX_PORT(BUSVOODOO_RS485_USART),
.rx_pin = USART_RX_PIN(BUSVOODOO_RS485_USART),
.rx_rcc = RCC_USART_PORT(BUSVOODOO_RS485_USART),
.rx_pre = &busvoodoo_rs485_receive_enable,
.rx_post = &busvoodoo_rs485_receive_disable,
.hwflowctl = false,
.rts_port = 0,
.rts_pin = 0,
.rts_rcc = 0,
.cts_port = 0,
.cts_pin = 0,
.cts_rcc = 0,
.timer = TIM(BUSVOODOO_RS485_RX_TIMER),
.timer_rcc = RCC_TIM(BUSVOODOO_RS485_RX_TIMER),
.timer_port = TIM_CH_PORT(BUSVOODOO_RS485_RX_TIMER, BUSVOODOO_RS485_RX_CHANNEL),
.timer_port_rcc = RCC_TIM_CH(BUSVOODOO_RS485_RX_TIMER, BUSVOODOO_RS485_RX_CHANNEL),
.timer_pin = TIM_CH_PIN(BUSVOODOO_RS485_RX_TIMER, BUSVOODOO_RS485_RX_CHANNEL),
.timer_ic = TIM_IC(BUSVOODOO_RS485_RX_CHANNEL),
.timer_ic_in_ti = TIM_IC_IN_TI(BUSVOODOO_RS485_RX_CHANNEL),
.timer_sr_ccif = TIM_SR_CCIF(BUSVOODOO_RS485_RX_CHANNEL),
.timer_sr_ccof = TIM_SR_CCOF(BUSVOODOO_RS485_RX_CHANNEL),
.timer_ccr = &TIM_CCR(BUSVOODOO_RS485_RX_TIMER, BUSVOODOO_RS485_RX_CHANNEL),
.timer_dier_ccie = TIM_DIER_CCIE(BUSVOODOO_RS485_RX_CHANNEL),
.timer_nvic_irq = NVIC_TIM_IRQ(BUSVOODOO_RS485_RX_TIMER),
};
static bool busvoodoo_rs485_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_rs485); // provide the RS-485 specific information
}
complete = busvoodoo_uart_generic_setup(prefix, line); // configure underlying generic UART
if (complete) { // generic configuration finished
gpio_clear(GPIO(BUSVOODOO_RS485_DE_PORT), GPIO(BUSVOODOO_RS485_DE_PIN)); // set low to disable RS-485 transceiver drive
gpio_set_mode(GPIO(BUSVOODOO_RS485_DE_PORT), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_RS485_DE_PIN)); // setup RS-485 Drive Enable GPIO as output (pulled low to disable by default)
gpio_set(GPIO(BUSVOODOO_RS485_RE_PORT), GPIO(BUSVOODOO_RS485_RE_PIN)); // set RS-485 transceiver Receive Enable pin high to disable received
gpio_set_mode(GPIO(BUSVOODOO_RS485_RE_PORT), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_RS485_RE_PIN)); // setup RS-485 Receive Enable GPIO as output (pulled high to disable by default)
busvoodoo_led_blue_off(); // disable blue LED because there is no activity
*prefix = "RS-485/422"; // display mode
busvoodoo_oled_text_left(*prefix); // set mode title on OLED display
const char* pinout_io[10] = {"GND", "5V", "3V3", "LV", NULL, NULL, NULL, NULL, NULL, NULL}; // RS-485 mode I/O 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_HARDWARE_VERSION==0
const char* pinout_rscan[5] = {"HV", NULL, NULL, "B", "A"}; // RS-485 mode RS/CAN pinout for hardware version 0
#else
const char* pinout_rscan[5] = {"HV", NULL, "A", "B", NULL}; // RS-485 mode RS/CAN pinout
#endif
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
}
const char* pinout[10] = {pinout_rscan[0], pinout_io[0], pinout_rscan[1], pinout_io[2], pinout_rscan[2], pinout_io[4], pinout_rscan[3], pinout_io[6], pinout_rscan[4], pinout_io[8]}; // pinout to display
busvoodoo_oled_text_pinout((const char**)pinout, false); // set pinout on display
busvoodoo_oled_update(); // update display to show text and pinout
}
return complete;
}
static void busvoodoo_rs485_exit(void)
{
busvoodoo_uart_generic_exit(); // exiting the underlying generic UART does everything we need
gpio_set(GPIO(BUSVOODOO_RS485_RE_PORT), GPIO(BUSVOODOO_RS485_RE_PIN)); // set high to disable RS-485 transceiver receiver
gpio_clear(GPIO(BUSVOODOO_RS485_DE_PORT), GPIO(BUSVOODOO_RS485_DE_PIN)); // set low to disable RS-485 transceiver driver
}
const struct busvoodoo_mode_t busvoodoo_rs485_mode = {
.name = "rs485",
.description = "Recommended Standard 485/422",
.full_only = true,
.setup = &busvoodoo_rs485_setup,
.commands = busvoodoo_uart_generic_commands,
.commands_nb = busvoodoo_uart_generic_commands_nb,
.exit = &busvoodoo_rs485_exit,
};
USART_TX_PORT
#define USART_TX_PORT(x)
get port for USART transmit pin based on USART identifier
Definition: global.h:194
RCC_USART
#define RCC_USART(x)
get RCC for USART based on USART identifier
Definition: global.h:186
RCC_TIM_CH
#define RCC_TIM_CH(x, y)
get RCC for port based on TIMx_CHy identifier
Definition: global.h:119
busvoodoo_uart_generic_setup
bool busvoodoo_uart_generic_setup(char **prefix, const char *line)
setup generic UART mode
Definition: busvoodoo_uart_generic.c:98
busvoodoo_global.h
BusVoodoo global definitions and methods (API)
busvoodoo_oled_text_pinout
void busvoodoo_oled_text_pinout(const char *pins[10], bool io_connector)
draw pin names on bottom (blue) part in display buffer
Definition: busvoodoo_oled.c:148
busvoodoo_mode_t::name
const char * name
name of the mode (i.e.
Definition: busvoodoo_global.h:116
TIM_SR_CCOF
#define TIM_SR_CCOF(x)
get TIM_SR_CCxOF based on CHx identifier
Definition: global.h:150
busvoodoo_rs485_receive_enable
static void busvoodoo_rs485_receive_enable(void)
enable RS-485 transceiver received to allow receiving
Definition: busvoodoo_rs485.c:60
NVIC_TIM_IRQ
#define NVIC_TIM_IRQ(x)
get NVIC IRQ for timer base on TIM identifier
Definition: global.h:111
BUSVOODOO_RS485_RX_TIMER
#define BUSVOODOO_RS485_RX_TIMER
timer ID to capture RX edges
Definition: busvoodoo_rs485.c:71
RCC_USART_PORT
#define RCC_USART_PORT(x)
get RCC for USART port based on USART identifier
Definition: global.h:210
busvoodoo_oled_update
void busvoodoo_oled_update(void)
update OLED display RAM with current display buffer
Definition: busvoodoo_oled.c:289
TIM_SR_CCIF
#define TIM_SR_CCIF(x)
get TIM_SR_CCxIF based on CHx identifier
Definition: global.h:148
busvoodoo_global_pinout_rscan
const char * busvoodoo_global_pinout_rscan[5]
RS/CAN connector pinout.
Definition: busvoodoo_global.c:63
TIM_DIER_CCIE
#define TIM_DIER_CCIE(x)
get TIM_DIER_CCxIE based on CHx identifier
Definition: global.h:152
global.h
global definitions and methods (API)
GPIO
#define GPIO(x)
get GPIO based on GPIO identifier
Definition: global.h:103
TIM_CCR
#define TIM_CCR(x, y)
get TIM_CCRy register based on TIMx_CHy identifier
Definition: global.h:154
BUSVOODOO_RS485_RE_PORT
#define BUSVOODOO_RS485_RE_PORT
RS-485 pin to enable receiver (active low, pulled up)
Definition: busvoodoo_global.h:81
RCC_TIM
#define RCC_TIM(x)
get RCC for timer based on TIM identifier
Definition: global.h:109
TIM_CH_PIN
#define TIM_CH_PIN(x, y)
get pin based on TIMx_CHy identifier
Definition: global.h:117
busvoodoo_rs485_setup
static bool busvoodoo_rs485_setup(char **prefix, const char *line)
setup RS-485 mode
Definition: busvoodoo_rs485.c:116
busvoodoo_led_blue_off
void busvoodoo_led_blue_off(void)
switch off blue LED
Definition: busvoodoo_global.c:426
busvoodoo_rs485_drive_enable
static void busvoodoo_rs485_drive_enable(void)
enable RS-485 transceiver driver to allow transmitting
Definition: busvoodoo_rs485.c:48
USART_RX_PIN
#define USART_RX_PIN(x)
get pin for USART receive pin based on USART identifier
Definition: global.h:204
USART_TX_PIN
#define USART_TX_PIN(x)
get pin for USART transmit pin based on USART identifier
Definition: global.h:202
TIM_IC
#define TIM_IC(x)
get TIM_IC based on CHx identifier
Definition: global.h:144
RST_USART
#define RST_USART(x)
get RST for USART based on USART identifier
Definition: global.h:188
USART
#define USART(x)
get USART based on USART identifier
Definition: global.h:184
BUSVOODOO_RS485_DE_PORT
#define BUSVOODOO_RS485_DE_PORT
RS-485 pin to enable transmitter (active high, pulled low)
Definition: busvoodoo_global.h:83
busvoodoo_uart_generic_exit
void busvoodoo_uart_generic_exit(void)
exit genetic UART mode
Definition: busvoodoo_uart_generic.c:287
TIM_IC_IN_TI
#define TIM_IC_IN_TI(x)
get TIM_IC_IN_TI based on CHx identifier
Definition: global.h:146
busvoodoo_global_pinout_io
const char * busvoodoo_global_pinout_io[10]
I/O connector pinout.
Definition: busvoodoo_global.c:62
busvoodoo_uart_generic_commands_nb
#define busvoodoo_uart_generic_commands_nb
number of commands supported by the generic UART mode
Definition: busvoodoo_uart_generic.h:79
TIM_CH_PORT
#define TIM_CH_PORT(x, y)
get port based on TIMx_CHy identifier
Definition: global.h:115
USART_RX_PORT
#define USART_RX_PORT(x)
get port for USART receive pin based on USART identifier
Definition: global.h:196
busvoodoo_uart_generic_configure
bool busvoodoo_uart_generic_configure(const struct busvoodoo_uart_generic_specific_t *conf)
provide the generic USART with mode specific information
Definition: busvoodoo_uart_generic.c:76
busvoodoo_rs485_receive_disable
static void busvoodoo_rs485_receive_disable(void)
enable RS-485 transceiver received to allow receiving
Definition: busvoodoo_rs485.c:66
busvoodoo_uart_generic.h
BusVoodoo generic UART mode (API)
print.h
printing utilities to replace the large printf from the standard library (API)
BUSVOODOO_RS485_DE_PIN
#define BUSVOODOO_RS485_DE_PIN
RS-485 pin to enable transmitter (active high, pulled low)
Definition: busvoodoo_global.h:84
busvoodoo_oled_text_left
void busvoodoo_oled_text_left(char *text)
draw mode text on top (yellow) left side in display buffer
Definition: busvoodoo_oled.c:118
busvoodoo_uart_generic_commands
const struct menu_command_t busvoodoo_uart_generic_commands[busvoodoo_uart_generic_commands_nb]
commands supported by the generic UART mode
Definition: busvoodoo_uart_generic.c:1018
LENGTH
#define LENGTH(x)
get the length of an array
Definition: global.h:26
busvoodoo_rs485_drive_disable
static void busvoodoo_rs485_drive_disable(void)
enable RS-485 transceiver driver to allow transmitting
Definition: busvoodoo_rs485.c:54
BUSVOODOO_RS485_RE_PIN
#define BUSVOODOO_RS485_RE_PIN
RS-485 pin to enable receiver (active low, pulled up)
Definition: busvoodoo_global.h:82
TIM
#define TIM(x)
get TIM based on TIM identifier
Definition: global.h:107
BUSVOODOO_RS485_RX_CHANNEL
#define BUSVOODOO_RS485_RX_CHANNEL
channel ID used as input capture to capture RX edges
Definition: busvoodoo_rs485.c:72
busvoodoo_uart_generic_rs485
static const struct busvoodoo_uart_generic_specific_t busvoodoo_uart_generic_rs485
RS-485 specific methods that will be called by the generic methods.
Definition: busvoodoo_rs485.c:75
busvoodoo_oled.h
library to show BusVoodoo mode information on SSD1306 OLED display: name, activity, pinout (API)
busvoodoo_mode_t
BusVoodoo mode interface.
Definition: busvoodoo_global.h:115
busvoodoo_rs485.h
BusVoodoo RS-485/422 mode (API)
busvoodoo_rs485_exit
static void busvoodoo_rs485_exit(void)
exit RS-485 mode
Definition: busvoodoo_rs485.c:152
BUSVOODOO_RS485_USART
#define BUSVOODOO_RS485_USART
USART peripheral.
Definition: busvoodoo_rs485.c:44
busvoodoo_rs485_mode
const struct busvoodoo_mode_t busvoodoo_rs485_mode
RS-485 mode interface definition.
Definition: busvoodoo_rs485.c:159