/*
   Copyright (C) 1998,1999 Scott Dattalo

This file is part of gpsim.

gpsim is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

gpsim 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with gpsim; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */

#include <stdio.h>
#include <iostream>

#include "../config.h"
#include "stimuli.h"
#include "uart.h"
#include "14bit-processors.h"
#include "14bit-tmrs.h"

#define p_cpu ((Processor *)cpu)


//#define DEBUG
#if defined(DEBUG)
#define Dprintf(arg) {printf("%s:%d-%s() ",__FILE__,__LINE__,__FUNCTION__); printf arg; }
#else
#define Dprintf(arg) {}
#endif

//--------------------------------------------------
// 
//--------------------------------------------------
class TXSignalSource : public SignalControl
{
public:
  TXSignalSource(_TXSTA *_txsta)
    : m_txsta(_txsta)
  {
    assert(m_txsta);
  }
  char getState()
  {
    return m_txsta->getState();
  }
private:
  _TXSTA *m_txsta;
};

//--------------------------------------------------
//
//--------------------------------------------------

class RXSignalSink : public SignalSink
{
public:
  RXSignalSink(_RCSTA *_rcsta)
    : m_rcsta(_rcsta)
  {
    assert(_rcsta);
  }

  void setSinkState(char new3State)
  {
    m_rcsta->setState(new3State);
  }
private:
  _RCSTA *m_rcsta;
};

//-----------------------------------------------------------
_RCSTA::_RCSTA(USART_MODULE *pUSART)
  : rcreg(0), spbrg(0), txsta(0), mUSART(pUSART), m_PinModule(0), m_sink(0), m_cRxState('?')
{
  assert(mUSART);
}

//-----------------------------------------------------------
_TXSTA::_TXSTA(USART_MODULE *pUSART)
  : txreg(0), spbrg(0), mUSART(pUSART), m_PinModule(0),  m_source(0), m_cTxState('?')
{
  assert(mUSART);
}

//-----------------------------------------------------------
_RCREG::_RCREG(USART_MODULE *pUSART)
  : mUSART(pUSART), m_rcsta(0)
{
  assert(mUSART);
}

_TXREG::_TXREG(USART_MODULE *pUSART)
  : m_txsta(0), mUSART(pUSART)
{
  assert(mUSART);
}


_SPBRG::_SPBRG()
  : txsta(0), rcsta(0)
{
}

//-----------------------------------------------------------
// TXREG - USART Transmit Register


void _TXREG::put(unsigned int new_value)
{

  trace.raw(write_trace.get() | value.get());
  value.put(new_value & 0xff);

  Dprintf(("txreg just got a new value:0x%x\n",new_value));

  // The transmit register has data,
  // so clear the TXIF flag

  mUSART->full();

  if(m_txsta &&
     ( (m_txsta->value.get() & (_TXSTA::TRMT | _TXSTA::TXEN)) == (_TXSTA::TRMT | _TXSTA::TXEN)))
    {
      // If the transmit buffer is empty and the transmitter is enabled
      // then transmit this new data now...

      m_txsta->start_transmitting();
    }

}

void _TXREG::put_value(unsigned int new_value)
{

  put(new_value);

  update();
}

//-----------------------------------------------------------
// TXSTA - setIOpin - assign the I/O pin associated with the
// the transmitter.


void _TXSTA::setIOpin(PinModule *newPinModule)
{
  if (!m_source) {
    m_source = new TXSignalSource(this);
    m_PinModule = newPinModule;
  }

}
//-----------------------------------------------------------
// TXSTA - putTXState - update the state of the TX output pin
//

void _TXSTA::putTXState(char newTXState)
{

  m_cTxState = newTXState;

  if (m_PinModule)
    m_PinModule->updatePinModule();

}

//-----------------------------------------------------------
// TXSTA - Transmit Register Status and Control

void _TXSTA::put_value(unsigned int new_value)
{

  put(new_value);

  update();

}

