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