From cd43eb4311356648ad9e69e617eb6ca0c13d08a1 Mon Sep 17 00:00:00 2001 From: Bernhard Guillon Date: Sun, 4 Dec 2016 12:05:21 +0100 Subject: [PATCH] extras/softuart: add initial port This is a initial port of esp8266-software-uart [1] and for now it only supports one RX port with 8n1. 1 https://github.com/plieningerweb/esp8266-software-uart --- extras/softuart/LICENSE | 23 +++++++ extras/softuart/component.mk | 10 +++ extras/softuart/softuart.c | 118 +++++++++++++++++++++++++++++++++++ extras/softuart/softuart.h | 87 ++++++++++++++++++++++++++ 4 files changed, 238 insertions(+) create mode 100644 extras/softuart/LICENSE create mode 100644 extras/softuart/component.mk create mode 100644 extras/softuart/softuart.c create mode 100644 extras/softuart/softuart.h diff --git a/extras/softuart/LICENSE b/extras/softuart/LICENSE new file mode 100644 index 0000000..104c838 --- /dev/null +++ b/extras/softuart/LICENSE @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (C) 2016 Bernhard Guillon +Copyright (c) 2015 plieningerweb + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/extras/softuart/component.mk b/extras/softuart/component.mk new file mode 100644 index 0000000..9517cf2 --- /dev/null +++ b/extras/softuart/component.mk @@ -0,0 +1,10 @@ +# Component makefile for extras/softuart + +# expected anyone using this driver includes it as 'softuart/softuart.h' +INC_DIRS += $(softuart_ROOT).. + +# args for passing into compile rule generation +softuart_SRC_DIR = $(softuart_ROOT) + +$(eval $(call component_compile_rules,softuart)) + diff --git a/extras/softuart/softuart.c b/extras/softuart/softuart.c new file mode 100644 index 0000000..05d5bcb --- /dev/null +++ b/extras/softuart/softuart.c @@ -0,0 +1,118 @@ +/* + * Softuart + * + * Copyright (C) 2016 Bernhard Guillon + * + * This code is based on Softuart from here [1] and reworked to + * fit into esp-open-rtos. For now only the RX part is ported. + * Also the configuration of the pin is for now hardcoded. + * + * it fits my needs to read the GY-GPS6MV2 module with 9600 8n1 + * + * Original Copyright: + * Copyright (c) 2015 plieningerweb + * + * MIT Licensed as described in the file LICENSE + * + * 1 https://github.com/plieningerweb/esp8266-software-uart + */ + +#include "softuart.h" +#include +#include +#include +#include + +static softuart s; + +void handle_rx(uint8_t gpio_num) +{ + // Disable interrupt + gpio_set_interrupt(rx_pin, GPIO_INTTYPE_NONE, handle_rx); + + // Wait till start bit is half over so we can sample the next one in the center + sdk_os_delay_us(s.bit_time/2); + + // Now sample bits + unsigned i; + unsigned d = 0; + unsigned start_time = 0x7FFFFFFF & sdk_system_get_time(); + + for(i = 0; i < 8; i ++ ) + { + while ((0x7FFFFFFF & sdk_system_get_time()) < (start_time + (s.bit_time*(i+1)))) + { + // If system timer overflow, escape from while loop + if ((0x7FFFFFFF & sdk_system_get_time()) < start_time) + { + break; + } + } + // Shift d to the right + d >>= 1; + + // Read bit + if(gpio_read(rx_pin)) + { + // If high, set msb of 8bit to 1 + d |= 0x80; + } + } + + // Store byte in buffer + // If buffer full, set the overflow flag and return + uint8_t next = (s.buffer.receive_buffer_tail + 1) % SOFTUART_MAX_RX_BUFF; + if (next != s.buffer.receive_buffer_head) + { + // save new data in buffer: tail points to where byte goes + s.buffer.receive_buffer[s.buffer.receive_buffer_tail] = d; // save new byte + s.buffer.receive_buffer_tail = next; + } + else + { + s.buffer.buffer_overflow = 1; + } + + // Wait for stop bit + sdk_os_delay_us(s.bit_time); + // Done + // Reenable interrupt + gpio_set_interrupt(rx_pin, GPIO_INTTYPE_EDGE_NEG, handle_rx); +} + +bool softuart_init(uint32_t baudrate) +{ + if (baudrate == 0) + return false; + + // Calculate bit_time + s.bit_time = (1000000 / baudrate); + if ( ((100000000 / baudrate) - (100*s.bit_time)) > 50 ) + s.bit_time++; + + gpio_enable(rx_pin, GPIO_INPUT); + gpio_set_pullup(rx_pin, true, false); + // Set up the interrupt handler to get the startbit + gpio_set_interrupt(rx_pin, GPIO_INTTYPE_EDGE_NEG, handle_rx); + + return true; +} + +// Read data from buffer +uint8_t softuart_read() +{ + // Empty buffer? + if (s.buffer.receive_buffer_head == s.buffer.receive_buffer_tail) + return 0; + + // Read from "head" + uint8_t d = s.buffer.receive_buffer[s.buffer.receive_buffer_head]; // grab next byte + s.buffer.receive_buffer_head = (s.buffer.receive_buffer_head + 1) % SOFTUART_MAX_RX_BUFF; + return d; +} + +// Is data in buffer available? +bool softuart_available() +{ + return (s.buffer.receive_buffer_tail + SOFTUART_MAX_RX_BUFF - s.buffer.receive_buffer_head) % SOFTUART_MAX_RX_BUFF; +} diff --git a/extras/softuart/softuart.h b/extras/softuart/softuart.h new file mode 100644 index 0000000..dd7a268 --- /dev/null +++ b/extras/softuart/softuart.h @@ -0,0 +1,87 @@ +/* + * Softuart for esp-open-rtos + * + * Copyright (C) 2016 Bernhard Guillon + * + * This code is based on Softuart from here [1] and reworked to + * fit into esp-open-rtos. For now only the RX part is ported. + * Also the configuration of the pin is for now hardcoded. + * + * it fits my needs to read the GY-GPS6MV2 module with 9600 8n1 + * + * Original Copyright: + * Copyright (c) 2015 plieningerweb + * + * MIT Licensed as described in the file LICENSE + * + * 1 https://github.com/plieningerweb/esp8266-software-uart + */ +#ifndef SOFTUART_H_ +#define SOFTUART_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +// FIXME: for now you need to provide the gpio number for RX here +#define rx_pin 13 + +#define SOFTUART_MAX_RX_BUFF 64 +#define SOFTUART_GPIO_COUNT 16 + +/** + * Private data buffer + */ +typedef struct softuart_buffer_t +{ + char receive_buffer[SOFTUART_MAX_RX_BUFF]; + uint8_t receive_buffer_tail; + uint8_t receive_buffer_head; + uint8_t buffer_overflow; +} softuart_buffer_t; + +/** + * Private softuart descriptor + */ +typedef struct +{ + uint8_t pin_rx; //!< This value is ignored by now but planned to get added again + volatile softuart_buffer_t buffer; //!< Internal buffer + uint16_t bit_time; //!< Time for one bit, filled by softuart +} softuart; + +/** + * Initialize software uart and setup interrup handlers + * + * FIXME: For now you will have to set up the + * rx_pin and handle_rx your self. + * + * @param baudrate actual baudrate + * @return true if no errors occured otherwise false + */ +bool softuart_init(uint32_t baudrate); + +/** + * Check if data is available + * @return true if data is available otherwise false + */ +bool softuart_available(); + +/** + * Read current byte from internal buffer if available. + * + * NOTE: This call is non blocking. + * NOTE: You have to check softuart_available first. + * @return current byte + */ +uint8_t softuart_read(); + +#ifdef __cplusplus +} +#endif + +#endif /* SOFTUART_H_ */