~arcachofo/simulide/1.1.0

« back to all changes in this revision

Viewing changes to src/gpsim/modules/14bit-tmrs.cc

  • Committer: arcachofo
  • Date: 2021-01-01 14:23:42 UTC
  • Revision ID: arcachofo@simulide.com-20210101142342-ozfljnll44g5lbl3
Initial Commit 0.5.15-RC3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Copyright (C) 1998 T. Scott Dattalo
 
3
   Copyright (C) 2006,2009,2010,2013,2015,2017 Roy R Rankin
 
4
 
 
5
This file is part of the libgpsim library of gpsim
 
6
 
 
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.
 
11
 
 
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.
 
16
 
 
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>.
 
20
*/
 
21
 
 
22
#include <stdio.h>
 
23
#include <algorithm>
 
24
#include <iostream>
 
25
#include <iomanip>
 
26
#include <string>
 
27
 
 
28
#include "14bit-tmrs.h"
 
29
#include "a2dconverter.h"
 
30
#include "clc.h"
 
31
 
 
32
//
 
33
// 14bit-tmrs.cc
 
34
//
 
35
// Timer 1&2  modules for the 14bit core pic processors.
 
36
//
 
37
//#define DEBUG
 
38
 
 
39
#if defined(DEBUG)
 
40
#define Dprintf(arg) {printf("%s:%d ",__FILE__,__LINE__); printf arg; }
 
41
#else
 
42
#define Dprintf(arg) {}
 
43
#endif
 
44
 
 
45
CCPRL::CCPRL(Processor *pCpu, const char *pName )
 
46
    : SfrReg(pCpu, pName ),
 
47
      ccprh(0), ccpcon(0), tmrl(0)
 
48
{
 
49
}
 
50
 
 
51
bool CCPRL::test_compare_mode()
 
52
{
 
53
    return tmrl && ccpcon && ccpcon->test_compare_mode();
 
54
}
 
55
 
 
56
void CCPRL::put( uint new_value )
 
57
{
 
58
    value.put( new_value );
 
59
    if(test_compare_mode()) start_compare_mode();   // Actually, re-start with new capture value.
 
60
}
 
61
 
 
62
void CCPRL::capture_tmr()
 
63
{
 
64
    tmrl->get_low_and_high();
 
65
 
 
66
    value.put( tmrl->value.get() );
 
67
 
 
68
    ccprh->value.put( tmrl->tmrh->value.get() );
 
69
}
 
70
 
 
71
void CCPRL::start_compare_mode(CCPCON *ref)
 
72
{
 
73
    int capture_value = value.get() + 256*ccprh->value.get();
 
74
 
 
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";
 
78
}
 
79
 
 
80
void CCPRL::stop_compare_mode()
 
81
{
 
82
    // If this CCP is in the compare mode, then change to non-compare and cancel
 
83
    // the tmr breakpoint.
 
84
 
 
85
    if(test_compare_mode()) tmrl->clear_compare_event ( ccpcon );
 
86
 
 
87
    ccpcon = 0;
 
88
}
 
89
 
 
90
void CCPRL::start_pwm_mode()
 
91
{
 
92
    ccprh->pwm_mode = 1;
 
93
}
 
94
 
 
95
void CCPRL::stop_pwm_mode()
 
96
{
 
97
    ccprh->pwm_mode = 0;
 
98
}
 
99
 
 
100
//--------------------------------------------------
 
101
// assign_tmr - assign a new timer to the capture compare module
 
102
//
 
103
// This was created for the 18f family where it's possible to dynamically
 
104
// choose which clock is captured during an event.
 
105
//
 
106
void CCPRL::assign_tmr( TMRL* ptmr )
 
107
{
 
108
    if( ptmr )
 
109
    {
 
110
        cout << "Reassigning CCPRL clock source\n";
 
111
        tmrl = ptmr;
 
112
    }
 
113
}
 
114
 
 
115
//--------------------------------------------------
 
116
// CCPRH
 
117
//--------------------------------------------------
 
118
 
 
119
CCPRH::CCPRH(Processor *pCpu, const char *pName )
 
120
    : SfrReg( pCpu, pName  ),
 
121
      ccprl(0),pwm_mode(0),pwm_value(0)
 
122
{
 
123
}
 
124
 
 
125
// put_value allows PWM code to put data
 
126
void CCPRH::put_value( uint new_value )
 
127
{
 
128
    value.put( new_value );
 
129
}
 
130
 
 
131
void CCPRH::put( uint new_value )
 
132
{
 
133
    if( pwm_mode == 0 )   // In pwm_mode, CCPRH is a read-only register.
 
134
    {
 
135
        put_value( new_value );
 
136
 
 
137
        if( ccprl && ccprl->test_compare_mode() )
 
138
            ccprl->start_compare_mode();   // Actually, re-start with new capture value.
 
139
    }
 
140
}
 
141
 
 
142
uint CCPRH::get()
 
143
{
 
144
    return value.get();
 
145
}
 
146
 
 
147
//--------------------------------------------------
 
148
//
 
149
//--------------------------------------------------
 
150
class CCPSignalSource : public SignalControl
 
151
{
 
152
public:
 
153
    CCPSignalSource( CCPCON *_ccp, int _index )
 
154
        : m_ccp(_ccp ),
 
155
          state('?'), index(_index)
 
156
    {
 
157
        assert(m_ccp);
 
158
    }
 
159
    virtual ~CCPSignalSource() { }
 
160
 
 
161
    void setState(char m_state) { state = m_state; }
 
162
    virtual char getState() { return state; }
 
163
    virtual void release() { m_ccp->releasePins(index); }
 
164
 
 
165
private:
 
166
    CCPCON *m_ccp;
 
167
    char state;
 
168
    int index;
 
169
};
 
170
 
 
171
//--------------------------------------------------
 
172
//
 
173
//--------------------------------------------------
 
174
 
 
175
class CCPSignalSink : public SignalSink
 
176
{
 
177
public:
 
178
    CCPSignalSink( CCPCON *_ccp, int _index )
 
179
        : m_ccp(_ccp), index(_index)
 
180
    {
 
181
        assert(_ccp);
 
182
    }
 
183
 
 
184
    virtual ~CCPSignalSink(){}
 
185
    virtual void release() { m_ccp->releaseSink(); }
 
186
    void setSinkState(char new3State)
 
187
    { m_ccp->new_edge( new3State=='1' || new3State=='W'); }
 
188
 
 
189
private:
 
190
    CCPCON *m_ccp;
 
191
    int index;
 
192
};
 
193
 
 
194
class Tristate : public SignalControl
 
195
{
 
196
public:
 
197
    Tristate() { }
 
198
    ~Tristate() { }
 
199
    char getState() { return '1'; }        // set port to high impedance by setting it to input
 
200
    virtual void release() { }
 
201
};
 
202
 
 
203
//--------------------------------------------------
 
204
// CCPCON
 
205
 
 
206
CCPCON::CCPCON(Processor *pCpu, const char *pName )
 
207
    : SfrReg( pCpu, pName  ),
 
208
      pstrcon(0),
 
209
      pwm1con(0),
 
210
      eccpas(0),
 
211
      m_sink(0),
 
212
      m_tristate(0),
 
213
      m_bInputEnabled(false),
 
214
      m_bOutputEnabled(false),
 
215
      m_cOutputState('?'),
 
216
      edges(0), delay_source0(false), delay_source1(false),
 
217
      bridge_shutdown(false),
 
218
      ccprl(0), pir(0), tmr2(0), adcon0(0)
 
219
{
 
220
    for(int i=0; i<4; i++)
 
221
    {
 
222
        m_PinModule[i] = 0;
 
223
        m_source[i] = 0;
 
224
        source_active[i] = false;
 
225
    }
 
226
    mValidBits = 0x3f;
 
227
}
 
228
 
 
229
CCPCON::~CCPCON()
 
230
{
 
231
    for( int i=0; i<4; i++ )
 
232
    {
 
233
        if( m_source[i] )
 
234
        {
 
235
            if( source_active[i] && m_PinModule[i] )
 
236
            {
 
237
                m_PinModule[i]->setSource(0);
 
238
            }
 
239
            delete m_source[i];
 
240
        }
 
241
    }
 
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;
 
245
}
 
246
 
 
247
void CCPCON::setIOPin1(PinModule *p1)
 
248
{
 
249
    if (p1 && &(p1->getPin()))
 
250
    {
 
251
        if (m_PinModule[0])
 
252
        {
 
253
            if (m_PinModule[0] != p1)
 
254
            {
 
255
                m_PinModule[0]->removeSink(m_sink);
 
256
                m_PinModule[0] = p1;
 
257
                p1->addSink(m_sink);
 
258
            }
 
259
        }
 
260
        else
 
261
        {
 
262
            m_PinModule[0] = p1;
 
263
            m_sink = new CCPSignalSink(this, 0);
 
264
            m_tristate = new Tristate();
 
265
            m_source[0] = new CCPSignalSource(this, 0);
 
266
            p1->addSink(m_sink);
 
267
        }
 
268
    }
 
269
}
 
270
 
 
271
void CCPCON::setIOPin2(PinModule *p2)
 
272
{
 
273
    if (p2)
 
274
    {
 
275
        m_PinModule[1] = p2;
 
276
        if (!m_source[1]) m_source[1] = new CCPSignalSource(this, 1);
 
277
    }
 
278
    else
 
279
    {
 
280
        if (m_source[1])
 
281
        {
 
282
            delete m_source[1];
 
283
            m_source[1] = 0;
 
284
        }
 
285
        m_PinModule[1] = 0;
 
286
    }
 
287
}
 
288
 
 
289
void CCPCON::setIOPin3(PinModule *p3)
 
290
{
 
291
    if (p3)
 
292
    {
 
293
        m_PinModule[2] = p3;
 
294
        if (!m_source[2]) m_source[2] = new CCPSignalSource(this, 2);
 
295
    }
 
296
    else
 
297
    {
 
298
        if (m_source[2])
 
299
        {
 
300
            delete m_source[2];
 
301
            m_source[2] = 0;
 
302
        }
 
303
        m_PinModule[2] = 0;
 
304
    }
 
305
}
 
306
 
 
307
void CCPCON::setIOPin4(PinModule *p4)
 
308
{
 
309
    if (p4)
 
310
    {
 
311
        m_PinModule[3] = p4;
 
312
        if (!m_source[3])  m_source[3] = new CCPSignalSource(this, 3);
 
313
    }
 
314
    else
 
315
    {
 
316
        if (m_source[3])
 
317
        {
 
318
            delete m_source[3];
 
319
            m_source[3] = 0;
 
320
        }
 
321
    }
 
322
}
 
323
 
 
324
void CCPCON::setIOpin(int data, PinModule *pin)
 
325
{
 
326
    switch(data)
 
327
    {
 
328
    case CCP_PIN:
 
329
        setIOPin1(pin);
 
330
        break;
 
331
 
 
332
    case PxB_PIN:
 
333
        setIOPin2(pin);
 
334
        break;
 
335
 
 
336
    case PxC_PIN:
 
337
        setIOPin3(pin);
 
338
        break;
 
339
 
 
340
    case PxD_PIN:
 
341
        setIOPin4(pin);
 
342
        break;
 
343
    }
 
344
}
 
345
 
 
346
// EPWM has four outputs PWM 1
 
347
void CCPCON::setIOpin(PinModule *p1, PinModule *p2, PinModule *p3, PinModule *p4)
 
348
{
 
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"
 
354
                                       ));
 
355
    if (p1 && !&(p1->getPin()))
 
