/* * 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); } static uint8_t inline chbit(uint8_t data, uint8_t bit) { if((data & bit) != 0) { return 1; } else { return 0; } } uint8_t softuart_putchar( char data) { unsigned i; unsigned start_time = 0x7FFFFFFF & sdk_system_get_time(); gpio_write(tx_pin, 0); for(i = 0; i <= 8; i++) { while((0x7FFFFFFF & sdk_system_get_time()) < (start_time + (s.bit_time*(i+1)))) { if((0x7FFFFFFF & sdk_system_get_time()) < start_time) { break; } } gpio_write(tx_pin, chbit(data, 1< 50 ) s.bit_time++; //Set Rx 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); //Set Tx gpio_enable(tx_pin, GPIO_OUTPUT); gpio_set_pullup(tx_pin, true, false); gpio_write(tx_pin, 1); sdk_os_delay_us(100000); 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; }