size_t GSM3SoftSerial::finalWrite(uint8_t c) { if(hwcomIsUsed == true) return HWSerial[hwcomport]->write(c); io_DisableINT(); // Write the start bit tx_pin_write(LOW); tunedDelay(_tx_delay); // Write each of the 8 bits for (byte mask = 0x01; mask; mask <<= 1) { if (c & mask) // choose bit tx_pin_write(HIGH); // send 1 else tx_pin_write(LOW); // send 0 tunedDelay(_tx_delay); } tx_pin_write(HIGH); // restore pin to natural state io_RestoreINT(); tunedDelay(_tx_delay); return 1; }
size_t SendOnlySoftwareSerial::write(uint8_t b) { if (_tx_delay == 0) { setWriteError(); return 0; } // By declaring these as local variables, the compiler will put them // in registers _before_ disabling interrupts and entering the // critical timing sections below, which makes it a lot easier to // verify the cycle timings volatile uint8_t *reg = _transmitPortRegister; uint8_t reg_mask = _transmitBitMask; uint8_t inv_mask = ~_transmitBitMask; uint8_t oldSREG = SREG; bool inv = _inverse_logic; uint16_t delay = _tx_delay; if (inv) b = ~b; cli(); // turn off interrupts for a clean txmit // Write the start bit if (inv) *reg |= reg_mask; else *reg &= inv_mask; tunedDelay(delay); // Write each of the 8 bits for (uint8_t i = 8; i > 0; --i) { if (b & 1) // choose bit *reg |= reg_mask; // send 1 else *reg &= inv_mask; // send 0 tunedDelay(delay); b >>= 1; } // restore pin to natural state if (inv) *reg &= inv_mask; else *reg |= reg_mask; SREG = oldSREG; // turn interrupts back on tunedDelay(_tx_delay); return 1; }
// // The receive routine called by the interrupt handler // void SoftwareSerial::recv() { DebugPulse(_DEBUG_PIN2, 1); uint8_t d = 0; // If RX line is high, then we don't see any start bit // so interrupt is probably not for us if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) { // Disable further interrupts during reception, this prevents // triggering another interrupt directly after we return, which can // cause problems at higher baudrates. setRxIntMsk(false); // Wait approximately 1/2 of a bit width to "center" the sample tunedDelay(_rx_delay_centering); DebugPulse(_DEBUG_PIN2, 1); // Read each of the 8 bits for (uint8_t i = 8; i > 0; --i) { tunedDelay(_rx_delay_intrabit); d >>= 1; DebugPulse(_DEBUG_PIN2, 1); if (rx_pin_read()) d |= 0x80; } DebugPulse(_DEBUG_PIN2, 1); if (_inverse_logic) d = ~d; // if buffer full, set the overflow flag and return uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; if (next != _receive_buffer_head) { // save new data in buffer: tail points to where byte goes _receive_buffer[_receive_buffer_tail] = d; // save new byte _receive_buffer_tail = next; } else { DebugPulse(_DEBUG_PIN1, 1); _buffer_overflow = true; } // skip the stop bit tunedDelay(_rx_delay_stopbit); DebugPulse(_DEBUG_PIN1, 1); // Re-enable interrupts when we're sure to be inside the stop bit setRxIntMsk(true); }
size_t SSerial_write(UINT8 b) { if(_tx_delay == 0) { // setWriteError(); return 0; } UINT8 oldGIE = GIE; di(); // Turn off interrupts for a clean txmit // Write the start bit SSerial_tx_pin_write(_inverse_logic ? HIGH : LOW); tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT); // Write each of the 8 bits if(_inverse_logic) { for (BYTE mask = 0x01; mask; mask <<= 1) { if(b & mask) // choose bit SSerial_tx_pin_write(LOW); // send 1 else SSerial_tx_pin_write(HIGH); // send 0 tunedDelay(_tx_delay); } SSerial_tx_pin_write(LOW); // restore pin to natural state } else { for (BYTE mask = 0x01; mask; mask <<= 1) { if(b & mask) // choose bit SSerial_tx_pin_write(HIGH); // send 1 else SSerial_tx_pin_write(LOW); // send 0 tunedDelay(_tx_delay); } SSerial_tx_pin_write(HIGH); // restore pin to natural state } GIE = oldGIE; // turn interrupts back on tunedDelay(_tx_delay); return 1; }
size_t SoftwareSerial::write(uint8_t b) { if (_tx_delay == 0) { setWriteError(); return 0; } io_DisableINT(); // Write the start bit tx_pin_write(_inverse_logic ? HIGH : LOW); tunedDelay(_tx_delay); // Write each of the 8 bits if (_inverse_logic) { for (byte mask = 0x01; mask; mask <<= 1) { if (b & mask) // choose bit tx_pin_write(LOW); // send 1 else tx_pin_write(HIGH); // send 0 tunedDelay(_tx_delay); } tx_pin_write(LOW); // restore pin to natural state } else { for (byte mask = 0x01; mask; mask <<= 1) { if (b & mask) // choose bit tx_pin_write(HIGH); // send 1 else tx_pin_write(LOW); // send 0 tunedDelay(_tx_delay); } tx_pin_write(HIGH); // restore pin to natural state } io_RestoreINT(); tunedDelay(_tx_delay); return 1; }
void SoftwareSerial::begin(long speed) { _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0; for (unsigned i=0; i<sizeof(table)/sizeof(table[0]); ++i) { long baud = pgm_read_dword(&table[i].baud); if (baud == speed) { _rx_delay_centering = pgm_read_word(&table[i].rx_delay_centering); _rx_delay_intrabit = pgm_read_word(&table[i].rx_delay_intrabit); _rx_delay_stopbit = pgm_read_word(&table[i].rx_delay_stopbit); _tx_delay = pgm_read_word(&table[i].tx_delay); break; } } // Set up RX interrupts, but only if we have a valid RX baud rate if (_rx_delay_stopbit) { pinMode(_receivePin, INPUT_PULLUP); tunedDelay(_tx_delay); // if we were low this establishes the end } listen(); }
// // The receive routine called by the interrupt handler // void SoftwareSerial::recv() { uint8_t d = 0; // If RX line is high, then we don't see any start bit // so interrupt is probably not for us if (_inverse_logic ? digitalReadQuick(_receivePin) : !digitalReadQuick(_receivePin)) { // Wait approximately 1/2 of a bit width to "center" the sample tunedDelay(halfbit / baud, true); uint8_t bit = 0; // Read each of the 8 bits for (uint8_t i=0x1; i; i <<= 1) { ++bit; tunedDelay((halfbit + fullbit * bit) / baud); uint8_t noti = ~i; if (digitalReadQuick(_receivePin)) d |= i; else // else clause added to ensure function timing is ~balanced d &= noti; } ++bit; // skip the stop bit tunedDelay((halfbit + fullbit * bit) / baud); if (_inverse_logic) d = ~d; // if buffer full, set the overflow flag and return if ((_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF != _receive_buffer_head) { // save new data in buffer: tail points to where byte goes _receive_buffer[_receive_buffer_tail] = d; // save new byte _receive_buffer_tail = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; } else { _buffer_overflow = true; } #ifdef DEBUG_SOFTWARESERIAL printf("recv 0x%02X\n", d); #endif } }
size_t SoftwareSerial::write(uint8_t b) { // Write the start bit digitalWriteQuick(_transmitPin, _inverse_logic ? HIGH : LOW); tunedDelay(fullbit / baud, true); int bit = 1; // Write each of the 8 bits if (_inverse_logic) { for (byte mask = 0x01; mask; mask <<= 1) { ++bit; if (b & mask) // choose bit digitalWriteQuick(_transmitPin, LOW); // send 1 else digitalWriteQuick(_transmitPin, HIGH); // send 0 tunedDelay(bit * fullbit / baud); } digitalWriteQuick(_transmitPin, LOW); // restore pin to natural state } else { for (byte mask = 0x01; mask; mask <<= 1) { ++bit; if (b & mask) // choose bit digitalWriteQuick(_transmitPin, HIGH); // send 1 else digitalWriteQuick(_transmitPin, LOW); // send 0 tunedDelay(bit * fullbit / baud); } digitalWriteQuick(_transmitPin, HIGH); // restore pin to natural state } tunedDelay(bit * fullbit / baud, true); #ifdef DEBUG_SOFTWARESERIAL printf("write 0x%02X - %c\n", b, b); #endif return 1; }
// // The receive routine called by the interrupt handler // void SoftwareSerial::recv() { uint8_t d = 0; io_outpb(CROSSBARBASE + 0x90 + pinMap[_receivePin], 0x01); // switch to GPIO // If RX line is high, then we don't see any start bit // so interrupt is probably not for us if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) { // Wait approximately 1/2 of a bit width to "center" the sample tunedDelay(_rx_delay_centering); //DebugPulse(_DEBUG_PIN2, 1); // Read each of the 8 bits for (uint8_t i=0x1; i; i <<= 1) { tunedDelay(_rx_delay_intrabit); //DebugPulse(_DEBUG_PIN2, 1); uint8_t noti = ~i; if (rx_pin_read()) d |= i; else // else clause added to ensure function timing is ~balanced d &= noti; } // skip the stop bit tunedDelay(_rx_delay_stopbit); //DebugPulse(_DEBUG_PIN2, 1); if (_inverse_logic) d = ~d; // if buffer full, set the overflow flag and return if ((_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF != _receive_buffer_head) { // save new data in buffer: tail points to where byte goes _receive_buffer[_receive_buffer_tail] = d; // save new byte _receive_buffer_tail = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; } else { _buffer_overflow = true; } } io_outpb(CROSSBARBASE + 0x90 + pinMap[_receivePin], 0x08); // switch to Encoder }
void SSerial_recv(void) { UINT8 d = 0; if(_inverse_logic ? SSerial_rx_pin_read() : !SSerial_rx_pin_read()) { tunedDelay(_rx_delay_centering); digitalToggle(_DEBUG_PIN); // Debug for(UINT8 i = 1; i; i <<= 1) { tunedDelay(_rx_delay_intrabit); digitalToggle(_DEBUG_PIN); // Debug UINT8 noti = ~i; if(SSerial_rx_pin_read()) d |= i; else // else clause added to ensure function timing is ~balanced d &= noti; } // skip the stop bit tunedDelay(_rx_delay_stopbit); digitalToggle(_DEBUG_PIN); // Debug if(_inverse_logic) d = ~d; // if buffer full, set the overflow flag and return if((_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF != _receive_buffer_head) { // save new data in buffer: tail points to where byte goes _receive_buffer[_receive_buffer_tail] = d; // save new byte _receive_buffer_tail = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; } else { // DebugPulse(_DEBUG_PIN1, 1); _buffer_overflow = true; } } }
void SoftwareSerial::begin(long speed) { baud = 0; for (unsigned i=0; i<sizeof(BAUDRATE)/sizeof(BAUDRATE[0]); ++i) { if(BAUDRATE[i] == speed){ baud = speed; } } // Set up RX interrupts, but only if we have a valid RX baud rate if (baud) { wiringPiISR(_receivePin, INT_EDGE_BOTH, handle_interrupt); tunedDelay(fullbit / baud, true); // if we were low this establishes the end } listen(); }
void SSerial_begin(long speed) { SoftwareSerial(2, 3); for(unsigned i = 0; i < sizeof(table)/sizeof(table[0]); ++i) { long baud = table[i].baud; if(baud == speed) { _rx_delay_centering = table[i].rx_delay_centering; _rx_delay_intrabit = table[i].rx_delay_intrabit; _rx_delay_stopbit = table[i].rx_delay_stopbit; _tx_delay = table[i].tx_delay; break; } } tunedDelay(_tx_delay); _buffer_overflow = false; _receive_buffer_head = _receive_buffer_tail = 0; }
void GSM3SoftSerial::recv() { bool firstByte=true; byte thisHead; uint8_t d = 0; bool morebytes=false; bool fullbuffer; bool capturado_fullbuffer = 0; int i; byte oldTail; // If RX line is high, then we don't see any start bit // so interrupt is probably not for us io_outpb(CROSSBARBASE + 0x90 + PIN86[__RXPIN__].gpN, 0x01); // switch to GPIO if (!rx_pin_read()) { do { oldTail=cb.getTail(); // Wait approximately 1/2 of a bit width to "center" the sample tunedDelay(_rx_delay_centering); fullbuffer=(cb.availableBytes()<6); if(fullbuffer&&(!capturado_fullbuffer)) tx_pin_write(LOW); // Read each of the 8 bits for (uint8_t i=0x1; i; i <<= 1) { tunedDelay(_rx_delay_intrabit); uint8_t noti = ~i; if (rx_pin_read()) d |= i; else // else clause added to ensure function timing is ~balanced d &= noti; if(fullbuffer&&(!capturado_fullbuffer)) { if((uint8_t)__XOFF__ & i) tx_pin_write(HIGH); else tx_pin_write(LOW); } } if(fullbuffer&&(!capturado_fullbuffer)) { tunedDelay(_rx_delay_intrabit); tx_pin_write(HIGH); } // So, we know the buffer is full, and we have sent a XOFF if (fullbuffer) { capturado_fullbuffer =1; _flags |=_GSMSOFTSERIALFLAGS_SENTXOFF_; } // skip the stop bit if (!fullbuffer) tunedDelay(_rx_delay_stopbit); if(keepThisChar(&d)) { cb.write(d); if(firstByte) { firstByte=false; thisHead=cb.getTail(); } } // This part is new. It is used to detect the end of a "paragraph" // Caveat: the old fashion would let processor a bit of time between bytes, // that here is lost // This active waiting avoids drifting morebytes=false; // TO-DO. This PARAGRAPHGUARD is empyric. We should test it for every speed for(i=0;i<__PARAGRAPHGUARD__;i++) { tunedDelay(1); if(!rx_pin_read()) { morebytes=true; break; } } }while(morebytes); // If we find a line feed, we are at the end of a paragraph // check! if (fullbuffer) { // And... go handle it! if(mgr) mgr->manageMsg(thisHead, cb.getTail()); } else if(d==10) { // And... go handle it! if(mgr) mgr->manageMsg(thisHead, cb.getTail()); } else if (d==32) { // And... go handle it! if(mgr) mgr->manageMsg(thisHead, cb.getTail()); } } io_outpb(CROSSBARBASE + 0x90 + PIN86[__RXPIN__].gpN, 0x08); // switch to Encoder }