├── examples ├── SoftwareSerialExample │ └── SoftwareSerialExample.ino └── TwoPortReceive │ └── TwoPortReceive.ino ├── keywords.txt ├── library.properties └── src ├── SoftwareSerial9.cpp └── SoftwareSerial9.h /examples/SoftwareSerialExample/SoftwareSerialExample.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Software serial multple serial test 3 | 4 | Receives from the hardware serial, sends to software serial. 5 | Receives from software serial, sends to hardware serial. 6 | 7 | The circuit: 8 | * RX is digital pin 10 (connect to TX of other device) 9 | * TX is digital pin 11 (connect to RX of other device) 10 | 11 | Note: 12 | Not all pins on the Mega and Mega 2560 support change interrupts, 13 | so only the following can be used for RX: 14 | 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 15 | 16 | Not all pins on the Leonardo support change interrupts, 17 | so only the following can be used for RX: 18 | 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI). 19 | 20 | created back in the mists of time 21 | modified 25 May 2012 22 | by Tom Igoe 23 | based on Mikal Hart's example 24 | 25 | This example code is in the public domain. 26 | 27 | */ 28 | #include 29 | 30 | SoftwareSerial mySerial(10, 11); // RX, TX 31 | 32 | void setup() { 33 | // Open serial communications and wait for port to open: 34 | Serial.begin(57600); 35 | while (!Serial) { 36 | ; // wait for serial port to connect. Needed for native USB port only 37 | } 38 | 39 | 40 | Serial.println("Goodnight moon!"); 41 | 42 | // set the data rate for the SoftwareSerial port 43 | mySerial.begin(4800); 44 | mySerial.println("Hello, world?"); 45 | } 46 | 47 | void loop() { // run over and over 48 | if (mySerial.available()) { 49 | Serial.write(mySerial.read()); 50 | } 51 | if (Serial.available()) { 52 | mySerial.write(Serial.read()); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /examples/TwoPortReceive/TwoPortReceive.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Software serial multple serial test 3 | 4 | Receives from the two software serial ports, 5 | sends to the hardware serial port. 6 | 7 | In order to listen on a software port, you call port.listen(). 8 | When using two software serial ports, you have to switch ports 9 | by listen()ing on each one in turn. Pick a logical time to switch 10 | ports, like the end of an expected transmission, or when the 11 | buffer is empty. This example switches ports when there is nothing 12 | more to read from a port 13 | 14 | The circuit: 15 | Two devices which communicate serially are needed. 16 | * First serial device's TX attached to digital pin 10(RX), RX to pin 11(TX) 17 | * Second serial device's TX attached to digital pin 8(RX), RX to pin 9(TX) 18 | 19 | Note: 20 | Not all pins on the Mega and Mega 2560 support change interrupts, 21 | so only the following can be used for RX: 22 | 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69 23 | 24 | Not all pins on the Leonardo support change interrupts, 25 | so only the following can be used for RX: 26 | 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI). 27 | 28 | created 18 Apr. 2011 29 | modified 19 March 2016 30 | by Tom Igoe 31 | based on Mikal Hart's twoPortRXExample 32 | 33 | This example code is in the public domain. 34 | 35 | */ 36 | 37 | #include 38 | // software serial #1: RX = digital pin 10, TX = digital pin 11 39 | SoftwareSerial portOne(10, 11); 40 | 41 | // software serial #2: RX = digital pin 8, TX = digital pin 9 42 | // on the Mega, use other pins instead, since 8 and 9 don't work on the Mega 43 | SoftwareSerial portTwo(8, 9); 44 | 45 | void setup() { 46 | // Open serial communications and wait for port to open: 47 | Serial.begin(9600); 48 | while (!Serial) { 49 | ; // wait for serial port to connect. Needed for native USB port only 50 | } 51 | 52 | 53 | // Start each software serial port 54 | portOne.begin(9600); 55 | portTwo.begin(9600); 56 | } 57 | 58 | void loop() { 59 | // By default, the last intialized port is listening. 60 | // when you want to listen on a port, explicitly select it: 61 | portOne.listen(); 62 | Serial.println("Data from port one:"); 63 | // while there is data coming in, read it 64 | // and send to the hardware serial port: 65 | while (portOne.available() > 0) { 66 | char inByte = portOne.read(); 67 | Serial.write(inByte); 68 | } 69 | 70 | // blank line to separate data from the two ports: 71 | Serial.println(); 72 | 73 | // Now listen on the second port 74 | portTwo.listen(); 75 | // while there is data coming in, read it 76 | // and send to the hardware serial port: 77 | Serial.println("Data from port two:"); 78 | while (portTwo.available() > 0) { 79 | char inByte = portTwo.read(); 80 | Serial.write(inByte); 81 | } 82 | 83 | // blank line to separate data from the two ports: 84 | Serial.println(); 85 | } 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map for SoftwareSerial 3 | # (formerly NewSoftSerial) 4 | ####################################### 5 | 6 | ####################################### 7 | # Datatypes (KEYWORD1) 8 | ####################################### 9 | 10 | SoftwareSerial9 KEYWORD1 11 | 12 | ####################################### 13 | # Methods and Functions (KEYWORD2) 14 | ####################################### 15 | 16 | begin KEYWORD2 17 | end KEYWORD2 18 | read KEYWORD2 19 | write KEYWORD2 20 | write9 KEYWORD2 21 | available KEYWORD2 22 | isListening KEYWORD2 23 | overflow KEYWORD2 24 | flush KEYWORD2 25 | listen KEYWORD2 26 | peek KEYWORD2 27 | 28 | ####################################### 29 | # Constants (LITERAL1) 30 | ####################################### 31 | 32 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SoftwareSerial9 2 | version=1.0 3 | author=Arduino 4 | maintainer=Drew Dibble 5 | sentence=Enables 9-bit serial communication on any digital pin. 6 | paragraph=Based on SoftwareSerial arduino library 7 | category=Communication 8 | url=http://www.arduino.cc/en/Reference/SoftwareSerial 9 | architectures=avr 10 | 11 | -------------------------------------------------------------------------------- /src/SoftwareSerial9.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SoftwareSerial.cpp (formerly NewSoftSerial.cpp) - 3 | Multi-instance software serial library for Arduino/Wiring 4 | -- Interrupt-driven receive and other improvements by ladyada 5 | (http://ladyada.net) 6 | -- Tuning, circular buffer, derivation from class Print/Stream, 7 | multi-instance support, porting to 8MHz processors, 8 | various optimizations, PROGMEM delay tables, inverse logic and 9 | direct port writing by Mikal Hart (http://www.arduiniana.org) 10 | -- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) 11 | -- 20MHz processor support by Garrett Mace (http://www.macetech.com) 12 | -- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) 13 | 14 | This library is free software; you can redistribute it and/or 15 | modify it under the terms of the GNU Lesser General Public 16 | License as published by the Free Software Foundation; either 17 | version 2.1 of the License, or (at your option) any later version. 18 | 19 | This library is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | Lesser General Public License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public 25 | License along with this library; if not, write to the Free Software 26 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 27 | 28 | The latest version of this library can always be found at 29 | http://arduiniana.org. 30 | */ 31 | 32 | // When set, _DEBUG co-opts pins 11 and 13 for debugging with an 33 | // oscilloscope or logic analyzer. Beware: it also slightly modifies 34 | // the bit times, so don't rely on it too much at high baud rates 35 | #define _DEBUG 0 36 | #define _DEBUG_PIN1 11 37 | #define _DEBUG_PIN2 13 38 | // 39 | // Includes 40 | // 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | // 48 | // Statics 49 | // 50 | SoftwareSerial9 *SoftwareSerial9::active_object = 0; 51 | uint16_t SoftwareSerial9::_receive_buffer[_SS_MAX_RX_BUFF]; 52 | volatile uint8_t SoftwareSerial9::_receive_buffer_tail = 0; 53 | volatile uint8_t SoftwareSerial9::_receive_buffer_head = 0; 54 | 55 | // 56 | // Debugging 57 | // 58 | // This function generates a brief pulse 59 | // for debugging or measuring on an oscilloscope. 60 | #if _DEBUG 61 | inline void DebugPulse(uint8_t pin, uint8_t count) 62 | { 63 | volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin)); 64 | 65 | uint8_t val = *pport; 66 | while (count--) 67 | { 68 | *pport = val | digitalPinToBitMask(pin); 69 | *pport = val; 70 | } 71 | } 72 | #else 73 | inline void DebugPulse(uint8_t, uint8_t) {} 74 | #endif 75 | 76 | // 77 | // Private methods 78 | // 79 | 80 | /* static */ 81 | inline void SoftwareSerial9::tunedDelay(uint16_t delay) { 82 | _delay_loop_2(delay); 83 | } 84 | 85 | // This function sets the current object as the "listening" 86 | // one and returns true if it replaces another 87 | bool SoftwareSerial9::listen() 88 | { 89 | if (!_rx_delay_stopbit) 90 | return false; 91 | 92 | if (active_object != this) 93 | { 94 | if (active_object) 95 | active_object->stopListening(); 96 | 97 | _buffer_overflow = false; 98 | _receive_buffer_head = _receive_buffer_tail = 0; 99 | active_object = this; 100 | 101 | setRxIntMsk(true); 102 | return true; 103 | } 104 | 105 | return false; 106 | } 107 | 108 | // Stop listening. Returns true if we were actually listening. 109 | bool SoftwareSerial9::stopListening() 110 | { 111 | if (active_object == this) 112 | { 113 | setRxIntMsk(false); 114 | active_object = NULL; 115 | return true; 116 | } 117 | return false; 118 | } 119 | 120 | // 121 | // The receive routine called by the interrupt handler 122 | // 123 | void SoftwareSerial9::recv() 124 | { 125 | 126 | #if GCC_VERSION < 40302 127 | // Work-around for avr-gcc 4.3.0 OSX version bug 128 | // Preserve the registers that the compiler misses 129 | // (courtesy of Arduino forum user *etracer*) 130 | asm volatile( 131 | "push r18 \n\t" 132 | "push r19 \n\t" 133 | "push r20 \n\t" 134 | "push r21 \n\t" 135 | "push r22 \n\t" 136 | "push r23 \n\t" 137 | "push r26 \n\t" 138 | "push r27 \n\t" 139 | ::); 140 | #endif 141 | 142 | uint16_t d = 0; 143 | 144 | // If RX line is high, then we don't see any start bit 145 | // so interrupt is probably not for us 146 | if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) 147 | { 148 | // Disable further interrupts during reception, this prevents 149 | // triggering another interrupt directly after we return, which can 150 | // cause problems at higher baudrates. 151 | setRxIntMsk(false); 152 | 153 | // Wait approximately 1/2 of a bit width to "center" the sample 154 | tunedDelay(_rx_delay_centering); 155 | DebugPulse(_DEBUG_PIN2, 1); 156 | 157 | // Read each of the 9 bits 158 | for (uint8_t i=9; i > 0; --i) 159 | { 160 | tunedDelay(_rx_delay_intrabit); 161 | d >>= 1; 162 | DebugPulse(_DEBUG_PIN2, 1); 163 | if (rx_pin_read()) 164 | d |= 0x100; 165 | } 166 | 167 | if (_inverse_logic) 168 | d = ~d; 169 | 170 | // if buffer full, set the overflow flag and return 171 | uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; 172 | if (next != _receive_buffer_head) 173 | { 174 | // save new data in buffer: tail points to where byte goes 175 | _receive_buffer[_receive_buffer_tail] = d; // save new byte 176 | _receive_buffer_tail = next; 177 | } 178 | else 179 | { 180 | DebugPulse(_DEBUG_PIN1, 1); 181 | _buffer_overflow = true; 182 | } 183 | 184 | // skip the stop bit 185 | tunedDelay(_rx_delay_stopbit); 186 | DebugPulse(_DEBUG_PIN1, 1); 187 | 188 | // Re-enable interrupts when we're sure to be inside the stop bit 189 | setRxIntMsk(true); 190 | 191 | } 192 | 193 | #if GCC_VERSION < 40302 194 | // Work-around for avr-gcc 4.3.0 OSX version bug 195 | // Restore the registers that the compiler misses 196 | asm volatile( 197 | "pop r27 \n\t" 198 | "pop r26 \n\t" 199 | "pop r23 \n\t" 200 | "pop r22 \n\t" 201 | "pop r21 \n\t" 202 | "pop r20 \n\t" 203 | "pop r19 \n\t" 204 | "pop r18 \n\t" 205 | ::); 206 | #endif 207 | } 208 | 209 | uint8_t SoftwareSerial9::rx_pin_read() 210 | { 211 | return *_receivePortRegister & _receiveBitMask; 212 | } 213 | 214 | // 215 | // Interrupt handling 216 | // 217 | 218 | /* static */ 219 | inline void SoftwareSerial9::handle_interrupt() 220 | { 221 | if (active_object) 222 | { 223 | active_object->recv(); 224 | } 225 | } 226 | 227 | #if defined(PCINT0_vect) 228 | ISR(PCINT0_vect) 229 | { 230 | SoftwareSerial9::handle_interrupt(); 231 | } 232 | #endif 233 | 234 | #if defined(PCINT1_vect) 235 | ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect)); 236 | #endif 237 | 238 | #if defined(PCINT2_vect) 239 | ISR(PCINT2_vect, ISR_ALIASOF(PCINT0_vect)); 240 | #endif 241 | 242 | #if defined(PCINT3_vect) 243 | ISR(PCINT3_vect, ISR_ALIASOF(PCINT0_vect)); 244 | #endif 245 | 246 | // 247 | // Constructor 248 | // 249 | SoftwareSerial9::SoftwareSerial9(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : 250 | _rx_delay_centering(0), 251 | _rx_delay_intrabit(0), 252 | _rx_delay_stopbit(0), 253 | _tx_delay(0), 254 | _buffer_overflow(false), 255 | _inverse_logic(inverse_logic) 256 | { 257 | setTX(transmitPin); 258 | setRX(receivePin); 259 | } 260 | 261 | // 262 | // Destructor 263 | // 264 | SoftwareSerial9::~SoftwareSerial9() 265 | { 266 | end(); 267 | } 268 | 269 | void SoftwareSerial9::setTX(uint8_t tx) 270 | { 271 | // First write, then set output. If we do this the other way around, 272 | // the pin would be output low for a short while before switching to 273 | // output high. Now, it is input with pullup for a short while, which 274 | // is fine. With inverse logic, either order is fine. 275 | digitalWrite(tx, _inverse_logic ? LOW : HIGH); 276 | pinMode(tx, OUTPUT); 277 | _transmitBitMask = digitalPinToBitMask(tx); 278 | uint8_t port = digitalPinToPort(tx); 279 | _transmitPortRegister = portOutputRegister(port); 280 | } 281 | 282 | void SoftwareSerial9::setRX(uint8_t rx) 283 | { 284 | pinMode(rx, INPUT); 285 | if (!_inverse_logic) 286 | digitalWrite(rx, HIGH); // pullup for normal logic! 287 | _receivePin = rx; 288 | _receiveBitMask = digitalPinToBitMask(rx); 289 | uint8_t port = digitalPinToPort(rx); 290 | _receivePortRegister = portInputRegister(port); 291 | } 292 | 293 | uint16_t SoftwareSerial9::subtract_cap(uint16_t num, uint16_t sub) { 294 | if (num > sub) 295 | return num - sub; 296 | else 297 | return 1; 298 | } 299 | 300 | // 301 | // Public methods 302 | // 303 | 304 | void SoftwareSerial9::begin(long speed) 305 | { 306 | _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0; 307 | 308 | // Precalculate the various delays, in number of 4-cycle delays 309 | uint16_t bit_delay = (F_CPU / speed) / 4; 310 | 311 | // 12 (gcc 4.8.2) or 13 (gcc 4.3.2) cycles from start bit to first bit, 312 | // 15 (gcc 4.8.2) or 16 (gcc 4.3.2) cycles between bits, 313 | // 12 (gcc 4.8.2) or 14 (gcc 4.3.2) cycles from last bit to stop bit 314 | // These are all close enough to just use 15 cycles, since the inter-bit 315 | // timings are the most critical (deviations stack 8 times) 316 | _tx_delay = subtract_cap(bit_delay, 15 / 4); 317 | 318 | // Only setup rx when we have a valid PCINT for this pin 319 | if (digitalPinToPCICR(_receivePin)) { 320 | #if GCC_VERSION > 40800 321 | // Timings counted from gcc 4.8.2 output. This works up to 115200 on 322 | // 16Mhz and 57600 on 8Mhz. 323 | // 324 | // When the start bit occurs, there are 3 or 4 cycles before the 325 | // interrupt flag is set, 4 cycles before the PC is set to the right 326 | // interrupt vector address and the old PC is pushed on the stack, 327 | // and then 75 cycles of instructions (including the RJMP in the 328 | // ISR vector table) until the first delay. After the delay, there 329 | // are 17 more cycles until the pin value is read (excluding the 330 | // delay in the loop). 331 | // We want to have a total delay of 1.5 bit time. Inside the loop, 332 | // we already wait for 1 bit time - 23 cycles, so here we wait for 333 | // 0.5 bit time - (71 + 18 - 22) cycles. 334 | _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4); 335 | 336 | // There are 23 cycles in each loop iteration (excluding the delay) 337 | _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4); 338 | 339 | // There are 37 cycles from the last bit read to the start of 340 | // stopbit delay and 11 cycles from the delay until the interrupt 341 | // mask is enabled again (which _must_ happen during the stopbit). 342 | // This delay aims at 3/4 of a bit time, meaning the end of the 343 | // delay will be at 1/4th of the stopbit. This allows some extra 344 | // time for ISR cleanup, which makes 115200 baud at 16Mhz work more 345 | // reliably 346 | _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4); 347 | #else // Timings counted from gcc 4.3.2 output 348 | // Note that this code is a _lot_ slower, mostly due to bad register 349 | // allocation choices of gcc. This works up to 57600 on 16Mhz and 350 | // 38400 on 8Mhz. 351 | _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 97 + 29 - 11) / 4); 352 | _rx_delay_intrabit = subtract_cap(bit_delay, 11 / 4); 353 | _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (44 + 17) / 4); 354 | #endif 355 | 356 | 357 | // Enable the PCINT for the entire port here, but never disable it 358 | // (others might also need it, so we disable the interrupt by using 359 | // the per-pin PCMSK register). 360 | *digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin)); 361 | // Precalculate the pcint mask register and value, so setRxIntMask 362 | // can be used inside the ISR without costing too much time. 363 | _pcint_maskreg = digitalPinToPCMSK(_receivePin); 364 | _pcint_maskvalue = _BV(digitalPinToPCMSKbit(_receivePin)); 365 | 366 | tunedDelay(_tx_delay); // if we were low this establishes the end 367 | } 368 | 369 | #if _DEBUG 370 | pinMode(_DEBUG_PIN1, OUTPUT); 371 | pinMode(_DEBUG_PIN2, OUTPUT); 372 | #endif 373 | 374 | listen(); 375 | } 376 | 377 | void SoftwareSerial9::setRxIntMsk(bool enable) 378 | { 379 | if (enable) 380 | *_pcint_maskreg |= _pcint_maskvalue; 381 | else 382 | *_pcint_maskreg &= ~_pcint_maskvalue; 383 | } 384 | 385 | void SoftwareSerial9::end() 386 | { 387 | stopListening(); 388 | } 389 | 390 | 391 | // Read data from buffer 392 | int SoftwareSerial9::read() 393 | { 394 | if (!isListening()) 395 | return -1; 396 | 397 | // Empty buffer? 398 | if (_receive_buffer_head == _receive_buffer_tail) 399 | return -1; 400 | 401 | // Read from "head" 402 | uint16_t d = _receive_buffer[_receive_buffer_head]; // grab next byte 403 | _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF; 404 | return d; 405 | } 406 | 407 | int SoftwareSerial9::available() 408 | { 409 | if (!isListening()) 410 | return 0; 411 | 412 | return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF; 413 | } 414 | 415 | size_t SoftwareSerial9::write(uint8_t b) 416 | { 417 | if (_tx_delay == 0) { 418 | setWriteError(); 419 | return 0; 420 | } 421 | 422 | // By declaring these as local variables, the compiler will put them 423 | // in registers _before_ disabling interrupts and entering the 424 | // critical timing sections below, which makes it a lot easier to 425 | // verify the cycle timings 426 | volatile uint8_t *reg = _transmitPortRegister; 427 | uint8_t reg_mask = _transmitBitMask; 428 | uint8_t inv_mask = ~_transmitBitMask; 429 | uint8_t oldSREG = SREG; 430 | bool inv = _inverse_logic; 431 | uint16_t delay = _tx_delay; 432 | 433 | if (inv) 434 | b = ~b; 435 | 436 | cli(); // turn off interrupts for a clean txmit 437 | 438 | // Write the start bit 439 | if (inv) 440 | *reg |= reg_mask; 441 | else 442 | *reg &= inv_mask; 443 | 444 | tunedDelay(delay); 445 | 446 | // Write each of the 8 bits 447 | for (uint8_t i = 8; i > 0; --i) 448 | { 449 | if (b & 1) // choose bit 450 | *reg |= reg_mask; // send 1 451 | else 452 | *reg &= inv_mask; // send 0 453 | 454 | tunedDelay(delay); 455 | b >>= 1; 456 | } 457 | 458 | // restore pin to natural state 459 | if (inv) 460 | *reg &= inv_mask; 461 | else 462 | *reg |= reg_mask; 463 | 464 | SREG = oldSREG; // turn interrupts back on 465 | tunedDelay(_tx_delay); 466 | 467 | return 1; 468 | } 469 | 470 | size_t SoftwareSerial9::write9(uint16_t b) 471 | { 472 | if (_tx_delay == 0) { 473 | setWriteError(); 474 | return 0; 475 | } 476 | 477 | // By declaring these as local variables, the compiler will put them 478 | // in registers _before_ disabling interrupts and entering the 479 | // critical timing sections below, which makes it a lot easier to 480 | // verify the cycle timings 481 | volatile uint8_t *reg = _transmitPortRegister; 482 | uint8_t reg_mask = _transmitBitMask; 483 | uint8_t inv_mask = ~_transmitBitMask; 484 | uint8_t oldSREG = SREG; 485 | bool inv = _inverse_logic; 486 | uint16_t delay = _tx_delay; 487 | 488 | if (inv) 489 | b = ~b; 490 | 491 | cli(); // turn off interrupts for a clean txmit 492 | 493 | // Write the start bit 494 | if (inv) 495 | *reg |= reg_mask; 496 | else 497 | *reg &= inv_mask; 498 | 499 | tunedDelay(delay); 500 | 501 | // Write each of the 9 bits 502 | for (uint8_t i = 9; i > 0; --i) 503 | { 504 | if (b & 1) // choose bit 505 | *reg |= reg_mask; // send 1 506 | else 507 | *reg &= inv_mask; // send 0 508 | 509 | tunedDelay(delay); 510 | b >>= 1; 511 | } 512 | 513 | // restore pin to natural state 514 | if (inv) 515 | *reg &= inv_mask; 516 | else 517 | *reg |= reg_mask; 518 | 519 | SREG = oldSREG; // turn interrupts back on 520 | tunedDelay(_tx_delay); 521 | 522 | return 1; 523 | } 524 | 525 | void SoftwareSerial9::flush() 526 | { 527 | // There is no tx buffering, simply return 528 | } 529 | 530 | int SoftwareSerial9::peek() 531 | { 532 | if (!isListening()) 533 | return -1; 534 | 535 | // Empty buffer? 536 | if (_receive_buffer_head == _receive_buffer_tail) 537 | return -1; 538 | 539 | // Read from "head" 540 | return _receive_buffer[_receive_buffer_head]; 541 | } 542 | -------------------------------------------------------------------------------- /src/SoftwareSerial9.h: -------------------------------------------------------------------------------- 1 | /* 2 | SoftwareSerial.h (formerly NewSoftSerial.h) - 3 | Multi-instance software serial library for Arduino/Wiring 4 | -- Interrupt-driven receive and other improvements by ladyada 5 | (http://ladyada.net) 6 | -- Tuning, circular buffer, derivation from class Print/Stream, 7 | multi-instance support, porting to 8MHz processors, 8 | various optimizations, PROGMEM delay tables, inverse logic and 9 | direct port writing by Mikal Hart (http://www.arduiniana.org) 10 | -- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) 11 | -- 20MHz processor support by Garrett Mace (http://www.macetech.com) 12 | -- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) 13 | 14 | This library is free software; you can redistribute it and/or 15 | modify it under the terms of the GNU Lesser General Public 16 | License as published by the Free Software Foundation; either 17 | version 2.1 of the License, or (at your option) any later version. 18 | 19 | This library is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | Lesser General Public License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public 25 | License along with this library; if not, write to the Free Software 26 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 27 | 28 | The latest version of this library can always be found at 29 | http://arduiniana.org. 30 | */ 31 | 32 | #ifndef SoftwareSerial9_h 33 | #define SoftwareSerial9_h 34 | 35 | #include 36 | #include 37 | 38 | /****************************************************************************** 39 | * Definitions 40 | ******************************************************************************/ 41 | 42 | #define _SS_MAX_RX_BUFF 64 // RX buffer size 43 | #ifndef GCC_VERSION 44 | #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 45 | #endif 46 | 47 | class SoftwareSerial9 : public Stream 48 | { 49 | private: 50 | // per object data 51 | uint8_t _receivePin; 52 | uint8_t _receiveBitMask; 53 | volatile uint8_t *_receivePortRegister; 54 | uint8_t _transmitBitMask; 55 | volatile uint8_t *_transmitPortRegister; 56 | volatile uint8_t *_pcint_maskreg; 57 | uint8_t _pcint_maskvalue; 58 | 59 | // Expressed as 4-cycle delays (must never be 0!) 60 | uint16_t _rx_delay_centering; 61 | uint16_t _rx_delay_intrabit; 62 | uint16_t _rx_delay_stopbit; 63 | uint16_t _tx_delay; 64 | 65 | uint16_t _buffer_overflow:1; 66 | uint16_t _inverse_logic:1; 67 | 68 | // static data 69 | static uint16_t _receive_buffer[_SS_MAX_RX_BUFF]; 70 | static volatile uint8_t _receive_buffer_tail; 71 | static volatile uint8_t _receive_buffer_head; 72 | static SoftwareSerial9 *active_object; 73 | 74 | // private methods 75 | inline void recv() __attribute__((__always_inline__)); 76 | uint8_t rx_pin_read(); 77 | void setTX(uint8_t transmitPin); 78 | void setRX(uint8_t receivePin); 79 | inline void setRxIntMsk(bool enable) __attribute__((__always_inline__)); 80 | 81 | // Return num - sub, or 1 if the result would be < 1 82 | static uint16_t subtract_cap(uint16_t num, uint16_t sub); 83 | 84 | // private static method for timing 85 | static inline void tunedDelay(uint16_t delay); 86 | 87 | public: 88 | // public methods 89 | SoftwareSerial9(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false); 90 | ~SoftwareSerial9(); 91 | void begin(long speed); 92 | bool listen(); 93 | void end(); 94 | bool isListening() { return this == active_object; } 95 | bool stopListening(); 96 | bool overflow() { bool ret = _buffer_overflow; if (ret) _buffer_overflow = false; return ret; } 97 | int peek(); 98 | 99 | virtual size_t write(uint8_t byte); 100 | virtual size_t write9(uint16_t byte); 101 | virtual int read(); 102 | virtual int available(); 103 | virtual void flush(); 104 | operator bool() { return true; } 105 | 106 | using Print::write; 107 | 108 | // public only for easy access by interrupt handlers 109 | static inline void handle_interrupt() __attribute__((__always_inline__)); 110 | }; 111 | 112 | // Arduino 0012 workaround 113 | #undef int 114 | #undef char 115 | #undef long 116 | #undef byte 117 | #undef float 118 | #undef abs 119 | #undef round 120 | 121 | #endif 122 | --------------------------------------------------------------------------------