void _TXSTA::put(unsigned int new_value)
{

  unsigned int old_value = value.get();

  trace.raw(write_trace.get() | value.get());

  // The TRMT bit is controlled entirely by hardware.
  // It is high if the TSR has any data.

  value.put((new_value & ~TRMT) | ( (bit_count) ? 0 : TRMT));

  Dprintf((" TXSTA value=0x%x\n",value.get()));


  if( (old_value ^ value.get()) & TXEN) {

    // The TXEN bit has changed states.
    //
    // If transmitter is being enabled and the transmit register
    // has some data that needs to be sent, then start a
    // transmission.
    // If the transmitter is being disabled, then abort any
    // transmission.

    if(value.get() & TXEN) {
      Dprintf(("TXSTA - enabling transmitter\n"));
      if (m_PinModule)
	m_PinModule->setSource(m_source);
      mUSART->emptyTX();
    } else {
      stop_transmitting();
      if (m_PinModule)
	m_PinModule->setSource(0);

    }
  }
}
//------------------------------------------------------------
//
char _TXSTA::getState()
{

  return m_cTxState;
}


// _TXSTA::stop_transmitting()
//
void _TXSTA::stop_transmitting()
{
  Dprintf(("stopping a USART transmission\n"));

  bit_count = 0;
  value.put(value.get() | TRMT);

  // It's not clear from the documentation as to what happens
  // to the TXIF when we are aborting a transmission. According
  // to the documentation, the TXIF is set when the TXEN bit
  // is set. In other words, when the Transmitter is enabled
  // the txreg is emptied (and hence TXIF set). But what happens
  // when TXEN is cleared? Should we clear TXIF too?
  // 
  // There is one sentence that says when the transmitter is
  // disabled that the whole transmitter is reset. So I interpret
  // this to mean that the TXIF gets cleared. I could be wrong
  // (and I don't have a way to test it on a real device).
  // 
  // Another interpretation is that TXIF retains it state 
  // through changing TXEN. However, when SPEN (serial port) is
  // set then the whole usart is reinitialized and TXIF will
  // get set.
  //
  //  txreg->full();   // Clear TXIF

}

void _TXSTA::start_transmitting()
{
  Dprintf(("starting a USART transmission\n"));

  // Build the serial byte that's about to be transmitted.
  // I doubt the pic really does this way, but gpsim builds
  // the entire bit stream including the start bit, 8 data 
  // bits, optional 9th data bit and the stop, and places
  // this into the tsr register. But since the contents of
  // the tsr are inaccessible, I guess we'll never know.
  //
  // (BTW, if you look carefully you may puzzle over why
  //  there appear to be 2 stop bits in the packet built
  //  below. Well, it's because the way gpsim implements
  //  the transmit logic. The second stop bit doesn't
  //  actually get transmitted - it merely causes the first
  //  stop bit to get transmitted before the TRMT bit is set.
  //
  //  RRR I believe the above paragraph is a mis-understanding
  //  The tsr register becomes empty, and the TRMT flag goes high,
  //  when we start to transmit the stop bit. Note that transmision
  //  is synchronous with the baud clock, so the start of transmision
  //  of a new character waits for the next callback. This delay maybe,
  //  in fact, the stop bit of the previous transmision,
  //
  //  [Recall that the TRMT bit indicates when the tsr 
  //  {transmit shift register} is empty. It's not tied to
  //  an interrupt pin, so the pic application software
  //  most poll this bit. 
  //
  //  RRR Also The following is wrong:
  //  This bit is set after the STOP
  //  bit is transmitted.] This is a cheap trick that saves
  //  one comparison in the callback code.)

  // The start bit, which is always low, occupies bit position
  // zero. The next 8 bits come from the txreg.
  if(!txreg)
    return;

  tsr = txreg->value.get() << 1;

  // Is this a 9-bit data transmission?
  if(value.get() & TX9)
    {
      // Copy the stop bit and the 9th data bit to the tsr.
      // (See note above for the reason why two stop bits 
      // are appended to the packet.)

      tsr |= ( (value.get() & TX9D) ? (3<<9) : (2<<9));
      bit_count = 11;  // 1 start, 9 data, 1 stop 
    }
  else
    {
      // The stop bit is always high. (See note above
      // for the reason why two stop bits are appended to
      // the packet.)
      tsr |= (1<<9);
      bit_count = 10;  // 1 start, 8 data, 1 stop 
    }


  // Set a callback breakpoint at the next SPBRG edge

  if(cpu)
    get_cycles().set_break(spbrg->get_cpu_cycle(1), this);

  // The TSR now has data, so clear the Transmit Shift 
  // Register Status bit.

  trace.raw(write_trace.get() | value.get());
  value.put(value.get() & ~TRMT);

  // Tell the TXREG that its data has been consumed.

  mUSART->emptyTX();

}