356
    {
 
357
        Dprintf(("FIXME %s::setIOpin called where p1 has unassigned pin\n", name().c_str()));
 
358
        return;
 
359
    }
 
360
    setIOPin1(p1);
 
361
    setIOPin2(p2);
 
362
    setIOPin3(p3);
 
363
    setIOPin4(p4);
 
364
}
 
365
 
 
366
void CCPCON::setCrosslinks( CCPRL *_ccprl, PIR *_pir, uint _mask,
 
367
                            TMR2 *_tmr2, ECCPAS *_eccpas )
 
368
{
 
369
    ccprl = _ccprl;
 
370
    pir = _pir;
 
371
    tmr2 = _tmr2;
 
372
    eccpas = _eccpas;
 
373
    pir_mask = _mask;
 
374
}
 
375
 
 
376
void CCPCON::setADCON(ADCON0 *_adcon0)
 
377
{
 
378
    adcon0 = _adcon0;
 
379
}
 
380
 
 
381
char CCPCON::getState()
 
382
{
 
383
    return m_bOutputEnabled ?  m_cOutputState : '?';
 
384
}
 
385
 
 
386
void CCPCON::new_edge(uint level)
 
387
{
 
388
    Dprintf(("%s::new_edge() level=%u\n",name().c_str(), level));
 
389
 
 
390
    switch(value.get() & (CCPM3 | CCPM2 | CCPM1 | CCPM0))
 
391
    {
 
392
    case ALL_OFF0:
 
393
    case ALL_OFF1:
 
394
    case ALL_OFF2:
 
395
    case ALL_OFF3:
 
396
        Dprintf(("--CCPCON not enabled\n"));
 
397
        return;
 
398
 
 
399
    case CAP_FALLING_EDGE:
 
400
        if (level == 0 && ccprl)
 
401
        {
 
402
            ccprl->capture_tmr();
 
403
            pir->set(pir_mask);
 
404
            Dprintf(("--CCPCON caught falling edge\n"));
 
405
        }
 
406
        break;
 
407
 
 
408
    case CAP_RISING_EDGE:
 
409
        if (level && ccprl)
 
410
        {
 
411
            ccprl->capture_tmr();
 
412
            pir->set(pir_mask);
 
413
            Dprintf(("--CCPCON caught rising edge\n"));
 
414
        }
 
415
        break;
 
416
 
 
417
    case CAP_RISING_EDGE4:
 
418
        if (level && --edges <= 0)
 
419
        {
 
420
            ccprl->capture_tmr();
 
421
            pir->set(pir_mask);
 
422
            edges = 4;
 
423
            Dprintf(("--CCPCON caught 4th rising edge\n"));
 
424
        }
 
425
        //else cout << "Saw rising edge, but skipped\n";
 
426
        break;
 
427
 
 
428
 
 
429
    case CAP_RISING_EDGE16:
 
430
        if (level && --edges <= 0)
 
431
        {
 
432
            ccprl->capture_tmr();
 
433
            pir->set(pir_mask);
 
434
            edges = 16;
 
435
            Dprintf(("--CCPCON caught 4th rising edge\n"));
 
436
        }
 
437
        //else cout << "Saw rising edge, but skipped\n";
 
438
        break;
 
439
 
 
440
    case COM_SET_OUT:
 
441
    case COM_CLEAR_OUT:
 
442
    case COM_INTERRUPT:
 
443
    case COM_TRIGGER:
 
444
    case PWM0:
 
445
    case PWM1:
 
446
    case PWM2:
 
447
    case PWM3:
 
448
        //cout << "CCPCON is set up as an output\n";
 
449
        return;
 
450
    }
 
451
}
 
452
 
 
453
void CCPCON::compare_match()
 
454
{
 
455
    Dprintf(("%s::compare_match()\n", name().c_str()));
 
456
 
 
457
    switch(value.get() & (CCPM3 | CCPM2 | CCPM1 | CCPM0))
 
458
    {
 
459
    case ALL_OFF0:
 
460
    case ALL_OFF1:
 
461
    case ALL_OFF2:
 
462
    case ALL_OFF3:
 
463
        Dprintf(("-- CCPCON not enabled\n"));
 
464
        return;
 
465
 
 
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"));
 
471
        break;
 
472
 
 
473
    case COM_SET_OUT:
 
474
        m_cOutputState = '1';
 
475
        m_source[0]->setState('1');
 
476
        m_PinModule[0]->updatePinModule();
 
477
        if (pir)
 
478
            pir->set(pir_mask);
 
479
        Dprintf(("-- CCPCON setting compare output to 1\n"));
 
480
        break;
 
481
 
 
482
    case COM_CLEAR_OUT:
 
483
        m_cOutputState = '0';
 
484
        m_source[0]->setState('0');
 
485
        m_PinModule[0]->updatePinModule();
 
486
        if (pir)
 
487
            pir->set(pir_mask);
 
488
        Dprintf(("-- CCPCON setting compare output to 0\n"));
 
489
        break;
 
490
 
 
491
    case COM_INTERRUPT:
 
492
        if (pir) pir->set(pir_mask);
 
493
        Dprintf(("-- CCPCON setting interrupt\n"));
 
494
        break;
 
495
 
 
496
    case COM_TRIGGER:
 
497
        if( ccprl) ccprl->tmrl->clear_timer();
 
498
        if( pir) pir->set(pir_mask);
 
499
        if( adcon0) adcon0->start_conversion();
 
500
 
 
501
        Dprintf(("-- CCPCON triggering an A/D conversion ccprl %p\n", ccprl));
 
502
        break;
 
503
 
 
504
    case PWM0:
 
505
    case PWM1:
 
506
    case PWM2:
 
507
    case PWM3:
 
508
        //cout << "CCPCON is set up as an output\n";
 
509
        return;
 
510
 
 
511
    }
 
512
}
 
513
 
 
514
// handle dead-band delay in half-bridge mode
 
515
void CCPCON::callback()
 
516
{
 
517
    if(delay_source0)
 
518
    {
 
519
        m_source[0]->setState('1');
 
520
        m_PinModule[0]->updatePinModule();
 
521
        delay_source0 = false;
 
522
    }
 
523
    if(delay_source1)
 
524
    {
 
525
        m_source[1]->setState('1');
 
526
        m_PinModule[1]->updatePinModule();
 
527
        delay_source1 = false;
 
528
    }
 
529
}
 
530
 
 
531
void CCPCON::releaseSink()
 
532
{
 
533
    delete m_sink;
 
534
    m_sink = 0;
 
535
}
 
536
void CCPCON::releasePins(int i)
 
537
{
 
538
    source_active[i] = false;
 
539
}
 
540
 
 
541
void CCPCON::pwm_match(int level)
 
542
{
 
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()));
 
545
 
 
546
 
 
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.
 
551
    if(level == 1) {
 
552
        // Auto shutdown comes off at start of PWM if ECCPASE clear
 
553
        if (bridge_shutdown && (!eccpas || !(eccpas->get_value() & ECCPAS::ECCPASE)))
 
554
        {
 
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++)
 
558
            {
 
559
                if(m_PinModule[i])
 
560
                {
 
561
                    m_PinModule[i]->setControl(0); //restore default pin direction
 
562
                    source_active[i] = false;
 
563
                    m_PinModule[i]->updatePinModule();
 
564
                }
 
565
            }
 
566
            bridge_shutdown = false;
 
567
        }
 
568
 
 
569
        tmr2->pwm_dc(pwm_latch_value(), address);
 
570
        ccprl->ccprh->put_value(ccprl->value.get());
 
571
    }
 
572
    if( !pwm1con)  // simple PWM
 
573
    {
 
574
        if (bridge_shutdown == false) // some processors use shutdown and simple PWM
 
575
        {
 
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;
 
580
 
 
581
            if(level && !pwm_latch_value())  // if duty cycle == 0 output stays low
 
582
                m_source[0]->setState('0');
 
583
 
 
584
            m_PinModule[0]->updatePinModule();
 
585
            //cout << "iopin should change\n";
 
586
        }
 
587
    }
 
588
    else        // EPWM
 
589
    {
 
590
        if (!bridge_shutdown) drive_bridge(level, new_value);
 
591
    }
 
592
}
 
593
//
 
594
//  Drive PWM bridge
 
595
//
 
596
void CCPCON::drive_bridge(int level, int new_value)
 
597
{
 
598
    uint pstrcon_value;
 
599
    // pstrcon allows port steering for "single output"
 
600
    // if it is not defined, just use the first port
 
601
    if (pstrcon)
 
602
        pstrcon_value = pstrcon->value.get();
 
603
    else
 
604
        pstrcon_value = 1;
 
605
    int pwm_width;
 
606
    int delay = pwm1con->value.get() & ~PWM1CON::PRSEN;
 
607
 
 
608
    bool active_high[4];
 
609
    switch (new_value & (CCPM3|CCPM2|CCPM1|CCPM0))
 
610
    {
 
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;
 
616
        break;
 
617
 
 
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;
 
623
        break;
 
624
 
 
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;
 
630
        break;
 
631
 
 
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;
 
637
        break;
 
638
 
 
639
    default:
 
640
        cout << "not pwm mode. bug?\n";
 
641
        return;
 
642
        break;
 
643
    }
 
644
    switch((new_value & (P1M1|P1M0))>>6) // ECCP bridge mode
 
645
    {
 
646
    case 0:        // Single
 
647
        Dprintf(("Single bridge %s pstrcon=0x%x\n", name().c_str(), pstrcon_value));
 
648
        for (int i = 0; i <4; i++)
 
649
        {
 
650
            if (pstrcon_value & (1<<i) && m_PinModule[i])
 
651
            {
 
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');
 
657
                else
 
658
                    m_source[i]->setState(active_high[i]?'0':'1');
 
659
 
 
660
                m_PinModule[i]->updatePinModule();
 
661
            }
 
662
            else if (m_PinModule[i])
 
663
            {
 
664
                m_PinModule[i]->setSource(0);
 
665
                source_active[i] = false;
 
666
            }
 
667
        }
 
668
        break;
 
669
 
 
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;
 
675
        if (m_PinModule[2])
 
676
        {
 
677
            m_PinModule[2]->setSource(0);
 
678
            source_active[2] = false;
 
679
        }
 
680
        if (m_PinModule[3])
 
681
        {
 
682
            m_PinModule[3]->setSource(0);
 
683
            source_active[3] = false;
 
684
        }
 
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();
 
691
 
 
692
        if (!(level^active_high[0]) && pwm_latch_value())
 
693
        {
 
694
            if (delay == 0) m_source[0]->setState('1'); // No delay, change state
 
695
 
 
696
            else if( delay < pwm_width ) // there is a delay
 
697
            {
 
698
                future_cycle = cpu->currentCycle() + delay;
 
699
                cpu->setBreakRel( delay, this );
 
700
                delay_source0 = true;
 
701
            }
 
702
        }
 
703
        else m_source[0]->setState('0');
 
704
 
 
705
        if (!(level^active_high[1]) && pwm_latch_value())
 
706
        {
 
707
            m_source[1]->setState('0');
 
708
        }
 
709
        else
 
710
        {
 
711
            // No delay, change state
 
712
            if (delay == 0) m_source[1]->setState('1');
 
713
            else if (delay < pwm_width) // there is a delay
 
714
            {
 
715
                future_cycle = cpu->currentCycle() + delay;
 
716
                cpu->setBreakRel( delay, this );
 
717
                delay_source1 = true;
 
718
            }
 
719
        }
 
720
        m_PinModule[0]->updatePinModule();
 
721
        m_PinModule[1]->updatePinModule();
 
722
        break;
 
723
 
 
724
    case 1:        // Full bidge Forward
 
725
        if (m_PinModule[0])
 
726
        {
 
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();
 
732
        }
 
733
        if (m_PinModule[1])
 
734
        {
 
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();
 
740
        }
 
741
        if (m_PinModule[2])
 
742
        {
 
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();
 
748
        }
 
749
        if (m_PinModule[3])
 
750
        {
 
751
            m_PinModule[3]->setSource(m_source[3]);
 
752
            source_active[3] = true;
 
753
            // P1D toggles
 
754
            if (level && pwm_latch_value())
 
755
                m_source[3]->setState(active_high[3]?'1':'0');
 
756
            else
 
757
                m_source[3]->setState(active_high[3]?'0':'1');
 
758
            m_PinModule[3]->updatePinModule();
 
759
        }
 
760
        break;
 
761
 
 
762
    case 3:        // Full bridge reverse
 
763
        Dprintf(("full-bridge reverse %s\n", name().c_str()));
 
764
        if (m_PinModule[0])
 
765
        {
 
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();
 
771
        }
 
772
        if (m_PinModule[1])
 
773
        {
 
774
            m_PinModule[1]->setSource(m_source[1]);
 
775
            source_active[1] = true;
 
776
            // P1B toggles
 
777
            if (level && pwm_latch_value())
 
778
                m_source[1]->setState(active_high[1]?'1':'0');
 
779
            else
 
780
                m_source[1]->setState(active_high[1]?'0':'1');
 
781
            m_PinModule[1]->updatePinModule();
 
782
        }
 
783
        if (m_PinModule[2])
 
784
        {
 
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();
 
790
        }
 
791
        if (m_PinModule[3])
 
792
        {
 
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();
 
798
        }
 
799
        break;
 
800
 
 
801
    default:
 
802
        printf("%s::pwm_match impossible ECCP bridge mode\n", name_str.c_str());
 
803
        break;
 
804
    }
 
805
}
 
