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