1 /*
2    Copyright (C) 1998 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 
22 #include <stdio.h>
23 #include <iostream>
24 #include <assert.h>
25 #include <string.h>
26 
27 #include "cmd_gpsim.h"
28 #include "ioports.h"
29 #include "processor.h"
30 #include "trace.h"
31 
32 #include "stimuli.h"
33 #include "intcon.h"
34 
35 class Module;
36 class Processor;
37 
38 //#define DEBUG
39 #if defined(DEBUG)
40 #define Dprintf(arg) {printf("%s:%d-%s ",__FILE__,__LINE__,__FUNCTION__); printf arg; }
41 #else
42 #define Dprintf(arg) {}
43 #endif
44 //#define D2
45 #ifdef D2
46 #define D2printf(arg) {fprintf(stderr, "%s:%d-%s ",__FILE__,__LINE__,__FUNCTION__); printf arg; }
47 #else
48 #define D2printf(arg) {}
49 #endif
50 
51 //--------------------------------------------------
52 //
53 //--------------------------------------------------
~SignalControl()54 SignalControl::~SignalControl()
55 {
56 }
PeripheralSignalSource(PinModule * _pin)57 PeripheralSignalSource::PeripheralSignalSource(PinModule *_pin)
58     : m_pin(_pin), m_cState('?')
59 {
60     assert(m_pin);
61 }
62 
~PeripheralSignalSource()63 PeripheralSignalSource::~PeripheralSignalSource()
64 {
65 }
66 
release()67 void PeripheralSignalSource::release()
68 {
69 }
70 
71 // getState is called when the PinModule is attempting to
72 // update the output state for the I/O Pin.
73 
getState()74 char PeripheralSignalSource::getState()
75 {
76     return m_cState;
77 }
78 
79 /// putState is called when the peripheral output source
80 /// wants to change the output state.
putState(const char new3State)81 void PeripheralSignalSource::putState(const char new3State)
82 {
83     if (new3State != m_cState)
84     {
85         m_cState = new3State;
86         m_pin->updatePinModule();
87     }
88 }
89 
toggle()90 void PeripheralSignalSource::toggle()
91 {
92     switch (m_cState)
93     {
94     case '1':
95     case 'W':
96         putState('0');
97         break;
98     case '0':
99     case 'w':
100         putState('1');
101         break;
102     }
103 }
104 
105 //-------------------------------------------------------------------
106 //
107 //                 ioports.cc
108 //
109 // The ioport infrastructure for gpsim is provided here. The class
110 // taxonomy for the IOPORT class is:
111 //
112 //  file_register
113 //     |-> sfr_register
114 //            |-> IOPORT
115 //                  |-> PORTA
116 //                  |-> PORTB
117 //                  |-> PORTC
118 //                  |-> PORTD
119 //                  |-> PORTE
120 //                  |-> PORTF
121 //
122 // Each I/O port has an associated array of I/O pins which provide an
123 // interface to the virtual external world of the stimuli.
124 //
125 //-------------------------------------------------------------------
126 
127 class SignalSource : public SignalControl
128 {
129 public:
SignalSource(PortRegister * _reg,unsigned int bitPosition)130     SignalSource(PortRegister *_reg, unsigned int bitPosition)
131         : m_register(_reg), m_bitMask(1 << bitPosition)
132     {
133     }
134 
~SignalSource()135     ~SignalSource()
136     {
137     }
release()138     virtual void release()
139     {
140         if (verbose)
141             std::cout << "Releasing  SignalSource 0x" << std::hex << this << '\n';
142     }
143 
getState()144     char getState()
145     {
146         // return m_register ?
147         //  (((m_register->getDriving()&m_bitMask)!=0)?'1':'0') : 'Z';
148         char r = m_register ? (((m_register->getDriving()&m_bitMask) != 0) ? '1' : '0') : 'Z';
149         /**/
150         Dprintf(("SignalSource::getState() %s  bitmask:0x%x state:%c\n",
151                  (m_register?m_register->name().c_str():"NULL"),
152                  m_bitMask,r));
153         /**/
154         return r;
155     }
156 private:
157     PortRegister *m_register;
158     unsigned int  m_bitMask;
159 };
160 
161 
162 //------------------------------------------------------------------------
PortSink(PortRegister * portReg,unsigned int iobit)163 PortSink::PortSink(PortRegister *portReg, unsigned int iobit)
164     : m_PortRegister(portReg), m_iobit(iobit)
165 {
166     assert (m_PortRegister);
167 }
168 
setSinkState(char cNewSinkState)169 void PortSink::setSinkState(char cNewSinkState)
170 {
171     Dprintf((" PortSink::setSinkState:bit=%u,val=%c\n", m_iobit, cNewSinkState));
172 
173     m_PortRegister->setbit(m_iobit,cNewSinkState);
174 }
175 
release()176 void PortSink::release()
177 {
178     delete this;
179 }
180 
181 //------------------------------------------------------------------------
PortRegister(Module * pCpu,const char * pName,const char * pDesc,unsigned int numIopins,unsigned int _mask)182 PortRegister::PortRegister(Module *pCpu, const char *pName, const char *pDesc,
183                            unsigned int numIopins, unsigned int _mask)
184     : sfr_register(pCpu, pName, pDesc),
185       PortModule(numIopins),
186       mEnableMask(_mask),
187       drivingValue(0), rvDrivenValue(0, 0)
188 
189 {
190     mValidBits = (1 << numIopins) - 1; // TODO: why - ugh.
191 }
192 
addPin(Module * mod,IOPIN * iopin,unsigned int iPinNumber)193 IOPIN * PortRegister::addPin(Module *mod, IOPIN *iopin, unsigned int iPinNumber)
194 {
195     mod->addSymbol(iopin);
196     return PortModule::addPin(iopin, iPinNumber);
197 }
198 
addPin(IOPIN * iopin,unsigned int iPinNumber)199 IOPIN * PortRegister::addPin(IOPIN *iopin, unsigned int iPinNumber)
200 {
201     cpu->addSymbol(iopin);
202     return PortModule::addPin(iopin, iPinNumber);
203 }
204 
setEnableMask(unsigned int newEnableMask)205 void PortRegister::setEnableMask(unsigned int newEnableMask)
206 {
207     Dprintf (( "PortRegister::setEnableMask for %s to %02X\n",
208                name_str.c_str(), newEnableMask ));
209     mOutputMask = newEnableMask;
210     //unsigned int maskDiff = getEnableMask() ^ newEnableMask;
211     unsigned int oldEnableMask = getEnableMask();
212 
213     for (unsigned int i = 0, m = 1; i < mNumIopins; i++, m <<= 1)
214     {
215         if ((newEnableMask & m) && ! (oldEnableMask & m ))
216         {
217             PinModule *pmP = PortModule::getIOpins(i);
218             if (!pmP)
219             {
220                 pmP = new PinModule(this, i);
221                 PortModule::addPinModule(pmP, i);
222                 pmP->setDefaultSource(new SignalSource(this, i));
223                 pmP->addSink(new PortSink(this, i));
224             }
225             else
226             {
227                 if (pmP->getSourceState() == '?')
228                 {
229                     pmP->setDefaultSource(new SignalSource(this, i));
230                     pmP->addSink(new PortSink(this, i));
231                 }
232             }
233         }
234     }
235     mEnableMask = newEnableMask;
236 }
237 
put(unsigned int new_value)238 void PortRegister::put(unsigned int new_value)
239 {
240     trace.raw(write_trace.get() | value.data);
241 
242     put_value(new_value);
243 }
244 
put_value(unsigned int new_value)245 void PortRegister::put_value(unsigned int new_value)
246 {
247     Dprintf(("PortRegister::put_value old=0x%x:new=0x%x\n",value.data,new_value));
248 
249     unsigned int diff = mEnableMask & (new_value ^ value.data);
250     drivingValue = new_value & mEnableMask;
251     value.data = drivingValue;
252 
253     if (diff)
254     {
255         // If no stimuli are connected to the Port pins, then the driving
256         // value and the driven value are the same. If there are external
257         // stimuli (or perhaps internal peripherals) overdriving or overriding
258         // this port, then the call to updatePort() will update 'drivenValue'
259         // to its proper value. In either case, calling updatePort ensures
260         // the drivenValue is updated properly
261 
262         updatePort();
263     }
264 }
265 //------------------------------------------------------------------------
266 // PortRegister::updateUI()  UI really means GUI.
267 // We just pass control to the update method, which is defined in gpsimValue.
268 
updateUI()269 void PortRegister::updateUI()
270 {
271     update();
272 }
273 
274 //------------------------------------------------------------------------
275 // PortRegister::setbit
276 //
277 // This method is called whenever a stimulus changes the state of
278 // an I/O pin associated with the port register. 3-state logic is
279 // used.
280 // FIXME -  rvDrivenValue and value are always the same, so why have
281 // FIXME -  both?
282 
setbit(unsigned int bit_number,char new3State)283 void PortRegister::setbit(unsigned int bit_number, char new3State)
284 {
285     int set_mask = (1 << bit_number);
286     if (set_mask & mValidBits)
287     {
288 
289 // The following traces just seem to muddy the water
290 #ifdef RRR
291         trace.raw(write_trace.get()  | value.data);
292         trace.raw(write_trace.geti() | value.init);
293 #endif
294 
295 
296         Dprintf(("PortRegister::setbit() %s bit=%u,val=%c\n",name().c_str(), bit_number,new3State));
297 
298         if (new3State == '1' || new3State == 'W')
299         {
300             rvDrivenValue.data |= (1 << bit_number);
301             rvDrivenValue.init &= ~(1 << bit_number);
302         }
303         else if (new3State == '0' || new3State == 'w')
304         {
305             rvDrivenValue.data &= ~(1 << bit_number);
306             rvDrivenValue.init &= ~(1 << bit_number);
307         }
308         else
309             // Not a 0 or 1, so it must be unknown.
310             rvDrivenValue.init |= (1 << bit_number);
311 
312         value = rvDrivenValue;
313     }
314     else
315     {
316         Dprintf(("PortRegister::::setbit() %s INVALID BIT bit=%u mask=0x%x\n",
317                  name().c_str(), bit_number, mValidBits));
318 
319     }
320 }
321 
get()322 unsigned int PortRegister::get()
323 {
324     trace.raw(read_trace.get()  | rvDrivenValue.data);
325     trace.raw(read_trace.geti() | rvDrivenValue.init);
326 
327     return mOutputMask & rvDrivenValue.data;
328 }
329 
get_value()330 unsigned int PortRegister::get_value()
331 {
332     Dprintf (( "PortRegister::get_value of %s mask=%02X, data=%02X\n",
333                name_str.c_str(), mOutputMask, rvDrivenValue.data ));
334     return mOutputMask & rvDrivenValue.data;
335 }
336 
putDrive(unsigned int new_value)337 void PortRegister::putDrive(unsigned int new_value)
338 {
339     put(new_value);
340 }
341 
getDriving()342 unsigned int PortRegister::getDriving()
343 {
344     return drivingValue;
345 }
346 
347 //========================================================================
348 //========================================================================
349 static PinModule AnInvalidPinModule;
350 
PortModule(unsigned int numIopins)351 PortModule::PortModule(unsigned int numIopins)
352     : mNumIopins(numIopins), mOutputMask(0), iopins(numIopins, &AnInvalidPinModule)
353 {
354 }
355 
~PortModule()356 PortModule::~PortModule()
357 {
358     for (unsigned int i = 0; i < mNumIopins; i++)
359     {
360         if (iopins[i] != &AnInvalidPinModule)
361         {
362             //std::cout << __FUNCTION__ << " deleting pin:"<<i<< ':' <<iopins[i] <<'\n';
363             delete iopins[i];
364         }
365     }
366 }
367 
operator [](unsigned int iPinNumber)368 PinModule &PortModule::operator [] (unsigned int iPinNumber)
369 {
370     if (iPinNumber < mNumIopins)
371         return *iopins[iPinNumber];
372 
373     // error...
374     return AnInvalidPinModule;
375 }
376 
getIOpins(unsigned int iPinNumber)377 PinModule * PortModule::getIOpins(unsigned int iPinNumber)
378 {
379     if (iPinNumber < mNumIopins && iopins[iPinNumber] != &AnInvalidPinModule)
380         return iopins[iPinNumber];
381 
382     // error...
383     return nullptr;
384 }
385 
updatePort()386 void PortModule::updatePort()
387 {
388     for (unsigned int i = 0; i < mNumIopins; i++)
389     {
390         if (iopins[i] != &AnInvalidPinModule)
391             iopins[i]->updatePinModule();
392     }
393 }
394 
updateUI()395 void PortModule::updateUI()
396 {
397     // hmmm nothing
398 }
399 
updatePin(unsigned int iPinNumber)400 void PortModule::updatePin(unsigned int iPinNumber)
401 {
402     if (iPinNumber < mNumIopins)
403         iopins[iPinNumber]->updatePinModule();
404 }
405 
updatePins(unsigned int iPinBitMask)406 void PortModule::updatePins(unsigned int iPinBitMask)
407 {
408     for (unsigned int i = 0, j = 1; i < mNumIopins; i++, j <<= 1)
409         if (j & iPinBitMask && iopins[i])
410             iopins[i]->updatePinModule();
411 }
412 
addSink(SignalSink * new_sink,unsigned int iPinNumber)413 SignalSink *PortModule::addSink(SignalSink *new_sink, unsigned int iPinNumber)
414 {
415     if (iPinNumber < mNumIopins)
416         iopins[iPinNumber]->addSink(new_sink);
417     return new_sink;
418 }
419 
addPin(IOPIN * new_pin,unsigned int iPinNumber)420 IOPIN *PortModule::addPin(IOPIN *new_pin, unsigned int iPinNumber)
421 {
422     if (iPinNumber < mNumIopins)
423     {
424         // If there is not a PinModule for this pin, then add one.
425         if (iopins[iPinNumber] == &AnInvalidPinModule)
426             iopins[iPinNumber] = new PinModule(this, iPinNumber);
427         iopins[iPinNumber]->setPin(new_pin);
428     }
429     else
430     {
431         printf("PortModule::addPin ERROR pin %u > %u\n", iPinNumber, mNumIopins);
432     }
433     return new_pin;
434 }
435 
addPinModule(PinModule * newModule,unsigned int iPinNumber)436 void PortModule::addPinModule(PinModule *newModule, unsigned int iPinNumber)
437 {
438     if (iPinNumber < mNumIopins  && iopins[iPinNumber] == &AnInvalidPinModule)
439         iopins[iPinNumber] = newModule;
440 }
441 
getPin(unsigned int iPinNumber)442 IOPIN *PortModule::getPin(unsigned int iPinNumber)
443 {
444     if (iPinNumber < mNumIopins)
445     {
446         return &iopins[iPinNumber]->getPin();
447     }
448     return nullptr;
449 }
450 
451 //------------------------------------------------------------------------
452 // PinModule
453 
PinModule()454 PinModule::PinModule()
455     : PinMonitor(),
456       m_cLastControlState('?'), m_cLastSinkState('?'),
457       m_cLastSourceState('?'), m_cLastPullupControlState('?'),
458       m_defaultSource(0), m_activeSource(0),
459       m_defaultControl(0), m_activeControl(0),
460       m_defaultPullupControl(0), m_activePullupControl(0),
461       m_pin(0), m_port(0), m_pinNumber(0),
462       m_bForcedUpdate(false)
463 {
464     std::fill_n(m_analog_reg, ANALOG_TABLE_SIZE, nullptr);
465     std::fill_n(m_analog_active, ANALOG_TABLE_SIZE, false);
466 }
467 
PinModule(PortModule * _port,unsigned int _pinNumber,IOPIN * _pin)468 PinModule::PinModule(PortModule *_port, unsigned int _pinNumber, IOPIN *_pin)
469     : PinMonitor(),
470       m_cLastControlState('?'), m_cLastSinkState('?'),
471       m_cLastSourceState('?'), m_cLastPullupControlState('?'),
472       m_defaultSource(0), m_activeSource(0),
473       m_defaultControl(0), m_activeControl(0),
474       m_defaultPullupControl(0), m_activePullupControl(0),
475       m_pin(_pin), m_port(_port), m_pinNumber(_pinNumber),
476       m_bForcedUpdate(false)
477 {
478     setPin(m_pin);
479     std::fill_n(m_analog_reg, ANALOG_TABLE_SIZE, nullptr);
480     std::fill_n(m_analog_active, ANALOG_TABLE_SIZE, false);
481 }
482 
~PinModule()483 PinModule::~PinModule()
484 {
485     if (m_pin && (m_activeSource != m_defaultSource))
486         D2printf(("Pin %s sources active %p default %p\n", m_pin->name().c_str(), m_activeSource, m_defaultSource));
487     if (m_activeSource && (m_activeSource != m_defaultSource))
488     {
489         //cout << __FUNCTION__ << " deleting active source:"<<m_activeSource<<endl;
490         //cout << "    state:" <<m_activeSource->getState() <<endl;
491         m_activeSource->release();
492         //RRR m_activeSource = m_defaultSource;
493         m_activeSource = 0;
494     }
495     if (m_defaultSource)
496     {
497         m_defaultSource->release();
498         delete m_defaultSource;
499         m_defaultSource = 0;
500     }
501 
502     if (m_activeControl && (m_activeControl != m_defaultControl))
503     {
504         m_activeControl->release();
505         m_activeControl = m_defaultControl;
506     }
507 
508     if (m_defaultControl)
509     {
510         m_defaultControl->release();
511         m_defaultControl = 0;
512     }
513 
514     if (m_activePullupControl && (m_activePullupControl != m_defaultPullupControl))
515         m_activePullupControl->release();
516     if (m_defaultPullupControl)
517         m_defaultPullupControl->release();
518 
519     if (m_pin)
520         m_pin->setMonitor(0);
521 }
522 
setPin(IOPIN * new_pin)523 void PinModule::setPin(IOPIN *new_pin)
524 {
525     // Replace our pin only if this one is valid and we don't have one already.
526     if (!m_pin && new_pin)
527     {
528         m_pin = new_pin;
529         m_pin->setMonitor(this);
530         m_cLastControlState = getControlState();
531         m_cLastSourceState = getSourceState();
532     }
533 
534 }
535 
refreshPinOnUpdate(bool bForcedUpdate)536 void PinModule::refreshPinOnUpdate(bool bForcedUpdate)
537 {
538     m_bForcedUpdate = bForcedUpdate;
539 }
540 
updatePinModule()541 void PinModule::updatePinModule()
542 {
543     if (!m_pin)
544         return;
545 
546     bool bStateChange=m_bForcedUpdate;
547 
548     Dprintf(("PinModule::updatePinModule():%s enter cont=%c,source=%c,pullup%c\n",
549              (m_pin ? m_pin->name().c_str() : "NOPIN"),
550              m_cLastControlState,m_cLastSourceState,m_cLastPullupControlState));
551 
552     char cCurrentControlState = getControlState();
553     unsigned int old_dir = m_pin->get_direction();
554     unsigned int new_dir = (cCurrentControlState == '1') ? IOPIN::DIR_INPUT :
555                            IOPIN::DIR_OUTPUT;
556 
557 
558     if (new_dir != old_dir)
559     {
560         m_cLastControlState = cCurrentControlState;
561         m_pin->update_direction(new_dir, false);
562         bStateChange = true;
563     }
564 
565     char cCurrentSourceState = getSourceState();
566 
567     if (cCurrentSourceState != m_cLastSourceState)
568     {
569         m_cLastSourceState = cCurrentSourceState;
570         m_pin->setDrivingState(cCurrentSourceState);
571         bStateChange = true;
572     }
573 
574     char cCurrentPullupControlState = getPullupControlState();
575 
576     if (cCurrentPullupControlState != m_cLastPullupControlState)
577     {
578         m_cLastPullupControlState = cCurrentPullupControlState;
579         m_pin->update_pullup(m_cLastPullupControlState,false);
580         bStateChange = true;
581     }
582 
583     if (bStateChange)
584     {
585 
586         Dprintf(("PinModule::updatePinModule() exit cont=%c,source=%c,pullup%c\n",
587                  m_cLastControlState,m_cLastSourceState,
588                  m_cLastPullupControlState));
589 
590         if (m_pin->snode)
591             m_pin->snode->update();
592         else
593             setDrivenState(cCurrentSourceState);
594     }
595 
596 }
597 
setDefaultControl(SignalControl * newDefaultControl)598 void PinModule::setDefaultControl(SignalControl *newDefaultControl)
599 {
600     if (!m_defaultControl && newDefaultControl)
601     {
602         m_defaultControl = newDefaultControl;
603         setControl(m_defaultControl);
604     }
605     else
606         delete newDefaultControl;   //// TODO: YIKES!!! -- wouldn't it be better to return an error code?
607 }
608 
setControl(SignalControl * newControl)609 void PinModule::setControl(SignalControl *newControl)
610 {
611     m_activeControl = newControl ? newControl : m_defaultControl;
612 }
613 
setDefaultSource(SignalControl * newDefaultSource)614 void PinModule::setDefaultSource(SignalControl *newDefaultSource)
615 {
616     if (!m_defaultSource && newDefaultSource)
617     {
618         m_defaultSource = newDefaultSource;
619         setSource(m_defaultSource);
620     }
621 }
setSource(SignalControl * newSource)622 void PinModule::setSource(SignalControl *newSource)
623 {
624     D2printf(("setSource  new %p old %p default %p\n", newSource, m_activeSource, m_defaultSource));
625     if (m_activeSource && newSource != m_activeSource)
626         m_activeSource->release();
627     m_activeSource = newSource ? newSource : m_defaultSource;
628 }
629 
setDefaultPullupControl(SignalControl * newDefaultPullupControl)630 void PinModule::setDefaultPullupControl(SignalControl *newDefaultPullupControl)
631 {
632     if (!m_defaultPullupControl && newDefaultPullupControl)
633     {
634         m_defaultPullupControl = newDefaultPullupControl;
635         setPullupControl(m_defaultPullupControl);
636     }
637 }
638 
setPullupControl(SignalControl * newPullupControl)639 void PinModule::setPullupControl(SignalControl *newPullupControl)
640 {
641     m_activePullupControl = newPullupControl ? newPullupControl : m_defaultPullupControl;
642 }
643 
getControlState()644 char PinModule::getControlState()
645 {
646     return m_activeControl ? m_activeControl->getState() : '?';
647 }
648 
getSourceState()649 char PinModule::getSourceState()
650 {
651     return m_activeSource ? m_activeSource->getState() : '?';
652 }
653 
getPullupControlState()654 char PinModule::getPullupControlState()
655 {
656     return m_activePullupControl ? m_activePullupControl->getState() : '?';
657 }
658 
setDrivenState(char new3State)659 void PinModule::setDrivenState(char new3State)
660 {
661     m_cLastSinkState = new3State;
662 
663     std::list<SignalSink *>::iterator ssi;
664     for (ssi = sinks.begin(); ssi != sinks.end(); ++ssi)
665         (*ssi)->setSinkState(new3State);
666 }
667 
setDrivingState(char)668 void PinModule::setDrivingState(char)
669 {
670     //printf("PinModule::%s -- does nothing\n",__FUNCTION__);
671 }
672 
set_nodeVoltage(double)673 void PinModule::set_nodeVoltage(double)
674 {
675     //printf("PinModule::%s -- does nothing\n",__FUNCTION__);
676 }
677 
putState(char)678 void PinModule::putState(char)
679 {
680     //printf("PinModule::%s -- does nothing\n",__FUNCTION__);
681 }
682 
setDirection()683 void PinModule::setDirection()
684 {
685     //printf("PinModule::%s -- does nothing\n",__FUNCTION__);
686 }
687 
updateUI()688 void PinModule::updateUI()
689 {
690     m_port->updateUI();
691 }
692 
693 //	AnalogReq is called by modules such as ADC and Comparator
694 //	to set or release a pin to/from analog mode. When a pin is in
695 //	analog mode the TRIS register is still active and output pins
696 //	are still driven high or low, but reads of the port register
697 //	return 0 for the pin. When a pin mode is changes the breadboard
698 //	name of the pin is changed to newname.
699 //
700 //	A table of each calling module is kept as a module may
701 //	request analog mode after another has. The pin is put in
702 //	analog mode when the first module requests it (up=true)
703 //	and is taken out of analog mode when all modules have
704 //	requested analog mode to be released (up=false);
705 //
AnalogReq(Register * reg,bool analog,const char * newname)706 void PinModule::AnalogReq(Register * reg, bool analog, const char *newname)
707 {
708     int i, index;
709     unsigned int total_cnt = 0;
710 
711     if (!m_port) return;
712 
713     // is the calling register in the table and what is the current
714     // count of modules requesting analog mode
715 
716     for (i = 0, index = -1; i < ANALOG_TABLE_SIZE && m_analog_reg[i]; i++)
717     {
718         if (m_analog_reg[i] == reg)
719             index = i;
720         if (m_analog_active[i])
721             total_cnt++;
722     }
723 
724     // Register is not in table so add it.
725     //
726     if (index < 0)
727     {
728         assert(i < ANALOG_TABLE_SIZE); // table not large enough
729         index = i;
730         m_analog_reg[index] = reg;
731         m_analog_active[index] = false;
732     }
733 
734     if (analog)	  // Set pin to analog mode request
735     {
736         m_analog_active[index] = true;
737         if (total_cnt == 0)
738         {
739             unsigned int mask = m_port->getOutputMask();
740             mask &= ~(1 << getPinNumber());
741             m_port->setOutputMask(mask);
742             Dprintf(("PinModule::UpAnalogCnt up %s  newname=%s mask=%x\n", getPin().name().c_str(), newname, mask));
743             getPin().newGUIname(newname);
744             getPin().set_is_analog(true);
745             getPin().set_Cth(5e-12);		// add analog pin input capacitance
746         }
747     }
748     else if (!analog && m_analog_active[index])      // release register request
749     {
750         // for analog pin
751         m_analog_active[index] = false;
752         if (total_cnt == 1)
753         {
754             unsigned int mask = m_port->getOutputMask();
755             mask |= (1 << getPinNumber());
756             Dprintf(("PinModule::UpAnalogCnt down %s  newname=%s mask=%x\n", getPin().name().c_str(), newname, mask));
757             m_port->setOutputMask(mask);
758             const char *pt = strchr(newname, '.');
759             getPin().newGUIname(pt ? pt + 1 : newname);
760             getPin().set_is_analog(false);
761             getPin().set_Cth(0.0);
762         }
763     }
764 }
765 
766 
767 // Alternate Pin function
APFCON(Processor * pCpu,const char * pName,const char * pDesc,unsigned int _mask)768 APFCON::APFCON(Processor *pCpu, const char *pName, const char *pDesc, unsigned int _mask)
769     : sfr_register(pCpu,pName,pDesc),
770       mValidBits(_mask)
771 {
772     for (int j = 0; j < 8; j++)
773     {
774         dispatch[j].pt_apfpin = 0;
775     }
776 }
777 
set_pins(unsigned int bit,class apfpin * pt_apfpin,int arg,PinModule * pin_default,PinModule * pin_alt)778 void APFCON::set_pins(unsigned int bit, class apfpin *pt_apfpin, int arg,
779                       PinModule *pin_default, PinModule *pin_alt)
780 {
781     dispatch[bit].pt_apfpin = pt_apfpin;
782     dispatch[bit].arg = arg;
783     dispatch[bit].pin_default = pin_default;
784     dispatch[bit].pin_alt = pin_alt;
785 }
786 
put(unsigned int new_value)787 void APFCON::put(unsigned int new_value)
788 {
789     unsigned int old_value = value.get();
790     unsigned int diff = (new_value ^ old_value) & mValidBits;
791 
792     trace.raw(write_trace.get() | value.get());
793     new_value &= mValidBits;
794     value.put(new_value);
795 
796     for (int i = 0; i < 8; i++)
797     {
798         unsigned int bit = 1 << i;
799         if (diff & bit)
800         {
801             assert(dispatch[i].pt_apfpin);
802             dispatch[i].pt_apfpin->setIOpin((bit & new_value) ? dispatch[i].pin_alt : dispatch[i].pin_default, dispatch[i].arg);
803         }
804     }
805 }
806 
807 // catch changes in pin input
808 class INTsignalSink : public SignalSink
809 {
810 public:
INTsignalSink(INT_pin * _int)811     explicit INTsignalSink(INT_pin *_int)
812         : m_int(_int)
813     {}
814 
setSinkState(char new3State)815     virtual void setSinkState(char new3State) { m_int->setState(new3State); }
release()816     virtual void release() {delete this; }
817 private:
818     INT_pin *m_int;
819 };
820 
INT_pin(Processor * pCpu,INTCON * _intcon,int _intedg_index)821 INT_pin::INT_pin(Processor *pCpu, INTCON *_intcon,  int _intedg_index) : p_cpu(pCpu),
822     p_intcon(_intcon), intedg_index(_intedg_index),
823     m_PinModule(nullptr), m_sink(nullptr), OldState(false)
824 {}
825 
setIOpin(PinModule * pinmod,int _arg)826 void INT_pin::setIOpin(PinModule * pinmod, int _arg)
827 {
828     Dprintf(("call INT_pin::setIOpin %s pin=%p %s arg=%d\n", p_cpu->name().c_str(), pinmod, pinmod ? pinmod->getPin().name().c_str():"unknown", _arg));
829 
830     if (m_PinModule != pinmod)
831     {
832         if (!m_sink) m_sink = new INTsignalSink(this);
833         if (m_PinModule)	//change of pin assignment
834             m_PinModule->removeSink(m_sink);
835         m_PinModule = pinmod;
836         m_PinModule->addSink(m_sink);
837     }
838 }
839 
setState(char new3state)840 void INT_pin::setState(char new3state)
841 {
842     // if true trigger on rising edge
843     bool level = p_cpu->get_intedgx(intedg_index);
844     bool bNewValue = new3state == '1' || new3state == 'W';
845     if (new3state == 'Z')
846         return;
847 
848     if ( (bNewValue ^ OldState) && (bNewValue == level))
849     {
850         Dprintf(("INT_pin::setState cpu=%s new3state=%c trig +edge=%d INTE=%d\n", p_cpu->name().c_str(), new3state, level, (bool)(p_intcon->get() & INTCON::INTE)));
851         if (p_intcon->get() & INTCON::INTE)
852         {
853             p_cpu->exit_sleep();
854         }
855         p_intcon->set_intf(true);
856     }
857     OldState = bNewValue;
858 }
859