806
//
 
807
// Set PWM bridge into shutdown mode
 
808
//
 
809
void CCPCON::shutdown_bridge(int eccpas)
 
810
{
 
811
    bridge_shutdown = true;
 
812
 
 
813
    Dprintf(("eccpas=0x%x\n", eccpas));
 
814
 
 
815
    switch(eccpas & (ECCPAS::PSSBD0 | ECCPAS::PSSBD1))
 
816
    {
 
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');
 
820
        break;
 
821
 
 
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');
 
825
        break;
 
826
 
 
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);
 
830
        break;
 
831
    }
 
832
    switch(eccpas & ((ECCPAS::PSSAC0 | ECCPAS::PSSAC1) >> 2))
 
833
    {
 
834
    case 0:        // A, C output 0
 
835
        m_source[0]->setState('0');
 
836
        if (m_source[2]) m_source[2]->setState('0');
 
837
        break;
 
838
 
 
839
    case 1:        // A, C output 1
 
840
        m_source[0]->setState('1');
 
841
        if (m_source[2]) m_source[2]->setState('1');
 
842
        break;
 
843
 
 
844
    default:        // Tristate A & C
 
845
        m_PinModule[0]->setControl(m_tristate);
 
846
        if(m_PinModule[2])  m_PinModule[2]->setControl(m_tristate);
 
847
        break;
 
848
    }
 
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();
 
853
}
 
854
 
 
855
void CCPCON::put(uint new_value)
 
856
{
 
857
    uint old_value =  value.get();
 
858
    new_value &= mValidBits;
 
859
 
 
860
    Dprintf(("%s::put() new_value=0x%x\n",name().c_str(), new_value));
 
861
 
 
862
    value.put(new_value);
 
863
    if (!ccprl || !tmr2) return;
 
864
 
 
865
    // Return if no change other than possibly the duty cycle
 
866
    if (((new_value ^ old_value) & ~(CCPY|CCPX)) == 0)
 
867
        return;
 
868
 
 
869
    bool oldbInEn  = m_bInputEnabled;
 
870
    bool oldbOutEn = m_bOutputEnabled;
 
871
 
 
872
    switch(value.get() & (CCPM3 | CCPM2 | CCPM1 | CCPM0))
 
873
    {
 
874
    case ALL_OFF0:
 
875
    case ALL_OFF1:
 
876
    case ALL_OFF2:
 
877
    case ALL_OFF3:
 
878
        if (ccprl)
 
879
        {
 
880
            ccprl->stop_compare_mode();
 
881
            ccprl->stop_pwm_mode();
 
882
        }
 
883
        if (tmr2)
 
884
            tmr2->stop_pwm(address);
 
885
        m_bInputEnabled = false;
 
886
        m_bOutputEnabled = false;
 
887
 
 
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');
 
891
        break;
 
892
 
 
893
    case CAP_FALLING_EDGE:
 
894
    case CAP_RISING_EDGE:
 
895
        edges = 0;
 
896
        ccprl->stop_compare_mode();
 
897
        ccprl->stop_pwm_mode();
 
898
        tmr2->stop_pwm(address);
 
899
        m_bInputEnabled = true;
 
900
        m_bOutputEnabled = false;
 
901
        break;
 
902
 
 
903
    case CAP_RISING_EDGE4:
 
904
        edges &= 3;
 
905
        ccprl->stop_compare_mode();
 
906
        ccprl->stop_pwm_mode();
 
907
        tmr2->stop_pwm(address);
 
908
        m_bInputEnabled = true;
 
909
        m_bOutputEnabled = false;
 
910
        break;
 
911
 
 
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;
 
918
        break;
 
919
 
 
920
    case COM_SET_OUT:
 
921
    case COM_CLEAR_OUT:
 
922
        m_bOutputEnabled = true;
 
923
    case COM_INTERRUPT:
 
924
    case COM_TRIGGER:
 
925
        ccprl->start_compare_mode(this);
 
926
        ccprl->stop_pwm_mode();
 
927
        tmr2->stop_pwm(address);
 
928
 
 
929
        // RP - just writing CCP2CON doesn't trigger the ADC; that only happens on a match
 
930
        //if(adcon0)
 
931
        //  adcon0->start_conversion();
 
932
 
 
933
        m_bInputEnabled = false;
 
934
        //if(adcon0) cout << "CCP triggering an A/D\n";
 
935
 
 
936
        break;
 
937
 
 
938
    case PWM0:
 
939
    case PWM1:
 
940
    case PWM2:
 
941
    case PWM3:
 
942
        ccprl->stop_compare_mode();
 
943
        /* do this when TMR2 == PR2
 
944
      ccprl->start_pwm_mode();
 
945
      tmr2->pwm_dc( pwm_latch_value(), address);
 
946
*/
 
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));
 
953
        }
 
954
        else pwm_match(0);
 
955
        //RRRpwm_match(2);
 
956
        return;
 
957
        break;
 
958
    }
 
959
 
 
960
    if (oldbOutEn != m_bOutputEnabled && m_PinModule)
 
961
    {
 
962
        if (m_bOutputEnabled)
 
963
        {
 
964
            m_PinModule[0]->setSource(m_source[0]);
 
965
            source_active[0] = true;
 
966
        }
 
967
        else
 
968
        {
 
969
            m_PinModule[0]->setSource(0);
 
970
            m_source[0]->setState('?');
 
971
            source_active[0] = false;
 
972
        }
 
973
    }
 
974
 
 
975
    if ((oldbInEn  != m_bInputEnabled  ||
 
976
         oldbOutEn != m_bOutputEnabled)
 
977
            && m_PinModule[0])
 
978
        m_PinModule[0]->updatePinModule();
 
979
 
 
980
}
 
981
 
 
982
bool CCPCON::test_compare_mode()
 
983
{
 
984
    switch(value.get() & (CCPM3 | CCPM2 | CCPM1 | CCPM0))
 
985
    {
 
986
    case ALL_OFF0:
 
987
    case ALL_OFF1:
 
988
    case ALL_OFF2:
 
989
    case ALL_OFF3:
 
990
    case CAP_FALLING_EDGE:
 
991
    case CAP_RISING_EDGE:
 
992
    case CAP_RISING_EDGE4:
 
993
    case CAP_RISING_EDGE16:
 
994
    case PWM0:
 
995
    case PWM1:
 
996
    case PWM2:
 
997
    case PWM3:
 
998
        return false;
 
999
        break;
 
1000
 
 
1001
    case COM_SET_OUT:
 
1002
    case COM_CLEAR_OUT:
 
1003
    case COM_INTERRUPT:
 
1004
    case COM_TRIGGER:
 
1005
        return true;
 
1006
        break;
 
1007
    }
 
1008
    return false;
 
1009
}
 
1010
 
 
1011
PWMxCON::PWMxCON(Processor *pCpu, const char *pName, char _index)
 
1012
    : CCPCON(pCpu, pName ),
 
1013
      pwmdcl(0), pwmdch(0), m_cwg(0), index(_index)
 
1014
{
 
1015
    mValidBits = 0xd0;
 
1016
    for(int i=0; i<4; i++) m_clc[i] = 0;
 
1017
}
 
1018
void PWMxCON::put(uint new_value)
 
1019
{
 
1020
    new_value &= mValidBits;
 
1021
    put_value(new_value);
 
1022
}
 
1023
 
 
1024
void PWMxCON::put_value(uint new_value)
 
1025
{
 
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));
 
1028
    if (!diff) return;
 
1029
 
 
1030
    value.put(new_value);
 
1031
    if (diff & PWMxEN)
 
1032
    {
 
1033
        if (new_value & PWMxEN) // Turn on PWM
 
1034
        {
 
1035
            pwm_match(0);
 
1036
        }
 
1037
        else                        // Turn off PWM
 
1038
        {
 
1039
            tmr2->stop_pwm(address);
 
1040
        }
 
1041
    }
 
1042
}
 
1043
/*
 
1044
 * level == 0 duty cycle match
 
1045
 * level == 1 tmr2 == PR2
 
1046
 * level == 2
 
1047
 */
 
1048
void PWMxCON::pwm_match(int level)
 
1049
{
 
1050
    uint reg = value.get();
 
1051
 
 
1052
    if (!(reg & PWMxEN)) return;
 
1053
 
 
1054
    Dprintf(("%s::pwm_match() level=%d now=%" PRINTF_GINT64_MODIFIER "d\n", name().c_str(), level, cpu->get_cycles()->get()));
 
1055
 
 
1056
    if (level == 1)
 
1057
    {
 
1058
        tmr2->pwm_dc(pwm_latch_value(), address);
 
1059
        if(!pwm_latch_value()) // if duty cycle == 0 output stays low
 
1060
            level = 0;
 
1061
 
 
1062
    }
 
1063
    if (reg & PWMxPOL)        // inverse output
 
1064
    {
 
1065
        level = level ? 0 : 1;
 
1066
        Dprintf(("invert output\n"));
 
1067
    }
 
1068
    if (level)
 
1069
        reg |= PWMxOUT;
 
1070
    else
 
1071
        reg &= ~PWMxOUT;
 
1072
    Dprintf(("reg 0x%x old 0x%x\n", reg, value.get()));
 
1073
    if (reg != value.get())
 
1074
        put_value(reg);
 
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);
 
1078
    if (reg & PWMxOE)
 
1079
    {
 
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));
 
1086
    }
 
1087
}
 
1088
 
 
1089
 
 
1090
 
 
1091
TRISCCP::TRISCCP(Processor *pCpu, const char *pName ) :
 
1092
    SfrReg(pCpu, pName), first(true)
 
1093
{
 
1094
}
 
1095
void TRISCCP::put(uint new_value)
 
