-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add iram option to MHZ19(B) driver (#1248)
Add iram option to MHZ19(B) driver (#1248)
- Loading branch information
Showing
9 changed files
with
422 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# EspSoftwareSerial | ||
|
||
Implementation of the Arduino software serial library for the ESP8266 | ||
|
||
Same functionality as the corresponding AVR library but several instances can be active at the same time. | ||
Speed up to 115200 baud is supported. The constructor also has an optional input buffer size. | ||
|
||
Please note that due to the fact that the ESP always have other activities ongoing, there will be some inexactness in interrupt | ||
timings. This may lead to bit errors when having heavy data traffic in high baud rates. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
/* | ||
SoftwareSerial.cpp - Implementation of the Arduino software serial for ESP8266. | ||
Copyright (c) 2015-2016 Peter Lerup. All rights reserved. | ||
This library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 2.1 of the License, or (at your option) any later version. | ||
This library 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 | ||
Lesser General Public License for more details. | ||
You should have received a copy of the GNU Lesser General Public | ||
License along with this library; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
|
||
#include <Arduino.h> | ||
|
||
// The Arduino standard GPIO routines are not enough, | ||
// must use some from the Espressif SDK as well | ||
extern "C" { | ||
#include "gpio.h" | ||
} | ||
|
||
#include <SoftwareSerial.h> | ||
|
||
#define MAX_PIN 15 | ||
|
||
// As the Arduino attachInterrupt has no parameter, lists of objects | ||
// and callbacks corresponding to each possible GPIO pins have to be defined | ||
SoftwareSerial *ObjList[MAX_PIN+1]; | ||
|
||
void ICACHE_RAM_ATTR sws_isr_0() { ObjList[0]->rxRead(); }; | ||
void ICACHE_RAM_ATTR sws_isr_1() { ObjList[1]->rxRead(); }; | ||
void ICACHE_RAM_ATTR sws_isr_2() { ObjList[2]->rxRead(); }; | ||
void ICACHE_RAM_ATTR sws_isr_3() { ObjList[3]->rxRead(); }; | ||
void ICACHE_RAM_ATTR sws_isr_4() { ObjList[4]->rxRead(); }; | ||
void ICACHE_RAM_ATTR sws_isr_5() { ObjList[5]->rxRead(); }; | ||
// Pin 6 to 11 can not be used | ||
void ICACHE_RAM_ATTR sws_isr_12() { ObjList[12]->rxRead(); }; | ||
void ICACHE_RAM_ATTR sws_isr_13() { ObjList[13]->rxRead(); }; | ||
void ICACHE_RAM_ATTR sws_isr_14() { ObjList[14]->rxRead(); }; | ||
void ICACHE_RAM_ATTR sws_isr_15() { ObjList[15]->rxRead(); }; | ||
|
||
static void (*ISRList[MAX_PIN+1])() = { | ||
sws_isr_0, | ||
sws_isr_1, | ||
sws_isr_2, | ||
sws_isr_3, | ||
sws_isr_4, | ||
sws_isr_5, | ||
NULL, | ||
NULL, | ||
NULL, | ||
NULL, | ||
NULL, | ||
NULL, | ||
sws_isr_12, | ||
sws_isr_13, | ||
sws_isr_14, | ||
sws_isr_15 | ||
}; | ||
|
||
SoftwareSerial::SoftwareSerial(int receivePin, int transmitPin, bool inverse_logic, unsigned int buffSize) { | ||
m_rxValid = m_txValid = m_txEnableValid = false; | ||
m_buffer = NULL; | ||
m_invert = inverse_logic; | ||
m_overflow = false; | ||
m_rxEnabled = false; | ||
if (isValidGPIOpin(receivePin)) { | ||
m_rxPin = receivePin; | ||
m_buffSize = buffSize; | ||
m_buffer = (uint8_t*)malloc(m_buffSize); | ||
if (m_buffer != NULL) { | ||
m_rxValid = true; | ||
m_inPos = m_outPos = 0; | ||
pinMode(m_rxPin, INPUT); | ||
ObjList[m_rxPin] = this; | ||
enableRx(true); | ||
} | ||
} | ||
if (isValidGPIOpin(transmitPin) || transmitPin == 16) { | ||
m_txValid = true; | ||
m_txPin = transmitPin; | ||
pinMode(m_txPin, OUTPUT); | ||
digitalWrite(m_txPin, !m_invert); | ||
} | ||
// Default speed | ||
begin(9600); | ||
} | ||
|
||
SoftwareSerial::~SoftwareSerial() { | ||
enableRx(false); | ||
if (m_rxValid) | ||
ObjList[m_rxPin] = NULL; | ||
if (m_buffer) | ||
free(m_buffer); | ||
} | ||
|
||
bool SoftwareSerial::isValidGPIOpin(int pin) { | ||
return (pin >= 0 && pin <= 5) || (pin >= 12 && pin <= MAX_PIN); | ||
} | ||
|
||
void SoftwareSerial::begin(long speed) { | ||
// Use getCycleCount() loop to get as exact timing as possible | ||
m_bitTime = ESP.getCpuFreqMHz()*1000000/speed; | ||
m_highSpeed = speed > 9600; | ||
|
||
if (!m_rxEnabled) | ||
enableRx(true); | ||
} | ||
|
||
long SoftwareSerial::baudRate() { | ||
return ESP.getCpuFreqMHz()*1000000/m_bitTime; | ||
} | ||
|
||
void SoftwareSerial::setTransmitEnablePin(int transmitEnablePin) { | ||
if (isValidGPIOpin(transmitEnablePin)) { | ||
m_txEnableValid = true; | ||
m_txEnablePin = transmitEnablePin; | ||
pinMode(m_txEnablePin, OUTPUT); | ||
digitalWrite(m_txEnablePin, LOW); | ||
} else { | ||
m_txEnableValid = false; | ||
} | ||
} | ||
|
||
void SoftwareSerial::enableRx(bool on) { | ||
if (m_rxValid) { | ||
if (on) | ||
attachInterrupt(m_rxPin, ISRList[m_rxPin], m_invert ? RISING : FALLING); | ||
else | ||
detachInterrupt(m_rxPin); | ||
m_rxEnabled = on; | ||
} | ||
} | ||
|
||
int SoftwareSerial::read() { | ||
if (!m_rxValid || (m_inPos == m_outPos)) return -1; | ||
uint8_t ch = m_buffer[m_outPos]; | ||
m_outPos = (m_outPos+1) % m_buffSize; | ||
return ch; | ||
} | ||
|
||
int SoftwareSerial::available() { | ||
if (!m_rxValid) return 0; | ||
int avail = m_inPos - m_outPos; | ||
if (avail < 0) avail += m_buffSize; | ||
return avail; | ||
} | ||
|
||
#define WAIT { while (ESP.getCycleCount()-start < wait) if (!m_highSpeed) optimistic_yield(1); wait += m_bitTime; } | ||
|
||
size_t SoftwareSerial::write(uint8_t b) { | ||
if (!m_txValid) return 0; | ||
|
||
if (m_invert) b = ~b; | ||
if (m_highSpeed) | ||
// Disable interrupts in order to get a clean transmit | ||
cli(); | ||
if (m_txEnableValid) digitalWrite(m_txEnablePin, HIGH); | ||
unsigned long wait = m_bitTime; | ||
digitalWrite(m_txPin, HIGH); | ||
unsigned long start = ESP.getCycleCount(); | ||
// Start bit; | ||
digitalWrite(m_txPin, LOW); | ||
WAIT; | ||
for (int i = 0; i < 8; i++) { | ||
digitalWrite(m_txPin, (b & 1) ? HIGH : LOW); | ||
WAIT; | ||
b >>= 1; | ||
} | ||
// Stop bit | ||
digitalWrite(m_txPin, HIGH); | ||
WAIT; | ||
if (m_txEnableValid) digitalWrite(m_txEnablePin, LOW); | ||
if (m_highSpeed) | ||
sei(); | ||
return 1; | ||
} | ||
|
||
void SoftwareSerial::flush() { | ||
m_inPos = m_outPos = 0; | ||
} | ||
|
||
bool SoftwareSerial::overflow() { | ||
bool res = m_overflow; | ||
m_overflow = false; | ||
return res; | ||
} | ||
|
||
int SoftwareSerial::peek() { | ||
if (!m_rxValid || (m_inPos == m_outPos)) return -1; | ||
return m_buffer[m_outPos]; | ||
} | ||
|
||
void ICACHE_RAM_ATTR SoftwareSerial::rxRead() { | ||
// Advance the starting point for the samples but compensate for the | ||
// initial delay which occurs before the interrupt is delivered | ||
unsigned long wait = m_bitTime + m_bitTime/3 - 500; | ||
unsigned long start = ESP.getCycleCount(); | ||
uint8_t rec = 0; | ||
for (int i = 0; i < 8; i++) { | ||
WAIT; | ||
rec >>= 1; | ||
if (digitalRead(m_rxPin)) | ||
rec |= 0x80; | ||
} | ||
if (m_invert) rec = ~rec; | ||
// Stop bit | ||
WAIT; | ||
// Store the received value in the buffer unless we have an overflow | ||
int next = (m_inPos+1) % m_buffSize; | ||
if (next != m_outPos) { | ||
m_buffer[m_inPos] = rec; | ||
m_inPos = next; | ||
} else { | ||
m_overflow = true; | ||
} | ||
// Must clear this bit in the interrupt register, | ||
// it gets set even when interrupts are disabled | ||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << m_rxPin); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
SoftwareSerial.h | ||
SoftwareSerial.cpp - Implementation of the Arduino software serial for ESP8266. | ||
Copyright (c) 2015-2016 Peter Lerup. All rights reserved. | ||
This library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 2.1 of the License, or (at your option) any later version. | ||
This library 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 | ||
Lesser General Public License for more details. | ||
You should have received a copy of the GNU Lesser General Public | ||
License along with this library; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
|
||
#ifndef SoftwareSerial_h | ||
#define SoftwareSerial_h | ||
|
||
#include <inttypes.h> | ||
#include <Stream.h> | ||
|
||
|
||
// This class is compatible with the corresponding AVR one, | ||
// the constructor however has an optional rx buffer size. | ||
// Speed up to 115200 can be used. | ||
|
||
|
||
class SoftwareSerial : public Stream | ||
{ | ||
public: | ||
SoftwareSerial(int receivePin, int transmitPin, bool inverse_logic = false, unsigned int buffSize = 64); | ||
~SoftwareSerial(); | ||
|
||
void begin(long speed); | ||
long baudRate(); | ||
void setTransmitEnablePin(int transmitEnablePin); | ||
|
||
bool overflow(); | ||
int peek(); | ||
|
||
virtual size_t write(uint8_t byte); | ||
virtual int read(); | ||
virtual int available(); | ||
virtual void flush(); | ||
operator bool() {return m_rxValid || m_txValid;} | ||
|
||
// Disable or enable interrupts on the rx pin | ||
void enableRx(bool on); | ||
|
||
void rxRead(); | ||
|
||
// AVR compatibility methods | ||
bool listen() { enableRx(true); return true; } | ||
void end() { stopListening(); } | ||
bool isListening() { return m_rxEnabled; } | ||
bool stopListening() { enableRx(false); return true; } | ||
|
||
using Print::write; | ||
|
||
private: | ||
bool isValidGPIOpin(int pin); | ||
|
||
// Member variables | ||
int m_rxPin, m_txPin, m_txEnablePin; | ||
bool m_rxValid, m_rxEnabled; | ||
bool m_txValid, m_txEnableValid; | ||
bool m_invert; | ||
bool m_overflow; | ||
unsigned long m_bitTime; | ||
bool m_highSpeed; | ||
unsigned int m_inPos, m_outPos; | ||
int m_buffSize; | ||
uint8_t *m_buffer; | ||
|
||
}; | ||
|
||
// If only one tx or rx wanted then use this as parameter for the unused pin | ||
#define SW_SERIAL_UNUSED_PIN -1 | ||
|
||
|
||
#endif |
27 changes: 27 additions & 0 deletions
27
lib/EspSoftwareSerial-3.3.1/examples/swsertest/swsertest.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
|
||
#include <SoftwareSerial.h> | ||
|
||
SoftwareSerial swSer(14, 12, false, 256); | ||
|
||
void setup() { | ||
Serial.begin(115200); | ||
swSer.begin(115200); | ||
|
||
Serial.println("\nSoftware serial test started"); | ||
|
||
for (char ch = ' '; ch <= 'z'; ch++) { | ||
swSer.write(ch); | ||
} | ||
swSer.println(""); | ||
|
||
} | ||
|
||
void loop() { | ||
while (swSer.available() > 0) { | ||
Serial.write(swSer.read()); | ||
} | ||
while (Serial.available() > 0) { | ||
swSer.write(Serial.read()); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
####################################### | ||
# Syntax Coloring Map for SoftwareSerial | ||
# (esp8266) | ||
####################################### | ||
|
||
####################################### | ||
# Datatypes (KEYWORD1) | ||
####################################### | ||
|
||
SoftwareSerial KEYWORD1 | ||
|
||
####################################### | ||
# Methods and Functions (KEYWORD2) | ||
####################################### | ||
|
||
begin KEYWORD2 | ||
read KEYWORD2 | ||
write KEYWORD2 | ||
available KEYWORD2 | ||
flush KEYWORD2 | ||
overflow KEYWORD2 | ||
peek KEYWORD2 | ||
listen KEYWORD2 | ||
end KEYWORD2 | ||
isListening KEYWORD2 | ||
stopListening KEYWORD2 | ||
|
||
####################################### | ||
# Constants (LITERAL1) | ||
####################################### | ||
|
Oops, something went wrong.