/*
Copyright (C) 1998,1999 T. 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 <iostream>
#include <stdio.h>
class InvalidRegister; // Forward reference
#ifndef __USART_H__
#define __USART_H__
#include "pic-processor.h"
#include "14bit-registers.h"
#include "pir.h"
class _TXSTA; // Forward references
class _SPBRG;
class _RCSTA;
class _14bit_processor;
class RXSignalSink;
class TXSignalSource;
class USART_MODULE;
#define TOTAL_BRGH_STATES 16
#define TOTAL_BRGL_STATES 64
class _TXREG : public sfr_register
{
public:
_TXREG(USART_MODULE *);
virtual void put(unsigned int);
virtual void put_value(unsigned int);
virtual void assign_txsta(_TXSTA *new_txsta) { m_txsta = new_txsta; };
private:
_TXSTA *m_txsta;
USART_MODULE *mUSART;
};
class _TXSTA : public sfr_register, public TriggerObject
{
public:
_TXREG *txreg;
_SPBRG *spbrg;
unsigned int tsr;
unsigned int bit_count;
enum {
TX9D = 1<<0,
TRMT = 1<<1,
BRGH = 1<<2,
SYNC = 1<<4,
TXEN = 1<<5,
TX9 = 1<<6,
CSRC = 1<<7
};
_TXSTA(USART_MODULE *);
virtual void put(unsigned int new_value);
virtual void put_value(unsigned int new_value);
virtual void transmit_a_bit();
virtual void start_transmitting();
virtual void stop_transmitting();
virtual void callback();
virtual void callback_print();
virtual char getState();
virtual void setIOpin(PinModule *);
virtual void putTXState(char newTXState);
bool bTXEN() { return (value.get() & TXEN) != 0; }
protected:
USART_MODULE *mUSART;
PinModule *m_PinModule;
TXSignalSource *m_source;
char m_cTxState;
};
class _RCREG : public sfr_register
{
public:
unsigned int oldest_value; /* rcreg has a 2-deep fifo. The oldest received
* value is stored here, while the most recent
* is stored in sfr_register.value . */
unsigned int fifo_sp; /* fifo stack pointer */
_RCREG(USART_MODULE *);
virtual unsigned int get();
virtual unsigned int get_value();
virtual void push(unsigned int);
virtual void pop();
virtual void assign_rcsta(_RCSTA *new_rcsta) { m_rcsta = new_rcsta; };
private:
USART_MODULE *mUSART;
_RCSTA *m_rcsta;
};
class _RCSTA : public sfr_register, public TriggerObject
{
public:
enum {
RX9D = 1<<0,
OERR = 1<<1,
FERR = 1<<2,
ADDEN = 1<<3,
CREN = 1<<4,
SREN = 1<<5,
RX9 = 1<<6,
SPEN = 1<<7
};
enum {
RCSTA_DISABLED,
RCSTA_WAITING_FOR_START,
RCSTA_MAYBE_START,
RCSTA_WAITING_MID1,
RCSTA_WAITING_MID2,
RCSTA_WAITING_MID3,
RCSTA_RECEIVING
};
// The usart samples the middle of the bit three times and
// produces a sample based on majority averaging.
//
#define BRGH_FIRST_MID_SAMPLE 4
#define BRGH_SECOND_MID_SAMPLE 8
#define BRGH_THIRD_MID_SAMPLE 12
#define BRGL_FIRST_MID_SAMPLE 28
#define BRGL_SECOND_MID_SAMPLE 32
#define BRGL_THIRD_MID_SAMPLE 36
_RCREG *rcreg;
_SPBRG *spbrg;
_TXSTA *txsta;
unsigned int rsr;
unsigned int bit_count;
unsigned int rx_bit;
unsigned int sample,state, sample_state;
guint64 future_cycle, last_cycle;
_RCSTA(USART_MODULE *);
virtual void put(unsigned int new_value);
virtual void put_value(unsigned int new_value);
void receive_a_bit(unsigned);
void receive_start_bit();
virtual void start_receiving();
virtual void stop_receiving();
virtual void overrun();
void set_callback_break(unsigned int spbrg_edge);
virtual void callback();
virtual void callback_print();
void setState(char new_RxState);
bool bSPEN() { return (value.get() & SPEN) != 0; }
virtual void setIOpin(PinModule *);
protected:
USART_MODULE *mUSART;
PinModule *m_PinModule;
RXSignalSink *m_sink;
char m_cRxState;
};
class _SPBRG : public sfr_register, public TriggerObject
{
public:
_TXSTA *txsta;
_RCSTA *rcsta;
guint64
start_cycle, // The cycle the SPBRG was started
last_cycle, // The cycle when the spbrg clock last changed
future_cycle; // The next cycle spbrg is predicted to change
_SPBRG();
virtual void callback();
virtual void callback_print() {
cout << "_SPBRG " << name() << " CallBack ID " << CallBackID << '\n';
}
virtual void start();
virtual void get_next_cycle_break();
virtual guint64 get_cpu_cycle(unsigned int edges_from_now);
virtual guint64 get_last_cycle();
};
//---------------------------------------------------------------
//---------------------------------------------------------------
class USART_MODULE
{
public:
_TXSTA txsta;
_RCSTA rcsta;
_SPBRG spbrg;
_TXREG *txreg;
_RCREG *rcreg;
PIR_SET *pir_set;
USART_MODULE();
void initialize(PIR_SET *,
PinModule *tx_pin, PinModule *rx_pin,
_TXREG *, _RCREG *);
bool bIsTXempty();
void emptyTX();
void full();
void set_rcif();
void clear_rcif();
};
#endif
syntax highlighted by Code2HTML, v. 0.9.1