1096
{
 
1097
    if (first) first = false;
 
1098
 
 
1099
    value.put(new_value);
 
1100
}
 
1101
 
 
1102
DATACCP::DATACCP(Processor* pCpu, const char* pName ) :
 
1103
    SfrReg(pCpu, pName), first(true)
 
1104
{
 
1105
}
 
1106
 
 
1107
void DATACCP::put(uint new_value)
 
1108
{
 
1109
    if (first) first = false;
 
1110
 
 
1111
    value.put(new_value);
 
1112
}
 
1113
 
 
1114
//--------------------------------------------------
 
1115
// T1CON
 
1116
//--------------------------------------------------
 
1117
T1CON::T1CON( Processor* pCpu, const char* pName  )
 
1118
    : SfrReg( pCpu, pName  )
 
1119
    , tmrl(0)
 
1120
    , cpu(pCpu)
 
1121
{
 
1122
    m_T1Freq = 32768.0;
 
1123
}
 
1124
T1CON::~T1CON()
 
1125
{
 
1126
}
 
1127
 
 
1128
void T1CON::put(uint new_value)
 
1129
{
 
1130
    uint diff = value.get() ^ new_value;
 
1131
    value.put(new_value);
 
1132
 
 
1133
    if (!tmrl) return;
 
1134
 
 
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();
 
1138
 
 
1139
    if( diff & TMR1ON)
 
1140
        tmrl->on_or_off(value.get() & TMR1ON);
 
1141
    else  if( diff & (T1CKPS0 | T1CKPS1 | TMR1GE | T1GINV))
 
1142
        tmrl->update();
 
1143
}
 
1144
 
 
1145
uint T1CON::get()
 
1146
{
 
1147
    return(value.get());
 
1148
}
 
1149
 
 
1150
uint T1CON::get_prescale()
 
1151
{
 
1152
    return( ((value.get() &(T1CKPS0 | T1CKPS1)) >> 4) );
 
1153
}
 
1154
 
 
1155
double T1CON::t1osc()
 
1156
{
 
1157
    return (value.get() & T1OSCEN) ? m_T1Freq : 0.;
 
1158
}
 
1159
//--------------------------------------------------
 
1160
//
 
1161
//--------------------------------------------------
 
1162
 
 
1163
//
 
1164
//  Signal T1GCon on change of state of Gate pin
 
1165
//
 
1166
class T1GCon_GateSignalSink : public SignalSink
 
1167
{
 
1168
public:
 
1169
    T1GCon_GateSignalSink(T1GCON *_t1gcon)
 
1170
        : m_t1gcon(_t1gcon)
 
1171
    {
 
1172
        assert(_t1gcon);
 
1173
    }
 
1174
    virtual ~T1GCon_GateSignalSink()
 
1175
    {
 
1176
    }
 
1177
 
 
1178
    virtual void release() {delete this; }
 
1179
    virtual void setSinkState(char new3State)
 
1180
    {
 
1181
        m_t1gcon->PIN_gate( new3State=='1' || new3State=='W');
 
1182
    }
 
1183
private:
 
1184
    T1GCON *m_t1gcon;
 
1185
};
 
1186
 
 
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)
 
1192
{
 
1193
}
 
1194
 
 
1195
T1GCON::~T1GCON()
 
1196
{
 
1197
    if (m_Interrupt) m_Interrupt->release();
 
1198
}
 
1199
 
 
1200
bool T1GCON::tmr1_isON()
 
1201
{
 
1202
    if (t1con_g) return t1con_g->get_tmr1on();
 
1203
 
 
1204
    if (tmrl->t1con) return tmrl->t1con->get_tmr1on();
 
1205
 
 
1206
    cerr << "Error " << name_str << " get_tmr1on() not found\n";
 
1207
    return false;
 
1208
}
 
1209
 
 
1210
 
 
1211
void T1GCON::put(uint new_value)
 
1212
{
 
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;
 
1217
 
 
1218
    assert(m_Interrupt);
 
1219
    assert(tmrl);
 
1220
 
 
1221
    if (!diff) return;
 
1222
 
 
1223
    value.put(new_value);
 
1224
 
 
1225
    if (diff & (T1GSS1 | T1GSS0 | T1GPOL | TMR1GE))
 
1226
    {
 
1227
        switch(new_value & (T1GSS1 | T1GSS0))
 
1228
        {
 
1229
        case 0:
 
1230
            new_gate(PIN_gate_state);
 
1231
            break;
 
1232
 
 
1233
        case 1:
 
1234
            new_gate(T0_gate_state);
 
1235
            break;
 
1236
 
 
1237
        case 2:
 
1238
            new_gate(CM1_gate_state);
 
1239
            break;
 
1240
 
 
1241
        case 3:
 
1242
            new_gate(CM2_gate_state);
 
1243
            break;
 
1244
        }
 
1245
        // Dont't allow gate change to clear new T1GG0
 
1246
        if((diff & T1GGO) && t1ggo)
 
1247
            value.put(value.get() | T1GGO);
 
1248
    }
 
1249
    // T1GGO  set and Single pulse mode
 
1250
    if ((diff & T1GGO) && (value.get() & (T1GGO | T1GSPM)))
 
1251
    {
 
1252
        //tmrl->IO_gate(true);
 
1253
        if (value.get() & T1GVAL)
 
1254
        {
 
1255
            value.put(value.get() & ~T1GVAL);
 
1256
            //tmrl->IO_gate(true);
 
1257
            tmrl->IO_gate(false);
 
1258
        }
 
1259
    }
 
1260
    if (diff & T1GTM)
 
1261
    {
 
1262
        if ((value.get() & T1GTM)) // T1GTM going high, set t1g_in to 0
 
1263
        {
 
1264
            if(value.get() & T1GVAL)
 
1265
            {
 
1266
                value.put(value.get() & ~(T1GVAL));
 
1267
                m_Interrupt->Trigger();
 
1268
            }
 
1269
            tmrl->IO_gate(false); // Counting should be stopped
 
1270
        }
 
1271
    }
 
1272
    tmrl->update();
 
1273
}
 
1274
 
 
1275
void T1GCON::setGatepin( PinModule* pin )
 
1276
{
 
1277
    if (pin != gate_pin)
 
1278
    {
 
1279
        if(sink) gate_pin->removeSink(sink);
 
1280
        else     sink = new T1GCon_GateSignalSink(this);
 
1281
 
 
1282
        gate_pin = pin;
 
1283
        Dprintf(("T1GCON::setGatepin %s\n", pin->getPin().name().c_str()));
 
1284
        pin->addSink(sink);
 
1285
    }
 
1286
}
 
1287
 
 
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 )
 
1291
{
 
1292
    PIN_gate_state = state;
 
1293
    if((value.get() & (T1GSS0|T1GSS1)) == 0) new_gate(state);
 
1294
}
 
1295
void T1GCON::T0_gate( bool state)
 
1296
{
 
1297
    T0_gate_state = state;
 
1298
    if((value.get() & (T1GSS0|T1GSS1)) == 1) new_gate(state);
 
1299
}
 
1300
// T[246] = PR[246]
 
1301
// overloads T0_gate_state
 
1302
void T1GCON::T2_gate( bool state)
 
1303
{
 
1304
    T0_gate_state = state;
 
1305
    if((value.get() & (T1GSS0|T1GSS1)) == 1) new_gate(state);
 
1306
}
 
1307
 
 
1308
void T1GCON::CM1_gate( bool state)
 
1309
{
 
1310
    CM1_gate_state = state;
 
1311
    if((value.get() & (T1GSS0|T1GSS1)) == 2) new_gate(state);
 
1312
}
 
1313
 
 
1314
void T1GCON::CM2_gate(bool state)
 
1315
{
 
1316
    CM2_gate_state = state;
 
1317
    if((value.get() & (T1GSS0|T1GSS1)) == 3) new_gate(state);
 
1318
}
 
1319
void T1GCON::new_gate(bool state)
 
1320
{
 
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();
 
1326
 
 
1327
    if ((t1g_in == last_t1g_in) && (t1g_in == t1g_val)) // no state change, do nothing
 
1328
    {
 
1329
        //          tmrl->IO_gate(t1g_val);
 
1330
        return;
 
1331
    }
 
1332
 
 
1333
    last_t1g_in = t1g_in;
 
1334
 
 
1335
    if ( reg_value & T1GTM) // Toggle mode
 
1336
    {
 
1337
        t1g_val = reg_value & T1GVAL;
 
1338
        if (t1g_in)        // rising edge
 
1339
        {
 
1340
            t1g_val = ! t1g_val;                // t1gval changes state
 
1341
        }
 
1342
        else return;
 
1343
    }
 
1344
    else        // Gate directly in control
 
1345
    {
 
1346
        t1g_val = t1g_in;
 
1347
    }
 
1348
 
 
1349
    if (reg_value & T1GSPM)        // Single pulse mode
 
1350
    {
 
1351
        if (!(reg_value & T1GGO))  // do nothing if T1GGO clear
 
1352
            return;
 
1353
 
 
1354
        if (!t1g_val)                // End of gate
 
1355
        {
 
1356
            reg_value &= ~T1GGO;  //set done
 
1357
        }
 
1358
        else                        // Start of gate
 
1359
        {
 
1360
        }
 
1361
        //t1g_val = t1g_in;
 
1362
    }
 
1363
 
 
1364
    if (t1g_val)reg_value |= T1GVAL;
 
1365
    else
 
1366
    {
 
1367
        if (reg_value & T1GVAL)        // interrupt on T1GVAL negative edge
 
1368
        {
 
1369
            m_Interrupt->Trigger();
 
1370
        }
 
1371
        reg_value &= ~T1GVAL;
 
1372
    }
 
1373
    value.put(reg_value);
 
1374
    tmrl->IO_gate(t1g_val);
 
1375
}
 
1376
 
 
1377
//--------------------------------------------------
 
1378
// T1CON_G
 
1379
//--------------------------------------------------
 
1380
T1CON_G::T1CON_G(Processor *pCpu, const char *pName)
 
1381
    : T1CON(pCpu, pName ),
 
1382
      tmrl(0),
 
1383
      t1gcon(pCpu, "t1gcon", this)
 
1384
{
 
1385
    new_name("T1CON");
 
1386
}
 
1387
 
 
1388
T1CON_G::~T1CON_G()
 
1389
{
 
1390
}
 
1391
 
 
1392
void T1CON_G::put(uint new_value)
 
1393
{
 
1394
    uint diff = value.get() ^ new_value;
 
1395
    value.put(new_value);
 
1396
 
 
1397
    if (!tmrl) return;
 
1398
 
 
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();
 
1403
 
 
1404
    if( diff & TMR1ON)
 
1405
        tmrl->on_or_off(value.get() & TMR1ON);
 
1406
    else  if( diff & (T1CKPS0 | T1CKPS1 ))
 
1407
        tmrl->update();
 
1408
}
 
1409
 
 
1410
// If Cap. sensing oscillator T1 clock source, pass to T1
 
1411
void T1CON_G::t1_cap_increment()
 
1412
{
 
1413
    if (get_tmr1cs() == 3)        // T1 input Cap. sensing oscillator
 
1414
        tmrl->increment();
 
1415
}
 
1416
//--------------------------------------------------
 
1417
// member functions for the TMRH base class
 
1418
//--------------------------------------------------
 
1419
TMRH::TMRH(Processor *pCpu, const char *pName )
 
1420
    : SfrReg(pCpu, pName ),
 
1421
      tmrl(0)
 
1422
{
 
1423
    value.put(0);
 
1424
}
 
1425
 
 
1426
void TMRH::put( uint new_value )
 
