/* 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 #include 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