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