detailed description of SoftwareSerial.Tx and SoftwareSerial.Rx functions

I've got my code working, but it bugs me that I don't understand some things that are going on under the hood. Can someone give me a line by line description of what the following functions (in bold) are actually doing?

void SoftwareSerial::setTX(uint8_t tx) { // First write, then set output. If we do this the other way around, // the pin would be output low for a short while before switching to // output high. Now, it is input with pullup for a short while, which // is fine. With inverse logic, either order is fine. digitalWrite(tx, _inverse_logic ? LOW : HIGH); pinMode(tx, OUTPUT); ** _transmitBitMask = digitalPinToBitMask(tx);** ** uint8_t port = digitalPinToPort(tx);** ** _transmitPortRegister = portOutputRegister(port);** }

void SoftwareSerial::setRX(uint8_t rx) { pinMode(rx, INPUT); if (!_inverse_logic) digitalWrite(rx, HIGH); // pullup for normal logic! _receivePin = rx; ** _receiveBitMask = digitalPinToBitMask(rx);** ** uint8_t port = digitalPinToPort(rx);** ** _receivePortRegister = portInputRegister(port);** }

Also, is there documentation on the functions and variables in the following lines of code that are given in the SoftwareSerial.h library. In general, I can see what the functions are doing, and I've got a good background in micros, just need some documentation to understand details. Is there anything from Atmel that has more info?

*digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin)); // Precalculate the pcint mask register and value, so setRxIntMask // can be used inside the ISR without costing too much time. _pcint_maskreg = digitalPinToPCMSK(_receivePin); _pcint_maskvalue = _BV(digitalPinToPCMSKbit(_receivePin));

That code maps some arbitrary pin (tx) to the port and output port associated with that pin.

E.g. your tx = D9 so that is pin 1 of PORTB so the variable port = PORTB and _trasmitPortRegister = DDRB (direction register for PORTB)

_transmitBitMask = digitalPinToBitMask(tx); uint8_t port = digitalPinToPort(tx); _transmitPortRegister = portOutputRegister(port);

You may be aware that the Arduino digitalRead() and digitalWrite() functions have a reputation for being quite "slow", compared to "moderate effort bare-metal C code." One of the reasons that they are so slow is that they need to translate the "Arduino pin number" (1-13, usually) into the address of the 8bit port that contains that pin, and the bit within that port. EVERY TIME the function is called. The above code moves that translation to the initialization of the SWSerial port, so that it is only done ONCE, and avoids some other code as well (checking whether PWM must be turned off.) This permits the read or write of values to the pin to be significantly faster.