Пример #1
0
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;
}
Пример #3
0
//
// 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);

  }
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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();
}
Пример #7
0
//
// 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
  }
}
Пример #8
0
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;
}
Пример #9
0
//
// 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
}
Пример #10
0
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;
    }
  }
}
Пример #11
0
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();
}
Пример #12
0
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;
}
Пример #13
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
}