void _TXSTA::transmit_a_bit()
{


  if(bit_count) {

    Dprintf(("Transmit bit #%x: bit val:%d time:0x%llx\n",bit_count, (tsr&1),get_cycles().value));

    putTXState(tsr&1 ? '1' : '0');

    tsr >>= 1;

    --bit_count;

  }

}

void _TXSTA::callback()
{
  Dprintf(("TXSTA callback - time:%llx\n",get_cycles().value));

  transmit_a_bit();

  if(!bit_count) {

    // tsr is empty.
    // If there is any more data in the TXREG, then move it to
    // the tsr and continue transmitting other wise set the TRMT bit

    // (See the note above about the 'extra' stop bit that was stuffed
    // into the tsr register. 

    if(mUSART->bIsTXempty())
      value.put(value.get() | TRMT);
    else
      start_transmitting();

  } else  {
    // bit_count is non zero which means there is still
    // data in the tsr that needs to be sent.

    if(cpu) {
      get_cycles().set_break(spbrg->get_cpu_cycle(1),this);
    }
  }

}

void _TXSTA::callback_print()
{
  cout << "TXSTA " << name() << " CallBack ID " << CallBackID << '\n';
}

//-----------------------------------------------------------
// Receiver portion of the USART
//-----------------------------------------------------------
//
// First RCSTA -- Receiver Control and Status 
// The RCSTA class controls the usart reception. The PIC usarts have
// two modes: synchronous and asynchronous.
// Asynchronous reception:
//   Asynchronous reception means that there is no external clock
// available for telling the usart when to sample the data. Sampling
// timing is all based upon the PIC's oscillator. The SPBRG divides
// this clock down to a frequency that's appropriate to the data
// being received. (e.g. 9600 baud defines the rate at which data
// will be sent to the pic - 9600 bits per second.) The start bit,
// which is a high to low transition on the receive line, defines
// when the usart should start sampling the incoming data.
//   The pic usarts sample asynchronous data three times in "approximately
// the middle" of each bit. The data sheet is not exactly specific
// on what's the middle. Consequently, gpsim takes a stab/ educated
// guess on when these three samples are to be taken. Once the
// three samples are taken, then simple majority summing determines
// the sample e.g. if two out of three of the samples are high, then
// then the data bit is considered high.
//
//-----------------------------------------------------------
// RCSTA::put
//
void _RCSTA::put(unsigned int new_value)
{
  unsigned int diff;

  diff = new_value ^ value.get();
  trace.raw(write_trace.get() | value.get());
  value.put( ( value.get() & (RX9D | OERR | FERR) )   |  (new_value & ~(RX9D | OERR | FERR)));

  if(!txsta || !txsta->txreg)
    return;
  // First check whether or not the serial port is being enabled
  if(diff & SPEN) {

    if(value.get() & SPEN) {
      spbrg->start();
      // Make the tx line high when the serial port is enabled.
      txsta->putTXState('1');
      mUSART->emptyTX();
    } else {

      // Completely disable the usart:

      txsta->stop_transmitting();
      mUSART->full();         // Turn off TXIF
      stop_receiving();

      return;
    }

  }

  if(!(txsta->value.get() & _TXSTA::SYNC)) {

    // Asynchronous receive.
    if( (value.get() & (SPEN | CREN)) == (SPEN | CREN) ) {

      // The receiver is enabled. Now check to see if that just happened
      
      if(diff & (SPEN | CREN)) {
    
	// The serial port has just been enabled. 
	start_receiving();

	// If the rx line is low, then go ahead and start receiving now.
	//if(uart_port && !uart_port->get_bit(rx_bit))
	if (m_cRxState == '0' || m_cRxState == 'w')
	  receive_start_bit();
      }

    } else {
      // The serial port is not enabled.

      state = RCSTA_DISABLED;
    }

  } else
    cout << "not doing syncronous receptions yet\n";

}

void _RCSTA::put_value(unsigned int new_value)
{

  put(new_value);

  update();
}

//-----------------------------------------------------------
// RCSTA - setIOpin - assign the I/O pin associated with the
// the receiver.


void _RCSTA::setIOpin(PinModule *newPinModule)
{
  if (!m_sink) {
    m_sink = new RXSignalSink(this);
    m_PinModule = newPinModule;
    if (m_PinModule)
      m_PinModule->addSink(m_sink);
  }

}

