2
Copyright (C) 1998 T. Scott Dattalo
3
Copyright (C) 2006,2009,2010,2013,2015,2017 Roy R Rankin
5
This file is part of the libgpsim library of gpsim
7
This library is free software; you can redistribute it and/or
8
modify it under the terms of the GNU Lesser General Public
9
License as published by the Free Software Foundation; either
10
version 2.1 of the License, or (at your option) any later version.
12
This library is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
Lesser General Public License for more details.
17
You should have received a copy of the GNU Lesser General Public
18
License along with this library; if not, see
19
<http://www.gnu.org/licenses/lgpl-2.1.html>.
28
#include "14bit-tmrs.h"
29
#include "a2dconverter.h"
35
// Timer 1&2 modules for the 14bit core pic processors.
40
#define Dprintf(arg) {printf("%s:%d ",__FILE__,__LINE__); printf arg; }
42
#define Dprintf(arg) {}
45
CCPRL::CCPRL(Processor *pCpu, const char *pName )
46
: SfrReg(pCpu, pName ),
47
ccprh(0), ccpcon(0), tmrl(0)
51
bool CCPRL::test_compare_mode()
53
return tmrl && ccpcon && ccpcon->test_compare_mode();
56
void CCPRL::put( uint new_value )
58
value.put( new_value );
59
if(test_compare_mode()) start_compare_mode(); // Actually, re-start with new capture value.
62
void CCPRL::capture_tmr()
64
tmrl->get_low_and_high();
66
value.put( tmrl->value.get() );
68
ccprh->value.put( tmrl->tmrh->value.get() );
71
void CCPRL::start_compare_mode(CCPCON *ref)
73
int capture_value = value.get() + 256*ccprh->value.get();
75
if ( ref ) ccpcon = ref;
76
if ( ccpcon ) tmrl->set_compare_event ( capture_value, ccpcon );
77
else cout << "CPRL: Attempting to set a compare callback with no CCPCON\n";
80
void CCPRL::stop_compare_mode()
82
// If this CCP is in the compare mode, then change to non-compare and cancel
83
// the tmr breakpoint.
85
if(test_compare_mode()) tmrl->clear_compare_event ( ccpcon );
90
void CCPRL::start_pwm_mode()
95
void CCPRL::stop_pwm_mode()
100
//--------------------------------------------------
101
// assign_tmr - assign a new timer to the capture compare module
103
// This was created for the 18f family where it's possible to dynamically
104
// choose which clock is captured during an event.
106
void CCPRL::assign_tmr( TMRL* ptmr )
110
cout << "Reassigning CCPRL clock source\n";
115
//--------------------------------------------------
117
//--------------------------------------------------
119
CCPRH::CCPRH(Processor *pCpu, const char *pName )
120
: SfrReg( pCpu, pName ),
121
ccprl(0),pwm_mode(0),pwm_value(0)
125
// put_value allows PWM code to put data
126
void CCPRH::put_value( uint new_value )
128
value.put( new_value );
131
void CCPRH::put( uint new_value )
133
if( pwm_mode == 0 ) // In pwm_mode, CCPRH is a read-only register.
135
put_value( new_value );
137
if( ccprl && ccprl->test_compare_mode() )
138
ccprl->start_compare_mode(); // Actually, re-start with new capture value.
147
//--------------------------------------------------
149
//--------------------------------------------------
150
class CCPSignalSource : public SignalControl
153
CCPSignalSource( CCPCON *_ccp, int _index )
155
state('?'), index(_index)
159
virtual ~CCPSignalSource() { }
161
void setState(char m_state) { state = m_state; }
162
virtual char getState() { return state; }
163
virtual void release() { m_ccp->releasePins(index); }
171
//--------------------------------------------------
173
//--------------------------------------------------
175
class CCPSignalSink : public SignalSink
178
CCPSignalSink( CCPCON *_ccp, int _index )
179
: m_ccp(_ccp), index(_index)
184
virtual ~CCPSignalSink(){}
185
virtual void release() { m_ccp->releaseSink(); }
186
void setSinkState(char new3State)
187
{ m_ccp->new_edge( new3State=='1' || new3State=='W'); }
194
class Tristate : public SignalControl
199
char getState() { return '1'; } // set port to high impedance by setting it to input
200
virtual void release() { }
203
//--------------------------------------------------
206
CCPCON::CCPCON(Processor *pCpu, const char *pName )
207
: SfrReg( pCpu, pName ),
213
m_bInputEnabled(false),
214
m_bOutputEnabled(false),
216
edges(0), delay_source0(false), delay_source1(false),
217
bridge_shutdown(false),
218
ccprl(0), pir(0), tmr2(0), adcon0(0)
220
for(int i=0; i<4; i++)
224
source_active[i] = false;
231
for( int i=0; i<4; i++ )
235
if( source_active[i] && m_PinModule[i] )
237
m_PinModule[i]->setSource(0);
242
if (m_tristate) delete m_tristate;
243
if (m_PinModule[0] && m_sink) m_PinModule[0]->removeSink(m_sink);
244
if (m_sink) delete m_sink;
247
void CCPCON::setIOPin1(PinModule *p1)
249
if (p1 && &(p1->getPin()))
253
if (m_PinModule[0] != p1)
255
m_PinModule[0]->removeSink(m_sink);
263
m_sink = new CCPSignalSink(this, 0);
264
m_tristate = new Tristate();
265
m_source[0] = new CCPSignalSource(this, 0);
271
void CCPCON::setIOPin2(PinModule *p2)
276
if (!m_source[1]) m_source[1] = new CCPSignalSource(this, 1);
289
void CCPCON::setIOPin3(PinModule *p3)
294
if (!m_source[2]) m_source[2] = new CCPSignalSource(this, 2);
307
void CCPCON::setIOPin4(PinModule *p4)
312
if (!m_source[3]) m_source[3] = new CCPSignalSource(this, 3);
324
void CCPCON::setIOpin(int data, PinModule *pin)
346
// EPWM has four outputs PWM 1
347
void CCPCON::setIOpin(PinModule *p1, PinModule *p2, PinModule *p3, PinModule *p4)
349
Dprintf(("%s::setIOpin %s %s %s %s\n", name().c_str(),
350
(p1 && &(p1->getPin())) ? p1->getPin().name().c_str():"unknown",
351
(p2 && &(p2->getPin())) ? p2->getPin().name().c_str():"unknown",
352
(p3 && &(p3->getPin())) ? p3->getPin().name().c_str():"unknown",
353
(p4 && &(p4->getPin())) ? p4->getPin().name().c_str():"unknown"
355
if (p1 && !&(p1->getPin()))
357
Dprintf(("FIXME %s::setIOpin called where p1 has unassigned pin\n", name().c_str()));
366
void CCPCON::setCrosslinks( CCPRL *_ccprl, PIR *_pir, uint _mask,
367
TMR2 *_tmr2, ECCPAS *_eccpas )
376
void CCPCON::setADCON(ADCON0 *_adcon0)
381
char CCPCON::getState()
383
return m_bOutputEnabled ? m_cOutputState : '?';
386
void CCPCON::new_edge(uint level)
388
Dprintf(("%s::new_edge() level=%u\n",name().c_str(), level));
390
switch(value.get() & (CCPM3 | CCPM2 | CCPM1 | CCPM0))
396
Dprintf(("--CCPCON not enabled\n"));
399
case CAP_FALLING_EDGE:
400
if (level == 0 && ccprl)
402
ccprl->capture_tmr();
404
Dprintf(("--CCPCON caught falling edge\n"));
408
case CAP_RISING_EDGE:
411
ccprl->capture_tmr();
413
Dprintf(("--CCPCON caught rising edge\n"));
417
case CAP_RISING_EDGE4:
418
if (level && --edges <= 0)
420
ccprl->capture_tmr();
423
Dprintf(("--CCPCON caught 4th rising edge\n"));
425
//else cout << "Saw rising edge, but skipped\n";
429
case CAP_RISING_EDGE16:
430
if (level && --edges <= 0)
432
ccprl->capture_tmr();
435
Dprintf(("--CCPCON caught 4th rising edge\n"));
437
//else cout << "Saw rising edge, but skipped\n";
448
//cout << "CCPCON is set up as an output\n";
453
void CCPCON::compare_match()
455
Dprintf(("%s::compare_match()\n", name().c_str()));
457
switch(value.get() & (CCPM3 | CCPM2 | CCPM1 | CCPM0))
463
Dprintf(("-- CCPCON not enabled\n"));
466
case CAP_FALLING_EDGE:
467
case CAP_RISING_EDGE:
468
case CAP_RISING_EDGE4:
469
case CAP_RISING_EDGE16:
470
Dprintf(("-- CCPCON is programmed for capture. bug?\n"));
474
m_cOutputState = '1';
475
m_source[0]->setState('1');
476
m_PinModule[0]->updatePinModule();
479
Dprintf(("-- CCPCON setting compare output to 1\n"));
483
m_cOutputState = '0';
484
m_source[0]->setState('0');
485
m_PinModule[0]->updatePinModule();
488
Dprintf(("-- CCPCON setting compare output to 0\n"));
492
if (pir) pir->set(pir_mask);
493
Dprintf(("-- CCPCON setting interrupt\n"));
497
if( ccprl) ccprl->tmrl->clear_timer();
498
if( pir) pir->set(pir_mask);
499
if( adcon0) adcon0->start_conversion();
501
Dprintf(("-- CCPCON triggering an A/D conversion ccprl %p\n", ccprl));
508
//cout << "CCPCON is set up as an output\n";
514
// handle dead-band delay in half-bridge mode
515
void CCPCON::callback()
519
m_source[0]->setState('1');
520
m_PinModule[0]->updatePinModule();
521
delay_source0 = false;
525
m_source[1]->setState('1');
526
m_PinModule[1]->updatePinModule();
527
delay_source1 = false;
531
void CCPCON::releaseSink()
536
void CCPCON::releasePins(int i)
538
source_active[i] = false;
541
void CCPCON::pwm_match(int level)
543
uint new_value = value.get();
544
Dprintf(("%s::pwm_match() level=%d pwm1con = %p now=0x%" PRINTF_GINT64_MODIFIER "x\n", name().c_str(), level, pwm1con, cpu->get_cycles()->get()));
547
// if the level is 1, then tmr2 == pr2 and the pwm cycle
548
// is starting over. In which case, we need to update the duty
549
// cycle by reading ccprl and the ccp X & Y and caching them
550
// in ccprh's pwm slave register.
552
// Auto shutdown comes off at start of PWM if ECCPASE clear
553
if (bridge_shutdown && (!eccpas || !(eccpas->get_value() & ECCPAS::ECCPASE)))
555
Dprintf(("bridge_shutdown=%d eccpas=%p ECCPAS=%x\n", bridge_shutdown, eccpas,
556
eccpas ? eccpas->get_value() & ECCPAS::ECCPASE: 0));
557
for(int i = 0; i < 4; i++)
561
m_PinModule[i]->setControl(0); //restore default pin direction
562
source_active[i] = false;
563
m_PinModule[i]->updatePinModule();
566
bridge_shutdown = false;
569
tmr2->pwm_dc(pwm_latch_value(), address);
570
ccprl->ccprh->put_value(ccprl->value.get());
572
if( !pwm1con) // simple PWM
574
if (bridge_shutdown == false) // some processors use shutdown and simple PWM
576
m_cOutputState = level ? '1' : '0';
577
m_source[0]->setState(level ? '1' : '0');
578
m_PinModule[0]->setSource(m_source[0]);
579
source_active[0] = true;
581
if(level && !pwm_latch_value()) // if duty cycle == 0 output stays low
582
m_source[0]->setState('0');
584
m_PinModule[0]->updatePinModule();
585
//cout << "iopin should change\n";
590
if (!bridge_shutdown) drive_bridge(level, new_value);
596
void CCPCON::drive_bridge(int level, int new_value)
599
// pstrcon allows port steering for "single output"
600
// if it is not defined, just use the first port
602
pstrcon_value = pstrcon->value.get();
606
int delay = pwm1con->value.get() & ~PWM1CON::PRSEN;
609
switch (new_value & (CCPM3|CCPM2|CCPM1|CCPM0))
611
case PWM0: //P1A, P1C, P1B, P1D active high
612
active_high[0] = true;
613
active_high[1] = true;
614
active_high[2] = true;
615
active_high[3] = true;
618
case PWM1: // P1A P1C active high P1B P1D active low
619
active_high[0] = true;
620
active_high[1] = false;
621
active_high[2] = true;
622
active_high[3] = false;
625
case PWM2: // P1A P1C active low P1B P1D active high
626
active_high[0] = false;
627
active_high[1] = true;
628
active_high[2] = false;
629
active_high[3] = true;
632
case PWM3: // //P1A, P1C, P1B, P1D active low
633
active_high[0] = false;
634
active_high[1] = false;
635
active_high[2] = false;
636
active_high[3] = false;
640
cout << "not pwm mode. bug?\n";
644
switch((new_value & (P1M1|P1M0))>>6) // ECCP bridge mode
647
Dprintf(("Single bridge %s pstrcon=0x%x\n", name().c_str(), pstrcon_value));
648
for (int i = 0; i <4; i++)
650
if (pstrcon_value & (1<<i) && m_PinModule[i])
652
m_PinModule[i]->setSource(m_source[i]);
653
source_active[i] = true;
654
// follow level except where duty cycle = 0
655
if (level && pwm_latch_value())
656
m_source[i]->setState(active_high[i]?'1':'0');
658
m_source[i]->setState(active_high[i]?'0':'1');
660
m_PinModule[i]->updatePinModule();
662
else if (m_PinModule[i])
664
m_PinModule[i]->setSource(0);
665
source_active[i] = false;
670
case 2: // Half-Bridge
671
m_PinModule[0]->setSource(m_source[0]);
672
source_active[0] = true;
673
m_PinModule[1]->setSource(m_source[1]);
674
source_active[1] = true;
677
m_PinModule[2]->setSource(0);
678
source_active[2] = false;
682
m_PinModule[3]->setSource(0);
683
source_active[3] = false;
685
delay_source0 = false;
686
delay_source1 = false;
687
// FIXME need to add deadband
688
// follow level except where duty cycle = 0
689
pwm_width = level ? pwm_latch_value() :
690
((tmr2->pr2->value.get()+1)*4)-pwm_latch_value();
692
if (!(level^active_high[0]) && pwm_latch_value())
694
if (delay == 0) m_source[0]->setState('1'); // No delay, change state
696
else if( delay < pwm_width ) // there is a delay
698
future_cycle = cpu->currentCycle() + delay;
699
cpu->setBreakRel( delay, this );
700
delay_source0 = true;
703
else m_source[0]->setState('0');
705
if (!(level^active_high[1]) && pwm_latch_value())
707
m_source[1]->setState('0');
711
// No delay, change state
712
if (delay == 0) m_source[1]->setState('1');
713
else if (delay < pwm_width) // there is a delay
715
future_cycle = cpu->currentCycle() + delay;
716
cpu->setBreakRel( delay, this );
717
delay_source1 = true;
720
m_PinModule[0]->updatePinModule();
721
m_PinModule[1]->updatePinModule();
724
case 1: // Full bidge Forward
727
m_PinModule[0]->setSource(m_source[0]);
728
source_active[0] = true;
729
// P1A High (if active high)
730
m_source[0]->setState(active_high[0]?'1':'0');
731
m_PinModule[0]->updatePinModule();
735
m_PinModule[1]->setSource(m_source[1]);
736
source_active[1] = true;
737
// P1B, P1C low (if active high)
738
m_source[1]->setState(active_high[1]?'0':'1');
739
m_PinModule[1]->updatePinModule();
743
m_PinModule[2]->setSource(m_source[2]);
744
source_active[2] = true;
745
// P1B, P1C low (if active high)
746
m_source[2]->setState(active_high[2]?'0':'1');
747
m_PinModule[2]->updatePinModule();
751
m_PinModule[3]->setSource(m_source[3]);
752
source_active[3] = true;
754
if (level && pwm_latch_value())
755
m_source[3]->setState(active_high[3]?'1':'0');
757
m_source[3]->setState(active_high[3]?'0':'1');
758
m_PinModule[3]->updatePinModule();
762
case 3: // Full bridge reverse
763
Dprintf(("full-bridge reverse %s\n", name().c_str()));
766
m_PinModule[0]->setSource(m_source[0]);
767
source_active[0] = true;
768
// P1A, P1D low (if active high)
769
m_source[0]->setState(active_high[0]?'0':'1');
770
m_PinModule[0]->updatePinModule();
774
m_PinModule[1]->setSource(m_source[1]);
775
source_active[1] = true;
777
if (level && pwm_latch_value())
778
m_source[1]->setState(active_high[1]?'1':'0');
780
m_source[1]->setState(active_high[1]?'0':'1');
781
m_PinModule[1]->updatePinModule();
785
m_PinModule[2]->setSource(m_source[2]);
786
source_active[2] = true;
787
// P1C High (if active high)
788
m_source[2]->setState(active_high[2]?'1':'0');
789
m_PinModule[2]->updatePinModule();
793
m_PinModule[3]->setSource(m_source[3]);
794
source_active[3] = true;
795
// P1A, P1D low (if active high)
796
m_source[3]->setState(active_high[3]?'0':'1');
797
m_PinModule[3]->updatePinModule();
802
printf("%s::pwm_match impossible ECCP bridge mode\n", name_str.c_str());
807
// Set PWM bridge into shutdown mode
809
void CCPCON::shutdown_bridge(int eccpas)
811
bridge_shutdown = true;
813
Dprintf(("eccpas=0x%x\n", eccpas));
815
switch(eccpas & (ECCPAS::PSSBD0 | ECCPAS::PSSBD1))
817
case 0: // B D output 0
818
if (m_source[1]) m_source[1]->setState('0');
819
if (m_source[3]) m_source[3]->setState('0');
822
case 1: // B, D output 1
823
if (m_source[1]) m_source[1]->setState('1');
824
if (m_source[3]) m_source[3]->setState('1');
827
default: // Tristate B & D
828
if(m_PinModule[1]) m_PinModule[1]->setControl(m_tristate);
829
if(m_PinModule[3]) m_PinModule[3]->setControl(m_tristate);
832
switch(eccpas & ((ECCPAS::PSSAC0 | ECCPAS::PSSAC1) >> 2))
834
case 0: // A, C output 0
835
m_source[0]->setState('0');
836
if (m_source[2]) m_source[2]->setState('0');
839
case 1: // A, C output 1
840
m_source[0]->setState('1');
841
if (m_source[2]) m_source[2]->setState('1');
844
default: // Tristate A & C
845
m_PinModule[0]->setControl(m_tristate);
846
if(m_PinModule[2]) m_PinModule[2]->setControl(m_tristate);
849
m_PinModule[0]->updatePinModule();
850
if (m_PinModule[1]) m_PinModule[1]->updatePinModule();
851
if (m_PinModule[2]) m_PinModule[2]->updatePinModule();
852
if (m_PinModule[3]) m_PinModule[3]->updatePinModule();
855
void CCPCON::put(uint new_value)
857
uint old_value = value.get();
858
new_value &= mValidBits;
860
Dprintf(("%s::put() new_value=0x%x\n",name().c_str(), new_value));
862
value.put(new_value);
863
if (!ccprl || !tmr2) return;
865
// Return if no change other than possibly the duty cycle
866
if (((new_value ^ old_value) & ~(CCPY|CCPX)) == 0)
869
bool oldbInEn = m_bInputEnabled;
870
bool oldbOutEn = m_bOutputEnabled;
872
switch(value.get() & (CCPM3 | CCPM2 | CCPM1 | CCPM0))
880
ccprl->stop_compare_mode();
881
ccprl->stop_pwm_mode();
884
tmr2->stop_pwm(address);
885
m_bInputEnabled = false;
886
m_bOutputEnabled = false;
888
// RP - According to 16F87x data sheet section 8.2.1 clearing CCPxCON also clears the latch
889
m_cOutputState = '0';
890
m_source[0]->setState('0');
893
case CAP_FALLING_EDGE:
894
case CAP_RISING_EDGE:
896
ccprl->stop_compare_mode();
897
ccprl->stop_pwm_mode();
898
tmr2->stop_pwm(address);
899
m_bInputEnabled = true;
900
m_bOutputEnabled = false;
903
case CAP_RISING_EDGE4:
905
ccprl->stop_compare_mode();
906
ccprl->stop_pwm_mode();
907
tmr2->stop_pwm(address);
908
m_bInputEnabled = true;
909
m_bOutputEnabled = false;
912
case CAP_RISING_EDGE16:
913
ccprl->stop_compare_mode();
914
ccprl->stop_pwm_mode();
915
tmr2->stop_pwm(address);
916
m_bInputEnabled = true;
917
m_bOutputEnabled = false;
922
m_bOutputEnabled = true;
925
ccprl->start_compare_mode(this);
926
ccprl->stop_pwm_mode();
927
tmr2->stop_pwm(address);
929
// RP - just writing CCP2CON doesn't trigger the ADC; that only happens on a match
931
// adcon0->start_conversion();
933
m_bInputEnabled = false;
934
//if(adcon0) cout << "CCP triggering an A/D\n";
942
ccprl->stop_compare_mode();
943
/* do this when TMR2 == PR2
944
ccprl->start_pwm_mode();
945
tmr2->pwm_dc( pwm_latch_value(), address);
947
m_bInputEnabled = false;
948
m_bOutputEnabled = false; // this is done in pwm_match
949
m_cOutputState = '0';
950
if ((old_value & P1M0) && (new_value & P1M0)) // old and new full-bridge
951
{ // need to adjust timer if P1M1 also changed
952
Dprintf(("full bridge repeat old=0x%x new=%x\n", old_value, new_value));
960
if (oldbOutEn != m_bOutputEnabled && m_PinModule)
962
if (m_bOutputEnabled)
964
m_PinModule[0]->setSource(m_source[0]);
965
source_active[0] = true;
969
m_PinModule[0]->setSource(0);
970
m_source[0]->setState('?');
971
source_active[0] = false;
975
if ((oldbInEn != m_bInputEnabled ||
976
oldbOutEn != m_bOutputEnabled)
978
m_PinModule[0]->updatePinModule();
982
bool CCPCON::test_compare_mode()
984
switch(value.get() & (CCPM3 | CCPM2 | CCPM1 | CCPM0))
990
case CAP_FALLING_EDGE:
991
case CAP_RISING_EDGE:
992
case CAP_RISING_EDGE4:
993
case CAP_RISING_EDGE16:
1011
PWMxCON::PWMxCON(Processor *pCpu, const char *pName, char _index)
1012
: CCPCON(pCpu, pName ),
1013
pwmdcl(0), pwmdch(0), m_cwg(0), index(_index)
1016
for(int i=0; i<4; i++) m_clc[i] = 0;
1018
void PWMxCON::put(uint new_value)
1020
new_value &= mValidBits;
1021
put_value(new_value);
1024
void PWMxCON::put_value(uint new_value)
1026
uint diff = value.get() ^ new_value;
1027
Dprintf(("PWMxCON::put %s new 0x%x diff 0x%x\n", name().c_str(), new_value, diff));
1030
value.put(new_value);
1033
if (new_value & PWMxEN) // Turn on PWM
1037
else // Turn off PWM
1039
tmr2->stop_pwm(address);
1044
* level == 0 duty cycle match
1045
* level == 1 tmr2 == PR2
1048
void PWMxCON::pwm_match(int level)
1050
uint reg = value.get();
1052
if (!(reg & PWMxEN)) return;
1054
Dprintf(("%s::pwm_match() level=%d now=%" PRINTF_GINT64_MODIFIER "d\n", name().c_str(), level, cpu->get_cycles()->get()));
1058
tmr2->pwm_dc(pwm_latch_value(), address);
1059
if(!pwm_latch_value()) // if duty cycle == 0 output stays low
1063
if (reg & PWMxPOL) // inverse output
1065
level = level ? 0 : 1;
1066
Dprintf(("invert output\n"));
1072
Dprintf(("reg 0x%x old 0x%x\n", reg, value.get()));
1073
if (reg != value.get())
1075
if (m_cwg) m_cwg->out_pwm(level, index);
1076
for(int i = 0; i<4; i++)
1077
if (m_clc[i]) m_clc[i]->out_pwm(level, index);
1080
m_cOutputState = level ? '1' : '0';
1081
m_source[0]->setState(level ? '1' : '0');
1082
m_PinModule[0]->setSource(m_source[0]);
1083
m_PinModule[0]->updatePinModule();
1084
source_active[0] = true;
1085
Dprintf(("PWMxOE level %c\n", m_cOutputState));
1091
TRISCCP::TRISCCP(Processor *pCpu, const char *pName ) :
1092
SfrReg(pCpu, pName), first(true)
1095
void TRISCCP::put(uint new_value)
1097
if (first) first = false;
1099
value.put(new_value);
1102
DATACCP::DATACCP(Processor* pCpu, const char* pName ) :
1103
SfrReg(pCpu, pName), first(true)
1107
void DATACCP::put(uint new_value)
1109
if (first) first = false;
1111
value.put(new_value);
1114
//--------------------------------------------------
1116
//--------------------------------------------------
1117
T1CON::T1CON( Processor* pCpu, const char* pName )
1118
: SfrReg( pCpu, pName )
1128
void T1CON::put(uint new_value)
1130
uint diff = value.get() ^ new_value;
1131
value.put(new_value);
1135
// First, check the tmr1 clock source bit to see if we are changing from
1136
// internal to external (or vice versa) clocks.
1137
if( diff & (TMR1CS | T1OSCEN)) tmrl->new_clock_source();
1140
tmrl->on_or_off(value.get() & TMR1ON);
1141
else if( diff & (T1CKPS0 | T1CKPS1 | TMR1GE | T1GINV))
1147
return(value.get());
1150
uint T1CON::get_prescale()
1152
return( ((value.get() &(T1CKPS0 | T1CKPS1)) >> 4) );
1155
double T1CON::t1osc()
1157
return (value.get() & T1OSCEN) ? m_T1Freq : 0.;
1159
//--------------------------------------------------
1161
//--------------------------------------------------
1164
// Signal T1GCon on change of state of Gate pin
1166
class T1GCon_GateSignalSink : public SignalSink
1169
T1GCon_GateSignalSink(T1GCON *_t1gcon)
1174
virtual ~T1GCon_GateSignalSink()
1178
virtual void release() {delete this; }
1179
virtual void setSinkState(char new3State)
1181
m_t1gcon->PIN_gate( new3State=='1' || new3State=='W');
1187
T1GCON::T1GCON(Processor *pCpu, const char *pName, T1CON_G *_t1con_g)
1188
: SfrReg(pCpu, pName), sink(0), write_mask(0xfb), tmrl(0),
1189
t1con_g(_t1con_g), m_Interrupt(0),
1190
PIN_gate_state(false), T0_gate_state(false), CM1_gate_state(false),
1191
CM2_gate_state(false), last_t1g_in(false), gate_pin(0)
1197
if (m_Interrupt) m_Interrupt->release();
1200
bool T1GCON::tmr1_isON()
1202
if (t1con_g) return t1con_g->get_tmr1on();
1204
if (tmrl->t1con) return tmrl->t1con->get_tmr1on();
1206
cerr << "Error " << name_str << " get_tmr1on() not found\n";
1211
void T1GCON::put(uint new_value)
1213
uint old_value = value.get();
1214
new_value = (new_value & write_mask) | (old_value & ~write_mask);
1215
uint diff = new_value ^ old_value;
1216
bool t1ggo = new_value & T1GGO;
1218
assert(m_Interrupt);
1223
value.put(new_value);
1225
if (diff & (T1GSS1 | T1GSS0 | T1GPOL | TMR1GE))
1227
switch(new_value & (T1GSS1 | T1GSS0))
1230
new_gate(PIN_gate_state);
1234
new_gate(T0_gate_state);
1238
new_gate(CM1_gate_state);
1242
new_gate(CM2_gate_state);
1245
// Dont't allow gate change to clear new T1GG0
1246
if((diff & T1GGO) && t1ggo)
1247
value.put(value.get() | T1GGO);
1249
// T1GGO set and Single pulse mode
1250
if ((diff & T1GGO) && (value.get() & (T1GGO | T1GSPM)))
1252
//tmrl->IO_gate(true);
1253
if (value.get() & T1GVAL)
1255
value.put(value.get() & ~T1GVAL);
1256
//tmrl->IO_gate(true);
1257
tmrl->IO_gate(false);
1262
if ((value.get() & T1GTM)) // T1GTM going high, set t1g_in to 0
1264
if(value.get() & T1GVAL)
1266
value.put(value.get() & ~(T1GVAL));
1267
m_Interrupt->Trigger();
1269
tmrl->IO_gate(false); // Counting should be stopped
1275
void T1GCON::setGatepin( PinModule* pin )
1277
if (pin != gate_pin)
1279
if(sink) gate_pin->removeSink(sink);
1280
else sink = new T1GCon_GateSignalSink(this);
1283
Dprintf(("T1GCON::setGatepin %s\n", pin->getPin().name().c_str()));
1288
// The following 4 functions are called on a state change.
1289
// They pass the state to new_gate if that input is selected.
1290
void T1GCON::PIN_gate( bool state )
1292
PIN_gate_state = state;
1293
if((value.get() & (T1GSS0|T1GSS1)) == 0) new_gate(state);
1295
void T1GCON::T0_gate( bool state)
1297
T0_gate_state = state;
1298
if((value.get() & (T1GSS0|T1GSS1)) == 1) new_gate(state);
1301
// overloads T0_gate_state
1302
void T1GCON::T2_gate( bool state)
1304
T0_gate_state = state;
1305
if((value.get() & (T1GSS0|T1GSS1)) == 1) new_gate(state);
1308
void T1GCON::CM1_gate( bool state)
1310
CM1_gate_state = state;
1311
if((value.get() & (T1GSS0|T1GSS1)) == 2) new_gate(state);
1314
void T1GCON::CM2_gate(bool state)
1316
CM2_gate_state = state;
1317
if((value.get() & (T1GSS0|T1GSS1)) == 3) new_gate(state);
1319
void T1GCON::new_gate(bool state)
1321
// TMR1 counts when state low (unless t1gpol is set)
1322
// t1g_in is inverted as per XOR in spec sheet flow chart
1323
bool t1g_in = (!get_t1GPOL()) ^ state ;
1324
bool t1g_val = value.get() & T1GVAL;
1325
uint reg_value = value.get();
1327
if ((t1g_in == last_t1g_in) && (t1g_in == t1g_val)) // no state change, do nothing
1329
// tmrl->IO_gate(t1g_val);
1333
last_t1g_in = t1g_in;
1335
if ( reg_value & T1GTM) // Toggle mode
1337
t1g_val = reg_value & T1GVAL;
1338
if (t1g_in) // rising edge
1340
t1g_val = ! t1g_val; // t1gval changes state
1344
else // Gate directly in control
1349
if (reg_value & T1GSPM) // Single pulse mode
1351
if (!(reg_value & T1GGO)) // do nothing if T1GGO clear
1354
if (!t1g_val) // End of gate
1356
reg_value &= ~T1GGO; //set done
1358
else // Start of gate
1364
if (t1g_val)reg_value |= T1GVAL;
1367
if (reg_value & T1GVAL) // interrupt on T1GVAL negative edge
1369
m_Interrupt->Trigger();
1371
reg_value &= ~T1GVAL;
1373
value.put(reg_value);
1374
tmrl->IO_gate(t1g_val);
1377
//--------------------------------------------------
1379
//--------------------------------------------------
1380
T1CON_G::T1CON_G(Processor *pCpu, const char *pName)
1381
: T1CON(pCpu, pName ),
1383
t1gcon(pCpu, "t1gcon", this)
1392
void T1CON_G::put(uint new_value)
1394
uint diff = value.get() ^ new_value;
1395
value.put(new_value);
1399
// First, check the tmr1 clock source bit to see if we are changing from
1400
// internal to external (or vice versa) clocks.
1401
if( diff & (TMR1CS0 | TMR1CS1 | T1OSCEN))
1402
tmrl->new_clock_source();
1405
tmrl->on_or_off(value.get() & TMR1ON);
1406
else if( diff & (T1CKPS0 | T1CKPS1 ))
1410
// If Cap. sensing oscillator T1 clock source, pass to T1
1411
void T1CON_G::t1_cap_increment()
1413
if (get_tmr1cs() == 3) // T1 input Cap. sensing oscillator
1416
//--------------------------------------------------
1417
// member functions for the TMRH base class
1418
//--------------------------------------------------
1419
TMRH::TMRH(Processor *pCpu, const char *pName )
1420
: SfrReg(pCpu, pName ),
1426
void TMRH::put( uint new_value )
1430
value.put( new_value & 0xff );
1433
tmrl->set_ext_scale();
1434
value.put( new_value & 0xff );
1435
tmrl->synchronized_cycle = cpu->currentCycle();
1436
tmrl->last_cycle = tmrl->synchronized_cycle
1437
- (int64_t)((tmrl->value.get()+(value.get()<<8)
1438
*tmrl->prescale*tmrl->ext_scale) +0.5);
1440
if( tmrl->t1con->get_tmr1on() ) tmrl->update();
1448
// For the gui and CLI
1449
uint TMRH::get_value()
1451
// If the TMR1 is being read immediately after being written, then
1452
// it hasn't had enough time to synchronize with the PIC's clock.
1453
if( cpu->currentCycle() <= tmrl->synchronized_cycle )
1456
if( !tmrl->t1con->get_tmr1on() ) return value.get(); // If the TMR is not running then return.
1458
tmrl->current_value();
1460
return( value.get() );
1463
//--------------------------------------------------
1465
class TMRl_GateSignalSink : public SignalSink
1468
TMRl_GateSignalSink(TMRL *_tmr1l)
1474
virtual void release() { delete this; }
1475
void setSinkState(char new3State)
1476
{ m_tmr1l->IO_gate( new3State=='1' || new3State=='W'); }
1482
//--------------------------------------------------
1483
// trivial class to represent a compare event reference
1484
//--------------------------------------------------
1489
TMR1CapComRef * next;
1494
TMR1CapComRef ( CCPCON * c, uint v ) : ccpcon(c), value(v) {}
1497
//--------------------------------------------------
1498
// member functions for the TMRL base class
1499
//--------------------------------------------------
1500
TMRL::TMRL(Processor *pCpu, const char *pName )
1501
: SfrReg(pCpu, pName ),
1503
m_cState('?'), m_GateState(false), m_compare_GateState(true),
1504
m_io_GateState(true), m_bExtClkEnabled(false),
1505
m_sleeping(false), m_t1gss(true), m_Interrupt(0)
1508
synchronized_cycle = 0;
1509
prescale_counter = prescale = 1;
1510
break_value = 0x10000;
1518
for (int i = 0; i < 4; i++) m_clc[i] = 0;
1523
if (m_Interrupt) m_Interrupt->release();
1526
* If we are similating an external RTC crystal for timer1,
1527
* compute scale factor between crsytal speed and processor
1528
* instruction cycle rate
1530
* If tmr1cs = 1 Fosc is 4 x normal speed so reduce ticks by 1/4
1532
void TMRL::set_ext_scale()
1535
if (t1con->get_t1oscen() && (t1con->get_tmr1cs() == 2)) // external clock
1536
ext_scale = cpu->instruction_cps()/t1con->m_T1Freq;
1538
else if( t1con->get_tmr1cs() == 1 ) ext_scale = 0.25; // Fosc
1539
else ext_scale = 1.;
1542
last_cycle = cpu->currentCycle()-(int64_t)(value_16bit*( prescale*ext_scale )+0.5);
1545
void TMRL::release()
1549
void TMRL::setIOpin(PinModule *extClkSource)
1551
Dprintf(("%s::setIOpin %s\n", name().c_str(), extClkSource?extClkSource->getPin().name().c_str():""));
1553
if (extClkSource) extClkSource->addSink(this);
1556
void TMRL::setSinkState(char new3State)
1558
if (new3State != m_cState)
1560
m_cState = new3State;
1561
if (m_bExtClkEnabled && (m_cState == '1' || m_cState == 'W'))
1566
void TMRL::set_compare_event ( uint value, CCPCON *host )
1568
TMR1CapComRef * event = compare_queue;
1574
if ( event->ccpcon == host )
1576
event->value = value;
1580
event = event->next;
1582
event = new TMR1CapComRef ( host, value );
1583
event->next = compare_queue;
1584
compare_queue = event;
1588
cout << "TMRL::set_compare_event called with no CAPCOM\n";
1591
void TMRL::clear_compare_event ( CCPCON *host )
1593
TMR1CapComRef * event = compare_queue;
1594
TMR1CapComRef * * eptr = &compare_queue;
1598
if ( event->ccpcon == host )
1600
*eptr = event->next;
1605
eptr = &event->next;
1606
event = event->next;
1610
void TMRL::setGatepin(PinModule *extGateSource)
1612
Dprintf(("TMRL::setGatepin\n"));
1614
if (extGateSource) extGateSource->addSink(new TMRl_GateSignalSink(this));
1617
void TMRL::set_T1GSS(bool arg)
1620
if (m_t1gss) IO_gate(m_io_GateState);
1621
else compare_gate(m_compare_GateState);
1623
void TMRL::compare_gate(bool state)
1625
m_compare_GateState = state;
1626
if (!m_t1gss && m_GateState != state)
1628
m_GateState = state;
1630
Dprintf(("TMRL::compare_gate state %d \n", state));
1632
if (t1con->get_tmr1GE()) update();
1635
void TMRL::IO_gate(bool state)
1637
m_io_GateState = state;
1639
if (m_t1gss && (m_GateState != state))
1641
m_GateState = state;
1643
Dprintf(("TMRL::IO_gate state %d \n", state));
1645
if (t1con->get_tmr1GE()) update();
1649
//------------------------------------------------------------
1650
// setInterruptSource()
1652
// This Timer can be an interrupt source. When the interrupt
1653
// needs to be generated, then the InterruptSource object will
1654
// direct the interrupt to where it needs to go (usually this
1655
// is the Peripheral Interrupt Register).
1657
void TMRL::setInterruptSource(InterruptSource *_int)
1662
void TMRL::increment()
1664
Dprintf(("TMRL increment because of external clock\n"));
1666
if( --prescale_counter == 0 )
1668
prescale_counter = prescale;
1670
if( t1con->get_t1sync() == 0 && m_sleeping ) return; // In synchronous counter mode prescaler works but rest of tmr1 does not
1671
if( !t1con->get_tmr1on() ) return; // prescaler works but rest of timer turned off
1673
// If TMRH/TMRL have been manually changed, we'll want to get the up-to-date values;
1676
value_16bit = 0xffff & ( value_16bit + 1);
1678
tmrh->value.put((value_16bit >> 8) & 0xff);
1679
value.put(value_16bit & 0xff);
1680
if(value_16bit == 0 && m_Interrupt)
1682
m_Interrupt->Trigger();
1683
for(int i=0; i<4; i++)
1684
if (m_clc[i]) m_clc[i]->t1_overflow();
1689
void TMRL::on_or_off( int new_state )
1691
if(new_state) // turn on the timer
1693
// Effective last cycle
1694
// Compute the "effective last cycle", i.e. the cycle
1695
// at which TMR1 was last 0 had it always been counting.
1697
last_cycle = (int64_t)(cpu->currentCycle()-(value.get()+(tmrh->value.get()<<8))*prescale*ext_scale+0.5);
1700
else // turn off the timer and save the current value
1705
cpu->clear_break(this);
1711
// If anything has changed to affect when the next TMR1 break point
1712
// will occur, this routine will make sure the break point is moved
1718
Dprintf(("TMR1 %s update now=0x%" PRINTF_GINT64_MODIFIER "x\n",name().c_str(), cpu->get_cycles()->get()));
1719
// if t1con->get_t1GINV() is false, timer can run if m_GateState == 0
1721
bool gate = t1con->get_t1GINV() ? m_GateState : !m_GateState;
1722
Dprintf(("TMRL::update gate %d GateState %d inv %d get_tmr1on %x tmr1GE %x tmr1cs %x t1oscen %x\n", gate, m_GateState, t1con->get_t1GINV(), t1con->get_tmr1on(), t1con->get_tmr1GE(), t1con->get_tmr1cs(), t1con->get_t1oscen()));
1723
/* When tmr1 is on, and t1con->get_tmr1GE() is true,
1724
gate == 1 allows timer to run, gate == 0 stops timer.
1725
However, if t1con->get_tmr1GE() is false gate has no
1726
effect on timer running or not.
1728
if(t1con->get_tmr1on() && (t1con->get_tmr1GE() ? gate : true))
1730
switch(t1con->get_tmr1cs())
1732
case 0: // internal clock Fosc/4
1735
case 1: // internal clock Fosc
1738
case 2: // External clock
1739
if (t1con->get_t1oscen()) // External clock enabled
1742
external timer1 clock runs off a crystal which is typically
1743
32768 Hz and is independant on the instruction clock, but
1744
gpsim runs on the instruction clock. Ext_scale is the ratio
1745
of these two clocks so the breakpoint can be adjusted to be
1746
triggered at the correct time.
1749
else // External stimuli(pin)
1751
prescale = 1 << t1con->get_prescale();
1752
prescale_counter = prescale;
1758
case 3: // Cap. sensing oscillator
1759
prescale = 1 << t1con->get_prescale();
1760
prescale_counter = prescale;
1766
cout << "TMR1SC reserved value " << t1con->get_tmr1cs() << endl;
1771
// Note, unlike TMR0, anytime something is written to TMRL, the
1772
// prescaler is unaffected on the P18 processors. However, it is
1773
// reset on the p16f88 processor, which is how the current code
1774
// works. This only effects the external drive mode.
1776
prescale = 1 << t1con->get_prescale();
1777
prescale_counter = prescale;
1779
// synchronized_cycle = cycles.get() + 2;
1780
synchronized_cycle = cpu->currentCycle();
1781
last_cycle = synchronized_cycle - (int64_t)(value_16bit*( prescale*ext_scale )+0.5);
1783
break_value = 0x10000; // Assume that a rollover will happen first.
1785
for( TMR1CapComRef* event=compare_queue; event; event=event->next )
1787
if ( event->value > value_16bit && event->value < break_value )
1789
// A compare interrupt is going to happen before the timer will rollover.
1790
break_value = event->value;
1793
uint64_t fc = cpu->currentCycle() + (uint64_t)((break_value-value_16bit)*prescale*ext_scale);
1795
if(future_cycle) cpu->reassign_break( future_cycle, fc, this );
1796
else cpu->setBreakAbs( fc, this );
1802
// turn off the timer and save the current value
1806
cpu->clear_break( this );
1812
void TMRL::put( uint new_value )
1816
value.put( new_value & 0xff );
1818
if( !tmrh || !t1con ) return;
1820
synchronized_cycle = cpu->currentCycle();
1821
last_cycle = synchronized_cycle-(int64_t)(( value.get()+(tmrh->value.get()<<8))*prescale*ext_scale+0.5);
1825
if( t1con->get_tmr1on() ) update();
1833
// For the gui and CLI
1834
uint TMRL::get_value()
1836
// If the TMRL is being read immediately after being written, then
1837
// it hasn't had enough time to synchronize with the PIC's clock.
1838
if( cpu->currentCycle() <= synchronized_cycle ) return value.get();
1840
if( !t1con->get_tmr1on() ) return value.get(); // If TMRL is not on, then return the current value
1844
return( value.get() );
1847
//%%%FIXME%%% inline this
1848
// if break inactive (future_cycle == 0), just read the TMR1H and TMR1L
1849
// registers otherwise compute what the register should be and then
1850
// update TMR1H and TMR1L.
1851
// RP: Using future_cycle here is not strictly right. What we really want is
1852
// the condition "TMR1 is running on a GPSIM-generated clock" (as opposed
1853
// to being off, or externally clocked by a stimulus). The presence of a
1854
// breakpoint is _usually_ a good indication of this, but not while we're
1855
// actually processing that breakpoint. For the time being, we work around
1856
// this by calling current_value "redundantly" in callback()
1858
void TMRL::current_value()
1862
if( future_cycle == 0 ) value_16bit = tmrh->value.get()*256+value.get();
1865
value_16bit = cpu->currentCycle();
1866
value_16bit = (uint64_t)((cpu->currentCycle()-last_cycle)/(prescale*ext_scale));
1868
if( value_16bit > 0x10000 )
1869
cerr << "overflow TMRL " << name_str << " " << value_16bit <<cpu->currentCycle()<< endl;
1871
value.put(value_16bit & 0xff);
1872
tmrh->value.put((value_16bit>>8) & 0xff);
1876
uint TMRL::get_low_and_high()
1878
// If the TMRL is being read immediately after being written, then
1879
// it hasn't had enough time to synchronize with the PIC's clock.
1880
if( cpu->currentCycle() <= synchronized_cycle ) return value.get();
1884
return(value_16bit);
1887
// set m_bExtClkEnable is tmr1 is being clocked by an external stimulus
1888
void TMRL::new_clock_source()
1890
m_bExtClkEnabled = false;
1893
switch(t1con->get_tmr1cs())
1903
case 2: // External pin or crystal
1905
if(t1con->get_t1oscen()) // External crystal, simulate
1907
put(value.get()); // let TMRL::put() set a cycle counter break point
1909
else // external pin
1913
// Compute value_16bit with old prescale and ext_scale
1915
cpu->clear_break(this);
1918
prescale = 1 << t1con->get_prescale();
1919
prescale_counter = prescale;
1921
m_bExtClkEnabled = true;
1925
case 3: // Capacitor sense oscillator
1928
// Compute value_16bit with old prescale and ext_scale
1930
cpu->clear_break(this);
1933
prescale = 1 << t1con->get_prescale();
1934
prescale_counter = prescale;
1941
// clear_timer - This is called by either the CCP or PWM modules to
1942
// reset the timer to zero. This is rather easy since the current TMR
1943
// value is always referenced to the cpu cycle counter.
1946
void TMRL::clear_timer()
1948
synchronized_cycle = cpu->currentCycle();
1949
last_cycle = synchronized_cycle;
1954
// TMRL callback is called when the cycle counter hits the break point that
1955
// was set in TMRL::put. The cycle counter will clear the break point, so
1956
// we don't need to worry about it. At this point, TMRL is rolling over.
1958
void TMRL::callback()
1960
// If TMRL is being clocked by the external clock, then at some point
1961
// the simulate code must have switched from the internal clock to
1962
// external clock. The cycle break point was still set, so just ignore it.
1963
if( (t1con->get_tmr1cs() == 2) && ! t1con->get_t1oscen() )
1967
future_cycle = 0; // indicates that TMRL no longer has a break point
1970
current_value(); // Because this relies on future_cycle, we must call it before clearing that
1972
future_cycle = 0; // indicate that there's no break currently set
1974
if( break_value < 0x10000 ) // The break was due to a "compare"
1976
if( value_16bit != break_value ) cout << "TMR1 compare break: value=" << value_16bit << " but break_value=" << break_value << '\n';
1978
for( TMR1CapComRef * event = compare_queue; event; event = event->next )
1979
if ( event->value == break_value ) event->ccpcon->compare_match(); // This CCP channel has a compare at this time
1981
else // The break was due to a roll-over
1983
//cout<<"TMRL rollover: " << hex << cycles.get() << '\n';
1984
if (m_Interrupt) m_Interrupt->Trigger();
1986
for(int i=0; i<4; i++) if (m_clc[i]) m_clc[i]->t1_overflow();
1988
// Reset the timer to 0.
1989
synchronized_cycle = cpu->currentCycle();
1990
last_cycle = synchronized_cycle;
1992
tmrh->value.put( 0 );
1997
void TMRL::callback_print()
1999
cout << "TMRL " << name_str << " CallBack ID " << CallBackID << '\n';
2005
// If tmr1 is running off Fosc/4 or Fosc this assumes Fosc stops during sleep
2007
if( t1con->get_tmr1on() && t1con->get_tmr1cs() < 2)
2012
cpu->clear_break(this);
2018
//---------------------------
2024
if ( t1con->get_tmr1on() && t1con->get_tmr1cs() < 2)
2030
//--------------------------------------------------
2031
// member functions for the PR2 base class
2032
//--------------------------------------------------
2034
PR2::PR2(Processor *pCpu, const char *pName )
2035
: SfrReg(pCpu, pName ),
2040
void PR2::put(uint new_value)
2042
Dprintf(("PR2:: put %x\n", new_value));
2044
if(value.get() != new_value)
2046
if (tmr2) tmr2->new_pr2(new_value);
2047
value.put(new_value);
2049
else value.put(new_value);
2052
//--------------------------------------------------
2053
// member functions for the T2CON base class
2054
//--------------------------------------------------
2056
T2CON::T2CON(Processor *pCpu, const char *pName )
2057
: SfrReg(pCpu, pName ),
2062
void T2CON::put(uint new_value)
2064
uint diff = value.get() ^ new_value;
2065
value.put(new_value);
2069
tmr2->new_pre_post_scale();
2070
if( diff & TMR2ON) tmr2->on_or_off(value.get() & TMR2ON);
2075
TMR2::TMR2(Processor *pCpu, const char *pName )
2076
: SfrReg(pCpu, pName ),
2078
update_state(TMR2_ANY_PWM_UPDATE | TMR2_PR2_UPDATE),
2081
prescale_counter(0), break_value(0), post_scale(0),
2083
pr2(0), pir_set(0), t2con(0), m_txgcon(0), m_Interrupt(0),
2086
ssp_module[0] = ssp_module[1] = 0;
2090
std::fill_n(duty_cycle, MAX_PWM_CHANS, 0);
2091
for (int i = 0; i < 4; i++)
2093
for (int cc = 0; cc < MAX_PWM_CHANS; cc++ )
2099
if (m_Interrupt) m_Interrupt->release();
2103
void TMR2::callback_print()
2105
cout << "TMR2 " << name_str << " CallBack ID " << CallBackID << '\n';
2116
bool TMR2::add_ccp ( CCPCON * _ccp )
2120
for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
2122
if ( ccp[cc] == 0 || ccp[cc] == _ccp )
2131
bool TMR2::rm_ccp ( CCPCON * _ccp )
2135
for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
2137
if ( ccp[cc] == _ccp )
2147
void TMR2::on_or_off(int new_state)
2149
if(new_state) // turn on the timer
2151
Dprintf(("TMR2 is being turned on\n"));
2153
// Effective last cycle
2154
// Compute the "effective last cycle", i.e. the cycle
2155
// at which TMR2 was last 0 had it always been counting.
2157
last_cycle = cpu->currentCycle() - value.get()*prescale;
2160
else current_value(); // turn off the timer and save the current value
2164
// pwm_dc - set PWM duty cycle
2166
void TMR2::pwm_dc(uint dc, uint ccp_address)
2168
int modeMask = TMR2_PWM1_UPDATE;
2172
for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
2174
if ( ccp[cc] && ( ccp_address == ccp[cc]->address ) )
2176
//cout << "TMR2: pwm mode with ccp1. duty cycle = " << hex << dc << '\n';
2177
Dprintf(("TMR2::pwm_dc duty cycle 0x%x ccp_addres 0x%x\n", dc, ccp_address));
2178
duty_cycle[cc] = dc;
2179
pwm_mode |= modeMask;
2186
cout << name_str <<": error bad ccpxcon address while in pwm_dc()\n";
2187
cout << "ccp_address = " << ccp_address << " expected one of";
2188
for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
2189
if ( ccp[cc] ) cout << " " << ccp[cc]->address;
2199
void TMR2::stop_pwm(uint ccp_address)
2201
int modeMask = TMR2_PWM1_UPDATE;
2203
int old_pwm = pwm_mode;
2205
for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
2207
if ( ccp[cc] && ( ccp_address == ccp[cc]->address ) )
2209
// cout << "TMR2: stopping pwm mode with ccp" << cc+1 << ".\n";
2210
pwm_mode &= ~modeMask;
2211
if(last_update & modeMask) update_state &= (~modeMask);
2216
if((pwm_mode ^ old_pwm) && future_cycle && t2con->get_tmr2on())
2217
update(update_state);
2222
// This member function will determine if/when there is a TMR2 break point
2223
// that needs to be set and will set/move it if so.
2224
// There are two different types of break sources:
2225
// 1) TMR2 matching PR2
2226
// 2) TMR2 matching one of the ccp registers in pwm mode
2229
void TMR2::update(int ut)
2231
int modeMask = TMR2_PWM1_UPDATE;
2234
//cout << "TMR2 update. cpu cycle " << hex << cycles.get() <<'\n';
2236
if(t2con->get_tmr2on())
2240
// If TMR2 is enabled (i.e. counting) then 'future_cycle' is non-zero,
2241
// which means there's a cycle break point set on TMR2 that needs to
2242
// be moved to a new cycle.
2246
// Assume that we are not in pwm mode (and hence the next break will
2247
// be due to tmr2 matching pr2)
2249
break_value = 1 + pr2->value.get();
2250
uint64_t fc = cpu->currentCycle() + (break_value - value.get()) * prescale;
2252
last_update = TMR2_PR2_UPDATE;
2254
// RP - I strongly suspect this is now entirely redundant, as I think the
2255
// result comes out the same as above.
2256
if (pwm_mode) fc = last_cycle + break_value * prescale;
2258
for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
2260
if ( pwm_mode & ut & modeMask )
2262
/* We are in pwm mode... So let's see what happens first: a pr2
2263
compare or a duty cycle compare. The duty cycle is 10-bits,
2264
but the two least significant match against the prescaler
2268
if ( (duty_cycle[cc] > (value.get()*4) ) && ( duty_cycle[cc] < break_value*4 ) )
2270
uint64_t nc = last_cycle + ( duty_cycle[cc] * prescale ) / 4;
2272
// cout << "TMR2:PWM" << cc+1 << " update at " << hex << nc <<
2273
// ", dc=" << duty_cycle[cc] << "\n";
2274
if ( nc < fc ) /// @bug not robust against wrap-around of uint64_t
2276
last_update = modeMask;
2279
else if ( nc == fc ) last_update |= modeMask;
2284
if (fc != future_cycle)
2286
// cout << "TMR2: update new break at cycle "<<hex<<fc<<'\n';
2287
cpu->reassign_break(future_cycle, fc, this);
2291
else cerr << "TMR2 BUG!! tmr2 is on but has no cycle_break set on it\n";
2295
// cout << "TMR2 is not running (no update occurred)\n";
2300
void TMR2::put(uint new_value)
2302
uint old_value = get_value();
2304
value.put(new_value & 0xff);
2308
// If TMR2 is enabled (i.e. counting) then 'future_cycle' is non-zero,
2309
// which means there's a cycle break point set on TMR2 that needs to
2310
// be moved to a new cycle.
2312
uint64_t current_cycle = cpu->currentCycle();
2313
uint delta = (future_cycle - last_cycle);
2314
int shift = (new_value - old_value) * prescale;
2316
// printf ( "TMR2::put(%02X) with future_cycle -\n", new_value );
2317
// printf ( " move break from 0x%" PRINTF_INT64_MODIFIER "X by %d\n", current_cycle, shift );
2319
// set cycle when tmr2 would have been zero
2321
last_cycle = current_cycle - shift;
2322
uint now = (current_cycle - last_cycle);
2324
// printf ( " value now is 0x%X\n", now );
2329
Three possible cases
2330
1> TMR2 is still before the next break point.
2331
Adjust the breakpoint to occur at correct TMR2 value
2332
2> TMR2 is now greater the PR2
2333
Assume TMR2 must count up to 0xff, roll-over and then
2334
we are back in business. High CCP outputs stay high.
2335
3> TMR2 is now less than PR2 but greater than a CCP duty cycle point.
2336
The CCP output stays as the duty cycle comparator does not
2337
match on this cycle.
2340
if (now < delta) // easy case, just shift break.
2342
fc = last_cycle + delta;
2344
// printf ( " now < delta (0x%X), set future_cycle to 0x%" PRINTF_INT64_MODIFIER "X\n", delta, fc );
2346
cpu->reassign_break(future_cycle, fc, this);
2349
else if (now >= break_value * prescale) // TMR2 now greater than PR2
2351
// set break to when TMR2 will overflow
2352
last_update |= TMR2_WRAP;
2353
fc = last_cycle + 0x100 * prescale;
2355
// printf ( " now > break (0x%X), set future_cycle to 0x%" PRINTF_INT64_MODIFIER "X\n", break_value * prescale, fc );
2357
cpu->reassign_break(future_cycle, fc, this);
2360
else // new break < PR2 but > duty cycle break
2362
// printf ( " new break < PR2 but > duty cycle\n" );
2363
update(update_state);
2367
'clear' the post scale counter. (I've actually implemented the
2368
post scale counter as a count-down counter, so 'clearing it'
2369
means resetting it to the starting point.
2371
if (t2con) post_scale = t2con->get_post_scale();
2377
if(t2con->get_tmr2on()) current_value();
2378
return(value.get());
2381
uint TMR2::get_value()
2383
if(t2con->get_tmr2on()) current_value();
2384
return(value.get());
2387
void TMR2::new_pre_post_scale()
2389
//cout << "T2CON was written to, so update TMR2 " << t2con->get_tmr2on() << "\n";
2391
if(!t2con->get_tmr2on())
2393
// TMR2 is not on. If has just been turned off, clear the callback breakpoint.
2397
cpu->clear_break(this);
2403
uint old_prescale = prescale;
2404
prescale = t2con->get_pre_scale();
2405
post_scale = t2con->get_post_scale();
2409
// If TMR2 is enabled (i.e. counting) then 'future_cycle' is non-zero,
2410
// which means there's a cycle break point set on TMR2 that needs to
2411
// be moved to a new cycle.
2414
if (prescale != old_prescale) // prescaler value change
2416
// togo is number of cycles to next callback based on new prescaler.
2417
uint64_t togo = (future_cycle - cpu->currentCycle()) * prescale / old_prescale;
2419
if (!togo) // I am not sure this can happen RRR
2423
uint64_t fc = togo + cpu->currentCycle();
2425
cpu->reassign_break(future_cycle, fc, this);
2432
//cout << "TMR2 was off, but now it's on.\n";
2434
if (value.get() == pr2->value.get()) // TMR2 == PR2
2436
future_cycle = cpu->currentCycle();
2437
cpu->setBreakAbs( future_cycle, this );
2440
else if (value.get() > pr2->value.get()) // TMR2 > PR2
2442
cout << "Warning TMR2 turned on with TMR2 greater than PR2\n";
2443
// this will cause TMR2 to wrap
2444
future_cycle = cpu->currentCycle() + (1 + pr2->value.get() + (0x100 - value.get())) * prescale;
2445
cpu->setBreakAbs( future_cycle, this );
2449
future_cycle = cpu->currentCycle() + 1;
2450
cpu->setBreakAbs( future_cycle, this );
2451
last_cycle = cpu->currentCycle() - value.get();
2452
update(update_state);
2457
void TMR2::new_pr2(uint new_value)
2459
if(t2con->get_tmr2on())
2461
uint cur_break = (future_cycle - last_cycle)/prescale;
2462
uint new_break = 1 + new_value;
2463
uint now_cycle = (cpu->currentCycle() - last_cycle) / prescale;
2465
uint64_t fc = last_cycle;
2469
1> TMR2 greater than new PR2
2470
TMR2 wraps through 0xff
2471
2> New PR2 breakpoint less than current breakpoint or
2472
current break point due to PR2
2473
Change breakpoint to new value based on PR2
2474
3> Other breakpoint < PR2 breakpoint
2475
No need to do anything.
2477
if (now_cycle > new_break) // TMR2 > PR2 do wrap
2479
// set break to when TMR2 will overflow
2480
last_update |= TMR2_WRAP;
2481
fc += 0x100 * prescale;
2482
cpu->reassign_break(future_cycle, fc, this);
2485
else if (cur_break == break_value || // breakpoint due to pr2
2486
new_break < cur_break) // new break less than current
2488
fc += new_break * prescale;
2489
if ( cur_break != break_value ) last_update = TMR2_PR2_UPDATE; // RP : fix bug 3092906
2490
cpu->reassign_break(future_cycle, fc, this);
2496
void TMR2::current_value()
2498
uint tmr2_val = (cpu->currentCycle() - last_cycle)/ prescale;
2499
if (future_cycle) tmr2_val = (cpu->currentCycle() - last_cycle)/ prescale;
2500
else tmr2_val = value.get();
2502
if (tmr2_val == max_counts())
2504
// tmr2 is about to roll over. However, the user code
2505
// has requested the current value before the callback function
2506
// has been invoked. So do callback and return 0.
2510
cpu->clear_break(this);
2515
value.put(tmr2_val & (max_counts() - 1));
2517
if(tmr2_val >= max_counts()) // Can get to max_counts during transition
2519
cerr << "TMR2 BUG!! value = 0x" << tmr2_val << " which is greater than 0x";
2520
cerr << max_counts() << endl;
2524
// TMR2 callback is called when the cycle counter hits the break point that
2525
// was set in TMR2::put. The cycle counter will clear the break point, so
2526
// we don't need to worry about it. At this point, TMR2 is equal to PR2.
2528
void TMR2::callback()
2532
//cout<<"TMR2 callback cycle: " << hex << cycles.value << '\n';
2534
// If tmr2 is still enabled, then set up for the next break.
2535
// If tmr2 was disabled then ignore this break point.
2536
if(t2con->get_tmr2on())
2539
// What caused the callback: PR2 match or duty cyle match ?
2541
if (last_update & TMR2_WRAP) // TMR2 > PR2
2543
last_update &= ~TMR2_WRAP;
2544
// This (implicitly) resets the timer to zero:
2545
last_cycle = cpu->currentCycle();
2547
else if ( last_update & TMR2_ANY_PWM_UPDATE )
2549
int modeMask = TMR2_PWM1_UPDATE;
2551
for ( cc=0; cc<MAX_PWM_CHANS && last_update; cc++ )
2553
if ( last_update & modeMask )
2556
//cout << name() << ": duty cycle match for pwm" << cc+1 << "\n";
2557
update_state &= (~modeMask);
2558
last_update &= ~modeMask;
2559
if ( ccp[cc] ) // shouldn't be needed
2560
ccp[cc]->pwm_match(0);
2562
cout << "TMR2::callback() found update of non-existent CCP\n";
2571
//cout << "TMR2: PR2 match. pwm_mode is " << pwm_mode <<'\n';
2573
// This (implicitly) resets the timer to zero:
2574
last_cycle = cpu->currentCycle();
2575
for(int i =0; i<4; i++) if(m_clc[i]) m_clc[i]->t2_match();
2577
if (ssp_module[0]) ssp_module[0]->tmr2_clock();
2578
if (ssp_module[1]) ssp_module[1]->tmr2_clock();
2579
if (m_txgcon) // toggle T2_gate, if present
2581
m_txgcon->T2_gate(1);
2582
m_txgcon->T2_gate(0);
2585
for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
2588
if ( ccp[cc] && ccp[cc]->is_pwm()) ccp[cc]->pwm_match(1);
2591
if(--post_scale < 0)
2593
//cout << "setting IF\n";
2594
if (pir_set) pir_set->set_tmr2if();
2595
else if (m_Interrupt) // for multiple T2 (T2, T4, T6)
2596
m_Interrupt->Trigger();
2598
post_scale = t2con->get_post_scale();
2600
update_state = TMR2_ANY_PWM_UPDATE | TMR2_PR2_UPDATE;
2602
update(update_state);
2604
else future_cycle = 0;
2607
//------------------------------------------------------------------------
2612
TMR2_MODULE::TMR2_MODULE()
2623
void TMR2_MODULE::initialize(T2CON *t2con_, PR2 *pr2_, TMR2 *tmr2_)
2632
//--------------------------------------------------
2634
//--------------------------------------------------
2636
class INT_SignalSink : public SignalSink
2639
INT_SignalSink(ECCPAS *_eccpas, int _index)
2640
: m_eccpas(_eccpas), m_index(_index)
2645
virtual void release() { delete this; }
2646
void setSinkState(char new3State)
2648
m_eccpas->set_trig_state( m_index, new3State=='0' || new3State=='w');
2655
//--------------------------------------------------
2657
//--------------------------------------------------
2658
ECCPAS::ECCPAS(Processor *pCpu, const char *pName )
2659
: SfrReg(pCpu, pName ),
2660
pwm1con(0), ccp1con(0),
2663
trig_state[0] = trig_state[1] = trig_state[2] = false;
2670
void ECCPAS::link_registers(PWM1CON *_pwm1con, CCPCON *_ccp1con)
2675
void ECCPAS::put(uint new_value)
2677
Dprintf(("ECCPAS::put() new_value=0x%x\n",new_value));
2679
put_value(new_value);
2681
void ECCPAS::put_value(uint new_value)
2684
int old_value = value.get();
2685
new_value &= mValidBits;
2688
// Auto-shutdown trigger active
2689
// make sure ECCPASE is set
2690
// if change in shutdown status, drive bridge outputs as per current flags
2691
if (shutdown_trigger(new_value))
2693
new_value |= ECCPASE;
2694
if ((new_value ^ old_value) & (ECCPASE|PSSAC1|PSSAC0|PSSBD1|PSSBD0))
2695
ccp1con->shutdown_bridge(new_value);
2697
else // no Auto-shutdown triggers active
2699
if (pwm1con->value.get() & PWM1CON::PRSEN) // clear ECCPASE bit
2700
new_value &= ~ ECCPASE;
2702
value.put(new_value);
2704
// Return true is shutdown trigger is active
2705
bool ECCPAS::shutdown_trigger(int key)
2707
if ((key & ECCPAS0) && trig_state[0]) return true;
2708
if ((key & ECCPAS1) && trig_state[1]) return true;
2709
if ((key & ECCPAS2) && trig_state[2]) return true;
2713
// connect IO pins to shutdown trigger source
2714
void ECCPAS::setIOpin(PinModule *p0, PinModule *p1, PinModule *p2)
2719
m_sink = new INT_SignalSink(this, 0);
2720
p0->addSink(m_sink);
2725
m_sink = new INT_SignalSink(this, 1);
2726
p1->addSink(m_sink);
2731
m_sink = new INT_SignalSink(this, 2);
2732
p2->addSink(m_sink);
2736
// set shutdown trigger states
2737
void ECCPAS::set_trig_state(int index, bool state)
2739
if (trig_state[index] != state)
2741
Dprintf(("index=%d state=%d old=%d\n", index, state, trig_state[index]));
2742
trig_state[index] = state;
2743
put_value(value.get());
2746
// Trigger state from comparator 1
2747
void ECCPAS::c1_output(int state)
2749
set_trig_state(0, state);
2751
// Trigger state from comparator 2
2752
void ECCPAS::c2_output(int state)
2754
set_trig_state(1, state);
2756
//--------------------------------------------------
2758
//--------------------------------------------------
2759
PWM1CON::PWM1CON(Processor *pCpu, const char *pName )
2760
: SfrReg(pCpu, pName )
2768
void PWM1CON::put(uint new_value)
2770
new_value &= mValidBits;
2771
Dprintf(("PWM1CON::put() new_value=0x%x\n",new_value));
2773
value.put(new_value);
2775
//--------------------------------------------------
2777
//--------------------------------------------------
2778
PSTRCON::PSTRCON(Processor *pCpu, const char *pName )
2779
: SfrReg(pCpu, pName )
2786
void PSTRCON::put(uint new_value)
2788
Dprintf(("PSTRCON::put() new_value=0x%x\n",new_value));
2789
new_value &= STRSYNC|STRD|STRC|STRB|STRA;
2791
value.put(new_value);
2794
//--------------------------------------------------------------------
2795
// PWM TIMER SELECTION CONTROL REGISTER
2796
//--------------------------------------------------------------------
2797
CCPTMRS14::CCPTMRS14(Processor *pCpu, const char *pName )
2798
: SfrReg(pCpu, pName )
2800
for(int i=0; i<4; i++) ccp[i] = 0;
2804
void CCPTMRS14::put(unsigned int new_value)
2807
value.put(new_value);
2809
for(int i=0; i<4; i++)
2811
switch(new_value & 0x3)
2831
ccp[i]->set_tmr2(tx);
2832
tx->add_ccp(ccp[i]);