1427
{
 
1428
    if(!tmrl)
 
1429
    {
 
1430
        value.put( new_value & 0xff );
 
1431
        return;
 
1432
    }
 
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);
 
1439
 
 
1440
    if( tmrl->t1con->get_tmr1on() ) tmrl->update();
 
1441
}
 
1442
 
 
1443
uint TMRH::get()
 
1444
{
 
1445
    return get_value();
 
1446
}
 
1447
 
 
1448
// For the gui and CLI
 
1449
uint TMRH::get_value()
 
1450
{
 
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 )
 
1454
        return value.get();
 
1455
 
 
1456
    if( !tmrl->t1con->get_tmr1on() ) return value.get(); // If the TMR is not running then return.
 
1457
 
 
1458
    tmrl->current_value();
 
1459
 
 
1460
    return( value.get() );
 
1461
}
 
1462
 
 
1463
//--------------------------------------------------
 
1464
 
 
1465
class TMRl_GateSignalSink : public SignalSink
 
1466
{
 
1467
public:
 
1468
    TMRl_GateSignalSink(TMRL *_tmr1l)
 
1469
        : m_tmr1l(_tmr1l)
 
1470
    {
 
1471
        assert(_tmr1l);
 
1472
    }
 
1473
 
 
1474
    virtual void release() { delete this; }
 
1475
    void setSinkState(char new3State)
 
1476
    { m_tmr1l->IO_gate( new3State=='1' || new3State=='W'); }
 
1477
 
 
1478
private:
 
1479
    TMRL *m_tmr1l;
 
1480
};
 
1481
 
 
1482
//--------------------------------------------------
 
1483
// trivial class to represent a compare event reference
 
1484
//--------------------------------------------------
 
1485
 
 
1486
class TMR1CapComRef
 
1487
{
 
1488
public:
 
1489
    TMR1CapComRef * next;
 
1490
 
 
1491
    CCPCON * ccpcon;
 
1492
    uint value;
 
1493
 
 
1494
    TMR1CapComRef ( CCPCON * c, uint v ) : ccpcon(c), value(v) {}
 
1495
};
 
1496
 
 
1497
//--------------------------------------------------
 
1498
// member functions for the TMRL base class
 
1499
//--------------------------------------------------
 
1500
TMRL::TMRL(Processor *pCpu, const char *pName )
 
1501
    : SfrReg(pCpu, pName ),
 
1502
      value_16bit(0),
 
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)
 
1506
{
 
1507
    value.put(0);
 
1508
    synchronized_cycle = 0;
 
1509
    prescale_counter = prescale = 1;
 
1510
    break_value = 0x10000;
 
1511
    last_cycle = 0;
 
1512
    future_cycle = 0;
 
1513
 
 
1514
    ext_scale = 1.;
 
1515
    tmrh    = 0;
 
1516
    t1con   = 0;
 
1517
    compare_queue = 0;
 
1518
    for (int i = 0; i < 4; i++) m_clc[i] = 0;
 
1519
}
 
1520
 
 
1521
TMRL::~TMRL()
 
1522
{
 
1523
    if (m_Interrupt) m_Interrupt->release();
 
1524
}
 
1525
/*
 
1526
 * If we are similating an external RTC crystal for timer1,
 
1527
 * compute scale factor between crsytal speed and processor
 
1528
 * instruction cycle rate
 
1529
 *
 
1530
 * If tmr1cs = 1 Fosc is 4 x normal speed so reduce ticks by 1/4
 
1531
 */
 
1532
void TMRL::set_ext_scale()
 
1533
{
 
1534
    current_value();
 
1535
    if (t1con->get_t1oscen() && (t1con->get_tmr1cs() == 2)) // external clock
 
1536
        ext_scale = cpu->instruction_cps()/t1con->m_T1Freq;
 
1537
 
 
1538
    else if( t1con->get_tmr1cs() == 1 ) ext_scale = 0.25; // Fosc
 
1539
    else ext_scale = 1.;
 
1540
 
 
1541
    if( future_cycle )
 
1542
        last_cycle = cpu->currentCycle()-(int64_t)(value_16bit*( prescale*ext_scale )+0.5);
 
1543
}
 
1544
 
 
1545
void TMRL::release()
 
1546
{
 
1547
}
 
1548
 
 
1549
void TMRL::setIOpin(PinModule *extClkSource)
 
1550
{
 
1551
    Dprintf(("%s::setIOpin %s\n", name().c_str(), extClkSource?extClkSource->getPin().name().c_str():""));
 
1552
 
 
1553
    if (extClkSource) extClkSource->addSink(this);
 
1554
}
 
1555
 
 
1556
void TMRL::setSinkState(char new3State)
 
1557
{
 
1558
    if (new3State != m_cState)
 
1559
    {
 
1560
        m_cState = new3State;
 
1561
        if (m_bExtClkEnabled && (m_cState == '1' || m_cState == 'W'))
 
1562
            increment();
 
1563
    }
 
1564
}
 
1565
 
 
1566
void TMRL::set_compare_event ( uint value, CCPCON *host )
 
1567
{
 
1568
    TMR1CapComRef * event = compare_queue;
 
1569
 
 
1570
    if ( host )
 
1571
    {
 
1572
        while ( event )
 
1573
        {
 
1574
            if ( event->ccpcon == host )
 
1575
            {
 
1576
                event->value = value;
 
1577
                update();
 
1578
                return;
 
1579
            }
 
1580
            event = event->next;
 
1581
        }
 
1582
        event = new TMR1CapComRef ( host, value );
 
1583
        event->next = compare_queue;
 
1584
        compare_queue = event;
 
1585
        update();
 
1586
    }
 
1587
    else
 
1588
        cout << "TMRL::set_compare_event called with no CAPCOM\n";
 
1589
}
 
1590
 
 
1591
void TMRL::clear_compare_event ( CCPCON *host )
 
1592
{
 
1593
    TMR1CapComRef * event = compare_queue;
 
1594
    TMR1CapComRef * * eptr = &compare_queue;
 
1595
 
 
1596
    while ( event )
 
1597
    {
 
1598
        if ( event->ccpcon == host )
 
1599
        {
 
1600
            *eptr = event->next;
 
1601
            delete event;
 
1602
            update();
 
1603
            return;
 
1604
        }
 
1605
        eptr = &event->next;
 
1606
        event = event->next;
 
1607
    }
 
1608
}
 
1609
 
 
1610
void TMRL::setGatepin(PinModule *extGateSource)
 
1611
{
 
1612
    Dprintf(("TMRL::setGatepin\n"));
 
1613
 
 
1614
    if (extGateSource) extGateSource->addSink(new TMRl_GateSignalSink(this));
 
1615
}
 
1616
 
 
1617
void TMRL::set_T1GSS(bool arg)
 
1618
{
 
1619
    m_t1gss = arg;
 
1620
    if (m_t1gss) IO_gate(m_io_GateState);
 
1621
    else         compare_gate(m_compare_GateState);
 
1622
}
 
1623
void TMRL::compare_gate(bool state)
 
1624
{
 
1625
    m_compare_GateState = state;
 
1626
    if (!m_t1gss && m_GateState != state)
 
1627
    {
 
1628
        m_GateState = state;
 
1629
 
 
1630
        Dprintf(("TMRL::compare_gate state %d \n", state));
 
1631
 
 
1632
        if (t1con->get_tmr1GE()) update();
 
1633
    }
 
1634
}
 
1635
void TMRL::IO_gate(bool state)
 
1636
{
 
1637
    m_io_GateState = state;
 
1638
 
 
1639
    if (m_t1gss && (m_GateState != state))
 
1640
    {
 
1641
        m_GateState = state;
 
1642
 
 
1643
        Dprintf(("TMRL::IO_gate state %d \n", state));
 
1644
 
 
1645
        if (t1con->get_tmr1GE()) update();
 
1646
    }
 
1647
}
 
1648
 
 
1649
//------------------------------------------------------------
 
1650
// setInterruptSource()
 
1651
//
 
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).
 
1656
 
 
1657
void TMRL::setInterruptSource(InterruptSource *_int)
 
1658
{
 
1659
    m_Interrupt = _int;
 
1660
}
 
1661
 
 
1662
void TMRL::increment()
 
1663
{
 
1664
    Dprintf(("TMRL increment because of external clock\n"));
 
1665
 
 
1666
    if( --prescale_counter == 0 )
 
1667
    {
 
1668
        prescale_counter = prescale;
 
1669
 
 
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
 
1672
 
 
1673
        // If TMRH/TMRL have been manually changed, we'll want to get the up-to-date values;
 
1674
        current_value();
 
1675
 
 
1676
        value_16bit = 0xffff & ( value_16bit + 1);
 
1677
 
 
1678
        tmrh->value.put((value_16bit >> 8) & 0xff);
 
1679
        value.put(value_16bit & 0xff);
 
1680
        if(value_16bit == 0 && m_Interrupt)
 
1681
        {
 
1682
            m_Interrupt->Trigger();
 
1683
            for(int i=0; i<4; i++)
 
1684
                if (m_clc[i]) m_clc[i]->t1_overflow();
 
1685
        }
 
1686
    }
 
1687
}
 
1688
 
 
1689
void TMRL::on_or_off( int new_state )
 
1690
{
 
1691
    if(new_state) // turn on the timer
 
1692
    {
 
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.
 
1696
 
 
1697
        last_cycle = (int64_t)(cpu->currentCycle()-(value.get()+(tmrh->value.get()<<8))*prescale*ext_scale+0.5);
 
1698
        update();
 
1699
    }
 
1700
    else // turn off the timer and save the current value
 
1701
    {
 
1702
        current_value();
 
1703
        if( future_cycle )
 
1704
        {
 
1705
            cpu->clear_break(this);
 
1706
            future_cycle = 0;
 
1707
        }
 
1708
    }
 
1709
}
 
1710
//
 
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
 
1713
// correctly.
 
1714
//
 
1715
 
 
1716
void TMRL::update()
 
1717
{
 
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
 
1720
 
 
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.
 
1727
  */
 
1728
    if(t1con->get_tmr1on() && (t1con->get_tmr1GE() ? gate : true))
 
1729
    {
 
1730
        switch(t1con->get_tmr1cs())
 
1731
        {
 
1732
        case 0:        // internal clock Fosc/4
 
1733
            break;
 
1734
 
 
1735
        case 1:        // internal clock Fosc
 
1736
            break;
 
1737
 
 
1738
        case 2:        // External clock
 
1739
            if (t1con->get_t1oscen())        // External clock enabled
 
1740
            {
 
1741
                /*
 
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.
 
1747
        */
 
1748
            }
 
1749
            else                        // External stimuli(pin)
 
1750
            {
 
1751
                prescale = 1 << t1con->get_prescale();
 
1752
                prescale_counter = prescale;
 
1753
                set_ext_scale();
 
1754
                return;
 
1755
            }
 
1756
            break;
 
1757
 
 
1758
        case 3:                        // Cap. sensing oscillator
 
1759
            prescale = 1 << t1con->get_prescale();
 
1760
            prescale_counter = prescale;
 
1761
            set_ext_scale();
 
1762
            return;
 
1763
            break;
 
1764
 
 
1765
        default:
 
1766
            cout << "TMR1SC reserved value " << t1con->get_tmr1cs() << endl;
 
1767
            break;
 
1768
        }
 
1769
        set_ext_scale();
 
1770
 
 
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.
 
1775
 
 
1776
        prescale = 1 << t1con->get_prescale();
 
1777
        prescale_counter = prescale;
 
1778
 
 
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);
 
1782
 
 
1783
        break_value = 0x10000;  // Assume that a rollover will happen first.
 
1784
 
 
1785
        for( TMR1CapComRef* event=compare_queue; event; event=event->next )
 
1786
        {
 
1787
            if ( event->value > value_16bit && event->value < break_value )
 
1788
            {
 
1789
                // A compare interrupt is going to happen before the timer will rollover.
 
1790
                break_value = event->value;
 
1791
            }
 
1792
        }
 
1793
        uint64_t fc = cpu->currentCycle() + (uint64_t)((break_value-value_16bit)*prescale*ext_scale);
 
1794
 
 
1795
        if(future_cycle) cpu->reassign_break( future_cycle, fc, this );
 
1796
        else             cpu->setBreakAbs( fc, this );
 
1797
 
 
1798
        future_cycle = fc;
 
1799
    }
 