//-----------------------------------------------------------
// RCSTA - setState
// This gets called whenever there's a change detected on the RX pin.
// The usart is only interested in those changes when it is waiting
// for the start bit. Otherwise, the rcsta callback function will sample
// the rx pin (if we're receiving).


void _RCSTA::setState(char new_RxState)
{
  Dprintf((" setState:%c\n",new_RxState));

  m_cRxState = new_RxState;

  if( (state == RCSTA_WAITING_FOR_START) && (m_cRxState =='0' || m_cRxState=='w'))
    receive_start_bit();

}
//-----------------------------------------------------------
// RCSTA::receive_a_bit(unsigned int bit)
//
// A new bit needs to be copied to the the Receive Shift Register.
// If the receiver is receiving data, then this routine will copy
// the incoming bit to the rsr. If this is the last bit, then a 
// check will be made to see if we need to set up for the next 
// serial byte.
// If this is not the last bit, then the receive state machine.

void _RCSTA::receive_a_bit(unsigned int bit)
{

  // If we're waiting for the start bit and this isn't it then
  // we don't need to look any further
  Dprintf(("receive_a_bit state:%d bit:%d time:0x%llx\n",state,bit,get_cycles().value));

  if( state == RCSTA_MAYBE_START) {
    if (bit)
      state = RCSTA_WAITING_FOR_START;
    else
      state = RCSTA_RECEIVING;
    return;
  }
  if (bit_count == 0) {
    // we should now have the stop bit
    if (bit) {
      // got the stop bit
      // If the rxreg has data from a previous reception then
      // we have a receiver overrun error.
      // cout << "rcsta.rsr is full\n";

      if((value.get() & RX9) == 0)
        rsr >>= 1;

      // copy the rsr to the fifo
      if(rcreg)
        rcreg->push( rsr & 0xff);

      Dprintf(("_RCSTA::receive_a_bit received 0x%02X\n",rsr & 0xff));

    } else {
      //not stop bit; discard the data and go back receiving
    }
    // If we're continuously receiving, then set up for the next byte.
    // FIXME -- may want to set a half bit delay before re-starting...
    if(value.get() & CREN)
      start_receiving();
    else
      state = RCSTA_DISABLED;
    return;
  }


  // Copy the bit into the Receive Shift Register
  if(bit)
    rsr |= 1<<9;

  //cout << "Receive bit #" << bit_count << ": " << (rsr&(1<<9)) << '\n';

  rsr >>= 1;
  bit_count--;

}

void _RCSTA::stop_receiving()
{

  rsr = 0;
  bit_count = 0;
  state = RCSTA_DISABLED;

}

void _RCSTA::start_receiving()
{
  Dprintf(("The USART is starting to receive data\n"));

  rsr = 0;
  sample = 0;

  // Is this a 9-bit data reception?
  bit_count = (value.get() & RX9) ? 9 : 8;

  state = RCSTA_WAITING_FOR_START;

}
void _RCSTA::overrun()
{
  value.put(value.get() | _RCSTA::OERR);
}

void _RCSTA::set_callback_break(unsigned int spbrg_edge)
{
  unsigned int cpi = (cpu) ? p_cpu->get_ClockCycles_per_Instruction() : 4;
  //  last_cycle = cycles.value;

  if(cpu && spbrg)
    get_cycles().set_break(get_cycles().value + (spbrg->value.get() + 1) * spbrg_edge/cpi, this);

}
void _RCSTA::receive_start_bit()
{
  Dprintf(("USART received a start bit\n"));

  if((value.get() & (CREN | SREN)) == 0) {
    Dprintf(("  but not enabled\n"));
    return;
  }
  
  if(txsta && (txsta->value.get() & _TXSTA::BRGH))
    set_callback_break(BRGH_FIRST_MID_SAMPLE);
  else
    set_callback_break(BRGL_FIRST_MID_SAMPLE);

  sample = 0;
  sample_state = RCSTA_WAITING_MID1;
  state = RCSTA_MAYBE_START;
}

