/*
Copyright (C) 1998 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. */
#ifndef __IOPORTS_H__
#define __IOPORTS_H__
#include "registers.h"
#include "stimuli.h"
class stimulus;
class Stimulus_Node;
class PinModule;
///**********************************************************************/
///
/// I/O ports
///
/// An I/O port is collection of I/O pins. For a PIC processor, these
/// are the PORTA, PORTB, etc, registers. gpsim models I/O ports in
/// a similar way it models other registers; there's a base class from
/// which all specific I/O ports are derived. However, I/O ports are
/// special in that they're an interface between a processor's core
/// and the outside world. The requirements vary wildly from one processor
/// to the next; in fact they even vary dynamically within one processor.
/// gpsim attempts to abstract this interface with a set of base classes
/// that are responsible for routing signal state information. These
/// base classes make no attempt to decipher this information, instead
/// this job is left to the peripherals and stimuli connected to the
/// I/O pins and ports.
///
///
/// PinModule
///
/// Here's a general description of gpsim I/O pin design:
///
/// Data
/// Select ======+
/// +-|-+ Outgoing
/// Source1 ===>| M | data
/// Source2 ===>| U |=============+
/// SourceN ===>| X | |
/// +---+ | +-------+
/// Control +===>| IOPIN |
/// Select ======+ | |
/// +-|-+ I/O Pin | |
/// Control1 ===>| M | Direction | |<======> Physical
/// Control2 ===>| U |=================>| | Interface
/// ControlN ===>| X | | |
/// +---+ | |
/// Sink Decode +===<| |
/// Select ======+ | +-------+
/// +-|-+ Incoming |
/// Sink1 <====| D | data |
/// Sink2 <====| E |<============|
/// SinkN <====| C |
/// +---+
///
/// The PinModule models a Processor's I/O Pin. The schematic illustrates
/// the abstract description of the PinModule. Its job is to merge together
/// all of the Processor's peripherals that can control a processor's pin.
/// For example, a UART peripheral may be shared with a general purpose I/O
/// pin. The UART may have a transmit and receive pin and select whether it's
/// in control of the I/O pins. The uart transmit pin and the port's I/O pin
/// can both act as a source for the physical interface. The PinModule
/// arbitrates between the two. Similarly, the UART receive pin can be multiplexed
/// with a register pin. In this case, the PinModule will route signal
/// changes to both devices. Finally, a peripheral like the '622's comparators
/// may overide the output control. The PinModule again arbitrates.
///
///
/// PortModule
///
/// The PortModule is the base class for processor I/O ports. It's essentially
/// a register that contains an array of PinModule's.
///
/// Register PortModule
/// |-> sfr_register |
/// | |
/// \------+--------/
/// |
/// +--> PortRegister
/// |--> PicPortRegister
///------------------------------------------------------------
///
/// SignalControl - A pure virtual class that defines the interface for
/// a signal control. The I/O Pin Modules will query the source's state
/// via SignalControl. The control is usually used to control the I/O pin
/// direction (i.e. whether it's an input or output...), drive value,
/// pullup state, etc.
class SignalControl
{
public:
virtual char getState()=0;
};
///------------------------------------------------------------
/// SinkRecipient
/// Interface class that redirects a driven I/O pin change
/// to the appropriate peripheral register that wants the
/// change.
class SinkRecipient
{
public:
virtual void setState(const char)=0;
};
///------------------------------------------------------------
/// PeripheralSignalSource - A class to interface I/O pins with
/// peripheral outputs.
class PeripheralSignalSource : public SignalControl
{
public:
PeripheralSignalSource(PinModule *_pin);
/// getState - called by the PinModule to determine the source state
virtual char getState();
/// putState - called by the peripheral to set a new state
virtual void putState(const char new3State);
/// toggle - called by the peripheral to toggle the current state.
virtual void toggle();
private:
PinModule *m_pin;
char m_cState;
};
///------------------------------------------------------------
/// PortModule - Manages all of the I/O pins associated with a single
/// port. The PortModule supplies the interface to the I/O pin's. It
/// is designed to handle a group of I/O pins. However, the low level
/// I/O pin processing is handled by PinModule objects contained within
/// the PortModule.
class PortModule
{
public:
PortModule(unsigned int numIopins);
virtual ~PortModule();
/// updatePort -- loop through update all I/O pins
virtual void updatePort();
/// updatePin -- Update a single I/O pin
virtual void updatePin(unsigned int iPinNumber);
/// updateUI -- convey pin state info to a User Interface (e.g. the gui).
virtual void updateUI();
/// addPinModule -- supply a pin module at a particular bit position.
/// Most of the low level I/O pin related processing will be handled
/// here. The PortModule per-pin helper methods below essentially
/// call methods in the PinModule to do the dirty work.
/// Each bit position can have only one PinModule. If multiple
/// modules are added, only the first will be used and the others
/// will be ignored.
void addPinModule(PinModule *, unsigned int iPinNumber);
/// addSource -- supply a pin with a source of data. There may
SignalControl *addSource(SignalControl *, unsigned int iPinNumber);
/// addControl -- supply a pin with a data direction control
SignalControl *addControl(SignalControl *, unsigned int iPinNumber);
/// addPullupControl -- supply a pin with a pullup control
SignalControl *addPullupControl(SignalControl *, unsigned int iPinNumber);
/// addSink -- supply a sink to receive info driven on to a pin
SignalSink *addSink(SignalSink *, unsigned int iPinNumber);
/// addPin -- supply an I/O pin. Note, this will create a default pin module
/// if one is not already created.
IOPIN *addPin(IOPIN *, unsigned int iPinNumber);
/// getPin -- an I/O pin accessor. This returns the I/O pin at a particular
/// bit position.
IOPIN *getPin(unsigned int iPinNumber);
/// operator[] -- PinModule accessor. This returns the pin module at
/// a particular bit position.
PinModule &operator [] (unsigned int pin_number);
PinModule * getIOpins(unsigned int pin_number);
protected:
unsigned int mNumIopins;
private:
/// PinModule -- The array of PinModules that are handled by PortModule.
PinModule **iopins;
};
///------------------------------------------------------------
/// PinModule - manages the interface to a physical I/O pin. Both
/// simple and complex I/O pins are handled. An example of a simple
/// I/O is one where there is a single data source, data sink and
/// control, like say the GPIO pin on a small PIC. A complex pin
/// is one that is multiplexed with peripherals.
///
/// The parent class 'PinMonitor', allows the PinModule to be
/// registered with the I/O pin. In other words, when the I/O pin
/// changes state, the PinModule will be notified.
class PinModule : public PinMonitor
{
public:
PinModule();
PinModule(PortModule *, unsigned int _pinNumber, IOPIN *new_pin=0);
virtual ~PinModule() {}
/// updatePinModule -- The low level I/O pin state is resolved here
/// by examined the direction and state of the I/O pin.
void updatePinModule();
/// refreshPinOnUpdate - modal behavior. If set to true, then
/// a pin's state will always be refreshed whenever the PinModule
/// is updated. If false, then the pin is updated only if there
/// is a detected state change.
void refreshPinOnUpdate(bool bForcedUpdate);
void setPin(IOPIN *);
void setDefaultSource(SignalControl *);
void setSource(SignalControl *);
void setDefaultControl(SignalControl *);
void setControl(SignalControl *);
void setPullupControl(SignalControl *);
void setDefaultPullupControl(SignalControl *);
char getControlState();
char getSourceState();
char getPullupControlState();
unsigned int getPinNumber() { return m_pinNumber;}
IOPIN &getPin() { return *m_pin;}
///
virtual void setDrivenState(char);
virtual void setDrivingState(char);
virtual void set_nodeVoltage(double);
virtual void putState(char);
virtual void setDirection();
virtual void updateUI();
private:
char m_cLastControlState;
char m_cLastSinkState;
char m_cLastSourceState;
char m_cLastPullupControlState;
SignalControl *m_defaultSource, *m_activeSource;
SignalControl *m_defaultControl, *m_activeControl;
SignalControl *m_defaultPullupControl, *m_activePullupControl;
IOPIN *m_pin;
PortModule *m_port;
unsigned int m_pinNumber;
bool m_bForcedUpdate;
};
///------------------------------------------------------------
class PortRegister : public sfr_register, public PortModule
{
public:
PortRegister(unsigned int numIopins, unsigned int enableMask);
virtual void put(unsigned int new_value);
virtual void put_value(unsigned int new_value);
virtual unsigned int get();
virtual unsigned int get_value();
virtual void putDrive(unsigned int new_drivingValue);
virtual unsigned int getDriving();
virtual void setbit(unsigned int bit_number, char new_value);
virtual void setEnableMask(unsigned int nEnableMask);
unsigned int getEnableMask()
{
return mEnableMask;
}
virtual void updateUI();
protected:
unsigned int mEnableMask;
unsigned int drivingValue;
RegisterValue rvDrivenValue;
};
class PortSink : public SignalSink
{
public:
PortSink(PortRegister *portReg, unsigned int iobit);
virtual void setSinkState(char);
private:
PortRegister *m_PortRegister;
unsigned int m_iobit;
};
/// IOPORT - Base class for I/O ports - deprecated
#if defined(OLD_IOPORT_DESIGN)
class IOPORT : public sfr_register
{
public:
IOPORT(unsigned int _num_iopins=8);
~IOPORT();
IOPIN *addPin(IOPIN *, unsigned int iPinNumber);
IOPIN *getIO(unsigned int pin_number);
virtual void put(unsigned int new_value);
virtual void put_value(unsigned int new_value);
// setbit() is called when a stimulus writes a value to one
// of the I/O pins in this Port.
virtual void setbit(unsigned int bit_number, bool new_value);
virtual bool get_bit(unsigned int bit_number);
virtual unsigned int get(void);
virtual unsigned int get_value(void);
virtual void trace_register_write(void);
protected:
/// The I/O pins associated with this I/O port.
/// This could be anything (or nothing.)
IOPIN **pins;
unsigned int
valid_iopins, // A mask that for those ports that don't have all 8 io bits.
stimulus_mask, // A mask indicating which io bits have a stimulus.
internal_latch, //
num_iopins; // Number of I/O pins attached to this port
// Deprecated functions of the IOPORT class
/// Stimuli
void attach_stimulus(stimulus *new_stim, unsigned int bit_position);
virtual int update_stimuli(void);
void attach_iopin(IOPIN * new_pin, unsigned int bit_position);
void attach_node(Stimulus_Node *new_node, unsigned int bit_position);
virtual double get_bit_voltage(unsigned int bit_number);
virtual void change_pin_direction(unsigned int bit_number, bool new_direction);
};
#endif // OLD_IOPORT_DESIGN
#endif // __IOPORTS_H__
syntax highlighted by Code2HTML, v. 0.9.1