1800
    else
 
1801
    {
 
1802
        // turn off the timer and save the current value
 
1803
        if (future_cycle)
 
1804
        {
 
1805
            current_value();
 
1806
            cpu->clear_break( this );
 
1807
            future_cycle = 0;
 
1808
        }
 
1809
    }
 
1810
}
 
1811
 
 
1812
void TMRL::put( uint new_value )
 
1813
{
 
1814
    set_ext_scale();
 
1815
 
 
1816
    value.put( new_value & 0xff );
 
1817
 
 
1818
    if( !tmrh || !t1con ) return;
 
1819
 
 
1820
    synchronized_cycle = cpu->currentCycle();
 
1821
    last_cycle = synchronized_cycle-(int64_t)(( value.get()+(tmrh->value.get()<<8))*prescale*ext_scale+0.5);
 
1822
 
 
1823
    current_value();
 
1824
 
 
1825
    if( t1con->get_tmr1on() ) update();
 
1826
}
 
1827
 
 
1828
uint TMRL::get()
 
1829
{
 
1830
    return get_value();
 
1831
}
 
1832
 
 
1833
// For the gui and CLI
 
1834
uint TMRL::get_value()
 
1835
{
 
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();
 
1839
 
 
1840
    if( !t1con->get_tmr1on() ) return value.get(); // If TMRL is not on, then return the current value
 
1841
 
 
1842
    current_value();
 
1843
 
 
1844
    return( value.get() );
 
1845
}
 
1846
 
 
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()
 
1857
//
 
1858
void TMRL::current_value()
 
1859
{
 
1860
    if( !tmrh ) return;
 
1861
 
 
1862
    if( future_cycle == 0 ) value_16bit = tmrh->value.get()*256+value.get();
 
1863
    else
 
1864
    {
 
1865
        value_16bit = cpu->currentCycle();
 
1866
        value_16bit = (uint64_t)((cpu->currentCycle()-last_cycle)/(prescale*ext_scale));
 
1867
 
 
1868
        if( value_16bit > 0x10000 )
 
1869
            cerr << "overflow TMRL " << name_str << " " << value_16bit <<cpu->currentCycle()<< endl;
 
1870
 
 
1871
        value.put(value_16bit & 0xff);
 
1872
        tmrh->value.put((value_16bit>>8) & 0xff);
 
1873
    }
 
1874
}
 
1875
 
 
1876
uint TMRL::get_low_and_high()
 
1877
{
 
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();
 
1881
 
 
1882
    current_value();
 
1883
 
 
1884
    return(value_16bit);
 
1885
}
 
1886
 
 
1887
// set m_bExtClkEnable is tmr1 is being clocked by an external stimulus
 
1888
void TMRL::new_clock_source()
 
1889
{
 
1890
    m_bExtClkEnabled = false;
 
1891
    current_value();
 
1892
 
 
1893
    switch(t1con->get_tmr1cs())
 
1894
    {
 
1895
    case 0:        // Fosc/4
 
1896
        put(value.get());
 
1897
        break;
 
1898
 
 
1899
    case 1:        // Fosc
 
1900
        put(value.get());
 
1901
        break;
 
1902
 
 
1903
    case 2:        // External pin or crystal
 
1904
 
 
1905
        if(t1con->get_t1oscen())        // External crystal, simulate
 
1906
        {
 
1907
            put(value.get());    // let TMRL::put() set a cycle counter break point
 
1908
        }
 
1909
        else        // external pin
 
1910
        {
 
1911
            if (future_cycle)
 
1912
            {
 
1913
                // Compute value_16bit with old prescale and ext_scale
 
1914
                current_value();
 
1915
                cpu->clear_break(this);
 
1916
                future_cycle = 0;
 
1917
            }
 
1918
            prescale = 1 << t1con->get_prescale();
 
1919
            prescale_counter = prescale;
 
1920
            set_ext_scale();
 
1921
            m_bExtClkEnabled = true;
 
1922
        }
 
1923
        break;
 
1924
 
 
1925
    case 3:        // Capacitor sense oscillator
 
1926
        if (future_cycle)
 
1927
        {
 
1928
            // Compute value_16bit with old prescale and ext_scale
 
1929
            current_value();
 
1930
            cpu->clear_break(this);
 
1931
            future_cycle = 0;
 
1932
        }
 
1933
        prescale = 1 << t1con->get_prescale();
 
1934
        prescale_counter = prescale;
 
1935
        set_ext_scale();
 
1936
        break;
 
1937
    }
 
1938
}
 
1939
 
 
1940
//
 
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.
 
1944
//
 
1945
 
 
1946
void TMRL::clear_timer()
 
1947
{
 
1948
    synchronized_cycle = cpu->currentCycle();
 
1949
    last_cycle = synchronized_cycle;
 
1950
    value.put(0);
 
1951
    tmrh->value.put(0);
 
1952
}
 
1953
 
 
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.
 
1957
 
 
1958
void TMRL::callback()
 
1959
{
 
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() )
 
1964
    {
 
1965
        value.put(0);
 
1966
        tmrh->value.put(0);
 
1967
        future_cycle = 0;  // indicates that TMRL no longer has a break point
 
1968
        return;
 
1969
    }
 
1970
    current_value();      // Because this relies on future_cycle, we must call it before clearing that
 
1971
 
 
1972
    future_cycle = 0;     // indicate that there's no break currently set
 
1973
 
 
1974
    if( break_value < 0x10000 ) // The break was due to a "compare"
 
1975
    {
 
1976
        if( value_16bit != break_value ) cout << "TMR1 compare break: value=" << value_16bit << " but break_value=" << break_value << '\n';
 
1977
 
 
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
 
1980
    }
 
1981
    else // The break was due to a roll-over
 
1982
    {
 
1983
        //cout<<"TMRL rollover: " << hex << cycles.get() << '\n';
 
1984
        if (m_Interrupt) m_Interrupt->Trigger();
 
1985
 
 
1986
        for(int i=0; i<4; i++) if (m_clc[i]) m_clc[i]->t1_overflow();
 
1987
 
 
1988
        // Reset the timer to 0.
 
1989
        synchronized_cycle = cpu->currentCycle();
 
1990
        last_cycle = synchronized_cycle;
 
1991
        value.put( 0 );
 
1992
        tmrh->value.put( 0 );
 
1993
    }
 
1994
    update();
 
1995
}
 
1996
 
 
1997
void TMRL::callback_print()
 
1998
{
 
1999
    cout << "TMRL " << name_str << " CallBack ID " << CallBackID << '\n';
 
2000
}
 
2001
 
 
2002
void TMRL::sleep()
 
2003
{
 
2004
    m_sleeping = true;
 
2005
    // If tmr1 is running off Fosc/4 or Fosc this assumes Fosc stops during sleep
 
2006
 
 
2007
    if(  t1con->get_tmr1on() && t1con->get_tmr1cs() < 2)
 
2008
    {
 
2009
        if( future_cycle )
 
2010
        {
 
2011
            current_value();
 
2012
            cpu->clear_break(this);
 
2013
            future_cycle = 0;
 
2014
        }
 
2015
    }
 
2016
}
 
2017
 
 
2018
//---------------------------
 
2019
 
 
2020
void TMRL::wake()
 
2021
{
 
2022
    m_sleeping = false;
 
2023
 
 
2024
    if (  t1con->get_tmr1on() && t1con->get_tmr1cs() < 2)
 
2025
    {
 
2026
        update();
 
2027
    }
 
2028
}
 
2029
 
 
2030
//--------------------------------------------------
 
2031
// member functions for the PR2 base class
 
2032
//--------------------------------------------------
 
2033
 
 
2034
PR2::PR2(Processor *pCpu, const char *pName )
 
2035
    : SfrReg(pCpu, pName ),
 
2036
      tmr2(0)
 
2037
{
 
2038
}
 
2039
 
 
2040
void PR2::put(uint new_value)
 
2041
{
 
2042
    Dprintf(("PR2:: put %x\n", new_value));
 
2043
 
 
2044
    if(value.get() != new_value)
 
2045
    {
 
2046
        if (tmr2) tmr2->new_pr2(new_value);
 
2047
        value.put(new_value);
 
2048
    }
 
2049
    else value.put(new_value);
 
2050
}
 
2051
 
 
2052
//--------------------------------------------------
 
2053
// member functions for the T2CON base class
 
2054
//--------------------------------------------------
 
2055
 
 
2056
T2CON::T2CON(Processor *pCpu, const char *pName )
 
2057
    : SfrReg(pCpu, pName ),
 
2058
      tmr2(0)
 
2059
{
 
2060
}
 
2061
 
 
2062
void T2CON::put(uint new_value)
 
2063
{
 
2064
    uint diff = value.get() ^ new_value;
 
2065
    value.put(new_value);
 
2066
 
 
2067
    if (tmr2)
 
2068
    {
 
2069
        tmr2->new_pre_post_scale();
 
2070
        if( diff & TMR2ON) tmr2->on_or_off(value.get() & TMR2ON);
 
2071
    }
 
2072
}
 
2073
 
 
2074
 
 
2075
TMR2::TMR2(Processor *pCpu, const char *pName )
 
2076
    : SfrReg(pCpu, pName ),
 
2077
      pwm_mode(0),
 
2078
      update_state(TMR2_ANY_PWM_UPDATE | TMR2_PR2_UPDATE),
 
2079
      last_update(0),
 
2080
      prescale(1),
 
2081
      prescale_counter(0), break_value(0), post_scale(0),
 
2082
      last_cycle(0),
 
2083
      pr2(0), pir_set(0), t2con(0), m_txgcon(0), m_Interrupt(0),
 
2084
      tmr2_interface(0)
 
2085
{
 
2086
    ssp_module[0] = ssp_module[1] = 0;
 
2087
    value.put(0);
 
2088
    future_cycle = 0;
 
2089
 
 
2090
    std::fill_n(duty_cycle, MAX_PWM_CHANS, 0);
 
2091
    for (int i = 0; i < 4; i++)
 
2092
        m_clc[i] = 0;
 
2093
    for (int cc = 0; cc < MAX_PWM_CHANS; cc++ )
 
2094
        ccp[cc] = 0;
 
2095
}
 
2096
 
 
2097
TMR2::~TMR2()
 
2098
{
 
2099
    if (m_Interrupt) m_Interrupt->release();
 
2100
}
 
2101
 
 
2102
 
 
2103
void TMR2::callback_print()
 
2104
{
 
2105
    cout << "TMR2 " << name_str << " CallBack ID " << CallBackID << '\n';
 
2106
}
 
2107
 
 
2108
void TMR2::start()
 
2109
{
 
2110
    value.put(0);
 
2111
    prescale = 0;
 
2112
    last_cycle = 0;
 
2113
    future_cycle = 0;
 
2114
}
 
2115
 
 
2116
bool TMR2::add_ccp ( CCPCON * _ccp )
 