//------------------------------------------------------------
void _RCSTA::callback()
{

  Dprintf(("RCSTA callback. time:0x%llx\n",cycles.value));

  // A bit is sampled 3 times.

  switch(sample_state) {
  case RCSTA_WAITING_MID1:
    if (m_cRxState == '1' || m_cRxState == 'W')
      sample++;

    if(txsta && (txsta->value.get() & _TXSTA::BRGH))
      set_callback_break(BRGH_SECOND_MID_SAMPLE - BRGH_FIRST_MID_SAMPLE);
    else
      set_callback_break(BRGL_SECOND_MID_SAMPLE - BRGL_FIRST_MID_SAMPLE);

    sample_state = RCSTA_WAITING_MID2;

    break;

  case RCSTA_WAITING_MID2:
    if (m_cRxState == '1' || m_cRxState == 'W')
      sample++;

    if(txsta && (txsta->value.get() & _TXSTA::BRGH))
      set_callback_break(BRGH_THIRD_MID_SAMPLE - BRGH_SECOND_MID_SAMPLE);
    else
      set_callback_break(BRGL_THIRD_MID_SAMPLE - BRGL_SECOND_MID_SAMPLE);

    sample_state = RCSTA_WAITING_MID3;

    break;

  case RCSTA_WAITING_MID3:
    if (m_cRxState == '1' || m_cRxState == 'W')
      sample++;

    receive_a_bit( (sample>=2));
    sample = 0;

    // If this wasn't the last bit then go ahead and set a break for the next bit.
    if(state==RCSTA_RECEIVING) {
      if(txsta && (txsta->value.get() & _TXSTA::BRGH))
	set_callback_break(TOTAL_BRGH_STATES -(BRGH_THIRD_MID_SAMPLE - BRGH_FIRST_MID_SAMPLE));
      else
	set_callback_break(TOTAL_BRGL_STATES -(BRGL_THIRD_MID_SAMPLE - BRGL_FIRST_MID_SAMPLE));

      sample_state = RCSTA_WAITING_MID1;
    }

    break;

  default:
    //cout << "Error RCSTA callback with bad state\n";
    // The receiver was probably disabled in the middle of a reception.
    ;
  }

}

//-----------------------------------------------------------
void _RCSTA::callback_print()
{
  cout << "RCSTA " << name() << " CallBack ID " << CallBackID << '\n';
}

//-----------------------------------------------------------
// RCREG
//
void _RCREG::push(unsigned int new_value)
{
  trace.raw(write_trace.get() | value.get());

  if(fifo_sp >= 2) {

    if (m_rcsta)
      m_rcsta->overrun();
      
    Dprintf(("receive overrun\n"));

  } else {

    Dprintf(("pushing uart reception onto rcreg stack, value received=0x%x\n",new_value));
    fifo_sp++;
    oldest_value = value.get();
    value.put(new_value);
  }

  mUSART->set_rcif();

}

void _RCREG::pop()
{

  if(fifo_sp == 0)
    return;

  if(--fifo_sp == 1)
    value.put(oldest_value);

  if(fifo_sp == 0)
    mUSART->clear_rcif();

}

unsigned int _RCREG::get_value()
{

  return value.get();

}

unsigned int _RCREG::get()
{

  pop();
  trace.raw(read_trace.get() | value.get());
  return value.get();
}

//-----------------------------------------------------------
// SPBRG - Serial Port Baud Rate Generator
//
// The SPBRG is essentially a continuously running programmable
// clock. (Note that this will slow the simulation down if the
// serial port is not used. Perhaps gpsim needs some kind of
// pragma type thing to disable cpu intensive peripherals...)

void _SPBRG::get_next_cycle_break()
{
  unsigned int cpi = (cpu) ? p_cpu->get_ClockCycles_per_Instruction() : 4;


  if(txsta && (txsta->value.get() & _TXSTA::SYNC))
    {
      // Synchronous mode
      future_cycle = last_cycle + (value.get() + 1)*4/cpi;
    }
  else
    {
      // Asynchronous mode
      if(txsta && (txsta->value.get() & _TXSTA::BRGH))
      {
	future_cycle = last_cycle + (value.get() + 1)*16/cpi;
      }
      else
      {
	future_cycle = last_cycle + (value.get() + 1)*64/cpi;
      }
    }

  if(cpu)
    get_cycles().set_break(future_cycle, this);

  //Dprintf(("SPBRG::callback next break at 0x%llx\n",future_cycle));
  
}

void _SPBRG::start()
{

  if(cpu)
    last_cycle = get_cycles().value;
  start_cycle = last_cycle;

  get_next_cycle_break();

  Dprintf((" SPBRG::start   last_cycle:0x%llx: future_cycle:0x%llx\n",last_cycle,future_cycle));


}

