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