1 /*
2 
3    Copyright (C) 1998 T. Scott Dattalo
4    Copyright (C) 2006,2010,2013,2015 Roy R. Rankin
5 
6 This file is part of the libgpsim library of gpsim
7 
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12 
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 Lesser General Public License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, see
20 <http://www.gnu.org/licenses/lgpl-2.1.html>.
21 */
22 
23 
24 #include <iostream>
25 #include <cstdio>
26 
27 #include <assert.h>
28 #include <math.h>
29 #include <stdio.h>
30 #include <string.h>
31 
32 #include "14bit-tmrs.h"
33 #include "trace.h"
34 #include "processor.h"
35 #include "stimuli.h"
36 #include "comparator.h"
37 #include "a2d_v2.h"
38 #include "ctmu.h"
39 #include "clc.h"
40 #include "cwg.h"
41 #include "ui.h"
42 #include "ioports.h"
43 #include "modules.h"
44 
45 //#define DEBUG
46 #if defined(DEBUG)
47 #include "../config.h"
48 #define Dprintf(arg) {printf("%s:%d ",__FILE__,__LINE__); printf arg; }
49 #else
50 #define Dprintf(arg) {}
51 #endif
52 
53 
ComparatorModule(Processor * pCpu)54 ComparatorModule::ComparatorModule(Processor *pCpu)
55     : cmcon(pCpu, "cmcon", "Comparator Module Control"),
56       cmcon1(pCpu, "cmcon1", "Comparator Configure Register"),
57       vrcon(pCpu, "vrcon", "Voltage Reference Control")
58 {
59 }
60 
61 
initialize(PIR_SET * pir_set,PinModule * pin_vr0,PinModule * pin_cm0,PinModule * pin_cm1,PinModule * pin_cm2,PinModule * pin_cm3,PinModule * pin_cm4,PinModule * pin_cm5)62 void ComparatorModule::initialize(PIR_SET *pir_set,
63                                   PinModule *pin_vr0, PinModule *pin_cm0,
64                                   PinModule *pin_cm1, PinModule *pin_cm2, PinModule *pin_cm3,
65                                   PinModule *pin_cm4, PinModule *pin_cm5)
66 {
67     //  cmcon = new CMCON;
68     cmcon.assign_pir_set(pir_set);
69     cmcon.setINpin(0, pin_cm0, "an0");
70     cmcon.setINpin(1, pin_cm1, "an1");
71     cmcon.setINpin(2, pin_cm2, "an2");
72     cmcon.setINpin(3, pin_cm3, "an3");
73     cmcon.setIOpin(pin_cm4, 0);
74     cmcon.setIOpin(pin_cm5, 1);
75     vrcon.setIOpin(pin_vr0);
76     cmcon._vrcon = &vrcon;
77     vrcon._cmcon = &cmcon;
78 }
79 
80 
81 //--------------------------------------------------
82 //
83 //--------------------------------------------------
84 class CMSignalSource : public SignalControl
85 {
86 public:
CMSignalSource(CMCON * _cmcon,int _index)87     CMSignalSource(CMCON *_cmcon, int _index)
88         : m_state('0'), m_cmcon(_cmcon), index(_index)
89     {
90     }
~CMSignalSource()91     ~CMSignalSource()
92     {
93         //    cout << "deleting CMsignal source " << this << endl;
94     }
95 
release()96     virtual void release()
97     {
98         m_cmcon->releasePin(index);
99     }
getState()100     virtual char getState()
101     {
102         return m_state;
103     }
putState(bool new_val)104     void putState(bool new_val)
105     {
106         m_state = new_val ? '1' : '0';
107     }
108 
109 private:
110     char m_state;
111     CMCON *m_cmcon;
112     int  index;
113 };
114 
115 
116 //--------------------------------------------------
117 //
118 //--------------------------------------------------
119 class CMxSignalSource : public PeripheralSignalSource
120 {
121 public:
CMxSignalSource(PinModule * _pin,CMxCON0_base * _cmcon)122     CMxSignalSource(PinModule *_pin, CMxCON0_base *_cmcon)
123         : PeripheralSignalSource(_pin),  m_cmcon(_cmcon)
124     {
125     }
~CMxSignalSource()126     ~CMxSignalSource()
127     {
128         //    cout << "deleting CMsignal source " << this << endl;
129     }
130 
release()131     virtual void release()
132     {
133         m_cmcon->releasePin();
134     }
135 
136 private:
137     CMxCON0_base *m_cmcon;
138 };
139 
140 
141 //--------------------------------------------------
142 //
143 //--------------------------------------------------
144 
CM_stimulus(CMCON * arg,const char * cPname,double _Vth,double _Zth)145 CM_stimulus::CM_stimulus(CMCON * arg, const char *cPname, double _Vth, double _Zth)
146     : stimulus(cPname, _Vth, _Zth), _cmcon(arg)
147 {
148 }
149 
150 
~CM_stimulus()151 CM_stimulus::~CM_stimulus()
152 {
153 }
154 
155 
set_nodeVoltage(double v)156 void   CM_stimulus::set_nodeVoltage(double v)
157 {
158     if (nodeVoltage != v)
159     {
160         nodeVoltage = v;
161         Dprintf(("set_nodeVoltage %s _cmcon %p %s v=%.2f\n", name().c_str(), _cmcon, _cmcon->name().c_str(), v));
162         _cmcon->get();  // recalculate comparator values
163     }
164 }
165 
166 
167 /*
168     Setup the configuration for the comparators. Must be called
169     for each comparator and each mode(CN2:CM0) that can be used.
170         il1 = input Vin- when CIS == 0
171         ih1 = input Vin+ when CIS == 0
172         il2 = input Vin- when CIS == 1
173         ih2 = input Vin+ when CIS == 1
174 
175         if input == VREF, reference voltage is used.
176 */
177 
set_configuration(int comp,int mode,int il1,int ih1,int il2,int ih2,int out)178 void CMCON::set_configuration(int comp, int mode, int il1, int ih1, int il2,
179                               int ih2, int out)
180 {
181     if (comp > cMaxComparators || comp < 1)
182     {
183         std::cout << "CMCON::set_configuration comp=" << comp << " out of range\n";
184         return;
185     }
186 
187     if (mode > cMaxConfigurations)
188     {
189         std::cout << "CMCON::set_configuration mode too large\n";
190         return;
191     }
192 
193     m_configuration_bits[comp - 1][mode] = (il1 << CFG_SHIFT * 4) |
194                                            (ih1 << CFG_SHIFT * 3) |
195                                            (il2 << CFG_SHIFT * 2) | (ih2 << CFG_SHIFT) | out;
196 }
197 
198 
199 //------------------------------------------------------------------------
CMCON(Processor * pCpu,const char * pName,const char * pDesc)200 CMCON::CMCON(Processor *pCpu, const char *pName, const char *pDesc)
201     : sfr_register(pCpu, pName, pDesc)
202 {
203     value.put(0);
204     cm_input[0] = cm_input[1] = cm_input[2] = cm_input[3] = nullptr;
205     cm_output[0] = cm_output[1] = nullptr;
206     cm_source[0] = cm_source[1] = nullptr;
207     cm_stimulus[0] = cm_stimulus[1] = cm_stimulus[2] = cm_stimulus[3] = nullptr;
208     cm_source_active[0] = cm_source_active[1] = false;
209     m_CMval[0] = m_CMval[1] = 0;
210 }
211 
212 
~CMCON()213 CMCON::~CMCON()
214 {
215     unsigned int mode = value.get() & 0x07;
216 
217     for (int i = 0; i < 2; i++)
218     {
219         if (cm_source[i])
220         {
221             int cfg = m_configuration_bits[i][mode] & CFG_MASK;
222 
223             // Our Source active so port still defined if cm_output defined,
224             // set default source.
225             if (cfg == i && cm_output[i] && cm_source_active[i])
226             {
227                 cm_output[i]->setSource(0);
228             }
229 
230             delete cm_source[i];
231         }
232     }
233 
234     for (int i = 0; i < 4; i++)
235     {
236         delete cm_stimulus[i];
237     }
238 }
239 
240 
releasePin(int i)241 void CMCON::releasePin(int i)
242 {
243     cm_source_active[i] = false;
244 }
245 
246 
setINpin(int i,PinModule * newPinModule,const char * an)247 void CMCON::setINpin(int i, PinModule *newPinModule, const char *an)
248 {
249     if (newPinModule == nullptr)
250     {
251         return;
252     }
253 
254     cm_input[i] = newPinModule;
255     cm_input_pin[i] = newPinModule->getPin().name();
256     cm_an[i] = an;
257 }
258 
259 
setIOpin(PinModule * newPinModule,int i)260 void CMCON::setIOpin(PinModule *newPinModule, int i)
261 {
262     if (newPinModule == nullptr)
263     {
264         return;
265     }
266 
267     cm_output[i] = newPinModule;
268     cm_output_pin[i] = newPinModule->getPin().name();
269 }
270 
271 
assign_pir_set(PIR_SET * new_pir_set)272 void CMCON::assign_pir_set(PIR_SET *new_pir_set)
273 {
274     pir_set = new_pir_set;
275 }
276 
277 
comp_voltage(int ind,int invert)278 double CMCON::comp_voltage(int ind, int invert)
279 {
280     double Voltage;
281     const char *name;
282 
283     switch (ind)
284     {
285     case V06:
286         Voltage = 0.6;
287         name = "V0.6";
288         break;
289 
290     case VREF:
291         Voltage = _vrcon->get_Vref();
292         name = "Vref";
293         break;
294 
295     case NO_IN:
296         Voltage = invert ? cpu->get_Vdd() : 0.0;
297         name = "No_IN";
298         break;
299 
300     default:
301         Voltage = cm_input[ind]->getPin().get_nodeVoltage();
302         name = cm_input[ind]->getPin().name().c_str();
303         break;
304     }
305     if (name)	// this is just to avoid a compiler warning
306     {
307         Dprintf(("CMCON::comp_voltage %s ind=%d IN%c %.2f %s\n", name, ind, invert?'-':'+', Voltage, name));
308     }
309     return Voltage;
310 }
311 
312 
313 /*
314 **      get()
315 **              read the comparator inputs and set C2OUT and C1OUT
316 **              as required. Also drive output pins if required.
317 */
get()318 unsigned int CMCON::get()
319 {
320     unsigned int cmcon_val = value.get();
321     int mode = cmcon_val & 0x07;
322     int i;
323 
324     for (i = 0; i < 2; i++)
325     {
326         int invert_bit = (i == 0) ? C1INV : C2INV;
327         int output_bit = (i == 0) ? C1OUT : C2OUT;
328         int shift = (cmcon_val & CIS) ? CFG_SHIFT : CFG_SHIFT * 3;
329 
330         if ((m_configuration_bits[i][mode] & CFG_MASK) != ZERO)
331         {
332             bool out_true;
333             int out;
334             double Vhigh = comp_voltage(
335                                (m_configuration_bits[i][mode] >> shift) & CFG_MASK,
336                                cmcon_val & invert_bit);
337             double Vlow = comp_voltage(
338                               (m_configuration_bits[i][mode] >> (shift + CFG_SHIFT)) & CFG_MASK,
339                               (cmcon_val & invert_bit) == 0);
340 
341             if (Vhigh > Vlow)
342             {
343                 out_true = (cmcon_val & invert_bit) ? false : true;
344 
345             }
346             else
347             {
348                 out_true = (cmcon_val & invert_bit) ? true : false;
349             }
350 
351             if (out_true)
352             {
353                 cmcon_val |= output_bit;
354 
355             }
356             else
357             {
358                 cmcon_val &= ~output_bit;
359             }
360 
361             if ((out = m_configuration_bits[i][mode] & CFG_MASK) < 2)
362             {
363                 cm_source[out]->putState(out_true);
364                 cm_output[out]->updatePinModule();
365                 update();
366             }
367 
368         }
369         else                    // Don't care about inputs, register value 0
370         {
371             cmcon_val &= ~output_bit;
372         }
373     }
374 
375     if (value.get() ^ cmcon_val)   // change of state
376     {
377         int diff = value.get() ^ cmcon_val;
378 
379         // Signal ECCPAS ?
380         if (m_eccpas)
381         {
382             if (diff & C1OUT)
383             {
384                 m_eccpas->c1_output(cmcon_val & C1OUT);
385             }
386 
387             if (diff & C2OUT)
388             {
389                 m_eccpas->c2_output(cmcon_val & C2OUT);
390             }
391         }
392 
393         // Generate interupt ?
394         if (pir_set)
395         {
396             if (diff & C1OUT)
397             {
398                 pir_set->set_c1if();
399             }
400 
401             if (diff & C2OUT)
402             {
403                 pir_set->set_c2if();
404             }
405         }
406     }
407 
408     if (m_tmrl)
409     {
410         m_tmrl->compare_gate((cmcon_val & C1OUT) == C1OUT);
411     }
412 
413     value.put(cmcon_val);
414     return cmcon_val;
415 }
416 
417 
put(unsigned int new_value)418 void CMCON::put(unsigned int new_value)
419 {
420     unsigned int mode = new_value & 0x7;
421     unsigned int in_mask = 0;
422     unsigned int out_mask = 0;
423     int i;
424 
425     if (verbose)
426     {
427         std::cout << "CMCON::put(new_value) =" << std::hex << new_value << '\n';
428     }
429 
430     trace.raw(write_trace.get() | value.get());
431 
432     // Determine used input and output pins
433     for (i = 0; i < 2; i++)
434     {
435         unsigned int configuration = m_configuration_bits[i][mode];
436 
437         if ((configuration & CFG_MASK) < 2)
438         {
439             out_mask |= (1 << (configuration & CFG_MASK));
440         }
441 
442         for (int j = 0; j < 4; j++)
443         {
444             configuration >>= CFG_SHIFT;
445 
446             if ((configuration & CFG_MASK) < 6)
447             {
448                 in_mask |= (1 << (configuration & CFG_MASK));
449             }
450         }
451     }
452 
453     if (verbose)
454     {
455         std::cout << "CMCON::put in_mask=" << in_mask << " out_mask=" << out_mask << '\n';
456     }
457 
458     if ((mode != 0) && (mode != 7) && ! cm_stimulus[0])   // initialize stimulus
459     {
460         cm_stimulus[0] = new CM_stimulus(this, "cm_stimulus_1", 0, 1e12);
461         cm_stimulus[1] = new CM_stimulus(this, "cm_stimulus_2", 0, 1e12);
462         cm_stimulus[2] = new CM_stimulus(this, "cm_stimulus_3", 0, 1e12);
463         cm_stimulus[3] = new CM_stimulus(this, "cm_stimulus_4", 0, 1e12);
464     }
465 
466     //
467     // setup outputs
468     //
469     for (i = 0; i < 2 && cm_output[i]; i++)
470     {
471         if (out_mask & (1 << i))
472         {
473             char name[20];
474 
475             if (! cm_source[i])
476             {
477                 cm_source[i] = new CMSignalSource(this, i);
478             }
479 
480             snprintf(name, sizeof(name), "c%dout", i + 1);
481             cm_output[i]->getPin().newGUIname(name);
482             cm_output[i]->setSource(cm_source[i]);
483             cm_source_active[i] = true;
484 
485         }
486         else if (cm_source_active[i])
487         {
488             cm_output[i]->getPin().newGUIname(cm_output[i]->getPin().name().c_str());
489             cm_output[i]->setSource(0);
490         }
491     }
492 
493     //
494     // setup inputs
495     for (i = 0; i < 4 ; i++)
496     {
497         if (cm_input[i])
498         {
499             const char *name = cm_input[i]->getPin().GUIname().c_str();
500 
501             if (cm_input[i]->getPin().snode)
502             {
503                 if (in_mask & (1 << i))
504                 {
505                     (cm_input[i]->getPin().snode)->attach_stimulus(cm_stimulus[i]);
506 
507                 }
508                 else
509                 {
510                     (cm_input[i]->getPin().snode)->detach_stimulus(cm_stimulus[i]);
511                 }
512             }
513 
514             // rewrite GUI name as required
515             if (in_mask & (1 << i))
516             {
517                 cm_input[i]->AnalogReq(this, true, cm_an[i].c_str());
518 
519             }
520             else
521             {
522                 if (!strncmp(name, "an", 2))
523                 {
524                     cm_input[i]->AnalogReq(this, false, cm_input[i]->getPin().name().c_str());
525                 }
526             }
527         }
528     }
529 
530     // if only one comparator,  mask C2INV
531     if (!cm_output[1])
532     {
533         new_value &= 0x1f;
534     }
535 
536     value.put(new_value);
537 
538     if (verbose)
539     {
540         std::cout << "CMCON::put() val=0x" << std::hex << new_value << '\n';
541     }
542 
543     get();        // update comparator values
544 }
545 
546 
547 //------------------------------------------------------------------------
CMCON1(Processor * pCpu,const char * pName,const char * pDesc)548 CMCON1::CMCON1(Processor *pCpu, const char *pName, const char *pDesc)
549     : sfr_register(pCpu, pName, pDesc), valid_bits(0x3)
550 {
551 }
552 
553 
~CMCON1()554 CMCON1::~CMCON1()
555 {
556 }
557 
558 
put(unsigned int new_value)559 void CMCON1::put(unsigned int new_value)
560 {
561     if (verbose)
562     {
563         std::cout << "CMCON1::put(new_value) =" << std::hex << new_value << '\n';
564     }
565 
566     assert(m_tmrl);
567     m_tmrl->set_T1GSS(new_value & T1GSS);
568     trace.raw(write_trace.get() | value.get());
569     value.put(new_value & valid_bits);
570 }
571 
572 
573 //------------------------------------------------------------------------
SRCON(Processor * pCpu,const char * pName,const char * pDesc)574 SRCON::SRCON(Processor *pCpu, const char *pName, const char *pDesc)
575     : sfr_register(pCpu, pName, pDesc), set(false), reset(false)
576 {
577     writable_bits = SR1 | SR0 | C1SEN | C2REN | FVREN;
578     SR_Q = false;
579 }
580 
581 
put(unsigned int new_value)582 void SRCON::put(unsigned int new_value)
583 {
584     // PULSR and PULSS should be only settable using bsf
585     // it is not clear if these bits read anything other than 0,
586     // but this is what I am assuming RRR
587     if (new_value & PULSR)
588     {
589         SR_Q = false;
590 
591     }
592     else if (new_value & PULSS && ! reset)
593     {
594         SR_Q = true;
595     }
596 
597     trace.raw(write_trace.get() | value.get());
598     value.put(new_value & writable_bits);
599 }
600 
601 
CMxCON0_base(Processor * pCpu,const char * pName,const char * pDesc,unsigned int _cm,ComparatorModule2 * cmModule)602 CMxCON0_base::CMxCON0_base(Processor *pCpu, const char *pName,
603                            const char *pDesc, unsigned int _cm, ComparatorModule2 *cmModule)
604     : sfr_register(pCpu, pName, pDesc), cm(_cm), m_cmModule(cmModule)
605 {
606     value.put(0);
607     cm_input[0] = cm_input[1] = cm_input[2] = cm_input[3] = cm_input[4] = nullptr;
608     cm_stimulus[0] = cm_stimulus[1] = nullptr;
609     cm_snode[0] = cm_snode[1] = nullptr;
610 }
611 
612 
~CMxCON0_base()613 CMxCON0_base::~CMxCON0_base()
614 {
615     if (cm_source_active && cm_output)
616     {
617         cm_output->setSource(0);
618     }
619 
620     delete cm_source;
621 
622     if ((!cm_snode[0]) && cm_stimulus[0])
623     {
624         delete cm_stimulus[0];
625     }
626 
627     if ((!cm_snode[1]) && cm_stimulus[1])
628     {
629         delete cm_stimulus[1];
630     }
631 
632     delete IntSrc;
633 }
634 
635 
636 //
637 // evaluate inputs and determine output
638 //
get()639 unsigned int CMxCON0_base::get()
640 {
641     bool output;
642 
643     if (! is_on())
644     {
645         // need to test what happens in a real device RRR
646         //output = out_invert()?true:false;
647         output = false;
648 
649     }
650     else
651     {
652         double Vpos = get_Vpos();
653         double Vneg = get_Vneg();
654         output = output_high();
655 
656         if (fabs(Vpos - Vneg) > get_hysteresis())
657         {
658             output = Vpos > Vneg;
659 
660             if (out_invert())
661             {
662                 output = !output;
663             }
664         }
665 
666         Dprintf(("%s ON Vpos %.2f Vneg %.2f output %d invert %d\n", name().c_str(), Vpos, Vneg, output, out_invert()));
667     }
668 
669     set_output(output);
670     return value.get();
671 }
672 
673 
674 //--------------------------------------------------
675 //      Voltage reference
676 //--------------------------------------------------
677 
VRCON(Processor * pCpu,const char * pName,const char * pDesc)678 VRCON::VRCON(Processor *pCpu, const char *pName, const char *pDesc)
679     : sfr_register(pCpu, pName, pDesc)
680 {
681     valid_bits = VR0 | VR1 | VR2 | VR3 | VRR | VROE | VREN;
682     value.put(0);
683 }
684 
685 
~VRCON()686 VRCON::~VRCON()
687 {
688 }
689 
690 
setIOpin(PinModule * newPinModule)691 void VRCON::setIOpin(PinModule *newPinModule)
692 {
693     if (newPinModule == nullptr)
694     {
695         return;
696     }
697 
698     vr_PinModule = newPinModule;
699     pin_name = newPinModule->getPin().name();
700 }
701 
702 
get_Vref()703 double VRCON::get_Vref()
704 {
705     unsigned int new_value = value.get();
706     Vref_high = ((Processor *)cpu)->get_Vdd();
707     Vref_low = 0.0;
708     vr_Rhigh = (8 + (16 - (new_value & 0x0f))) * 2000.0;
709     vr_Rlow = (new_value & 0x0f) * 2000.0;
710 
711     if (!(new_value & VRR))         // High range ?
712     {
713         vr_Rlow += 16000.0;
714     }
715 
716     vr_Vref = (Vref_high - Vref_low) * vr_Rlow / (vr_Rhigh + vr_Rlow) + Vref_low;
717 
718     if (verbose)
719     {
720         std::cout << "VRCON::put Rhigh=" << vr_Rhigh << " Rlow=" << vr_Rlow
721                   << " Vout=" << vr_Vref << '\n';
722     }
723 
724     return vr_Vref;
725 }
726 
727 
put(unsigned int new_value)728 void VRCON::put(unsigned int new_value)
729 {
730     new_value &= valid_bits;
731     unsigned int old_value = value.get();
732     unsigned int diff = new_value ^ old_value;
733     trace.raw(write_trace.get() | value.get());
734 
735     if (verbose & 2)
736     {
737         std::cout << "VRCON::put old=" << std::hex << old_value << " new=" << new_value << '\n';
738     }
739 
740     if (!diff)
741     {
742         return;
743     }
744 
745     // if no PinModule clear VROE bit
746     if (!vr_PinModule)
747     {
748         new_value &= ~VROE;
749     }
750 
751     value.put(new_value);
752 
753     if (new_value & VREN)         // Vreference enable set
754     {
755         get_Vref();
756 
757         if (new_value & VROE)   // output voltage to pin
758         {
759             if (! vr_pu)
760             {
761                 vr_pu = new stimulus("vref_pu", Vref_high, vr_Rhigh);
762             }
763 
764             if (! vr_pd)
765             {
766                 vr_pd = new stimulus("vref_pd", Vref_low, vr_Rlow);
767             }
768 
769             if (strcmp("Vref", vr_PinModule->getPin().name().c_str()))
770             {
771                 vr_PinModule->getPin().newGUIname("Vref");
772             }
773 
774             if (vr_PinModule->getPin().snode)
775             {
776                 vr_pu->set_Zth(vr_Rhigh);
777                 vr_pd->set_Zth(vr_Rlow);
778                 vr_PinModule->getPin().snode->attach_stimulus(vr_pu);
779                 vr_PinModule->getPin().snode->attach_stimulus(vr_pd);
780                 vr_PinModule->getPin().snode->update();
781             }
782 
783         }
784         else if (vr_PinModule)     // not outputing voltage to pin
785         {
786             if (!strcmp("Vref", vr_PinModule->getPin().name().c_str()))
787             {
788                 vr_PinModule->getPin().newGUIname(pin_name.c_str());
789             }
790 
791             if (diff & 0x2f)    // did value of vreference change ?
792             {
793                 _cmcon->get();
794             }
795 
796             if (vr_PinModule && vr_PinModule->getPin().snode)
797             {
798                 vr_PinModule->getPin().snode->detach_stimulus(vr_pu);
799                 vr_PinModule->getPin().snode->detach_stimulus(vr_pd);
800                 vr_PinModule->getPin().snode->update();
801             }
802 
803         }
804         else  	// output pin not defined
805         {
806             if (diff & 0x2f)    // did value of vreference change ?
807             {
808                 _cmcon->get();
809             }
810         }
811 
812     }
813     else     // vref disable
814     {
815         if (vr_PinModule && !strcmp("Vref", vr_PinModule->getPin().name().c_str()))
816         {
817             vr_PinModule->getPin().newGUIname(pin_name.c_str());
818         }
819 
820         if (vr_PinModule && vr_PinModule->getPin().snode)
821         {
822             vr_PinModule->getPin().snode->detach_stimulus(vr_pu);
823             vr_PinModule->getPin().snode->detach_stimulus(vr_pd);
824             vr_PinModule->getPin().snode->update();
825         }
826     }
827 }
828 
829 
830 //--------------------------------------------------
831 //      Voltage reference
832 //--------------------------------------------------
833 
VRCON_2(Processor * pCpu,const char * pName,const char * pDesc)834 VRCON_2::VRCON_2(Processor *pCpu, const char *pName, const char *pDesc)
835     : sfr_register(pCpu, pName, pDesc)
836 {
837     value.put(0);
838     vr_06v = new stimulus("vref_06v", 0.0, 100.0);
839     vr_pu = new stimulus("Cvref_pu", 0.0, 48000.0);
840     vr_pd = new stimulus("Cvref_pd", 0.0, 0.0);
841     ((Processor *)cpu)->CVREF = new Stimulus_Node("CVREF");
842     ((Processor *)cpu)->V06REF = new Stimulus_Node("V0.6REF");
843     ((Processor *)cpu)->CVREF->attach_stimulus(vr_pu);
844     ((Processor *)cpu)->CVREF->attach_stimulus(vr_pd);
845     ((Processor *)cpu)->V06REF->attach_stimulus(vr_06v);
846 }
847 
848 
~VRCON_2()849 VRCON_2::~VRCON_2()
850 {
851     delete vr_06v;
852     delete vr_pu;
853     delete vr_pd;
854     delete ((Processor *)cpu)->CVREF;
855     delete ((Processor *)cpu)->V06REF;
856 }
857 
858 
put(unsigned int new_value)859 void VRCON_2::put(unsigned int new_value)
860 {
861     unsigned int old_value = value.get();
862     unsigned int diff = new_value ^ old_value;
863     trace.raw(write_trace.get() | value.get());
864 
865     if (verbose & 2)
866     {
867         std::cout << "VRCON_2::put old=" << std::hex << old_value << " new=" << new_value << '\n';
868     }
869 
870     if (!diff)
871     {
872         return;
873     }
874 
875     value.put(new_value);
876 
877     // Turn 0.6 V reference on or off ?
878     if (diff & VP6EN)
879     {
880         if (new_value & VP6EN)
881         {
882             vr_06v->set_Vth(0.6);
883 
884         }
885         else
886         {
887             vr_06v->set_Vth(0.0);
888         }
889 
890         ((Processor *)cpu)->V06REF->update();
891     }
892 
893     if (diff & (C1VREN | C2VREN | VRR | VR3 | VR2 | VR1 | VR0))
894     {
895         double vr_Rhigh, vr_Rlow;
896 
897         if (new_value & (C1VREN | C2VREN))
898         {
899             vr_pu->set_Vth(((Processor *)cpu)->get_Vdd());
900 
901         }
902         else
903         {
904             vr_pu->set_Vth(0.0);
905         }
906 
907         vr_Rhigh = (8 + (16 - (new_value & 0x0f))) * 2000.0;
908         vr_pu->set_Zth(vr_Rhigh);
909         vr_Rlow = (new_value & 0x0f) * 2000.0;
910 
911         if (!(new_value & VRR))         // High range ?
912         {
913             vr_Rlow += 16000.0;
914         }
915 
916         vr_pd->set_Zth(vr_Rlow);
917         ((Processor *)cpu)->CVREF->update();
918         ((Processor *)cpu)->CVREF->update();
919     }
920 }
921 
922 
CMxCON0(Processor * pCpu,const char * pName,const char * pDesc,unsigned int _cm,ComparatorModule2 * cmModule)923 CMxCON0::CMxCON0(Processor *pCpu, const char *pName,
924                  const char *pDesc, unsigned int _cm, ComparatorModule2 *cmModule)
925     : CMxCON0_base(pCpu, pName, pDesc, _cm, cmModule)
926 {
927 }
928 
929 
~CMxCON0()930 CMxCON0::~CMxCON0()
931 {
932 }
933 
934 
put(unsigned int new_value)935 void CMxCON0::put(unsigned int new_value)
936 {
937     unsigned int old_value = value.get();
938     unsigned int diff = (new_value ^ old_value) & mValidBits;
939     // assume masked bits are read-only
940     new_value = (new_value & mValidBits) | (old_value & ~mValidBits);
941     trace.raw(write_trace.get() | value.get());
942     value.put(new_value);
943 
944     if (diff == 0)
945     {
946         get();
947         return;
948     }
949 
950     if (diff & CxOE)
951     {
952         cm_output = m_cmModule->cmxcon1[cm]->output_pin();
953 
954         if (new_value & CxOE)
955         {
956             char name[20];
957 
958             if (! cm_source)
959             {
960                 cm_source = new CMxSignalSource(cm_output, this);
961             }
962 
963             snprintf(name, sizeof(name), "c%uout", cm + 1);
964             assert(cm_output);
965             cm_output->getPin().newGUIname(name);
966             cm_output->setSource(cm_source);
967             cm_source_active = true;
968 
969         }
970         else if (cm_source_active)  	// Enable output enable turned off
971         {
972             cm_output->getPin().newGUIname(cm_output->getPin().name().c_str());
973             cm_output->setSource(0);
974         }
975     }
976 
977     get();
978 }
979 
980 
get_hysteresis()981 double CMxCON0::get_hysteresis()
982 {
983     double ret = 0.0;
984 
985     if (value.get() & CxHYS)
986     {
987         ret = 0.05;
988     }
989 
990     return ret;
991 }
992 
993 
get_Vpos()994 double CMxCON0::get_Vpos()
995 {
996     return m_cmModule->cmxcon1[cm]->get_Vpos();
997 }
998 
999 
get_Vneg()1000 double CMxCON0::get_Vneg()
1001 {
1002     return m_cmModule->cmxcon1[cm]->get_Vneg();
1003 }
1004 
1005 
set_output(bool output)1006 void CMxCON0::set_output(bool output)
1007 {
1008     unsigned int cmxcon0 = value.get();
1009     bool old_out = cmxcon0 & CxOUT;
1010 
1011     if (output)
1012     {
1013         cmxcon0 |= CxOUT;
1014 
1015     }
1016     else
1017     {
1018         cmxcon0 &= ~CxOUT;
1019     }
1020 
1021     Dprintf(("cm%u POL %d output %d cmxcon0=%x old_out %d\n", cm + 1, (bool)(cmxcon0 & CxPOL), output, cmxcon0, old_out));
1022     value.put(cmxcon0);
1023     m_cmModule->set_cmout(cm, output);
1024 
1025     if (cmxcon0 & CxOE)
1026     {
1027         cm_source->putState(output ? '1' : '0');
1028         m_cmModule->cmxcon1[cm]->output_pin()->updatePinModule();
1029     }
1030 
1031     if (old_out != output)   // state change
1032     {
1033         // Positive going edge, set interrupt ?
1034         if (output && (m_cmModule->cmxcon1[cm]->value.get() & CMxCON1::CxINTP))
1035         {
1036             IntSrc->Trigger();
1037         }
1038 
1039         // Negative going edge, set interrupt ?
1040         if (!output && (m_cmModule->cmxcon1[cm]->value.get() & CMxCON1::CxINTN))
1041         {
1042             IntSrc->Trigger();
1043         }
1044     }
1045 }
1046 
1047 
put(unsigned int new_value)1048 void CMxCON0_V2::put(unsigned int new_value)
1049 {
1050     unsigned int old_value = value.get();
1051     unsigned int diff = (new_value ^ old_value) & mValidBits;
1052 
1053     if (verbose)
1054     {
1055         std::cout << name() << " put(new_value) =" << std::hex << new_value << '\n';
1056     }
1057 
1058     trace.raw(write_trace.get() | value.get());
1059     value.put(new_value);
1060 
1061     // assume masked bits are read-only
1062 
1063     if (diff == 0)
1064     {
1065         get();
1066         return;
1067     }
1068 
1069     if ((diff & CxON) && !(new_value & CxON))   // turning off
1070     {
1071         cm_output = m_cmModule->cmxcon1[cm]->output_pin(cm);
1072         cm_output->getPin().newGUIname(cm_output->getPin().name().c_str());
1073         cm_output->setSource(0);
1074         // remove stimulus from input pins
1075         m_cmModule->cmxcon1[0]->setPinStimulus(0, POS + cm * 2);
1076         m_cmModule->cmxcon1[0]->setPinStimulus(0, NEG + cm * 2);
1077         return;
1078     }
1079 
1080     if (diff & CxOE)
1081     {
1082         cm_output = m_cmModule->cmxcon1[cm]->output_pin(cm);
1083 
1084         if (new_value & CxOE)
1085         {
1086             char name[20];
1087 
1088             if (! cm_source)
1089             {
1090                 cm_source = new CMxSignalSource(cm_output, this);
1091             }
1092 
1093             snprintf(name, sizeof(name), "c%uout", cm + 1);
1094             assert(cm_output);
1095             cm_output->getPin().newGUIname(name);
1096             cm_output->setSource(cm_source);
1097             cm_source_active = true;
1098 
1099         }
1100         else if (cm_source_active)  	// Enable output enable turned off
1101         {
1102             cm_output->getPin().newGUIname(cm_output->getPin().name().c_str());
1103             cm_output->setSource(0);
1104         }
1105     }
1106 
1107     get();
1108 }
1109 
1110 
set_output(bool output)1111 void CMxCON0_V2::set_output(bool output)
1112 {
1113     unsigned int cmxcon0 = value.get();
1114     unsigned int cmxcon1 = m_cmModule->cmxcon1[cm]->value.get();
1115     bool old_out = cmxcon0 & CxOUT;
1116 
1117     if (output)
1118     {
1119         cmxcon0 |= CxOUT;
1120         cmxcon1 |= ((cm == 0) ? CM2CON1_V2::MC1OUT : CM2CON1_V2::MC2OUT);
1121 
1122     }
1123     else
1124     {
1125         cmxcon0 &= ~CxOUT;
1126         cmxcon1 &= ~((cm == 0) ? CM2CON1_V2::MC1OUT : CM2CON1_V2::MC2OUT);
1127     }
1128 
1129     Dprintf(("cm%u POL %d output %d cmxcon0=%x old_out %d\n", cm + 1, (bool)(cmxcon0 & CxPOL), output, cmxcon0, old_out));
1130     value.put(cmxcon0);
1131     m_cmModule->cmxcon1[cm]->value.put(cmxcon1);
1132     m_cmModule->set_cmout(cm, output);
1133 
1134     if (cmxcon0 & CxOE)
1135     {
1136         cm_source->putState(output ? '1' : '0');
1137         m_cmModule->cmxcon1[cm]->output_pin(cm)->updatePinModule();
1138     }
1139 
1140     if (old_out != output)   // state change
1141     {
1142         m_cmModule->cmxcon1[cm]->tmr_gate(cm, output);
1143 
1144         // Positive going edge, set interrupt ?
1145         if (output)
1146         {
1147             IntSrc->Trigger();
1148         }
1149     }
1150 }
1151 
1152 
get_hysteresis()1153 double CMxCON0_V2::get_hysteresis()
1154 {
1155     double hyst_volt = 0.0;
1156 
1157     if (m_cmModule->cmxcon1[cm]->hyst_active(cm))
1158     {
1159         hyst_volt =  0.05; // assume 50 mv hysteresis
1160     }
1161 
1162     return hyst_volt;
1163 }
1164 
1165 
CMxCON0_V2(Processor * pCpu,const char * pName,const char * pDesc,unsigned int _cm,ComparatorModule2 * cmModule)1166 CMxCON0_V2::CMxCON0_V2(Processor *pCpu, const char *pName,
1167                        const char *pDesc, unsigned int _cm, ComparatorModule2 *cmModule)
1168     : CMxCON0_base(pCpu, pName, pDesc, _cm, cmModule)
1169 {
1170     stimulus_pin[0] = nullptr;
1171     stimulus_pin[1] = nullptr;
1172 }
1173 
1174 
~CMxCON0_V2()1175 CMxCON0_V2::~CMxCON0_V2()
1176 {
1177 }
1178 
1179 
get_Vpos()1180 double CMxCON0_V2::get_Vpos()
1181 {
1182     return m_cmModule->cmxcon1[cm]->get_Vpos(cm, value.get());
1183 }
1184 
1185 
get_Vneg()1186 double CMxCON0_V2::get_Vneg()
1187 {
1188     return m_cmModule->cmxcon1[cm]->get_Vneg(cm, value.get());
1189 }
1190 
1191 
put(unsigned int new_value)1192 void CM2CON1_V4::put(unsigned int new_value)
1193 {
1194     trace.raw(write_trace.get() | value.get());
1195     value.put(new_value & mValidBits);
1196 
1197     if (m_cmModule->tmr1l[0])
1198     {
1199         m_cmModule->tmr1l[0]->set_T1GSS((new_value & T1GSS) == T1GSS);
1200     }
1201 }
1202 
1203 
get_Vpos(unsigned int cm,unsigned int cmxcon0)1204 double CM2CON1_V4::get_Vpos(unsigned int cm, unsigned int cmxcon0)
1205 {
1206     double Voltage = 0.0;
1207     assert(m_vrcon);
1208 
1209     if (cmxcon0 & CMxCON0_V2::CxR)   // use Vref defined in cm2con1
1210     {
1211         if ((cm == 0 && (m_vrcon->value.get() & VRCON_2::C1VREN)) ||
1212                 (cm == 1 && (m_vrcon->value.get() & VRCON_2::C2VREN)))
1213         {
1214             Voltage = ((Processor *)cpu)->CVREF->get_nodeVoltage();
1215             Dprintf(("%s CVref %.2f\n", __FUNCTION__, Voltage));
1216 
1217         }
1218         else
1219         {
1220             Voltage = ((Processor *)cpu)->V06REF->get_nodeVoltage();
1221             Dprintf(("%s cm%u V06ref %.2f\n", __FUNCTION__, cm + 1, Voltage));
1222         }
1223 
1224     }
1225     else  	// use CM1IN+ or CM2IN+
1226     {
1227         if (!stimulus_pin[POS])
1228         {
1229             setPinStimulus(cm_inputPos[cm], POS);
1230         }
1231 
1232         Voltage =  cm_inputPos[cm]->getPin().get_nodeVoltage();
1233         Dprintf(("%s cm%u %s %.2f\n", __FUNCTION__, cm + 1, cm_inputPos[cm]->getPin().name().c_str(), Voltage));
1234     }
1235 
1236     return Voltage;
1237 }
1238 
1239 
CM2CON1_V4(Processor * pCpu,const char * pName,const char * pDesc,unsigned int _cm,ComparatorModule2 * cmModule)1240 CM2CON1_V4::CM2CON1_V4(Processor *pCpu, const char *pName, const char *pDesc,
1241                        unsigned int _cm, ComparatorModule2 * cmModule) :
1242     CM2CON1_V3(pCpu, pName, pDesc, _cm, cmModule)
1243 {
1244     cm1_cvref = new CM_stimulus((CMCON *)m_cmModule->cmxcon0[0], "cm1_cvref", 0, 1e12);
1245     cm1_v06ref = new CM_stimulus((CMCON *)m_cmModule->cmxcon0[0], "cm1_v06ref", 0, 1e12);
1246     cm2_cvref = new CM_stimulus((CMCON *)m_cmModule->cmxcon0[1], "cm2_cvref", 0, 1e12);
1247     cm2_v06ref = new CM_stimulus((CMCON *)m_cmModule->cmxcon0[1], "cm2_v06ref", 0, 1e12);
1248     ((Processor *)cpu)->CVREF->attach_stimulus(cm1_cvref);
1249     ((Processor *)cpu)->V06REF->attach_stimulus(cm1_v06ref);
1250     ((Processor *)cpu)->CVREF->attach_stimulus(cm2_cvref);
1251     ((Processor *)cpu)->V06REF->attach_stimulus(cm2_v06ref);
1252 }
1253 
1254 
~CM2CON1_V4()1255 CM2CON1_V4::~CM2CON1_V4()
1256 {
1257     ((Processor *)cpu)->CVREF->detach_stimulus(cm1_cvref);
1258     ((Processor *)cpu)->V06REF->detach_stimulus(cm1_v06ref);
1259     ((Processor *)cpu)->CVREF->detach_stimulus(cm2_cvref);
1260     ((Processor *)cpu)->V06REF->detach_stimulus(cm2_v06ref);
1261     delete cm1_cvref;
1262     delete cm1_v06ref;
1263     delete cm2_cvref;
1264     delete cm2_v06ref;
1265 }
1266 
1267 
put(unsigned int new_value)1268 void CM2CON1_V3::put(unsigned int new_value)
1269 {
1270     unsigned int old_value = value.get();
1271     trace.raw(write_trace.get() | value.get());
1272     value.put(new_value & mValidBits);
1273 
1274     if ((new_value ^ old_value) & C1RSEL)
1275     {
1276         m_cmModule->cmxcon0[0]->get();
1277     }
1278 
1279     if ((new_value ^ old_value) & C2RSEL)
1280     {
1281         m_cmModule->cmxcon0[1]->get();
1282     }
1283 
1284     if (m_cmModule->tmr1l[0])
1285     {
1286         m_cmModule->tmr1l[0]->set_T1GSS((new_value & T1GSS) == T1GSS);
1287     }
1288 }
1289 
1290 
get_Vpos(unsigned int cm,unsigned int cmxcon0)1291 double CM2CON1_V3::get_Vpos(unsigned int cm, unsigned int cmxcon0)
1292 {
1293     double Voltage = 0.0;
1294     unsigned int cmxcon1 = value.get();
1295     assert(m_vrcon);
1296 
1297     if (cmxcon0 & CMxCON0_V2::CxR)   // use Vref defined in cm2con1
1298     {
1299         if ((cm == 0 && (cmxcon1 & C1RSEL)) |
1300                 (cm == 1 && (cmxcon1 & C2RSEL)))
1301         {
1302             Voltage =  m_vrcon->get_Vref();
1303             Dprintf(("%s cm%u Vref %.2f\n", __FUNCTION__, cm + 1, Voltage));
1304 
1305         }
1306         else
1307         {
1308             Voltage =  0.6;
1309             Dprintf(("%s cm%u Absref %.2f\n", __FUNCTION__, cm + 1, Voltage));
1310         }
1311 
1312     }
1313     else  	// use CM1IN+ or CM2IN+
1314     {
1315         if (stimulus_pin[POS] != cm_inputPos[cm])
1316         {
1317             setPinStimulus(cm_inputPos[cm], POS);
1318         }
1319 
1320         Voltage =  cm_inputPos[cm]->getPin().get_nodeVoltage();
1321         Dprintf(("%s cm%u %s %.2f\n", __FUNCTION__, cm + 1, cm_inputPos[cm]->getPin().name().c_str(), Voltage));
1322     }
1323 
1324     return Voltage;
1325 }
1326 
1327 
get_Vneg(unsigned int,unsigned int cmxcon0)1328 double CM2CON1_V3::get_Vneg(unsigned int /* cm */, unsigned int cmxcon0)
1329 {
1330     unsigned int cxNchan = cmxcon0 & (CMxCON0_V2::CxCH0 | CMxCON0_V2::CxCH1);
1331 
1332     if (stimulus_pin[NEG] != cm_inputNeg[cxNchan])
1333     {
1334         setPinStimulus(cm_inputNeg[cxNchan], NEG);
1335     }
1336 
1337     Dprintf(("%s cm%u pin %u %s %.2f\n", __FUNCTION__, cm + 1, cxNchan, cm_inputNeg[cxNchan]->getPin().name().c_str(), cm_inputNeg[cxNchan]->getPin().get_nodeVoltage()));
1338     return cm_inputNeg[cxNchan]->getPin().get_nodeVoltage();
1339 }
1340 
1341 
1342 //*************************************************************
1343 // CM2CON1_V2
1344 
put(unsigned int new_value)1345 void CM2CON1_V2::put(unsigned int new_value)
1346 {
1347     unsigned int old_value = value.get();
1348     new_value &= mValidBits;
1349     unsigned int diff = old_value ^ new_value;
1350     trace.raw(write_trace.get() | value.get());
1351     value.put(new_value);
1352 
1353     if (diff & (C1RSEL | C1HYS))
1354     {
1355         m_cmModule->cmxcon0[0]->get();
1356     }
1357 
1358     if (diff & (C2RSEL | C2HYS))
1359     {
1360         m_cmModule->cmxcon0[1]->get();
1361     }
1362 }
1363 
1364 
tmr_gate(unsigned int cm,bool output)1365 void CM2CON1_V3::tmr_gate(unsigned int cm, bool output)
1366 {
1367     if (cm == 1 && m_cmModule->tmr1l[0])   //CM2
1368     {
1369         Dprintf(("CM2CON1_V3::tmr_gate cm%u output=%d\n", cm + 1, output));
1370         m_cmModule->tmr1l[0]->compare_gate(output);
1371     }
1372 }
1373 
1374 
CM2CON1_V2(Processor * pCpu,const char * pName,const char * pDesc,ComparatorModule2 * cmModule)1375 CM2CON1_V2::CM2CON1_V2(Processor *pCpu, const char *pName,
1376                        const char *pDesc, ComparatorModule2 * cmModule):
1377     CMxCON1_base(pCpu, pName, pDesc, 0, cmModule)
1378 {
1379     assert(m_cmModule->cmxcon0[1]);
1380     cm_stimulus[2] = new CM_stimulus((CMCON *)m_cmModule->cmxcon0[1], "cm_stimulus_2-", 0, 1e12);
1381     cm_stimulus[3] = new CM_stimulus((CMCON *)m_cmModule->cmxcon0[1], "cm_stimulus_2+", 0, 1e12);
1382     ctmu_stimulus_pin = 0;
1383 }
1384 
1385 
~CM2CON1_V2()1386 CM2CON1_V2::~CM2CON1_V2()
1387 {
1388     delete cm_stimulus[2];
1389     delete cm_stimulus[3];
1390 }
1391 
1392 
get_Vpos(unsigned int cm,unsigned int cmxcon0)1393 double CM2CON1_V2::get_Vpos(unsigned int cm, unsigned int cmxcon0)
1394 {
1395     double Voltage = 0.0;
1396     unsigned int cmxcon1 = value.get();
1397 
1398     if (cmxcon0 & CMxCON0_V2::CxR)   // use Vref defined in cm2con1
1399     {
1400         if ((cm == 0 && (cmxcon1 & C1RSEL)) |
1401                 (cm == 1 && (cmxcon1 & C2RSEL)))
1402         {
1403             Voltage =  m_cmModule->FVR_voltage;
1404             Dprintf(("%s cm%u FVR %.2f\n", __FUNCTION__, cm + 1, Voltage));
1405 
1406         }
1407         else
1408         {
1409             Voltage =  m_cmModule->DAC_voltage;
1410             Dprintf(("%s cm%u DAC %.2f\n", __FUNCTION__, cm + 1, Voltage));
1411         }
1412 
1413     }
1414     else  	// use CM1IN+ or CM2IN+
1415     {
1416         if (stimulus_pin[POS + cm * 2] != cm_inputPos[cm])
1417         {
1418             setPinStimulus(cm_inputPos[cm], POS + cm * 2);
1419         }
1420 
1421         Voltage =  cm_inputPos[cm]->getPin().get_nodeVoltage();
1422         Dprintf(("%s cm%u %s %.2f\n", __FUNCTION__, cm + 1, cm_inputPos[cm]->getPin().name().c_str(), Voltage));
1423     }
1424 
1425     return Voltage;
1426 }
1427 
1428 
get_Vneg(unsigned int cm,unsigned int cmxcon0)1429 double CM2CON1_V2::get_Vneg(unsigned int cm, unsigned int cmxcon0)
1430 {
1431     unsigned int cxNchan = cmxcon0 & (CMxCON0_V2::CxCH0 | CMxCON0_V2::CxCH1);
1432 
1433     if (stimulus_pin[NEG + cm * 2] != cm_inputNeg[cxNchan])
1434     {
1435         setPinStimulus(cm_inputNeg[cxNchan], NEG + cm * 2);
1436     }
1437 
1438     if (cm_inputNeg[cxNchan]->getPin().snode)
1439     {
1440         cm_inputNeg[cxNchan]->getPin().snode->update();
1441     }
1442 
1443     Dprintf(("%s cm%u pin %u %s %.2f\n", __FUNCTION__, cm + 1, cxNchan, cm_inputNeg[cxNchan]->getPin().name().c_str(), cm_inputNeg[cxNchan]->getPin().get_nodeVoltage()));
1444     return cm_inputNeg[cxNchan]->getPin().get_nodeVoltage();
1445 }
1446 
1447 
hyst_active(unsigned int cm)1448 bool CM2CON1_V2::hyst_active(unsigned int cm)
1449 {
1450     bool hyst = false;
1451 
1452     if (cm == 0)
1453     {
1454         hyst = value.get() & C1HYS;
1455 
1456     }
1457     else if (cm == 1)
1458     {
1459         hyst = value.get() & C2HYS;
1460     }
1461 
1462     return hyst;
1463 }
1464 
1465 
tmr_gate(unsigned int cm,bool output)1466 void CM2CON1_V2::tmr_gate(unsigned int cm, bool output)
1467 {
1468     Dprintf(("CM2CON1_V2::tmr_gate cm%u output %d\n", cm + 1, output));
1469 
1470     for (int i = 0; i < 3; i++)
1471     {
1472         if (m_cmModule->t1gcon[i])
1473         {
1474             if (cm == 0)   // CM1
1475             {
1476                 m_cmModule->t1gcon[i]->CM1_gate(output);
1477 
1478             }
1479             else if (cm == 1)     //CM2
1480             {
1481                 m_cmModule->t1gcon[i]->CM2_gate(output);
1482             }
1483         }
1484     }
1485 }
1486 
1487 
set_ctmu_stim(stimulus * _ctmu_stim,CTMU * _ctmu_module)1488 void CM2CON1_V2::set_ctmu_stim(stimulus *_ctmu_stim, CTMU *_ctmu_module)
1489 {
1490     if (_ctmu_stim)
1491     {
1492         if (!m_cmModule->ctmu_module)
1493         {
1494             m_cmModule->ctmu_module = _ctmu_module;
1495         }
1496 
1497         ctmu_stim = _ctmu_stim;
1498         attach_ctmu_stim();
1499 
1500     }
1501     else
1502     {
1503         detach_ctmu_stim();
1504         ctmu_stim = 0;
1505     }
1506 }
1507 
1508 
attach_ctmu_stim()1509 void CM2CON1_V2::attach_ctmu_stim()
1510 {
1511     if (!cm_inputNeg[1])
1512     {
1513         fprintf(stderr, "ERROR CM2CON1_V2::attach_ctmu_stim C12IN1- not defined\n");
1514         return;
1515     }
1516 
1517     if (!(cm_inputNeg[1]->getPin().snode))
1518     {
1519         printf("Warning CM2CON1_V2::attach_ctmu_stim %s has no node attached CTMU will not work properly\n", cm_inputNeg[1]->getPin().name().c_str());
1520         return;
1521     }
1522 
1523     if (ctmu_stim)
1524     {
1525         cm_inputNeg[1]->getPin().snode->attach_stimulus(ctmu_stim);
1526         cm_inputNeg[1]->getPin().snode->update();
1527         ctmu_attached = true;
1528     }
1529 }
1530 
1531 
detach_ctmu_stim()1532 void CM2CON1_V2::detach_ctmu_stim()
1533 {
1534     if (ctmu_attached)
1535     {
1536         cm_inputNeg[1]->getPin().snode->detach_stimulus(ctmu_stim);
1537         cm_inputNeg[1]->getPin().snode->update();
1538         ctmu_attached = false;
1539     }
1540 }
1541 
1542 
CMxCON1(Processor * pCpu,const char * pName,const char * pDesc,unsigned int _cm,ComparatorModule2 * cmModule)1543 CMxCON1::CMxCON1(Processor *pCpu, const char *pName, const char *pDesc, unsigned int _cm, ComparatorModule2 *cmModule)
1544     : CMxCON1_base(pCpu, pName, pDesc, _cm, cmModule)
1545 {
1546 }
1547 
1548 
~CMxCON1()1549 CMxCON1::~CMxCON1()
1550 {
1551 }
1552 
1553 
CMxCON1_base(Processor * pCpu,const char * pName,const char * pDesc,unsigned int _cm,ComparatorModule2 * cmModule)1554 CMxCON1_base::CMxCON1_base(Processor *pCpu, const char *pName,
1555                            const char *pDesc, unsigned int _cm, ComparatorModule2 *cmModule)
1556     : sfr_register(pCpu, pName, pDesc),
1557       cm(_cm), m_cmModule(cmModule)
1558 {
1559     assert(m_cmModule->cmxcon0[cm]);
1560     cm_stimulus[NEG] = new CM_stimulus((CMCON *)m_cmModule->cmxcon0[cm], "cm_stimulus_-", 0, 1e12);
1561     cm_stimulus[POS] = new CM_stimulus((CMCON *)m_cmModule->cmxcon0[cm], "cm_stimulus_+", 0, 1e12);
1562 
1563     for (int i = 0; i < 5; i++)
1564     {
1565         cm_inputNeg[i] = nullptr;
1566     }
1567 
1568     for (int i = 0; i < 2; i++)
1569     {
1570         stimulus_pin[i] = nullptr;
1571         stimulus_pin[i + 2] = nullptr;
1572         cm_inputPos[i] = nullptr;
1573         cm_output[i] = nullptr;
1574     }
1575 
1576     ctmu_stimulus_pin = 0;
1577 }
1578 
1579 
~CMxCON1_base()1580 CMxCON1_base::~CMxCON1_base()
1581 {
1582     delete cm_stimulus[NEG];
1583     delete cm_stimulus[POS];
1584 }
1585 
1586 
get_Vneg(unsigned int,unsigned int)1587 double CMxCON1::get_Vneg(unsigned int /* arg */, unsigned int /* arg2 */ )
1588 {
1589     unsigned int cxNchan = value.get() & CxNMASK;
1590 
1591     if (!stimulus_pin[NEG])
1592     {
1593         setPinStimulus(cm_inputNeg[cxNchan], NEG);
1594     }
1595 
1596     if (cm_inputNeg[cxNchan]->getPin().snode)
1597     {
1598         cm_inputNeg[cxNchan]->getPin().snode->update();
1599     }
1600 
1601     Dprintf(("%s pin %u %s %.2f\n", __FUNCTION__, cxNchan, cm_inputNeg[cxNchan]->getPin().name().c_str(), cm_inputNeg[cxNchan]->getPin().get_nodeVoltage()));
1602     return cm_inputNeg[cxNchan]->getPin().get_nodeVoltage();
1603 }
1604 
1605 
get_Vpos(unsigned int,unsigned int)1606 double CMxCON1::get_Vpos(unsigned int /* arg */, unsigned int /* arg2 */ )
1607 {
1608     unsigned int cxPchan = (value.get() & CxPMASK) >> 3;
1609     double	Voltage;
1610 
1611     switch (cxPchan)
1612     {
1613     case 0:
1614         if (stimulus_pin[POS] != cm_inputPos[cxPchan])
1615         {
1616             setPinStimulus(cm_inputPos[cxPchan], POS);
1617         }
1618 
1619         Voltage = cm_inputPos[cxPchan]->getPin().get_nodeVoltage();
1620         Dprintf(("%s %s %s v=%.2f\n", name().c_str(), __FUNCTION__, cm_inputPos[cxPchan]->getPin().name().c_str(), Voltage));
1621         break;
1622 
1623     case 2:
1624         Voltage = m_cmModule->DAC_voltage;
1625         Dprintf(("%s %s %s v=%.2f\n", name().c_str(), __FUNCTION__, "DAC", Voltage));
1626         break;
1627 
1628     case 4:
1629         Voltage = m_cmModule->FVR_voltage;
1630         Dprintf(("%s %s %s v=%.2f\n", name().c_str(), __FUNCTION__, "FVR", Voltage));
1631         break;
1632 
1633     default:
1634         printf("CMxCON1::get_Vpos unexpected Pchan %x\n", cxPchan);
1635 
1636     case 6:
1637         Voltage = 0.;
1638         Dprintf(("%s %s %s v=%.2f\n", name().c_str(), __FUNCTION__, "AGND", Voltage));
1639         break;
1640     }
1641 
1642     return Voltage;
1643 }
1644 
1645 
1646 // Attach a stimulus to an input pin so that changes
1647 // in the pin voltage can be reflected in the comparator output.
1648 //
1649 // pin may be 0 in which case a current stimulus, if any, will be detached
1650 // pol is either the enum POS or NEG
1651 //
setPinStimulus(PinModule * pin,int pol)1652 void CMxCON1_base::setPinStimulus(PinModule *pin, int pol)
1653 {
1654     if (pin == stimulus_pin[pol])
1655     {
1656         return;
1657     }
1658 
1659     if (stimulus_pin[pol])
1660     {
1661         (stimulus_pin[pol]->getPin().snode)->detach_stimulus(cm_stimulus[pol]);
1662         stimulus_pin[pol] = 0;
1663     }
1664 
1665     if (pin && pin->getPin().snode)
1666     {
1667         stimulus_pin[pol] = pin;
1668         (stimulus_pin[pol]->getPin().snode)->attach_stimulus(cm_stimulus[pol]);
1669     }
1670 }
1671 
1672 
put(unsigned int new_value)1673 void CMxCON1::put(unsigned int new_value)
1674 {
1675     unsigned int old_value = value.get();
1676     new_value &= mValidBits;
1677     unsigned int diff = old_value ^ new_value;
1678     trace.raw(write_trace.get() | value.get());
1679     value.put(new_value);
1680 
1681     if ((diff & CxNMASK) || !stimulus_pin[NEG])
1682     {
1683         unsigned int cxNchan = new_value & CxNMASK;
1684         setPinStimulus(cm_inputNeg[cxNchan], NEG);
1685     }
1686 
1687     if ((diff & CxPMASK) || !stimulus_pin[POS])
1688     {
1689         unsigned int cxPchan = (new_value & CxPMASK) >> 3;
1690 
1691         if (cxPchan == 0)
1692         {
1693             setPinStimulus(cm_inputPos[cxPchan], POS);
1694 
1695         }
1696         else if (stimulus_pin[POS])
1697         {
1698             setPinStimulus(0, POS);
1699         }
1700     }
1701 
1702     m_cmModule->run_get(cm);
1703 }
1704 
1705 
set_OUTpin(PinModule * pin_cm0,PinModule * pin_cm1)1706 void CMxCON1_base::set_OUTpin(PinModule *pin_cm0, PinModule *pin_cm1)
1707 {
1708     cm_output[0] = pin_cm0;
1709     cm_output[1] = pin_cm1;
1710 }
1711 
setIOpin(PinModule * pin_cm,int arg)1712 void CMxCON1_base::setIOpin(PinModule *pin_cm, int arg)
1713 {
1714     cm_output[arg] = pin_cm;
1715 }
1716 
set_INpinNeg(PinModule * pin_cm0,PinModule * pin_cm1,PinModule * pin_cm2,PinModule * pin_cm3,PinModule * pin_cm4)1717 void CMxCON1_base::set_INpinNeg(PinModule *pin_cm0, PinModule *pin_cm1, PinModule *pin_cm2,  PinModule *pin_cm3,  PinModule *pin_cm4)
1718 {
1719     cm_inputNeg[0] = pin_cm0;
1720     cm_inputNeg[1] = pin_cm1;
1721     cm_inputNeg[2] = pin_cm2;
1722     cm_inputNeg[3] = pin_cm3;
1723     cm_inputNeg[4] = pin_cm4;
1724 }
1725 
1726 
set_INpinPos(PinModule * pin_cm0,PinModule * pin_cm1)1727 void CMxCON1_base::set_INpinPos(PinModule *pin_cm0, PinModule *pin_cm1)
1728 {
1729     cm_inputPos[0] = pin_cm0;
1730     cm_inputPos[1] = pin_cm1;
1731 }
1732 
1733 
ComparatorModule2(Processor *)1734 ComparatorModule2::ComparatorModule2(Processor * )
1735 {
1736     for (int i = 0; i < 4; i++)
1737     {
1738         cmxcon0[i] = nullptr;
1739         cmxcon1[i] = nullptr;
1740     }
1741 
1742     t1gcon[0] = t1gcon[1] = t1gcon[2] = nullptr;
1743     tmr1l[0] = tmr1l[1] = tmr1l[2] = nullptr;
1744     eccpas[0] = eccpas[1] = eccpas[2] = nullptr;
1745 
1746     for (int i = 0; i < 4; i++)
1747     {
1748         m_clc[i] = nullptr;
1749     }
1750 }
1751 
1752 
~ComparatorModule2()1753 ComparatorModule2::~ComparatorModule2()
1754 {
1755     for (int i = 0; i < 4; i++)
1756     {
1757         if (cmxcon0[i])
1758         {
1759             delete cmxcon0[i];
1760         }
1761 
1762         if (cmxcon1[i])
1763         {
1764             delete cmxcon1[i];
1765         }
1766 
1767         if (i < 3 && cmxcon1[i] == cmxcon1[i + 1])
1768         {
1769             cmxcon1[i + 1] = nullptr;
1770         }
1771     }
1772 
1773     if (cmout)
1774     {
1775         delete cmout;
1776     }
1777 }
1778 
1779 
1780 // this function sets the bits in the CMOUT register and also
1781 // sends the state to the T1GCON class if t1gcon is defined
1782 //
set_cmout(unsigned int bit,bool value)1783 void ComparatorModule2::set_cmout(unsigned int bit, bool value)
1784 {
1785     int i;
1786 
1787     if (cmout)
1788     {
1789         if (value)
1790         {
1791             cmout->value.put(cmout->value.get() | (1 << bit));
1792         }
1793         else
1794         {
1795             cmout->value.put(cmout->value.get() & ~(1 << bit));
1796         }
1797     }
1798 
1799     for (i = 0; i < 4; i++)
1800     {
1801         if (m_clc[i])
1802             m_clc[i]->CxOUT_sync(value, bit);
1803     }
1804     if (p_cog)
1805         p_cog->out_Cx(value,bit);
1806 
1807     switch (bit)
1808     {
1809     case 0:		//CM1
1810         for (i = 0; i < 3; i++)
1811         {
1812             if (t1gcon[i])
1813             {
1814                 t1gcon[i]->CM1_gate(value);
1815             }
1816 
1817             if (eccpas[i])
1818             {
1819                 eccpas[i]->c1_output(value);
1820             }
1821         }
1822 
1823         if (sr_module)
1824         {
1825             sr_module->syncC1out(value);
1826         }
1827 
1828         break;
1829 
1830     case 1:		//CM2
1831         for (i = 0; i < 3; i++)
1832         {
1833             if (t1gcon[i])
1834             {
1835                 t1gcon[i]->CM2_gate(value);
1836             }
1837 
1838             if (eccpas[i])
1839             {
1840                 eccpas[i]->c2_output(value);
1841             }
1842         }
1843 
1844         if (sr_module)
1845         {
1846             sr_module->syncC2out(value);
1847         }
1848 
1849         if (ctmu_module)
1850         {
1851             ctmu_module->syncC2out(value);
1852         }
1853 
1854         break;
1855 
1856     default:	//Do nothing other CMs
1857         break;
1858     }
1859 }
1860 
1861 
set_DAC_volt(double _volt)1862 void ComparatorModule2::set_DAC_volt(double _volt)
1863 {
1864     DAC_voltage = _volt;
1865 
1866     for (int i = 0; i < 4; i++)
1867     {
1868         if (cmxcon0[i])
1869         {
1870             cmxcon0[i]->get();
1871         }
1872     }
1873 }
1874 
1875 
set_FVR_volt(double _volt)1876 void ComparatorModule2::set_FVR_volt(double _volt)
1877 {
1878     FVR_voltage = _volt;
1879     Dprintf(("ComparatorModule2::set_FVR_volt %.2f\n", FVR_voltage));
1880 
1881     for (int i = 0; i < 4; i++)
1882     {
1883         if (cmxcon0[i])
1884         {
1885             cmxcon0[i]->get();
1886         }
1887     }
1888 }
1889 
1890 
1891 // set interrupt for comparator cm
set_if(unsigned int cm)1892 void ComparatorModule2::set_if(unsigned int cm)
1893 {
1894     switch (cm)
1895     {
1896     case 0:
1897         pir_set->set_c1if();
1898         break;
1899 
1900     case 1:
1901         pir_set->set_c2if();
1902         break;
1903 
1904     case 2:
1905         pir_set->set_c3if();
1906         break;
1907 
1908     case 3:
1909         pir_set->set_c4if();
1910         break;
1911     }
1912 }
1913