//--------------------------
//guint64 _SPBRG::get_last_cycle()
//
// Get the cpu cycle corresponding to the last edge of the SPBRG
//

guint64 _SPBRG::get_last_cycle()
{

  // There's a chance that a SPBRG break point exists on the current
  // cpu cycle, but has not yet been serviced.
  if(cpu)
    return( (get_cycles().value == future_cycle) ? future_cycle : last_cycle);
  else
    return 0;
}
//--------------------------
//guint64 _SPBRG::get_cpu_cycle(unsigned int edges_from_now)
//
//  When the SPBRG is enabled, it becomes a free running counter
// that's synchronous with the cpu clock. The frequency of the
// counter depends on the mode of the usart:
//
//  Synchronous mode:
//    baud = cpu frequency / 4 / (spbrg.value + 1)
//
//  Asynchronous mode:
//   high frequency:
//     baud = cpu frequency / 16 / (spbrg.value + 1)
//   low frequency:
//     baud = cpu frequency / 64 / (spbrg.value + 1)
//
// What this routine will do is return the cpu cycle corresponding
// to a (rising) edge of the spbrg clock. 

guint64 _SPBRG::get_cpu_cycle(unsigned int edges_from_now)
{

  unsigned int cpi = (cpu) ? p_cpu->get_ClockCycles_per_Instruction() : 4;

  // There's a chance that a SPBRG break point exists on the current
  // cpu cycle, but has not yet been serviced. 
  guint64 cycle = (get_cycles().value == future_cycle) ? future_cycle : last_cycle;

  if(txsta && (txsta->value.get() & _TXSTA::SYNC))
    // Synchronous mode
    return ( edges_from_now * (value.get() + 1)*4/cpi + cycle);

  else  {
      // Asynchronous mode
    if(txsta && (txsta->value.get() & _TXSTA::BRGH))
      return ( edges_from_now * (value.get() + 1)*16/cpi + cycle);
    else
      return ( edges_from_now * (value.get() + 1)*64/cpi + cycle);
  }

}
void _SPBRG::callback()
{

  last_cycle = get_cycles().value;

  //Dprintf(("SPBRG rollover at cycle:0x%llx\n",last_cycle));

  if(rcsta && (rcsta->value.get() & _RCSTA::SPEN))
    {

      // If the serial port is enabled, then set another 
      // break point for the next clock edge.
      get_next_cycle_break();

    }
}

//--------------------------------------------------
// member functions for the USART
//--------------------------------------------------
void USART_MODULE::initialize(PIR_SET *_pir_set,
			      PinModule *tx_pin, PinModule *rx_pin,
			      _TXREG *_txreg, _RCREG *_rcreg)
{
  assert(_txreg && _rcreg);

  pir_set = _pir_set;

  spbrg.txsta = &txsta;
  spbrg.rcsta = &rcsta;

  txreg = _txreg;
  txreg->assign_txsta(&txsta);

  rcreg = _rcreg;
  rcreg->assign_rcsta(&rcsta);

  txsta.txreg = txreg;
  txsta.spbrg = &spbrg;
  txsta.bit_count = 0;
  txsta.setIOpin(tx_pin);

  rcsta.rcreg = rcreg;
  rcsta.spbrg = &spbrg;
  rcsta.txsta = &txsta;
  rcsta.setIOpin(rx_pin);

}

bool USART_MODULE::bIsTXempty()
{
  return pir_set ? pir_set->get_txif() : true;
}
void USART_MODULE::emptyTX()
{
  Dprintf(("usart::empty - setting TXIF\n"));
  if (rcsta.bSPEN() && txsta.bTXEN() && pir_set)
    pir_set->set_txif();

}

void USART_MODULE::full()
{
  Dprintf(("txreg::full - clearing TXIF\n"));
  if(pir_set)
    pir_set->clear_txif();
}

void USART_MODULE::set_rcif()
{
  Dprintf((" - setting RCIF\n"));
  if(pir_set)
    pir_set->set_rcif();
}

void USART_MODULE::clear_rcif()
{
  Dprintf((" - clearing RCIF\n"));
  if(pir_set)
    pir_set->clear_rcif();
}

//--------------------------------------------------
USART_MODULE::USART_MODULE()
  : txsta(this), rcsta(this)
{
}



syntax highlighted by Code2HTML, v. 0.9.1