Add support for the TX_ENABLE signal for RS-485 trancievers

pull/138/head
Alastair D'Silva 9 years ago
parent ac92202ef6
commit dbab746e3c
  1. 16
      esp-link/cgipins.c
  2. 1
      esp-link/config.h
  3. 5
      esp-link/main.c
  4. 5
      html/home.html
  5. 16
      html/ui.js
  6. 15
      serial/serbridge.c
  7. 89
      serial/uart.c
  8. 4
      serial/uart.h

@ -32,9 +32,10 @@ int ICACHE_FLASH_ATTR cgiPinsGet(HttpdConnData *connData) {
int len;
len = os_sprintf(buff,
"{ \"reset\":%d, \"isp\":%d, \"conn\":%d, \"ser\":%d, \"swap\":%d, \"rxpup\":%d }",
"{ \"reset\":%d, \"isp\":%d, \"conn\":%d, \"ser\":%d, \"swap\":%d, \"rxpup\":%d, \"uart0_tx_enable\":%d }",
flashConfig.reset_pin, flashConfig.isp_pin, flashConfig.conn_led_pin,
flashConfig.ser_led_pin, !!flashConfig.swap_uart, !!flashConfig.rx_pullup);
flashConfig.ser_led_pin, !!flashConfig.swap_uart, !!flashConfig.rx_pullup,
flashConfig.uart0_tx_enable_pin);
jsonHeader(connData, 200);
httpdSend(connData, buff, len);
@ -48,7 +49,7 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) {
}
int8_t ok = 0;
int8_t reset, isp, conn, ser;
int8_t reset, isp, conn, ser, uart0_tx_enable;
uint8_t swap, rxpup;
ok |= getInt8Arg(connData, "reset", &reset);
ok |= getInt8Arg(connData, "isp", &isp);
@ -56,6 +57,7 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) {
ok |= getInt8Arg(connData, "ser", &ser);
ok |= getBoolArg(connData, "swap", &swap);
ok |= getBoolArg(connData, "rxpup", &rxpup);
ok |= getInt8Arg(connData, "uart0_tx_enable", &uart0_tx_enable);
if (ok < 0) return HTTPD_CGI_DONE;
char *coll;
@ -75,6 +77,10 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) {
if (pins & (1<<ser)) { coll = "Serial LED"; goto collision; }
pins |= 1 << ser;
}
if (uart0_tx_enable >= 0) {
if (pins & (1<<uart0_tx_enable)) { coll = "UART0 TX Enable"; goto collision; }
pins |= 1 << uart0_tx_enable;
}
if (swap) {
if (pins & (1<<15)) { coll = "Uart TX"; goto collision; }
if (pins & (1<<13)) { coll = "Uart RX"; goto collision; }
@ -90,8 +96,8 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) {
flashConfig.ser_led_pin = ser;
flashConfig.swap_uart = swap;
flashConfig.rx_pullup = rxpup;
os_printf("Pins changed: reset=%d isp=%d conn=%d ser=%d swap=%d rx-pup=%d\n",
reset, isp, conn, ser, swap, rxpup);
os_printf("Pins changed: reset=%d isp=%d conn=%d ser=%d swap=%d rx-pup=%d uart0_tx_enable=%d\n",
reset, isp, conn, ser, swap, rxpup, uart0_tx_enable);
// apply the changes
serbridgeInitPins();

@ -37,6 +37,7 @@ typedef struct {
uint8_t mdns_enable;
char mdns_servername[32];
int8_t timezone_offset;
int8_t uart0_tx_enable_pin;
} FlashConfig;
extern FlashConfig flashConfig;

@ -9,6 +9,8 @@
* ----------------------------------------------------------------------------
*/
#define USE_US_TIMER
#include <esp8266.h>
#include "httpd.h"
#include "httpdespfs.h"
@ -110,6 +112,7 @@ void user_rf_pre_init(void) {
// Main routine to initialize esp-link.
void user_init(void) {
system_timer_reinit();
// get the flash config so we know how to init things
//configWipe(); // uncomment to reset the config for testing purposes
bool restoreOk = configRestore();
@ -117,7 +120,7 @@ void user_init(void) {
gpio_init();
gpio_output_set(0, 0, 0, (1<<15)); // some people tie it to GND, gotta ensure it's disabled
// init UART
uart_init(flashConfig.baud_rate, 115200);
uart_init(flashConfig.baud_rate, flashConfig.uart0_tx_enable_pin, 115200);
logInit(); // must come after init of uart
// Say hello (leave some time to cause break in TX after boot loader's msg
os_delay_us(10000L);

@ -76,6 +76,11 @@
<div class="popup">Second signal to program &#xb5;C.
AVR:not used, esp8266:gpio2, ARM:ISP</div>
</div>
<div class="pure-control-group">
<label for="pin-uart0-tx-enable">TX Enable</label>
<select id="pin-uart0-tx-enable"></select>
<div class="popup">A pin that should be asserted high whilst transmitting (eg. to put RS/485 trancievers into TX mode)</div>
</div>
<div class="pure-control-group">
<label for="pin-conn">Conn LED</label>
<select id="pin-conn"></select>

@ -393,12 +393,12 @@ function showNotification(text) {
//===== GPIO Pin mux card
var pinPresets = {
// array: reset, isp, conn, ser, swap, rxpup
"esp-01": [ 0, -1, 2, -1, 0, 1 ],
"esp-12": [ 12, 14, 0, 2, 0, 1 ],
"esp-12 swap": [ 1, 3, 0, 2, 1, 1 ],
"esp-bridge": [ 12, 13, 0, 14, 0, 0 ],
"wifi-link-12": [ 1, 3, 0, 2, 1, 0 ],
// array: reset, isp, conn, ser, swap, rxpup, uart0_tx_enable
"esp-01": [ 0, -1, 2, -1, 0, 1, -1 ],
"esp-12": [ 12, 14, 0, 2, 0, 1, -1 ],
"esp-12 swap": [ 1, 3, 0, 2, 1, 1, -1 ],
"esp-bridge": [ 12, 13, 0, 14, 0, 0, -1 ],
"wifi-link-12": [ 1, 3, 0, 2, 1, 0, -1 ],
};
function createPresets(sel) {
@ -418,6 +418,7 @@ function createPresets(sel) {
setPP("ser", pp[3]);
setPP("swap", pp[4]);
$("#pin-rxpup").checked = !!pp[5];
setPP("uart0-tx-enable", pp[6]);
sel.value = 0;
};
@ -453,6 +454,7 @@ function displayPins(resp) {
createSelectForPin("ser", resp["ser"]);
$("#pin-swap").value = resp["swap"];
$("#pin-rxpup").checked = !!resp["rxpup"];
createSelectForPin("uart0_tx_enable", resp["uart0_tx_enable"]);
createPresets($("#pin-preset"));
$("#pin-spinner").setAttribute("hidden", "");
@ -469,7 +471,7 @@ function setPins(ev) {
ev.preventDefault();
var url = "/pins";
var sep = "?";
["reset", "isp", "conn", "ser", "swap"].forEach(function(p) {
["reset", "isp", "conn", "ser", "swap", "uart0_tx_enable"].forEach(function(p) {
url += sep + p + "=" + $("#pin-"+p).value;
sep = "&";
});

@ -17,7 +17,7 @@
static struct espconn serbridgeConn1; // plain bridging port
static struct espconn serbridgeConn2; // programming port
static esp_tcp serbridgeTcp1, serbridgeTcp2;
static int8_t mcu_reset_pin, mcu_isp_pin;
static int8_t mcu_reset_pin, mcu_isp_pin, uart0_tx_enable_pin;
extern uint8_t slip_disabled; // disable slip to allow flashing of attached MCU
@ -439,9 +439,10 @@ serbridgeInitPins()
{
mcu_reset_pin = flashConfig.reset_pin;
mcu_isp_pin = flashConfig.isp_pin;
uart0_tx_enable_pin = flashConfig.uart0_tx_enable_pin;
#ifdef SERBR_DBG
os_printf("Serbridge pins: reset=%d isp=%d swap=%d\n",
mcu_reset_pin, mcu_isp_pin, flashConfig.swap_uart);
os_printf("Serbridge pins: reset=%d isp=%d tx_enable=%d swap=%d\n",
mcu_reset_pin, mcu_isp_pin, uart0_tx_enable_pin, flashConfig.swap_uart);
#endif
if (flashConfig.swap_uart) {
@ -463,9 +464,17 @@ serbridgeInitPins()
// set both pins to 1 before turning them on so we don't cause a reset
if (mcu_isp_pin >= 0) GPIO_OUTPUT_SET(mcu_isp_pin, 1);
if (mcu_reset_pin >= 0) GPIO_OUTPUT_SET(mcu_reset_pin, 1);
// set TX_ENABLE to 0 so we start up listening
if (mcu_reset_pin >= 0) GPIO_OUTPUT_SET(uart0_tx_enable_pin, 0);
// switch pin mux to make these pins GPIO pins
if (mcu_reset_pin >= 0) makeGpio(mcu_reset_pin);
if (mcu_isp_pin >= 0) makeGpio(mcu_isp_pin);
if (uart0_tx_enable_pin >= 0) {
makeGpio(uart0_tx_enable_pin);
uart0_set_tx_enable_pin(uart0_tx_enable_pin);
}
}
// Start transparent serial bridge TCP server on specified port (typ. 23)

@ -17,9 +17,11 @@
* ----------------------------------------------------------------------------
* Heavily modified and enhanced by Thorsten von Eicken in 2015
*/
#define USE_US_TIMER
#include "esp8266.h"
#include "task.h"
#include "uart.h"
#include <osapi.h>
#ifdef UART_DBG
#define DBG_UART(format, ...) os_printf(format, ## __VA_ARGS__)
@ -28,6 +30,7 @@
#endif
LOCAL uint8_t uart_recvTaskNum;
LOCAL int8_t uart0_tx_enable_pin;
// UartDev is defined and initialized in rom code.
extern UartDevice UartDev;
@ -36,6 +39,52 @@ static UartRecv_cb uart_recv_cb[4];
static void uart0_rx_intr_handler(void *para);
/******************************************************************************
* FunctionName : set_tx_enable_pin
* Description : Set which pin to use for RS-485 TX_ENABLE
* Parameters : pin, the pin to use
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
uart0_set_tx_enable_pin(int8_t pin) {
uart0_tx_enable_pin = pin;
}
/******************************************************************************
* FunctionName : tx_enable
* Description : Internal used function
* Set the TX_ENABLE line for RS-485 communications
* Parameters : state, true if the TX_ENABLE line should be asserted high
* Returns : NONE
*******************************************************************************/
static void ICACHE_FLASH_ATTR
tx_enable(bool state)
{
if (uart0_tx_enable_pin >= 0) {
#ifdef SERBR_DBG
os_printf("TX_ENABLE gpio%d state=%d\n", uart0_tx_enable_pin, (int)state);
#endif
GPIO_OUTPUT_SET(uart0_tx_enable_pin, (state) ? 1 : 0);
}
#ifdef SERBR_DBG
else { os_printf("TX Enable: no pin\n"); }
#endif
}
/******************************************************************************
* FunctionName : tx_completed_interrupt
* Description : Internal used function
* Set the TX enable line low, after the UART has completed tranmission
* Parameters : unused unused
* Returns : NONE
*******************************************************************************/
static void ICACHE_FLASH_ATTR
tx_completed_interrupt(void *arg)
{
tx_enable(false);
}
/******************************************************************************
* FunctionName : uart_config
* Description : Internal used function
@ -81,12 +130,19 @@ uart_config(uint8 uart_no)
// to set the threshold here...
// We do not enable framing error interrupts 'cause they tend to cause an interrupt avalanche
// and instead just poll for them when we get a std RX interrupt.
uint32_t tx_empty_bits = 0;
if (uart0_tx_enable_pin >= 0) {
tx_empty_bits = (0 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S | UART_TXFIFO_EMPTY_INT_ENA;
}
WRITE_PERI_REG(UART_CONF1(uart_no),
((80 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
((100 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) |
UART_RX_FLOW_EN |
(4 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S |
UART_RX_TOUT_EN);
UART_RX_TOUT_EN) |
tx_empty_bits
;
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
} else {
WRITE_PERI_REG(UART_CONF1(uart_no),
@ -97,6 +153,9 @@ uart_config(uint8 uart_no)
WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff);
}
os_timer_t uart_tx_enable_timer;
bool uart_tx_enable_timer_inited = false;
/******************************************************************************
* FunctionName : uart1_tx_one_char
* Description : Internal used function
@ -110,6 +169,16 @@ uart_tx_one_char(uint8 uart, uint8 c)
//Wait until there is room in the FIFO
while (((READ_PERI_REG(UART_STATUS(uart))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=100) ;
//Send the character
if (UART0 == uart) {
if (uart_tx_enable_timer_inited) {
// If a tx_completed_interrupt has already been scheduled, cancel it before it fires during our transmission
os_timer_disarm(&uart_tx_enable_timer);
} else {
os_timer_setfn(&uart_tx_enable_timer, tx_completed_interrupt, NULL);
}
tx_enable(true);
}
WRITE_PERI_REG(UART_FIFO(uart), c);
return OK;
}
@ -168,6 +237,7 @@ uart0_sendStr(const char *str)
}
static uint32 last_frm_err; // time in us when last framing error message was printed
static int uart0_baud_rate = 0; // The baud rate for uart0
/******************************************************************************
* FunctionName : uart0_rx_intr_handler
@ -206,6 +276,12 @@ uart0_rx_intr_handler(void *para)
//DBG_UART("stat:%02X",*(uint8 *)UART_INT_ENA(uart_no));
ETS_UART_INTR_DISABLE();
post_usr_task(uart_recvTaskNum, 0);
} else if (UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST)) {
// TX Queue is empty, disable the TX_ENABLE line once the transmission is complete
if (0 != uart0_baud_rate) {
int tx_char_time = 8 * 1000000 / uart0_baud_rate; // assumes 8 bits per character
os_timer_arm_us(&uart_tx_enable_timer, tx_char_time, false);
}
}
}
@ -255,6 +331,7 @@ done:
void ICACHE_FLASH_ATTR
uart0_baud(int rate) {
uart0_baud_rate = rate;
os_printf("UART %d baud\n", rate);
uart_div_modify(UART0, UART_CLK_FREQ / rate);
}
@ -263,13 +340,19 @@ uart0_baud(int rate) {
* FunctionName : uart_init
* Description : user interface for init uart
* Parameters : UartBautRate uart0_br - uart0 bautrate
* uart0TxEnablePin
* UartBautRate uart1_br - uart1 bautrate
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
uart_init(UartBautRate uart0_br, UartBautRate uart1_br)
uart_init(UartBautRate uart0_br, int8_t uart0TxEnablePin, UartBautRate uart1_br)
{
if (uart0TxEnablePin >= 0) {
uart0_set_tx_enable_pin(uart0TxEnablePin);
}
// rom use 74880 baut_rate, here reinitialize
uart0_baud_rate = (int)uart0_br;
UartDev.baut_rate = uart0_br;
uart_config(UART0);
UartDev.baut_rate = uart1_br;
@ -298,7 +381,7 @@ uart_add_recv_cb(UartRecv_cb cb) {
void ICACHE_FLASH_ATTR
uart_reattach()
{
uart_init(BIT_RATE_74880, BIT_RATE_74880);
uart_init(BIT_RATE_74880, -1, BIT_RATE_74880);
// ETS_UART_INTR_ATTACH(uart_rx_intr_handler_ssc, &(UartDev.rcv_buff));
// ETS_UART_INTR_ENABLE();
}

@ -8,7 +8,7 @@ typedef void (*UartRecv_cb)(char *buf, short len);
// Initialize UARTs to the provided baud rates (115200 recommended). This also makes the os_printf
// calls use uart1 for output (for debugging purposes)
void uart_init(UartBautRate uart0_br, UartBautRate uart1_br);
void uart_init(UartBautRate uart0_br, int8_t uart0TxEnablePin, UartBautRate uart1_br);
// Transmit a buffer of characters on UART0
void uart0_tx_buffer(char *buf, uint16 len);
@ -28,4 +28,6 @@ uint16_t uart0_rx_poll(char *buff, uint16_t nchars, uint32_t timeout_us);
void uart0_baud(int rate);
void uart0_set_tx_enable_pin(int8_t pin);
#endif /* __UART_H__ */

Loading…
Cancel
Save