1 /*
2 Copyright (C) 2017,2018 Roy R. Rankin
3
4 This file is part of the libgpsim library of gpsim
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, see
18 <http://www.gnu.org/licenses/lgpl-2.1.html>.
19 */
20
21 // Complimentry Waveform Generated (CWG) module
22
23 //#define DEBUG
24 #if defined(DEBUG)
25 #include "../config.h"
26 #define Dprintf(arg) {printf("%s:%d ",__FILE__,__LINE__); printf arg; }
27 #else
28 #define Dprintf(arg) {}
29 #endif
30
31 #include <assert.h>
32 #include <iostream>
33
34 #include "cwg.h"
35 #include "ioports.h"
36 #include "processor.h"
37 #include "stimuli.h"
38 #include "trace.h"
39
40
41 // Set pin direction
42 class TristateControl : public SignalControl
43 {
44 public:
TristateControl(CWG * _cwg,PinModule * _pin)45 TristateControl(CWG *_cwg, PinModule *_pin)
46 : m_cwg(_cwg), m_pin(_pin)
47 {}
~TristateControl()48 ~TristateControl() {}
49
set_pin_direction(char _direction)50 void set_pin_direction(char _direction)
51 {
52 direction = _direction;
53 }
getState()54 virtual char getState()
55 {
56 return direction;
57 }
release()58 virtual void release()
59 {
60 m_cwg->releasePin(m_pin);
61 }
62
63 private:
64 CWG *m_cwg;
65 PinModule *m_pin;
66 char direction = 0;
67 };
68
69
70 class CWGSignalSource : public SignalControl
71 {
72 public:
CWGSignalSource(CWG * _cwg,PinModule * _pin)73 CWGSignalSource(CWG *_cwg, PinModule *_pin)
74 : m_cwg(_cwg), m_pin(_pin), m_state('?')
75 {
76 assert(m_cwg);
77 }
~CWGSignalSource()78 virtual ~CWGSignalSource() {}
79
setState(char _state)80 void setState(char _state)
81 {
82 m_state = _state;
83 }
getState()84 virtual char getState()
85 {
86 return m_state;
87 }
release()88 virtual void release()
89 {
90 Dprintf(("CWGSignalSource release\n"));
91 m_cwg->releasePinSource(m_pin);
92 }
93
94 private:
95 CWG *m_cwg;
96 PinModule *m_pin;
97 char m_state;
98 };
99
100
101 // Report state changes on incoming FLT pin
102 class FLTSignalSink : public SignalSink
103 {
104 public:
FLTSignalSink(CWG * _cwg)105 explicit FLTSignalSink(CWG *_cwg)
106 : m_cwg(_cwg)
107 {
108 }
109
setSinkState(char new3State)110 virtual void setSinkState(char new3State)
111 {
112 m_cwg->setState(new3State);
113 }
release()114 virtual void release()
115 {
116 delete this;
117 }
118
119 private:
120 CWG *m_cwg;
121 };
122
123
CWG(Processor * pCpu)124 CWG::CWG(Processor *pCpu) :
125 cwg1con0(this, pCpu, "cwg1con0", "CWG Control Register 0"),
126 cwg1con1(this, pCpu, "cwg1con1", "CWG Control Register 1"),
127 cwg1con2(this, pCpu, "cwg1con2", "CWG Control Register 2"),
128 cwg1dbf(this, pCpu, "cwg1dbf", "CWG Falling Dead-Band Count Register"),
129 cwg1dbr(this, pCpu, "cwg1dbr", "CWG Rising Dead-Band Count Register"),
130 cpu(pCpu)
131 {
132 for (auto &state : pwm_state)
133 {
134 state = false;
135 }
136
137 for (auto &state : clc_state)
138 {
139 state = false;
140 }
141 }
142
143
~CWG()144 CWG::~CWG()
145 {
146 if (Atri)
147 {
148 if (pinAactive)
149 {
150 releasePin(pinA);
151 }
152
153 delete Atri;
154 delete Asrc;
155 }
156
157 if (Btri)
158 {
159 if (pinBactive)
160 {
161 releasePin(pinB);
162 }
163
164 delete Btri;
165 delete Bsrc;
166 }
167 }
168
169
setState(char state)170 void CWG::setState(char state)
171 {
172 Dprintf(("CWG::setState state=%c\n", state));
173
174 if (state == '0' && FLTstate) // new low edge
175 {
176 con2_value |= GxASE;
177 cwg1con2.put_value(con2_value);
178 autoShutEvent(true);
179 active_next_edge = false;
180
181 }
182 else if (state == '1' && !FLTstate)
183 {
184 con2_value &= ~GxASE;
185 cwg1con2.put_value(con2_value);
186 active_next_edge = true;
187 }
188
189 FLTstate = (state != '0');
190 }
191
192
set_IOpins(PinModule * p1,PinModule * p2,PinModule * _pinFLT)193 void CWG::set_IOpins(PinModule *p1, PinModule *p2, PinModule *_pinFLT)
194 {
195 pinA = p1;
196 pinB = p2;
197 pinFLT = _pinFLT;
198
199 if (Atri)
200 {
201 delete Atri;
202 delete Asrc;
203 }
204
205 Atri = new TristateControl(this, pinA);
206 Asrc = new CWGSignalSource(this, pinA);
207
208 if (Btri)
209 {
210 delete Btri;
211 delete Bsrc;
212 }
213
214 Btri = new TristateControl(this, pinB);
215 Bsrc = new CWGSignalSource(this, pinB);
216 }
217
218
oeA()219 void CWG::oeA()
220 {
221 Dprintf(("CWG::oeA() %u %u\n", (con0_value & GxEN), (con0_value & GxOEA)));
222
223 if ((con0_value & GxEN) && (con0_value & GxOEA))
224 {
225 if (!pinAactive)
226 {
227 Agui = pinA->getPin().GUIname();
228 pinA->getPin().newGUIname("CWGA");
229 Atri->set_pin_direction('0');
230 pinA->setControl(Atri);
231 pinA->setSource(Asrc);
232 pinA->updatePinModule();
233 pinAactive = true;
234 srcAactive = true;
235 }
236
237 }
238 else if (pinAactive)
239 {
240 if (Agui.length())
241 {
242 pinA->getPin().newGUIname(Agui.c_str());
243
244 }
245 else
246 {
247 pinA->getPin().newGUIname(pinA->getPin().name().c_str());
248 }
249
250 pinA->setControl(0);
251 pinA->setSource(0);
252 pinA->updatePinModule();
253 pinAactive = false;
254 srcAactive = false;
255 }
256 }
257
258
oeB()259 void CWG::oeB()
260 {
261 if ((con0_value & GxEN) && (con0_value & GxOEB))
262 {
263 if (!pinBactive)
264 {
265 Bgui = pinB->getPin().GUIname();
266 pinB->getPin().newGUIname("CWGB");
267 Btri->set_pin_direction('0');
268 pinB->setControl(Btri);
269 pinB->setSource(Bsrc);
270 pinB->updatePinModule();
271 pinBactive = true;
272 srcBactive = true;
273 }
274
275 }
276 else if (pinBactive)
277 {
278 if (Bgui.length())
279 {
280 pinB->getPin().newGUIname(Bgui.c_str());
281
282 }
283 else
284 {
285 pinB->getPin().newGUIname(pinB->getPin().name().c_str());
286 }
287
288 pinB->setControl(0);
289 pinB->setSource(0);
290 pinB->updatePinModule();
291 pinBactive = false;
292 srcBactive = false;
293 }
294 }
295
296
cwg_con0(unsigned int value)297 void CWG::cwg_con0(unsigned int value)
298 {
299 unsigned int diff = con0_value ^ value;
300 con0_value = value;
301
302 if (diff & GxEN)
303 {
304 if (diff & GxOEA) oeA();
305 if (diff & GxOEB) oeB();
306
307 }
308 }
309
310
cwg_con1(unsigned int value)311 void CWG::cwg_con1(unsigned int value)
312 {
313 con1_value = value;
314 }
315
316
cwg_con2(unsigned int value)317 void CWG::cwg_con2(unsigned int value)
318 {
319 unsigned int diff = value ^ con2_value;
320 con2_value = value;
321
322 if (diff & GxASE)
323 {
324 if (value & GxASE)
325 {
326 if (value & GxARSEN)
327 {
328 active_next_edge = true;
329 }
330
331 autoShutEvent(true);
332
333 }
334 else
335 {
336 if (shutdown_active)
337 {
338 active_next_edge = true;
339 autoShutEvent(false);
340 }
341 }
342 }
343
344 if (diff & GxASDFLT)
345 {
346 enableAutoShutPin(value & GxASDFLT);
347 }
348 }
349
350
autoShutEvent(bool on)351 void CWG::autoShutEvent(bool on)
352 {
353 if (on)
354 {
355 Dprintf(("CWG::autoShutEvent on A 0x%x\n", con1_value & (GxASDLA0 | GxASDLA1)));
356
357 switch (con1_value & (GxASDLA0 | GxASDLA1))
358 {
359 case 0: // to inactive state
360 cwg1dbr.new_edge(false, 0.0);
361 break;
362
363 case GxASDLA0: // pin tristated
364 cwg1dbr.kill_callback();
365 Atri->set_pin_direction('1');
366 pinA->updatePinModule();
367 break;
368
369 case GxASDLA1: // pin to 0
370 cwg1dbr.kill_callback();
371 Asrc->setState('0');
372 pinA->updatePinModule();
373 break;
374
375 case GxASDLA0|GxASDLA1: // pin to 1
376 cwg1dbr.kill_callback();
377 Asrc->setState('1');
378 pinA->updatePinModule();
379 break;
380 }
381
382 Dprintf(("CWG::autoShutEvent on B 0x%x\n", con1_value & (GxASDLB0 | GxASDLB1)));
383
384 switch (con1_value & (GxASDLB0 | GxASDLB1))
385 {
386 case 0: // to inactive state
387 cwg1dbf.new_edge(true, 0.0);
388 break;
389
390 case GxASDLB0: // pin tristated
391 cwg1dbf.kill_callback();
392 Btri->set_pin_direction('1');
393 pinB->updatePinModule();
394 break;
395
396 case GxASDLB1: // pin to 0
397 cwg1dbf.kill_callback();
398 Bsrc->setState('0');
399 pinB->updatePinModule();
400 break;
401
402 case GxASDLB0|GxASDLB1: // pin to 1
403 cwg1dbf.kill_callback();
404 Bsrc->setState('1');
405 pinB->updatePinModule();
406 break;
407 }
408
409 shutdown_active = true;
410
411 }
412 else
413 {
414 shutdown_active = false;
415 Atri->set_pin_direction('0');
416 pinA->updatePinModule();
417 Btri->set_pin_direction('0');
418 pinB->updatePinModule();
419 }
420 }
421
422
enableAutoShutPin(bool on)423 void CWG::enableAutoShutPin(bool on)
424 {
425 if (on)
426 {
427 FLTgui = pinFLT->getPin().GUIname();
428 pinFLT->getPin().newGUIname("_FLT");
429
430 if (!FLTsink)
431 {
432 FLTsink = new FLTSignalSink(this);
433 pinFLT->addSink(FLTsink);
434 FLTstate = pinFLT->getPin().getState();
435 Dprintf(("CWG::enableAutoShutPin FLTstate=%x\n", FLTstate));
436 }
437
438 }
439 else
440 {
441 if (FLTgui.length())
442 {
443 pinFLT->getPin().newGUIname(FLTgui.c_str());
444
445 }
446 else
447 {
448 pinFLT->getPin().newGUIname(pinFLT->getPin().name().c_str());
449 }
450
451 if (FLTsink)
452 {
453 pinFLT->removeSink(FLTsink);
454 FLTsink->release();
455 FLTsink = nullptr;
456 }
457 }
458 }
459
460
releasePin(PinModule * pin)461 void CWG::releasePin(PinModule *pin)
462 {
463 if (pin)
464 {
465 Dprintf(("CWG::releasePin %s pinAactive %d pinBactive %d\n", pin->getPin().name().c_str(), pinAactive, pinBactive));
466 pin->getPin().newGUIname(pin->getPin().name().c_str());
467 pin->setControl(0);
468
469 if (pin == pinA)
470 {
471 pinAactive = false;
472 }
473
474 if (pin == pinB)
475 {
476 pinBactive = false;
477 }
478 }
479 }
480
481
releasePinSource(PinModule * pin)482 void CWG::releasePinSource(PinModule *pin)
483 {
484 Dprintf(("CWG::releasePinSource %p\n", pin));
485
486 if (pin)
487 {
488 if (pin == pinA)
489 {
490 srcAactive = false;
491 }
492
493 if (pin == pinB)
494 {
495 srcBactive = false;
496 }
497
498 //pin->setSource(0);
499 }
500 }
501
502
input_source(bool level)503 void CWG::input_source(bool level)
504 {
505 if (level && active_next_edge)
506 {
507 con2_value &= ~GxASE;
508 cwg1con2.put_value(con2_value);
509 autoShutEvent(false);
510 active_next_edge = false;
511 }
512
513 if (!shutdown_active)
514 {
515 double mult = (con0_value & GxCS0) ? 16e6 / cpu->get_frequency() : 1;
516 cwg1dbr.new_edge(level, mult);
517 cwg1dbf.new_edge(!level, mult);
518 }
519 }
520
521
522 // Catch pwm output change
out_pwm(bool level,char index)523 void CWG::out_pwm(bool level, char index)
524 {
525 if (index >= 2)
526 {
527 return;
528 }
529
530 if ((level != pwm_state[index - 1])
531 && (con0_value & GxEN)
532 && ((int)(con1_value & (GxIS0 | GxIS1)) == index - 1))
533 {
534 Dprintf(("CWG::out_pwm level=%d shutdown_active=%d con2=0x%x\n", level, shutdown_active, con2_value));
535 input_source(level);
536 }
537
538 pwm_state[index - 1] = level;
539 }
540
541
542 // catch CLC (Config Logic Cell) output
out_CLC(bool level,char index)543 void CWG::out_CLC(bool level, char index)
544 {
545 assert(index > 1);
546
547 if ((level != clc_state[index - 1])
548 && (con0_value & GxEN)
549 && ((int)(con1_value & (GxIS0 | GxIS1)) == 3))
550 {
551 Dprintf(("CWG::out_clc level=%d shutdown_active=%d con2=0x%x\n", level, shutdown_active, con2_value));
552 input_source(level);
553 }
554
555 clc_state[index - 1] = level;
556 }
557
558
559 // Catch NCO (Numerically Controlled Oscillator) output
out_NCO(bool level)560 void CWG::out_NCO(bool level)
561 {
562 if ((level != nco_state)
563 && (con0_value & GxEN)
564 && ((int)(con1_value & (GxIS0 | GxIS1)) == 2))
565 {
566 Dprintf(("CWG::out_NCO level=%d shutdown_active=%d con2=0x%x\n", level, shutdown_active, con2_value));
567 input_source(level);
568 }
569
570 nco_state = level;
571 }
572
573
set_outA(bool level)574 void CWG::set_outA(bool level)
575 {
576 bool invert = con0_value & GxPOLA;
577 Dprintf(("CWG::set_outA now=%" PRINTF_GINT64_MODIFIER "d level=%d invert=%d out=%d\n", get_cycles().get(), level, invert, level ^ invert));
578 Asrc->setState((level ^ invert) ? '1' : '0');
579 pinA->updatePinModule();
580 }
581
582
set_outB(bool level)583 void CWG::set_outB(bool level)
584 {
585 bool invert = con0_value & GxPOLB;
586 Dprintf(("CWG::set_outB now=%" PRINTF_GINT64_MODIFIER "d level=%d invert=%d out=%d\n", get_cycles().get(), level, invert, level ^ invert));
587 Bsrc->setState((level ^ invert) ? '1' : '0');
588 pinB->updatePinModule();
589 }
590
591
CWG4(Processor * pCpu)592 CWG4::CWG4(Processor *pCpu) : CWG(pCpu)
593 {
594 cwg1con1.set_con1_mask(0xf7);
595 }
596
597
598 // catch PWM (Pulse Width Mod) output
out_pwm(bool level,char index)599 void CWG4::out_pwm(bool level, char index)
600 {
601 if (index >= 4)
602 {
603 return;
604 }
605
606 if ((level != pwm_state[index - 1])
607 && (con0_value & GxEN)
608 && ((int)(con1_value & (GxIS0 | GxIS1 | GxIS2)) == index - 1))
609 {
610 Dprintf(("CWG4::out_pwm level=%d shutdown_active=%d con2=0x%x\n", level, shutdown_active, con2_value));
611 input_source(level);
612 }
613
614 pwm_state[index - 1] = level;
615 }
616
617
618 // Catch NCO (Numerically Controlled Oscillator) output
out_NCO(bool level)619 void CWG4::out_NCO(bool level)
620 {
621 if ((level != nco_state)
622 && (con0_value & GxEN)
623 && ((int)(con1_value & (GxIS0 | GxIS1 | GxIS2)) == 6))
624 {
625 Dprintf(("CWG4::out_NCO level=%d shutdown_active=%d con2=0x%x\n", level, shutdown_active, con2_value));
626 input_source(level);
627 }
628
629 nco_state = level;
630 }
631
632
CWGxCON0(CWG * pt,Processor * pCpu,const char * pName,const char * pDesc)633 CWGxCON0::CWGxCON0(CWG* pt, Processor *pCpu, const char *pName, const char *pDesc)
634 : sfr_register(pCpu, pName, pDesc), pt_cwg(pt), con0_mask(0xf9)
635 {
636 }
637
638
put(unsigned int new_value)639 void CWGxCON0::put(unsigned int new_value)
640 {
641 new_value &= con0_mask;
642
643 if (!(new_value ^ value.get()))
644 {
645 return;
646 }
647
648 trace.raw(write_trace.get() | value.get());
649 value.put(new_value);
650 pt_cwg->cwg_con0(new_value);
651 }
652
653
CWGxCON1(CWG * pt,Processor * pCpu,const char * pName,const char * pDesc)654 CWGxCON1::CWGxCON1(CWG *pt, Processor *pCpu, const char *pName, const char *pDesc)
655 : sfr_register(pCpu, pName, pDesc), pt_cwg(pt), con1_mask(0xf3)
656 {
657 }
658
659
put(unsigned int new_value)660 void CWGxCON1::put(unsigned int new_value)
661 {
662 new_value &= con1_mask;
663 unsigned int diff = new_value ^ value.get();
664
665 if (!diff)
666 {
667 return;
668 }
669
670 trace.raw(write_trace.get() | value.get());
671 value.put(new_value);
672 pt_cwg->cwg_con1(new_value);
673 }
674
675
CWGxCON2(CWG * pt,Processor * pCpu,const char * pName,const char * pDesc)676 CWGxCON2::CWGxCON2(CWG *pt, Processor *pCpu, const char *pName, const char *pDesc)
677 : sfr_register(pCpu, pName, pDesc), pt_cwg(pt), con2_mask(0xc3)
678 {
679 }
680
681
put(unsigned int new_value)682 void CWGxCON2::put(unsigned int new_value)
683 {
684 new_value &= con2_mask;
685 unsigned int diff = new_value ^ value.get();
686
687 if (!diff)
688 {
689 return;
690 }
691
692 trace.raw(write_trace.get() | value.get());
693 value.put(new_value);
694 pt_cwg->cwg_con2(new_value);
695 }
696
697
CWGxDBF(CWG * pt,Processor * pCpu,const char * pName,const char * pDesc)698 CWGxDBF::CWGxDBF(CWG *pt, Processor *pCpu, const char *pName, const char *pDesc)
699 : sfr_register(pCpu, pName, pDesc), pt_cwg(pt)
700 {
701 }
702
703
callback()704 void CWGxDBF::callback()
705 {
706 Dprintf(("CWGxDBF::callback() %" PRINTF_GINT64_MODIFIER "d\n", get_cycles().get()));
707 pt_cwg->set_outB(next_level);
708 future_cycle = 0;
709 }
710
711
callback_print()712 void CWGxDBF::callback_print()
713 {
714 std::cout << "CWGxDBF " << name() << " CallBack ID " << CallBackID << '\n';
715 }
716
717
kill_callback()718 void CWGxDBF::kill_callback()
719 {
720 if (future_cycle)
721 {
722 Dprintf(("CWGxDBF::kill_callback() clear future_cycle=%" PRINTF_GINT64_MODIFIER "d\n", future_cycle));
723 get_cycles().clear_break(future_cycle);
724 future_cycle = 0;
725 }
726 }
727
728
new_edge(bool level,double multi)729 void CWGxDBF::new_edge(bool level, double multi)
730 {
731 /* gpsim delay increment is Fosc/4 which is 1/4
732 resolution of deadband, so deadband is approximate
733 */
734 int delay = (value.get() * multi + 2) / 4;
735 next_level = level;
736 Dprintf(("CWGxDBF::new_edge now=%" PRINTF_GINT64_MODIFIER "d f=%.0f level=%d delay=%d\n", get_cycles().get(), ((Processor *)cpu)->get_frequency(), level, delay));
737
738 if (future_cycle)
739 {
740 Dprintf(("\t clear future_cycle=%" PRINTF_GINT64_MODIFIER "d\n", future_cycle));
741 get_cycles().clear_break(future_cycle);
742 future_cycle = 0;
743 }
744
745 if (!delay || !level)
746 {
747 pt_cwg->set_outB(next_level);
748
749 }
750 else
751 {
752 future_cycle = get_cycles().get() + delay;
753 get_cycles().set_break(future_cycle, this);
754 }
755 }
756
757
CWGxDBR(CWG * pt,Processor * pCpu,const char * pName,const char * pDesc)758 CWGxDBR::CWGxDBR(CWG *pt, Processor *pCpu, const char *pName, const char *pDesc)
759 : sfr_register(pCpu, pName, pDesc), pt_cwg(pt)
760 {
761 }
762
763
kill_callback()764 void CWGxDBR::kill_callback()
765 {
766 if (future_cycle)
767 {
768 Dprintf(("CWGxDBR::kill_callback() clear future_cycle=%" PRINTF_GINT64_MODIFIER "d\n", future_cycle));
769 get_cycles().clear_break(future_cycle);
770 future_cycle = 0;
771 }
772 }
773
774
new_edge(bool level,double multi)775 void CWGxDBR::new_edge(bool level, double multi)
776 {
777 /* gpsim delay increment is Fosc/4 which is 1/4
778 resolution of deadband, so deadband is approximate
779 */
780 int delay = (value.get() * multi + 2) / 4;
781 next_level = level;
782 Dprintf(("CWGxDBR::new_edge now=%" PRINTF_GINT64_MODIFIER "d f=%.0f level=%d delay=%d\n", get_cycles().get(), ((Processor *)cpu)->get_frequency(), level, delay));
783
784 if (future_cycle)
785 {
786 Dprintf(("clear future_cycle=%" PRINTF_GINT64_MODIFIER "d\n", future_cycle));
787 get_cycles().clear_break(future_cycle);
788 future_cycle = 0;
789 }
790
791 if (!delay || !level)
792 {
793 pt_cwg->set_outA(next_level);
794
795 }
796 else
797 {
798 future_cycle = get_cycles().get() + delay;
799 get_cycles().set_break(future_cycle, this);
800 }
801 }
802
803
callback()804 void CWGxDBR::callback()
805 {
806 Dprintf(("CWGxDBR::callback() %" PRINTF_GINT64_MODIFIER "d\n", get_cycles().get()));
807 pt_cwg->set_outA(next_level);
808 future_cycle = 0;
809 }
810
811
callback_print()812 void CWGxDBR::callback_print()
813 {
814 std::cout << "CWGxDBR " << name() << " CallBack ID " << CallBackID << '\n';
815 }
816
817
818 class COGSignalSource : public SignalControl
819 {
820 public:
COGSignalSource(COG * _cog,int _index)821 COGSignalSource(COG *_cog, int _index)
822 : m_cog(_cog),
823 state('?'), index(_index)
824 {
825 assert(m_cog);
826 }
~COGSignalSource()827 virtual ~COGSignalSource() { }
828
setState(char m_state)829 void setState(char m_state) { state = m_state; }
getState()830 virtual char getState() { return state; }
release()831 virtual void release() { m_cog->releasePins(index); }
832
833 private:
834 COG *m_cog;
835 char state;
836 int index;
837 };
838
839 class COGTristate : public SignalControl
840 {
841 public:
COGTristate()842 COGTristate() { }
~COGTristate()843 ~COGTristate() { }
getState()844 virtual char getState() { return '0'; } // set port as output
release()845 virtual void release() { }
846 };
847
848 class COGSink : public SignalSink
849 {
850 public:
COGSink(COG * _cog)851 explicit COGSink(COG *_cog)
852 : m_cog(_cog)
853 {
854 assert(_cog);
855 }
856
setSinkState(char new3State)857 virtual void setSinkState(char new3State) { m_cog->cogx_in(new3State); }
release()858 virtual void release() {}
859 private:
860 COG *m_cog;
861 };
862
863
864
865 //---------------------------------------------------------------------
866
867
COG(Processor * pCpu,const char * pName)868 COG::COG(Processor *pCpu, const char *pName) :
869 cogxcon0(this, pCpu, "cog1con0", "COG Control Register 0"),
870 cogxcon1(this, pCpu, "cog1con1", "COG Control Register 1"),
871 cogxris(this, pCpu, "cog1ris", "COG Rising Event Input Selection Register"),
872 cogxrsim(this, pCpu, "cog1rsim", "COG Rising Event Source Input Mode Registe"),
873 cogxfis(this, pCpu, "cog1fis", "COG Falling Event Input Selection Register"),
874 cogxfsim(this, pCpu, "cog1fsim", "COG Falling Event Source Input Mode Register"),
875 cogxasd0(this, pCpu, "cog1asd0", "COG Auto-shutdown Control Register 0"),
876 cogxasd1(this, pCpu, "cog1asd1", "COG Auto-shutdown Control Register 1"),
877 cogxstr(this, pCpu, "cog1str", "COG Steering Control Register"),
878 cogxdbr(this, pCpu, "cog1dbr", "COG Rising Event Dead-band Count Register"),
879 cogxdbf(this, pCpu, "cog1dbf", "COG Falling Event Dead-band Count Register"),
880 cogxblkr(this, pCpu, "cog1blkr", "COG Rising Event Blanking Count Register"),
881 cogxblkf(this, pCpu, "cog1blkf", "COG Falling Event Blanking Count Register"),
882 cogxphr(this, pCpu, "cog1phr", "COG Rising Edge Phase Delay Count Register"),
883 cogxphf(this, pCpu, "cog1phf", "COG Falling Edge Phase Delay Count Register"),
884 cpu(pCpu), name_str(pName),
885 pinIN(nullptr), cogSink(nullptr), set_cycle(0), reset_cycle(0),
886 bridge_shutdown(false), input_set(true), input_clear(false),
887 full_forward(true), push_pull_level(false)
888 {
889 for (int i=0; i<4; i++)
890 {
891 m_PinModule[i] = 0;
892 m_source[i] = 0;
893 source_active[i] = 0;
894 steer_ctl[i] = false;
895 }
896 m_tristate = new COGTristate();
897 }
898
~COG()899 COG::~COG()
900 {
901 delete m_tristate;
902 if (cogSink)
903 delete cogSink;
904
905 for(int i=0; i < 4; i++)
906 {
907 if (m_source[i])
908 delete m_source[i];
909 }
910 }
911
912 // set or switch output pin, i = 0-3 for outputs A-D
setIOpin(PinModule * _pin,int i)913 void COG::setIOpin(PinModule * _pin, int i)
914 {
915
916 if (i > 3) // Input_pin
917 {
918 Dprintf(("COG::setpinIN i=%d pin=%s\n", i, _pin->getPin().name().c_str()));
919 // remove cogSink from old input pin
920 if (cogSink)
921 {
922 pinIN->removeSink(cogSink);
923 delete cogSink;
924 cogSink = nullptr;
925 }
926 pinIN = _pin;
927 set_inputPin();
928 return;
929 }
930 // Disconnect existing output pin
931 if (m_PinModule[i] && m_PinModule[i] != _pin && m_source[i])
932 {
933 m_PinModule[i]->setSource(0);
934 m_PinModule[i]->setControl(0);
935 delete m_source[i];
936 m_source[i] = nullptr;
937 }
938 m_PinModule[i] = _pin;
939 if (_pin)
940 set_outputPins();
941 }
942
set_outputPins()943 void COG::set_outputPins()
944 {
945 char name[] = "COGA";
946 for (int i=0; i< 4; i++)
947 {
948 if (cogxcon0.value.get() & GxEN)
949 {
950 // COG is enabled, setup defines output pins that are not enabled.
951 if (m_PinModule[i] && !m_source[i])
952 {
953 m_source[i] = new COGSignalSource(this, i);
954 m_PinModule[i]->setSource(m_source[i]);
955 m_PinModule[i]->setControl(m_tristate);
956 name[3] = 'A'+i;
957 m_PinModule[i]->getPin().newGUIname(name);
958 m_PinModule[i]->updatePinModule();
959 }
960 }
961 else
962 {
963 // COG not enabled, disconnect active output pins
964 if (m_PinModule[i] && m_source[i])
965 {
966 m_PinModule[i]->setSource(0);
967 m_PinModule[i]->setControl(0);
968 delete m_source[i];
969 m_source[i] = nullptr;
970 m_PinModule[i]->getPin().newGUIname(m_PinModule[i]->getPin().name().c_str());
971 }
972 }
973 }
974 }
975 // connect or disconnect pinIN from COG based on COGxCON1, COGxRIS and COGxFIS
set_inputPin()976 void COG::set_inputPin()
977 {
978
979 if ((cogxcon0.value.get() & GxEN) &&
980 ((cogxfis.value.get() & 1) || (cogxfis.value.get() & 1)))
981 {
982 if (!cogSink)
983 {
984 cogSink = new COGSink(this);
985 pinIN->addSink(cogSink);
986 char name[] = "COGIN";
987 pinIN->getPin().newGUIname(name);
988 }
989 }
990 else // pinIN no longer active in COG
991 {
992 if (cogSink)
993 {
994 pinIN->removeSink(cogSink);
995 delete cogSink;
996 cogSink = nullptr;
997 pinIN->getPin().newGUIname(pinIN->getPin().name().c_str());
998 }
999
1000 }
1001 }
1002
input_event(int index,bool level)1003 void COG::input_event(int index, bool level)
1004 {
1005 unsigned int mask = 1<<index;
1006 bool enabled = cogxcon0.value.get() & GxEN;
1007
1008 if (!enabled)
1009 {
1010 input_set = level;
1011 input_clear = !level;
1012 return;
1013 }
1014
1015 bool set = (cogxris.value.get() & mask);
1016 bool clear = (cogxris.value.get() & mask);
1017 bool change = false;
1018 if (set && (input_set != level))
1019 {
1020 input_set = level;
1021 if (level)
1022 {
1023 change = true;
1024 drive_bridge(level, FIRST_STATE);
1025 }
1026 }
1027 if (clear && (input_clear != !level))
1028 {
1029 input_clear = !level;
1030 if (!level)
1031 {
1032 drive_bridge(level, FIRST_STATE);
1033 change = true;
1034 }
1035 }
1036 if (change && enabled)
1037 {
1038 // prod COG
1039 }
1040 }
1041
cogx_in(char new3State)1042 void COG::cogx_in(char new3State)
1043 {
1044 bool level = (new3State == '1' || new3State == 'W');
1045 input_event(0, level);
1046 }
1047
1048 // catch Comparator events
out_Cx(bool level,char index)1049 void COG::out_Cx(bool level, char index)
1050 {
1051 if (index > 2) return;
1052
1053 input_event(index+1, level);
1054 }
1055
1056 // catch CCP events
out_ccp(bool level,char index)1057 void COG::out_ccp(bool level, char index)
1058 {
1059 if (index >= 3) return;
1060 input_event(index+4, level);
1061 }
1062 // catch pwm events
out_pwm(bool level,char index)1063 void COG::out_pwm(bool level, char index)
1064 {
1065 if (index >= 3) return;
1066 input_event(index+4, level);
1067 }
1068 // catch clc events
out_clc(bool level,char index)1069 void COG::out_clc(bool level, char index)
1070 {
1071 if (index) return;
1072 input_event(3, level);
1073 }
1074
1075
cog_con0(unsigned int old)1076 void COG::cog_con0(unsigned int old)
1077 {
1078 unsigned int new_value = cogxcon0.value.get();
1079
1080 if ((old ^ new_value) & GxEN)
1081 {
1082 set_inputPin();
1083 set_outputPins();
1084 }
1085 if (!(old & GxEN) && ((new_value & GxMD_MASK) & 2))
1086 full_forward = !((new_value & GxMD_MASK) & 1);
1087 }
1088
cog_con1(unsigned int new_value)1089 void COG::cog_con1(unsigned int new_value)
1090 {
1091 unsigned int diff = cogxcon1.value.get() ^ new_value;
1092 if (!diff) return;
1093
1094 for (int i=0; i<4; i++)
1095 {
1096 active_high[i] = !(new_value & (1<<i));
1097 }
1098 }
1099
cog_asd0(unsigned int new_value,unsigned int old)1100 void COG::cog_asd0(unsigned int new_value, unsigned int old)
1101 {
1102 if ((old^new_value) & GxASE)
1103 {
1104 if (new_value & GxASE) // GxASE high transition
1105 {
1106 bridge_shutdown = true;
1107 if (!auto_shut_src)
1108 shutdown_bridge();
1109
1110 auto_shut_src |= GXASE;
1111 }
1112 else // GxASE low transition
1113 {
1114 auto_shut_src &= ~GXASE;
1115 if (!auto_shut_src && !(new_value & GxARSEN))
1116 {
1117 bridge_shutdown = false;
1118 drive_bridge(false, 0);
1119 }
1120 }
1121 }
1122 else if ((old^new_value) & 0x37) // changed output settings
1123 {
1124 if (bridge_shutdown)
1125 shutdown_bridge();
1126 }
1127 }
1128
cog_str(unsigned int new_value)1129 void COG::cog_str(unsigned int new_value)
1130 {
1131 unsigned int diff = cogxstr.value.get() ^ new_value;
1132 // if steer control changed and COG not enabled or not in sync steer mode
1133 // update steer_ctl
1134 if ((diff & 0x0f) && (cogxcon0.value.get() & 0x81) != 0x81)
1135 {
1136 for(int i=0; i<4; i++)
1137 {
1138 steer_ctl[i] = new_value & (1<<i);
1139 }
1140 }
1141 }
COGxCON0(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1142 COGxCON0::COGxCON0(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1143 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0xdf)
1144 {
1145 }
1146
put(unsigned int new_value)1147 void COGxCON0::put(unsigned int new_value)
1148 {
1149 unsigned int old = value.get();
1150 new_value &= mask;
1151 if (!(new_value ^ old)) return;
1152 trace.raw(write_trace.get() | value.get());
1153 value.put(new_value);
1154 pt_cog->cog_con0(old);
1155 }
COGxCON1(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1156 COGxCON1::COGxCON1(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1157 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0xcf)
1158 {
1159 }
put(unsigned int new_value)1160 void COGxCON1::put(unsigned int new_value)
1161 {
1162 new_value &= mask;
1163 if (!(new_value ^ value.get())) return;
1164 trace.raw(write_trace.get() | value.get());
1165 pt_cog->cog_con1(new_value);
1166 value.put(new_value);
1167 }
1168
COGxRIS(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1169 COGxRIS::COGxRIS(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1170 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x7f)
1171 {
1172 }
1173
put(unsigned int new_value)1174 void COGxRIS::put(unsigned int new_value)
1175 {
1176 new_value &= mask;
1177 if (!(new_value ^ value.get())) return;
1178 trace.raw(write_trace.get() | value.get());
1179 value.put(new_value);
1180 pt_cog->set_inputPin();
1181 }
1182
COGxFIS(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1183 COGxFIS::COGxFIS(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1184 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x7f)
1185 {
1186 }
1187
1188
put(unsigned int new_value)1189 void COGxFIS::put(unsigned int new_value)
1190 {
1191 new_value &= mask;
1192 if (!(new_value ^ value.get())) return;
1193 trace.raw(write_trace.get() | value.get());
1194 value.put(new_value);
1195 pt_cog->set_inputPin();
1196 }
COGxRSIM(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1197 COGxRSIM::COGxRSIM(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1198 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x7f)
1199 {
1200 }
1201
COGxFSIM(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1202 COGxFSIM::COGxFSIM(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1203 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x7f)
1204 {
1205 }
1206
1207
COGxASD1(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1208 COGxASD1::COGxASD1(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1209 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x0f)
1210 {
1211 }
1212
COGxSTR(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1213 COGxSTR::COGxSTR(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1214 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0xff)
1215 {
1216 }
1217
put(unsigned int new_value)1218 void COGxSTR::put(unsigned int new_value)
1219 {
1220 new_value &= mask;
1221 if (!(new_value ^ value.get())) return;
1222 trace.raw(write_trace.get() | value.get());
1223 pt_cog->cog_str(new_value);
1224 value.put(new_value);
1225 }
1226
COGxDBR(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1227 COGxDBR::COGxDBR(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1228 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x3f)
1229 {
1230 }
1231
COGxDBF(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1232 COGxDBF::COGxDBF(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1233 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x3f)
1234 {
1235 }
1236
COGxASD0(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1237 COGxASD0::COGxASD0(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1238 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x7c)
1239 {
1240 }
1241
put(unsigned int new_value)1242 void COGxASD0::put(unsigned int new_value)
1243 {
1244 new_value &= mask;
1245 unsigned int old = value.get();
1246 if (!(new_value ^ value.get())) return;
1247 trace.raw(write_trace.get() | old);
1248 value.put(new_value);
1249 pt_cog->cog_asd0(new_value, old);
1250 }
1251
COGxBLKR(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1252 COGxBLKR::COGxBLKR(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1253 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x3f)
1254 {
1255 }
1256
COGxBLKF(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1257 COGxBLKF::COGxBLKF(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1258 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x3f)
1259 {
1260 }
1261
COGxPHR(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1262 COGxPHR::COGxPHR(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1263 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x3f)
1264 {}
1265
COGxPHF(COG * pt,Processor * pCpu,const char * pName,const char * pDesc)1266 COGxPHF::COGxPHF(COG *pt, Processor *pCpu, const char *pName, const char *pDesc):
1267 sfr_register(pCpu, pName, pDesc), pt_cog(pt), mask(0x3f)
1268 {}
1269
1270
output_pin(int pin,bool set)1271 void COG::output_pin(int pin, bool set)
1272 {
1273 if (m_PinModule[pin])
1274 {
1275 Dprintf(("output_pin %d %s active_high=%d set=%d\n", pin, m_PinModule[pin]->getPin().GUIname().c_str(), active_high[pin], set));
1276 m_source[pin]->setState(active_high[pin]^set?'0':'1');
1277 m_PinModule[pin]->updatePinModule();
1278 }
1279 }
callback()1280 void COG::callback()
1281 {
1282
1283 if (phase_cycle == get_cycles().get())
1284 {
1285 phase_cycle = 0;
1286 if (input_set)
1287 drive_bridge(1, PHASE_STATE);
1288 else if (input_clear)
1289 drive_bridge(0, PHASE_STATE);
1290 }
1291 if (set_cycle == get_cycles().get())
1292 {
1293 set_cycle = 0;
1294 drive_bridge(input_set, LAST_STATE);
1295 }
1296 if (reset_cycle == get_cycles().get())
1297 {
1298 drive_bridge(!input_clear, LAST_STATE);
1299 reset_cycle = 0;
1300 }
1301 }
1302 //
1303 // Drive PWM bridge
1304 //
drive_bridge(int level,int state)1305 void COG::drive_bridge(int level, int state)
1306 {
1307 unsigned int con1_reg = cogxcon1.value.get();
1308 int phase_delay = 0;
1309 int deadband_delay = 0;
1310 double clock_div = 1;
1311
1312 if (auto_shut_src || bridge_shutdown)
1313 if (auto_shut_src)
1314 return;
1315
1316 if (bridge_shutdown)
1317 return;
1318
1319 /* if (!(asd0_reg & GxASE)) // auto-shutdown active
1320 {
1321 return;
1322 }
1323 */
1324
1325 int clock = (con1_reg & GxCS_MASK) >> GxCS_SHIFT;
1326 switch(clock)
1327 {
1328 case 0: //Fosc/4
1329 clock_div = 1;
1330 break;
1331 case 1: //Fosc
1332 clock_div = 4;
1333 break;
1334
1335 case 2: //HFINTOSC
1336 clock_div = 16e6 / cpu->get_frequency ();
1337 break;
1338 }
1339 if (state == FIRST_STATE)
1340 {
1341 if (level)
1342 phase_delay = cogxphr.value.get()/clock_div;
1343 else
1344 phase_delay = cogxphf.value.get()/clock_div;
1345 }
1346 if (phase_delay == 0 && state <= PHASE_STATE)
1347 {
1348 if (level && cogxcon1.value.get() & GxRDBS)
1349 {
1350 deadband_delay = cogxdbr.value.get()/clock_div;
1351 }
1352 if (!level && cogxcon1.value.get() & GxFDBS)
1353 {
1354 deadband_delay = cogxdbf.value.get()/clock_div;
1355 }
1356
1357 }
1358 switch(cogxcon0.value.get() & GxMD_MASK) // bridge mode
1359 {
1360 case 0: // STEERED PWM MODE
1361 {
1362 unsigned int str_reg = cogxstr.value.get();
1363 Dprintf(("STEERED PWM MODE %s cogxstr=0x%x\n", name().c_str(), str_reg));
1364 for (int i = 0; i < 4; i++)
1365 {
1366 if (steer_ctl[i]) // Steering Control bit
1367 output_pin(i, level);
1368 else
1369 {
1370 // need to output data regardless of active_high
1371 bool out = str_reg & (1<<(i+4));
1372 out ^= active_high[i];
1373 output_pin(i, out);
1374 }
1375 }
1376 }
1377 break;
1378
1379 case 1: // Synchronous STEERED PWM MODE
1380 {
1381 unsigned int str_reg = cogxstr.value.get();
1382 Dprintf(("STEERED PWM MODE %s cogxstr=0x%x\n", name().c_str(), str_reg));
1383 for (int i = 0; i < 4; i++)
1384 {
1385 if (level) steer_ctl[i] = str_reg & (1<<i);
1386 if (steer_ctl[i]) // Steering Control bit
1387 output_pin(i, level);
1388 else
1389 {
1390 // need to output data regardless of active_high
1391 bool out = str_reg & (1<<(i+4));
1392 out ^= active_high[i];
1393 output_pin(i, out);
1394 }
1395 }
1396 }
1397 break;
1398
1399 case 2: // Full bidge Forward
1400 Dprintf(("full-bridge %s, forward level=%d\n", name().c_str(), level));
1401 if (!full_forward)
1402 {
1403 if (!level) // stay with reverse
1404 {
1405 output_pin(0, 0);
1406 output_pin(1, level);
1407 output_pin(2, 1);
1408 output_pin(3, 0);
1409 }
1410 else // switch direction
1411 {
1412 output_pin(0, 1);
1413 output_pin(1, 0);
1414 output_pin(2, 0);
1415 full_forward = true;
1416 deadband_delay = cogxdbr.value.get()/clock_div;
1417 if (cogxcon1.value.get() & GxRDBS && deadband_delay)
1418 {
1419 set_cycle = get_cycles().get() + deadband_delay;
1420 get_cycles().set_break(set_cycle, this);
1421 }
1422 else
1423 {
1424 output_pin(3, level);
1425 }
1426 }
1427 }
1428 else
1429 {
1430
1431 output_pin(0, 1);
1432 output_pin(1, 0);
1433 output_pin(2, 0);
1434 output_pin(3, level);
1435 }
1436 break;
1437
1438 case 3: // Full bridge reverse
1439 Dprintf(("full-bridge %s, reverse level=%d\n", name().c_str(), level));
1440 if (full_forward)
1441 {
1442 if (!level) // stay with forward
1443 {
1444 output_pin(0, 1);
1445 output_pin(1, 0);
1446 output_pin(2, 0);
1447 output_pin(3, level);
1448 }
1449 else // switch direction
1450 {
1451 output_pin(0, 0);
1452 output_pin(2, 1);
1453 output_pin(3, 0);
1454 full_forward = false;
1455 deadband_delay = cogxdbf.value.get()/clock_div;
1456 if (cogxcon1.value.get() & GxFDBS && deadband_delay)
1457 {
1458 set_cycle = get_cycles().get() + deadband_delay;
1459 get_cycles().set_break(set_cycle, this);
1460 }
1461 else
1462 {
1463 output_pin(1, level);
1464 }
1465 }
1466 }
1467 else
1468 {
1469 output_pin(0, 0);
1470 output_pin(1, level);
1471 output_pin(2, 1);
1472 output_pin(3, 0);
1473 }
1474 break;
1475
1476 case 4: // Half-Bridge
1477 Dprintf(("half-bridge %s cycles=%" PRINTF_GINT64_MODIFIER "d, level=%d state=%d phase=%d deadband=%d\n", name().c_str(), level, state, phase_delay, deadband_delay));
1478
1479 if (phase_delay)
1480 {
1481 phase_cycle = get_cycles().get() + phase_delay;
1482 get_cycles().set_break(phase_cycle, this);
1483 }
1484 else if (deadband_delay)
1485 {
1486 if (level)
1487 {
1488 set_cycle = get_cycles().get() + deadband_delay;
1489 get_cycles().set_break(set_cycle, this);
1490 output_pin(2, !level);
1491 output_pin(3, !level);
1492 }
1493 else
1494 {
1495 reset_cycle = get_cycles().get() + deadband_delay;
1496 get_cycles().set_break(reset_cycle, this);
1497 output_pin(0, level);
1498 output_pin(1, level);
1499 }
1500 }
1501 else
1502 {
1503 output_pin(0, level);
1504 output_pin(1, level);
1505 output_pin(2, !level);
1506 output_pin(3, !level);
1507 }
1508 break;
1509
1510 case 5: // Push-Pull
1511 Dprintf(("Push-Pull %s\n", name().c_str()));
1512 if (level)
1513 {
1514 output_pin(0, !push_pull_level);
1515 output_pin(1, !push_pull_level);
1516 output_pin(2, push_pull_level);
1517 output_pin(3, push_pull_level);
1518 push_pull_level = !push_pull_level;
1519 }
1520 break;
1521
1522 default:
1523 printf("%s::pwm_match impossible COG bridge mode\n", name().c_str());
1524 break;
1525 }
1526
1527 }
1528 //
1529 // Set PWM bridge into shutdown mode
1530 //
shutdown_bridge()1531 void COG::shutdown_bridge()
1532 {
1533 bridge_shutdown = true;
1534
1535 unsigned int COGxasd0 = cogxasd0.value.get();
1536 Dprintf(("cogxasd0=0x%x\n", COGxasd0));
1537
1538 switch((COGxasd0 & GxASDBD_MSK) >> GxASDBD_SFT)
1539 {
1540 case 3: // B, D output 1
1541 output_pin(1, 1);
1542 output_pin(3, 1);
1543 break;
1544
1545 case 2: // B D output 0
1546 output_pin(1, 0);
1547 output_pin(3, 0);
1548 break;
1549
1550 case 1: // B D tristate
1551 if(m_PinModule[1]) m_PinModule[1]->setControl(m_tristate);
1552 if(m_PinModule[3]) m_PinModule[3]->setControl(m_tristate);
1553 break;
1554
1555 case 0: // B D inactive state
1556 break;
1557 }
1558 switch((COGxasd0 & GxASDAC_MSK) >> GxASDAC_SFT)
1559 {
1560 case 3: // A, C output 1
1561 output_pin(0, 1);
1562 output_pin(2, 1);
1563 break;
1564
1565 case 2: // A, C output 0
1566 output_pin(0, 0);
1567 output_pin(2, 0);
1568 break;
1569
1570 case 1: // A C tristate
1571 if(m_PinModule[0]) m_PinModule[0]->setControl(m_tristate);
1572 if(m_PinModule[2]) m_PinModule[2]->setControl(m_tristate);
1573 break;
1574
1575 case 0: // A C inactive state
1576 break;
1577 }
1578 m_PinModule[0]->updatePinModule();
1579 if (m_PinModule[1]) m_PinModule[1]->updatePinModule();
1580 if (m_PinModule[2]) m_PinModule[2]->updatePinModule();
1581 if (m_PinModule[3]) m_PinModule[3]->updatePinModule();
1582 }
1583