2117
{
 
2118
    int cc;
 
2119
 
 
2120
    for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
 
2121
    {
 
2122
        if ( ccp[cc] == 0 || ccp[cc] == _ccp )
 
2123
        {
 
2124
            ccp[cc] = _ccp;
 
2125
            return true;
 
2126
        }
 
2127
    }
 
2128
    return false;
 
2129
}
 
2130
 
 
2131
bool TMR2::rm_ccp ( CCPCON * _ccp )
 
2132
{
 
2133
    int cc;
 
2134
 
 
2135
    for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
 
2136
    {
 
2137
        if ( ccp[cc] == _ccp )
 
2138
        {
 
2139
            ccp[cc] = 0;
 
2140
            return true;
 
2141
        }
 
2142
    }
 
2143
    return false;
 
2144
}
 
2145
 
 
2146
 
 
2147
void TMR2::on_or_off(int new_state)
 
2148
{
 
2149
    if(new_state) // turn on the timer
 
2150
    {
 
2151
        Dprintf(("TMR2 is being turned on\n"));
 
2152
 
 
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.
 
2156
 
 
2157
        last_cycle = cpu->currentCycle() - value.get()*prescale;
 
2158
        update();
 
2159
    }
 
2160
    else current_value(); // turn off the timer and save the current value
 
2161
}
 
2162
 
 
2163
//
 
2164
// pwm_dc - set PWM duty cycle
 
2165
//
 
2166
void TMR2::pwm_dc(uint dc, uint ccp_address)
 
2167
{
 
2168
    int modeMask = TMR2_PWM1_UPDATE;
 
2169
    bool found = false;
 
2170
    int cc;
 
2171
 
 
2172
    for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
 
2173
    {
 
2174
        if ( ccp[cc] && ( ccp_address == ccp[cc]->address ) )
 
2175
        {
 
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;
 
2180
            return;
 
2181
        }
 
2182
        modeMask <<= 1;
 
2183
    }
 
2184
    if ( ! found )
 
2185
    {
 
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;
 
2190
 
 
2191
        cout << '\n';
 
2192
    }
 
2193
}
 
2194
 
 
2195
//
 
2196
// stop_pwm
 
2197
//
 
2198
 
 
2199
void TMR2::stop_pwm(uint ccp_address)
 
2200
{
 
2201
    int modeMask = TMR2_PWM1_UPDATE;
 
2202
    int cc;
 
2203
    int old_pwm = pwm_mode;
 
2204
 
 
2205
    for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
 
2206
    {
 
2207
        if ( ccp[cc] && ( ccp_address == ccp[cc]->address ) )
 
2208
        {
 
2209
            // cout << "TMR2:  stopping pwm mode with ccp" << cc+1 << ".\n";
 
2210
            pwm_mode &= ~modeMask;
 
2211
            if(last_update & modeMask) update_state &= (~modeMask);
 
2212
        }
 
2213
        modeMask <<= 1;
 
2214
    }
 
2215
 
 
2216
    if((pwm_mode ^ old_pwm) && future_cycle && t2con->get_tmr2on())
 
2217
        update(update_state);
 
2218
}
 
2219
 
 
2220
//
 
2221
// update
 
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
 
2227
//
 
2228
 
 
2229
void TMR2::update(int ut)
 
2230
{
 
2231
    int modeMask = TMR2_PWM1_UPDATE;
 
2232
    int cc;
 
2233
 
 
2234
    //cout << "TMR2 update. cpu cycle " << hex << cycles.get() <<'\n';
 
2235
 
 
2236
    if(t2con->get_tmr2on())
 
2237
    {
 
2238
        if(future_cycle)
 
2239
        {
 
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.
 
2243
 
 
2244
            current_value();
 
2245
 
 
2246
            // Assume that we are not in pwm mode (and hence the next break will
 
2247
            // be due to tmr2 matching pr2)
 
2248
 
 
2249
            break_value = 1 + pr2->value.get();
 
2250
            uint64_t fc = cpu->currentCycle() + (break_value - value.get()) * prescale;
 
2251
 
 
2252
            last_update = TMR2_PR2_UPDATE;
 
2253
 
 
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;
 
2257
 
 
2258
            for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
 
2259
            {
 
2260
                if ( pwm_mode & ut & modeMask )
 
2261
                {
 
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
 
2265
             rather than TMR2.
 
2266
          */
 
2267
 
 
2268
                    if ( (duty_cycle[cc] > (value.get()*4) ) && ( duty_cycle[cc] < break_value*4 ) )
 
2269
                    {
 
2270
                        uint64_t nc = last_cycle + ( duty_cycle[cc] * prescale ) / 4;
 
2271
 
 
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
 
2275
                        {
 
2276
                            last_update = modeMask;
 
2277
                            fc = nc;
 
2278
                        }
 
2279
                        else if ( nc == fc ) last_update |= modeMask;
 
2280
                    }
 
2281
                }
 
2282
                modeMask <<= 1;
 
2283
            }
 
2284
            if (fc != future_cycle)
 
2285
            {
 
2286
                // cout << "TMR2: update new break at cycle "<<hex<<fc<<'\n';
 
2287
                cpu->reassign_break(future_cycle, fc, this);
 
2288
                future_cycle = fc;
 
2289
            }
 
2290
        }
 
2291
        else cerr << "TMR2 BUG!! tmr2 is on but has no cycle_break set on it\n";
 
2292
    }
 
2293
    else
 
2294
    {
 
2295
        // cout << "TMR2 is not running (no update occurred)\n";
 
2296
    }
 
2297
}
 
2298
 
 
2299
 
 
2300
void TMR2::put(uint new_value)
 
2301
{
 
2302
    uint old_value = get_value();
 
2303
 
 
2304
    value.put(new_value & 0xff);
 
2305
 
 
2306
    if(future_cycle)
 
2307
    {
 
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.
 
2311
 
 
2312
        uint64_t current_cycle = cpu->currentCycle();
 
2313
        uint delta = (future_cycle - last_cycle);
 
2314
        int shift = (new_value - old_value) * prescale;
 
2315
 
 
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 );
 
2318
 
 
2319
        // set cycle when tmr2 would have been zero
 
2320
 
 
2321
        last_cycle = current_cycle - shift;
 
2322
        uint now = (current_cycle - last_cycle);
 
2323
 
 
2324
        //      printf ( "   value now is 0x%X\n", now );
 
2325
 
 
2326
        uint64_t fc;
 
2327
 
 
2328
        /*
 
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.
 
2338
      */
 
2339
 
 
2340
        if (now < delta) // easy case, just shift break.
 
2341
        {
 
2342
            fc = last_cycle + delta;
 
2343
 
 
2344
            //          printf ( "   now < delta (0x%X), set future_cycle to 0x%" PRINTF_INT64_MODIFIER "X\n", delta, fc );
 
2345
 
 
2346
            cpu->reassign_break(future_cycle, fc, this);
 
2347
            future_cycle = fc;
 
2348
        }
 
2349
        else if (now >= break_value * prescale)  // TMR2 now greater than PR2
 
2350
        {
 
2351
            // set break to when TMR2 will overflow
 
2352
            last_update |= TMR2_WRAP;
 
2353
            fc = last_cycle + 0x100 * prescale;
 
2354
 
 
2355
            //        printf ( "   now > break (0x%X), set future_cycle to 0x%" PRINTF_INT64_MODIFIER "X\n", break_value * prescale, fc );
 
2356
 
 
2357
            cpu->reassign_break(future_cycle, fc, this);
 
2358
            future_cycle = fc;
 
2359
        }
 
2360
        else        // new break < PR2 but > duty cycle break
 
2361
        {
 
2362
            //          printf ( "   new break < PR2 but > duty cycle\n" );
 
2363
            update(update_state);
 
2364
        }
 
2365
 
 
2366
        /*
 
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.
 
2370
     */
 
2371
        if (t2con) post_scale = t2con->get_post_scale();
 
2372
    }
 
2373
}
 
2374
 
 
2375
uint TMR2::get()
 
2376
{
 
2377
    if(t2con->get_tmr2on()) current_value();
 
2378
    return(value.get());
 
2379
}
 
2380
 
 
2381
uint TMR2::get_value()
 
2382
{
 
2383
    if(t2con->get_tmr2on()) current_value();
 
2384
    return(value.get());
 
2385
}
 
2386
 
 
2387
void TMR2::new_pre_post_scale()
 
2388
{
 
2389
    //cout << "T2CON was written to, so update TMR2 " << t2con->get_tmr2on() << "\n";
 
2390
 
 
2391
    if(!t2con->get_tmr2on())
 
2392
    {
 
2393
        // TMR2 is not on. If has just been turned off, clear the callback breakpoint.
 
2394
 
 
2395
        if(future_cycle)
 
2396
        {
 
2397
            cpu->clear_break(this);
 
2398
            future_cycle = 0;
 
2399
        }
 
2400
        return;
 
2401
    }
 
2402
 
 
2403
    uint old_prescale = prescale;
 
2404
    prescale = t2con->get_pre_scale();
 
2405
    post_scale = t2con->get_post_scale();
 
2406
 
 
2407
    if(future_cycle)
 
2408
    {
 
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.
 
2412
 
 
2413
 
 
2414
        if (prescale != old_prescale)        // prescaler value change
 
2415
        {
 
2416
            // togo is number of cycles to next callback based on new prescaler.
 
2417
            uint64_t togo = (future_cycle - cpu->currentCycle()) * prescale / old_prescale;
 
2418
 
 
2419
            if (!togo)        // I am not sure this can happen RRR
 
2420
                callback();
 
2421
            else
 
2422
            {
 
2423
                uint64_t fc = togo + cpu->currentCycle();
 
2424
 
 
2425
                cpu->reassign_break(future_cycle, fc, this);
 
2426
                future_cycle = fc;
 
2427
            }
 
2428
        }
 
2429
    }
 
2430
    else
 
2431
    {
 
2432
        //cout << "TMR2 was off, but now it's on.\n";
 
2433
 
 
2434
        if (value.get() == pr2->value.get()) // TMR2 == PR2
 
2435
        {
 
2436
            future_cycle = cpu->currentCycle();
 
2437
            cpu->setBreakAbs( future_cycle, this );
 
2438
            callback();
 
2439
        }
 
2440
        else if (value.get() > pr2->value.get()) // TMR2 > PR2
 
2441
        {
 
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 );
 
2446
        }
 
2447
        else
 
2448
        {
 
2449
            future_cycle = cpu->currentCycle() + 1;
 
2450
            cpu->setBreakAbs( future_cycle, this );
 
2451
            last_cycle = cpu->currentCycle() - value.get();
 
2452
            update(update_state);
 
2453
        }
 
2454
    }
 
2455
}
 
2456
 
 
2457
void TMR2::new_pr2(uint new_value)
 
2458
{
 
2459
    if(t2con->get_tmr2on())
 
2460
    {
 
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;
 
2464
 
 
2465
        uint64_t fc = last_cycle;
 
2466
        /*
 
2467
        PR2 change cases
 
2468
 
 
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.
 
2476
     */
 
2477
        if (now_cycle > new_break)        // TMR2 > PR2 do wrap
 
2478
        {
 
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);
 
2483
            future_cycle = fc;
 
2484
        }
 
2485
        else if (cur_break == break_value ||        // breakpoint due to pr2
 
2486
                 new_break < cur_break)                // new break less than current
 
2487
        {
 
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);
 
2491
            future_cycle = fc;
 
2492
        }
 
2493
    }
 
2494
}
 
2495
 
 
2496
void TMR2::current_value()
 
