1 /*
2    Copyright (C) 1998 T. Scott Dattalo
3 
4 This file is part of the libgpsim library of gpsim
5 
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10 
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 Lesser General Public License for more details.
15 
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, see
18 <http://www.gnu.org/licenses/lgpl-2.1.html>.
19 */
20 
21 #ifndef SRC_IOPORTS_H_
22 #define SRC_IOPORTS_H_
23 
24 #include "registers.h"
25 #include "stimuli.h"
26 
27 #include <stdio.h>
28 
29 class Module;
30 class PinModule;
31 class Processor;
32 
33 ///**********************************************************************/
34 ///
35 /// I/O ports
36 ///
37 /// An I/O port is collection of I/O pins. For a PIC processor, these
38 /// are the PORTA, PORTB, etc, registers. gpsim models I/O ports in
39 /// a similar way it models other registers; there's a base class from
40 /// which all specific I/O ports are derived. However, I/O ports are
41 /// special in that they're an interface between a processor's core
42 /// and the outside world. The requirements vary wildly from one processor
43 /// to the next; in fact they even vary dynamically within one processor.
44 /// gpsim attempts to abstract this interface with a set of base classes
45 /// that are responsible for routing signal state information. These
46 /// base classes make no attempt to decipher this information, instead
47 /// this job is left to the peripherals and stimuli connected to the
48 /// I/O pins and ports.
49 ///
50 ///
51 /// PinModule
52 ///
53 /// Here's a general description of gpsim I/O pin design:
54 ///
55 ///    Data
56 ///    Select  ======+
57 ///                +-|-+  Outgoing
58 ///    Source1 ===>| M |  data
59 ///    Source2 ===>| U |=============+
60 ///    SourceN ===>| X |             |
61 ///                +---+             |    +-------+
62 ///    Control                       +===>| IOPIN |
63 ///    Select  ======+                    |       |
64 ///                +-|-+  I/O Pin         |       |
65 ///   Control1 ===>| M |  Direction       |       |<======> Physical
66 ///   Control2 ===>| U |=================>|       |         Interface
67 ///   ControlN ===>| X |                  |       |
68 ///                +---+                  |       |
69 ///    Sink Decode                   +===<|       |
70 ///    Select  ======+               |    +-------+
71 ///                +-|-+   Incoming  |
72 ///    Sink1  <====| D |   data      |
73 ///    Sink2  <====| E |<============|
74 ///    SinkN  <====| C |
75 ///                +---+
76 ///
77 /// The PinModule models a Processor's I/O Pin. The schematic illustrates
78 /// the abstract description of the PinModule. Its job is to merge together
79 /// all of the Processor's peripherals that can control a processor's pin.
80 /// For example, a UART peripheral may be shared with a general purpose I/O
81 /// pin. The UART may have a transmit and receive pin and select whether it's
82 /// in control of the I/O pins. The uart transmit pin and the port's I/O pin
83 /// can both act as a source for the physical interface. The PinModule
84 /// arbitrates between the two. Similarly, the UART receive pin can be multiplexed
85 /// with a register pin. In this case, the PinModule will route signal
86 /// changes to both devices. Finally, a peripheral like the '622's comparators
87 /// may overide the output control. The PinModule again arbitrates.
88 ///
89 ///
90 /// PortModule
91 ///
92 /// The PortModule is the base class for processor I/O ports. It's essentially
93 /// a register that contains an array of PinModule's.
94 ///
95 ///  Register               PortModule
96 ///    |-> sfr_register         |
97 ///             |               |
98 ///             \------+--------/
99 ///                    |
100 ///                    +--> PortRegister
101 ///                            |--> PicPortRegister
102 
103 
104 ///------------------------------------------------------------
105 ///
106 /// SignalControl  - A pure virtual class that defines the interface for
107 /// a signal control. The I/O Pin Modules will query the source's state
108 /// via SignalControl. The control is usually used to control the I/O pin
109 /// direction (i.e. whether it's an input or output...), drive value,
110 /// pullup state, etc.
111 /// When a Pin Module is through with the SignalControl, it will call
112 /// the release() method. This is primarily used to delete the SignalControl
113 /// objects.
114 
115 class SignalControl
116 {
117 public:
118     virtual ~SignalControl();  //// fixme
119     virtual char getState() = 0;
120     virtual void release() = 0;
121 };
122 
123 ///------------------------------------------------------------
124 /// PeripheralSignalSource - A class to interface I/O pins with
125 /// peripheral outputs.
126 
127 class PeripheralSignalSource : public SignalControl
128 {
129 public:
130     explicit PeripheralSignalSource(PinModule *_pin);
131     virtual ~PeripheralSignalSource();
132     virtual void release();
133 
134     /// getState - called by the PinModule to determine the source state
135     virtual char getState();
136 
137     /// putState - called by the peripheral to set a new state
138     virtual void putState(const char new3State);
139 
140     /// toggle - called by the peripheral to toggle the current state.
141     virtual void toggle();
142 private:
143     PinModule *m_pin;
144     char m_cState;
145 };
146 
147 ///------------------------------------------------------------
148 /// PortModule - Manages all of the I/O pins associated with a single
149 /// port. The PortModule supplies the interface to the I/O pin's. It
150 /// is designed to handle a group of I/O pins. However, the low level
151 /// I/O pin processing is handled by PinModule objects contained within
152 /// the PortModule.
153 
154 class PortModule
155 {
156 public:
157     explicit PortModule(unsigned int numIopins);
158     virtual ~PortModule();
159 
160     /// updatePort -- loop through update all I/O pins
161 
162     virtual void updatePort();
163 
164     /// updatePin -- Update a single I/O pin
165 
166     virtual void updatePin(unsigned int iPinNumber);
167 
168     /// updatePins -- Update several I/O pins
169 
170     virtual void updatePins(unsigned int iPinBitMask);
171 
172     /// updateUI -- convey pin state info to a User Interface (e.g. the gui).
173 
174     virtual void   updateUI();
175 
176     /// addPinModule -- supply a pin module at a particular bit position.
177     ///      Most of the low level I/O pin related processing will be handled
178     ///      here. The PortModule per-pin helper methods below essentially
179     ///      call methods in the PinModule to do the dirty work.
180     ///      Each bit position can have only one PinModule. If multiple
181     ///      modules are added, only the first will be used and the others
182     ///      will be ignored.
183 
184     void           addPinModule(PinModule *, unsigned int iPinNumber);
185 
186     /// addSource -- supply a pin with a source of data. There may
187 
188     SignalControl *addSource(SignalControl *, unsigned int iPinNumber);
189 
190     /// addControl -- supply a pin with a data direction control
191 
192     SignalControl *addControl(SignalControl *, unsigned int iPinNumber);
193 
194     /// addPullupControl -- supply a pin with a pullup control
195 
196     SignalControl *addPullupControl(SignalControl *, unsigned int iPinNumber);
197 
198     /// addSink -- supply a sink to receive info driven on to a pin
199 
200     SignalSink    *addSink(SignalSink *, unsigned int iPinNumber);
201 
202     /// addPin -- supply an I/O pin. Note, this will create a default pin module
203     ///           if one is not already created.
204 
205     IOPIN         *addPin(IOPIN *, unsigned int iPinNumber);
206 
207 
208     /// getPin -- an I/O pin accessor. This returns the I/O pin at a particular
209     ///           bit position.
210 
211     IOPIN         *getPin(unsigned int iPinNumber);
212 
213     /// operator[] -- PinModule accessor. This returns the pin module at
214     ///               a particular bit position.
215 
216     PinModule &operator [] (unsigned int pin_number);
217 
218     PinModule * getIOpins(unsigned int pin_number);
219 
220     // set/get OutputMask which controls bits returned on I/O
221     // port register get() call. Used to return 0 for  analog pins
setOutputMask(unsigned int OutputMask)222     virtual void setOutputMask (unsigned int OutputMask)
223     { mOutputMask = OutputMask;}
getOutputMask()224     virtual unsigned int getOutputMask ()
225     { return(mOutputMask);}
226 protected:
227     unsigned int mNumIopins;
228     unsigned int mOutputMask;
229 
230 private:
231 
232     /// PinModule -- The array of PinModules that are handled by PortModule.
233 
234     std::vector<PinModule *> iopins;
235 };
236 
237 ///------------------------------------------------------------
238 /// PinModule - manages the interface to a physical I/O pin. Both
239 /// simple and complex I/O pins are handled. An example of a simple
240 /// I/O is one where there is a single data source, data sink and
241 /// control, like say the GPIO pin on a small PIC. A complex pin
242 /// is one that is multiplexed with peripherals.
243 ///
244 /// The parent class 'PinMonitor', allows the PinModule to be
245 /// registered with the I/O pin. In other words, when the I/O pin
246 /// changes state, the PinModule will be notified.
247 #define ANALOG_TABLE_SIZE 3
248 
249 class PinModule : public PinMonitor
250 {
251 public:
252     PinModule();
253     PinModule(PortModule *, unsigned int _pinNumber, IOPIN *new_pin = nullptr);
254     virtual ~PinModule();
255 
256     /// updatePinModule -- The low level I/O pin state is resolved here
257     /// by examining the direction and state of the I/O pin.
258 
259     virtual void updatePinModule();
260 
261     /// refreshPinOnUpdate - modal behavior. If set to true, then
262     /// a pin's state will always be refreshed whenever the PinModule
263     /// is updated. If false, then the pin is updated only if there
264     /// is a detected state change.
265     void refreshPinOnUpdate(bool bForcedUpdate);
266 
267     void setPin(IOPIN *);
clrPin()268     void clrPin() { m_pin = nullptr; }
269     void setDefaultSource(SignalControl *);
270     void setSource(SignalControl *);
271     void setDefaultControl(SignalControl *);
272     virtual void setControl(SignalControl *);
273     void setPullupControl(SignalControl *);
274     void setDefaultPullupControl(SignalControl *);
275 
276     char getControlState();
277     char getSourceState();
278     char getPullupControlState();
getPinNumber()279     unsigned int getPinNumber() { return m_pinNumber;}
280     void AnalogReq(Register *reg, bool analog, const char *newName);
281     // If active control not default, return it
getActiveControl()282     SignalControl *getActiveControl() {return (m_activeControl == m_defaultControl) ? 0 : m_activeControl;}
283     // If active source not default, return it
getActiveSource()284     SignalControl *getActiveSource() {return (m_activeSource == m_defaultSource) ? 0 : m_activeSource;}
285 
getPin()286     IOPIN &getPin() { return *m_pin;}
287 
288     ///
289     virtual void setDrivenState(char);
290     virtual void setDrivingState(char);
291     virtual void set_nodeVoltage(double);
292     virtual void putState(char);
293     virtual void setDirection();
294     virtual void updateUI();
295 
296 
297 private:
298     char          m_cLastControlState;
299     char          m_cLastSinkState;
300     char          m_cLastSourceState;
301     char          m_cLastPullupControlState;
302 
303     SignalControl *m_defaultSource,  *m_activeSource;
304     SignalControl *m_defaultControl, *m_activeControl;
305     SignalControl *m_defaultPullupControl, *m_activePullupControl;
306 
307     IOPIN        *m_pin;
308     PortModule   *m_port;
309     unsigned int  m_pinNumber;
310     bool          m_bForcedUpdate;
311     Register     *m_analog_reg[ANALOG_TABLE_SIZE + 1];
312     bool	  m_analog_active[ANALOG_TABLE_SIZE + 1];
313 };
314 
315 
316 
317 ///------------------------------------------------------------
318 class PortRegister : public sfr_register, public PortModule
319 {
320 public:
321     PortRegister(Module *pCpu, const char *pName, const char *pDesc,
322                  unsigned int numIopins, unsigned int enableMask);
323 
324     virtual void put(unsigned int new_value);
325     virtual void put_value(unsigned int new_value);
326     virtual unsigned int get();
327     virtual unsigned int get_value();
328     virtual void putDrive(unsigned int new_drivingValue);
329     virtual unsigned int getDriving();
330     virtual void setbit(unsigned int bit_number, char new_value);
331     virtual void setEnableMask(unsigned int nEnableMask);
332     IOPIN         *addPin(IOPIN *, unsigned int iPinNumber);
333     IOPIN         *addPin(Module *mod, IOPIN *pin, unsigned int iPinNumber);
334 
getEnableMask()335     unsigned int getEnableMask()
336     {
337         return mEnableMask;
338     }
339     virtual void   updateUI();
340 
341 protected:
342     unsigned int  mEnableMask;
343     unsigned int  drivingValue;
344     RegisterValue rvDrivenValue;
345 };
346 
347 class PortSink : public SignalSink
348 {
349 public:
350     PortSink(PortRegister *portReg, unsigned int iobit);
351 
~PortSink()352     virtual ~PortSink()
353     {
354     }
355 
356     virtual void setSinkState(char);
357     virtual void release();
358 private:
359     PortRegister *m_PortRegister;
360     unsigned int  m_iobit;
361 };
362 
363 
364 
365 // Base class to allow changing of IO pins
366 class apfpin
367 {
368 public:
369     virtual void setIOpin(PinModule * pin, int arg=0)
370     {
371         fprintf(stderr, "unexpected call afpin::setIOpin pin=%p %s arg=%d\n", pin, pin ? pin->getPin().name().c_str():"unknown", arg);
372     }
373 };
374 
375 class INTsignalSink;
376 class INTCON;
377 
378 // class to support INT pin
379 class INT_pin : public apfpin
380 {
381 public:
382     INT_pin(Processor *pCpu, INTCON *_intcon,  int _intedg_index);
383     virtual void setIOpin(PinModule * pin, int arg=0);
384     virtual void setState(char new3State);
385 
386 private:
387     Processor 	*p_cpu;
388     INTCON		*p_intcon;
389     int		intedg_index;	// index for get_intedg(index)
390     PinModule       *m_PinModule;
391     INTsignalSink   *m_sink;
392     int	        arg;
393     bool	        OldState;
394 };
395 
396 // ALTERNATE PIN LOCATIONS register
397 // set_pins is used to configure operation
398 class APFCON : public  sfr_register
399 {
400 public:
401     APFCON(Processor *pCpu, const char *pName, const char *pDesc, unsigned int _mask);
402     virtual void put(unsigned int new_value);
403     void set_pins(unsigned int bit, class apfpin *pt_apfpin, int arg,
404                   PinModule *pin_default, PinModule *pin_alt);
set_ValidBits(unsigned int _mask)405     void set_ValidBits(unsigned int _mask) {mValidBits = _mask;}
406 
407 private:
408     unsigned int mValidBits;
409     struct dispatch
410     {
411         class apfpin *pt_apfpin;	// pointer to pin setting function
412         int          arg;	        // argument for pin setting function
413         PinModule    *pin_default; // pin when bit=0
414         PinModule    *pin_alt;	// pin when bit=1
415     } dispatch[8];
416 };
417 
418 
419 
420 
421 #endif  // __IOPORTS_H__
422