2497
{
 
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();
 
2501
 
 
2502
    if (tmr2_val == max_counts())
 
2503
    {
 
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.
 
2507
        if (future_cycle)
 
2508
        {
 
2509
            future_cycle = 0;
 
2510
            cpu->clear_break(this);
 
2511
            callback();
 
2512
        }
 
2513
        tmr2_val = 0;
 
2514
    }
 
2515
    value.put(tmr2_val & (max_counts() - 1));
 
2516
 
 
2517
    if(tmr2_val >= max_counts())        // Can get to max_counts  during transition
 
2518
    {
 
2519
        cerr << "TMR2 BUG!! value = 0x" << tmr2_val << " which is greater than 0x";
 
2520
        cerr << max_counts() << endl;
 
2521
    }
 
2522
}
 
2523
 
 
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.
 
2527
 
 
2528
void TMR2::callback()
 
2529
{
 
2530
    int cc;
 
2531
 
 
2532
    //cout<<"TMR2 callback cycle: " << hex << cycles.value << '\n';
 
2533
 
 
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())
 
2537
    {
 
2538
 
 
2539
        // What caused the callback: PR2 match or duty cyle match ?
 
2540
 
 
2541
        if (last_update & TMR2_WRAP) // TMR2 > PR2
 
2542
        {
 
2543
            last_update &= ~TMR2_WRAP;
 
2544
            // This (implicitly) resets the timer to zero:
 
2545
            last_cycle = cpu->currentCycle();
 
2546
        }
 
2547
        else if ( last_update & TMR2_ANY_PWM_UPDATE )
 
2548
        {
 
2549
            int modeMask = TMR2_PWM1_UPDATE;
 
2550
 
 
2551
            for ( cc=0; cc<MAX_PWM_CHANS && last_update; cc++ )
 
2552
            {
 
2553
                if ( last_update & modeMask )
 
2554
                {
 
2555
                    // duty cycle match
 
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);
 
2561
                    else
 
2562
                        cout << "TMR2::callback() found update of non-existent CCP\n";
 
2563
                }
 
2564
                modeMask <<= 1;
 
2565
            }
 
2566
        }
 
2567
        else
 
2568
        {
 
2569
            // matches PR2
 
2570
 
 
2571
            //cout << "TMR2: PR2 match. pwm_mode is " << pwm_mode <<'\n';
 
2572
 
 
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();
 
2576
 
 
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
 
2580
            {
 
2581
                m_txgcon->T2_gate(1);
 
2582
                m_txgcon->T2_gate(0);
 
2583
            }
 
2584
 
 
2585
            for ( cc=0; cc<MAX_PWM_CHANS; cc++ )
 
2586
            {
 
2587
                // RRR FIX
 
2588
                if ( ccp[cc] &&  ccp[cc]->is_pwm()) ccp[cc]->pwm_match(1);
 
2589
            }
 
2590
 
 
2591
            if(--post_scale < 0)
 
2592
            {
 
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();
 
2597
 
 
2598
                post_scale = t2con->get_post_scale();
 
2599
            }
 
2600
            update_state = TMR2_ANY_PWM_UPDATE | TMR2_PR2_UPDATE;
 
2601
        }
 
2602
        update(update_state);
 
2603
    }
 
2604
    else future_cycle = 0;
 
2605
}
 
2606
 
 
2607
//------------------------------------------------------------------------
 
2608
// TMR2_MODULE
 
2609
//
 
2610
//
 
2611
 
 
2612
TMR2_MODULE::TMR2_MODULE()
 
2613
{
 
2614
 
 
2615
    t2con = 0;
 
2616
    pr2   = 0;
 
2617
    tmr2  = 0;
 
2618
    cpu   = 0;
 
2619
    name_str = 0;
 
2620
 
 
2621
}
 
2622
 
 
2623
void TMR2_MODULE::initialize(T2CON *t2con_, PR2 *pr2_, TMR2  *tmr2_)
 
2624
{
 
2625
 
 
2626
    t2con = t2con_;
 
2627
    pr2   = pr2_;
 
2628
    tmr2  = tmr2_;
 
2629
 
 
2630
}
 
2631
 
 
2632
//--------------------------------------------------
 
2633
//
 
2634
//--------------------------------------------------
 
2635
 
 
2636
class INT_SignalSink : public SignalSink
 
2637
{
 
2638
public:
 
2639
    INT_SignalSink(ECCPAS *_eccpas, int _index)
 
2640
        : m_eccpas(_eccpas), m_index(_index)
 
2641
    {
 
2642
        assert(_eccpas);
 
2643
    }
 
2644
 
 
2645
    virtual void release() { delete this; }
 
2646
    void setSinkState(char new3State)
 
2647
    {
 
2648
        m_eccpas->set_trig_state( m_index, new3State=='0' || new3State=='w');
 
2649
    }
 
2650
private:
 
2651
    ECCPAS *m_eccpas;
 
2652
    int     m_index;
 
2653
};
 
2654
 
 
2655
//--------------------------------------------------
 
2656
// ECCPAS
 
2657
//--------------------------------------------------
 
2658
ECCPAS::ECCPAS(Processor *pCpu, const char *pName )
 
2659
    : SfrReg(pCpu, pName ),
 
2660
      pwm1con(0), ccp1con(0),
 
2661
      m_PinModule(0)
 
2662
{
 
2663
    trig_state[0] = trig_state[1] = trig_state[2] = false;
 
2664
    mValidBits = 0xff;
 
2665
}
 
2666
 
 
2667
ECCPAS::~ECCPAS()
 
2668
{
 
2669
}
 
2670
void ECCPAS::link_registers(PWM1CON *_pwm1con, CCPCON *_ccp1con)
 
2671
{
 
2672
    pwm1con = _pwm1con;
 
2673
    ccp1con = _ccp1con;
 
2674
}
 
2675
void ECCPAS::put(uint new_value)
 
2676
{
 
2677
    Dprintf(("ECCPAS::put() new_value=0x%x\n",new_value));
 
2678
 
 
2679
    put_value(new_value);
 
2680
}
 
2681
void ECCPAS::put_value(uint new_value)
 
2682
{
 
2683
 
 
2684
    int old_value = value.get();
 
2685
    new_value &= mValidBits;
 
2686
 
 
2687
 
 
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))
 
2692
    {
 
2693
        new_value |= ECCPASE;
 
2694
        if ((new_value ^ old_value) &  (ECCPASE|PSSAC1|PSSAC0|PSSBD1|PSSBD0))
 
2695
            ccp1con->shutdown_bridge(new_value);
 
2696
    }
 
2697
    else // no Auto-shutdown triggers active
 
2698
    {
 
2699
        if (pwm1con->value.get() & PWM1CON::PRSEN) // clear ECCPASE bit
 
2700
            new_value &= ~ ECCPASE;
 
2701
    }
 
2702
    value.put(new_value);
 
2703
}
 
2704
// Return true is shutdown trigger is active
 
2705
bool ECCPAS::shutdown_trigger(int key)
 
2706
{
 
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;
 
2710
 
 
2711
    return false;
 
2712
}
 
2713
// connect IO pins to shutdown trigger source
 
2714
void ECCPAS::setIOpin(PinModule *p0, PinModule *p1, PinModule *p2)
 
2715
{
 
2716
    if (p0)
 
2717
    {
 
2718
        m_PinModule = p0;
 
2719
        m_sink = new INT_SignalSink(this, 0);
 
2720
        p0->addSink(m_sink);
 
2721
    }
 
2722
    if (p1)
 
2723
    {
 
2724
        m_PinModule = p1;
 
2725
        m_sink = new INT_SignalSink(this, 1);
 
2726
        p1->addSink(m_sink);
 
2727
    }
 
2728
    if (p2)
 
2729
    {
 
2730
        m_PinModule = p2;
 
2731
        m_sink = new INT_SignalSink(this, 2);
 
2732
        p2->addSink(m_sink);
 
2733
    }
 
2734
}
 
2735
 
 
2736
// set shutdown trigger states
 
2737
void ECCPAS::set_trig_state(int index, bool state)
 
2738
{
 
2739
    if (trig_state[index] != state)
 
2740
    {
 
2741
        Dprintf(("index=%d state=%d old=%d\n", index, state, trig_state[index]));
 
2742
        trig_state[index] = state;
 
2743
        put_value(value.get());
 
2744
    }
 
2745
}
 
2746
// Trigger state from comparator 1
 
2747
void ECCPAS::c1_output(int state)
 
2748
{
 
2749
    set_trig_state(0, state);
 
2750
}
 
2751
// Trigger state from comparator 2
 
2752
void ECCPAS::c2_output(int state)
 
2753
{
 
2754
    set_trig_state(1, state);
 
2755
}
 
2756
//--------------------------------------------------
 
2757
// PWM1CON
 
2758
//--------------------------------------------------
 
2759
PWM1CON::PWM1CON(Processor *pCpu, const char *pName )
 
2760
    : SfrReg(pCpu, pName )
 
2761
{
 
2762
    mValidBits = 0xff;
 
2763
}
 
2764
 
 
2765
PWM1CON::~PWM1CON()
 
2766
{
 
2767
}
 
2768
void PWM1CON::put(uint new_value)
 
2769
{
 
2770
    new_value &= mValidBits;
 
2771
    Dprintf(("PWM1CON::put() new_value=0x%x\n",new_value));
 
2772
 
 
2773
    value.put(new_value);
 
2774
}
 
2775
//--------------------------------------------------
 
2776
// PSTRCON
 
2777
//--------------------------------------------------
 
2778
PSTRCON::PSTRCON(Processor *pCpu, const char *pName )
 
2779
    : SfrReg(pCpu, pName )
 
2780
{
 
2781
}
 
2782
 
 
2783
PSTRCON::~PSTRCON()
 
2784
{
 
2785
}
 
2786
void PSTRCON::put(uint new_value)
 
2787
{
 
2788
    Dprintf(("PSTRCON::put() new_value=0x%x\n",new_value));
 
2789
    new_value &= STRSYNC|STRD|STRC|STRB|STRA;
 
2790
 
 
2791
    value.put(new_value);
 
2792
}
 
2793
 
 
2794
//--------------------------------------------------------------------
 
2795
//  PWM TIMER SELECTION CONTROL REGISTER
 
2796
//--------------------------------------------------------------------
 
2797
CCPTMRS14::CCPTMRS14(Processor *pCpu, const char *pName )
 
2798
    : SfrReg(pCpu, pName )
 
2799
{
 
2800
    for(int i=0; i<4; i++) ccp[i] = 0;
 
2801
    t2=t4=t6=0;
 
2802
}
 
2803
 
 
2804
void CCPTMRS14::put(unsigned int new_value)
 
2805
{
 
2806
    TMR2* tx;
 
2807
    value.put(new_value);
 
2808
    
 
2809
    for(int i=0; i<4; i++)
 
2810
    {
 
2811
        switch(new_value & 0x3)
 
2812
        {
 
2813
        case 0:
 
2814
            tx = t2;
 
2815
            break;
 
2816
 
 
2817
        case 1:
 
2818
            tx = t4;
 
2819
            break;
 
2820
 
 
2821
        case 2:
 
2822
            tx = t6;
 
2823
            break;
 
2824
 
 
2825
        default:
 
2826
            tx = 0;
 
2827
            break;
 
2828
        }
 
2829
        if (ccp[i] && tx)
 
2830
        {
 
2831
            ccp[i]->set_tmr2(tx);
 
2832
            tx->add_ccp(ccp[i]);
 
2833
        }
 
2834
        new_value >>= 2;
 
2835
    }
 
2836
}