~arcachofo/simulide/1.1.0

« back to all changes in this revision

Viewing changes to src/gpsim/devices/p12x.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
 
 
4
This file is part of the libgpsim library of gpsim
 
5
 
 
6
This library is free software; you can redistribute it and/or
 
7
modify it under the terms of the GNU Lesser General Public
 
8
License as published by the Free Software Foundation; either
 
9
version 2.1 of the License, or( at your option) any later version.
 
10
 
 
11
This library is distributed in the hope that it will be useful,
 
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
Lesser General Public License for more details.
 
15
 
 
16
You should have received a copy of the GNU Lesser General Public
 
17
License along with this library; if not, see
 
18
<http://www.gnu.org/licenses/lgpl-2.1.html>.
 
19
*/
 
20
 
 
21
 
 
22
//
 
23
// p12x
 
24
//
 
25
//  This file supports:
 
26
//    PIC12C508 PIC12C509
 
27
//    PIC12CE518 PIC12CE519
 
28
//    PIC10F200 PIC10F202 PIC10F204
 
29
//    PIC10F220 PIC10F222
 
30
//
 
31
 
 
32
#include <stdio.h>
 
33
#include <iostream>
 
34
#include <string>
 
35
 
 
36
//#include "i2c-ee.h"
 
37
#include "p12x.h"
 
38
 
 
39
//========================================================================
 
40
// Generic Configuration word for the midrange family.
 
41
 
 
42
class Generic12bitConfigWord : public ConfigWord
 
43
{
 
44
public:
 
45
    Generic12bitConfigWord(P12bitBase *pCpu)
 
46
        : ConfigWord("CONFIG", 0xfff, pCpu, 0xfff), m_pCpu(pCpu)
 
47
    {
 
48
        assert(pCpu);
 
49
        pCpu->wdt.initialize(true);
 
50
    }
 
51
 
 
52
    enum {
 
53
        FOSC0  = 1<<0,
 
54
        FOSC1  = 1<<1,
 
55
        WDTEN  = 1<<2,
 
56
        CP     = 1<<3,
 
57
        MCLRE  = 1<<4
 
58
    };
 
59
 
 
60
    virtual void set(int64_t v)
 
61
    {
 
62
        int64_t oldV = getVal();
 
63
 
 
64
        Integer::set(v);
 
65
        if( m_pCpu)
 
66
        {
 
67
            int64_t diff = oldV ^ v;
 
68
            m_pCpu->setConfigWord(v & 0x3ff, diff & 0x3ff);
 
69
        }
 
70
    }
 
71
    virtual string toString()
 
72
    {
 
73
        int64_t i64;
 
74
        get(i64);
 
75
        int i = i64 &0xfff;
 
76
 
 
77
        char buff[256];
 
78
 
 
79
        snprintf(buff,sizeof(buff),
 
80
                 "$%3x\n"
 
81
                 " FOSC=%d - Clk source = %s\n"
 
82
                 " WDTEN=%d - WDT is %s\n"
 
83
                 " CP=%d - Code protect is %s\n"
 
84
                 " MCLRE=%d - /MCLR is %s",
 
85
                 i,
 
86
                 i &( FOSC0 | FOSC1),
 
87
                 ( (i & FOSC0) ?( (i & FOSC1) ? "EXTRC" : "XT") :( (i & FOSC1) ? "INTRC" : "LP")),
 
88
                 ( (i & WDTEN) ? 1 : 0),( (i & WDTEN) ? "enabled" : "disabled"),
 
89
                 ( (i & CP) ? 1 : 0),( (i & CP) ? "enabled" : "disabled"),
 
90
                 ( (i & MCLRE) ? 1 : 0),( (i & MCLRE) ? "enabled" : "disabled"));
 
91
        return string(buff);
 
92
    }
 
93
 
 
94
private:
 
95
    P12bitBase *m_pCpu;
 
96
};
 
97
 
 
98
void  P12_OSCCON::put(uint new_value)
 
99
{
 
100
    uint old = value.get();
 
101
 
 
102
    value.put(new_value);
 
103
    if((new_value ^ old) & FOSC4 && m_CPU) m_CPU->updateGP2Source();
 
104
    if( (new_value ^ old) & 0xfe && m_CPU) m_CPU->freqCalibration();
 
105
}
 
106
 
 
107
//========================================================================
 
108
// The P12 devices with an EEPROM contain two die. One is the 12C core and
 
109
// the other is an I2C EEPROM( Actually, it is not know if there are two
 
110
// physical die. However, it is known that there are two functional layouts
 
111
// in the same package.) These two devices are connected internally.
 
112
/*class P12_I2C_EE : public I2C_EE
 
113
{
 
114
    public:
 
115
      P12_I2C_EE(pic_processor *, uint _rom_size);
 
116
      ~P12_I2C_EE();
 
117
};
 
118
 
 
119
P12_I2C_EE::P12_I2C_EE(pic_processor* pcpu, uint _rom_size)
 
120
          : I2C_EE(pcpu,_rom_size)
 
121
{
 
122
  if(pcpu) pcpu->ema.set_Registers(rom, rom_size);
 
123
}
 
124
 
 
125
P12_I2C_EE::~P12_I2C_EE()
 
126
{
 
127
}*/
 
128
 
 
129
//-------------------------------------------------------------------
 
130
 
 
131
P12bitBase::P12bitBase(const char *_name)
 
132
    : _12bit_processor(_name ),
 
133
      m_gpio(0),
 
134
      m_tris(0),
 
135
      osccal (this, "osccal" )
 
136
{
 
137
 
 
138
    configWord = 0;
 
139
    set_frequency(4e6);
 
140
}
 
141
 
 
142
P12bitBase::~P12bitBase()
 
143
{
 
144
    if( m_gpio)
 
145
    {
 
146
        ( &(*m_gpio)[3])->setControl(0);
 
147
        ( &(*m_gpio)[2])->setControl(0);
 
148
    }
 
149
    delete m_IN_SignalControl;
 
150
    delete_SfrReg(m_gpio);
 
151
    delete_SfrReg(m_tris);
 
152
    remove_SfrReg(&tmr0);
 
153
    remove_SfrReg(&osccal);
 
154
}
 
155
 
 
156
void P12bitBase::create_config_memory()
 
157
{
 
158
    m_configMemory = new ConfigMemory(this,1);
 
159
    m_configMemory->addConfigWord( 0, new Generic12bitConfigWord(this) );
 
160
}
 
161
 
 
162
//========================================================================
 
163
void P12bitBase::create_iopin_map()
 
164
{
 
165
    assign_pin(7, m_gpio->addPin(new IO_bi_directional_pu("gpio0"),0));
 
166
    assign_pin(6, m_gpio->addPin(new IO_bi_directional_pu("gpio1"),1));
 
167
    assign_pin(5, m_gpio->addPin(new IO_bi_directional("gpio2"),2));
 
168
    assign_pin(4, m_gpio->addPin(new IO_bi_directional_pu("gpio3"),3));
 
169
    assign_pin(3, m_gpio->addPin(new IO_bi_directional("gpio4"),4));
 
170
    assign_pin(2, m_gpio->addPin(new IO_bi_directional("gpio5"),5));
 
171
    assign_pin(1, 0);
 
172
    assign_pin(8, 0);
 
173
 
 
174
    // gpio3 is input only, but we want pullup, so use IO_bi_directional_pu
 
175
    // but force as input pin disableing TRIS control
 
176
    m_IN_SignalControl = new IN_SignalControl;
 
177
    ( &(*m_gpio)[3])->setControl(m_IN_SignalControl);
 
178
}
 
179
 
 
180
//--------------------------------------------------------
 
181
void P12bitBase::reset( RESET_TYPE r )
 
182
{
 
183
    m_tris->reset(r);
 
184
 
 
185
    if( r == IO_RESET) status->put(status->value.get() | 0x80); // Set GPWUF flag
 
186
 
 
187
    _12bit_processor::reset(r);
 
188
}
 
189
 
 
190
//------------------------------------------------------------------------
 
191
#define STATUS_GPWUF  0x80
 
192
 
 
193
void P12bitBase::enter_sleep()
 
194
{
 
195
    pic_processor::enter_sleep();
 
196
 
 
197
    status->put( status->value.get() & ~STATUS_GPWUF);
 
198
    cout << "enter sleep status="<<hex <<status->get()<<endl;
 
199
}
 
200
 
 
201
void  P12bitBase::updateGP2Source()
 
202
{
 
203
    PinModule *pmGP2 = &(*m_gpio)[2];
 
204
 
 
205
    if(option_reg->value.get() & OPTION_REG::T0CS)
 
206
    {
 
207
        printf("OPTION_REG::T0CS forcing GPIO2 as input, TRIS disabled\n");
 
208
        pmGP2->setControl( m_IN_SignalControl );
 
209
    }
 
210
    else
 
211
    {
 
212
        cout << "TRIS now controlling gpio2\n";
 
213
        pmGP2->setControl(0);
 
214
    }
 
215
}
 
216
// freqCalibrate modifies the internal RC frequency
 
217
// the base varsion is for the 12C508 and 12C509 Processors
 
218
// the spec sheet does not indicate the range or step size of corrections
 
219
// so this is based on +/- 12.5 % as per 16f88
 
220
void  P12bitBase::freqCalibration()
 
221
{
 
222
    // If internal RC oscilator
 
223
    if((configWord &( FOSC0 | FOSC1)) == FOSC1)
 
224
    {
 
225
        int osccal_val =( osccal.get() >> 4) - 0x07;
 
226
        double freq = get_frequency();
 
227
        freq *= 1. + 0.125 * osccal_val / 0x08;
 
228
        set_frequency(freq);
 
229
    }
 
230
}
 
231
// option_new_bits_6_7 is called from class OPTION_REG when
 
232
// bits 5, 6, or 7 of  OPTION_REG change state
 
233
//
 
234
void  P12bitBase::option_new_bits_6_7(uint bits)
 
235
{
 
236
    // Weak pullup if NOT_GPPU == 0
 
237
    m_gpio->setPullUp( ( bits & OPTION_REG::BIT6) != OPTION_REG::BIT6 ,( configWord & MCLRE));
 
238
    updateGP2Source();
 
239
}
 
240
 
 
241
void P12bitBase::create_sfr_map()
 
242
{
 
243
    RegisterValue porVal(0,0);
 
244
 
 
245
    add_SfrReg(indf,   0, porVal);
 
246
    add_SfrReg(&tmr0,  1, porVal);
 
247
    add_SfrReg(pcl,    2, RegisterValue(0xff,0));
 
248
    add_SfrReg(status, 3, porVal);
 
249
    add_SfrReg(fsr,    4, porVal);
 
250
    add_SfrReg(&osccal,5, RegisterValue(0x70,0));
 
251
    add_SfrReg(m_gpio, 6, porVal);
 
252
    add_SfrReg(m_tris, 0xffffffff, RegisterValue(0x3f,0));
 
253
    add_SfrReg(Wreg, 0xffffffff, porVal);
 
254
    option_reg->set_cpu(this);
 
255
 
 
256
    osccal.set_cpu(this);
 
257
}
 
258
 
 
259
void  P12bitBase::setConfigWord(uint val, uint diff)
 
260
{
 
261
    PinModule *pmGP3 = &(*m_gpio)[3];
 
262
 
 
263
    configWord = val;
 
264
    if( diff & WDTEN)  wdt.initialize((val & WDTEN) == WDTEN);
 
265
 
 
266
    if( (val & MCLRE) == MCLRE) pmGP3->getPin().update_pullup('1', true);
 
267
}
 
268
 
 
269
void P12bitBase::tris_instruction(uint tris_register)
 
270
{
 
271
    m_tris->put(Wget());
 
272
}
 
273
 
 
274
void P12C508::create()
 
275
{
 
276
    create_iopin_map();
 
277
 
 
278
    _12bit_processor::create();
 
279
 
 
280
    add_file_registers(0x07, 0x1f, 0);
 
281
    P12bitBase::create_sfr_map();
 
282
    create_invalid_registers( );
 
283
 
 
284
    tmr0.set_cpu(this,m_gpio,2,option_reg);
 
285
    tmr0.start(0);
 
286
 
 
287
    pc->reset();
 
288
}
 
289
 
 
290
 
 
291
Processor * P12C508::construct(const char *name)
 
292
{
 
293
    P12C508 *p = new P12C508(name);
 
294
 
 
295
    p->pc->set_reset_address(0x1ff);
 
296
    p->create();
 
297
 
 
298
    return p;
 
299
}
 
300
 
 
301
P12C508::P12C508( const char *_name  )
 
302
    : P12bitBase(_name)
 
303
{
 
304
    m_gpio = new GPIO( this, "gpio", 8, 0x3f);
 
305
    m_tris = new PicTrisRegister( this, "tris", m_gpio, false );
 
306
    m_tris->wdtr_value=RegisterValue(0x3f,0);
 
307
}
 
308
 
 
309
P12C508::~P12C508()
 
310
{
 
311
    delete_file_registers(0x07, 0x1f);
 
312
}
 
313
 
 
314
P12F508::P12F508(const char *_name )
 
315
    : P12C508(_name )
 
316
{
 
317
}
 
318
P12F508::~P12F508()
 
319
{
 
320
}
 
321
 
 
322
Processor * P12F508::construct(const char *name)
 
323
{
 
324
    P12F508 *p = new P12F508(name);
 
325
    p->pc->set_reset_address(0x1ff);
 
326
    p->create();
 
327
 
 
328
    return p;
 
329
}
 
330
//--------------------------------------------------------
 
331
 
 
332
void P12C509::create_sfr_map()
 
333
{
 
334
}
 
335
 
 
336
Processor * P12C509::construct(const char *name)
 
337
{
 
338
    P12C509 *p = new P12C509(name);
 
339
 
 
340
    p->pc->set_reset_address(0x3ff);
 
341
    p->create();
 
342
 
 
343
    return p;
 
344
}
 
345
 
 
346
void P12C509::create()
 
347
{
 
348
    P12C508::create();
 
349
 
 
350
    alias_file_registers(0x00,0x0f,0x20);
 
351
    add_file_registers(0x30, 0x3f, 0);
 
352
 
 
353
    pa_bits = PA0;                 // the 509 has two code pages( i.e. PAO in status is used)
 
354
    indf->base_address_mask2 = 0x3F;  // RP - need this or INDF won't work right
 
355
}
 
356
 
 
357
P12C509::P12C509(const char *_name  )
 
358
    : P12C508(_name  )
 
359
{
 
360
}
 
361
 
 
362
P12C509::~P12C509()
 
363
{
 
364
    delete_file_registers(0x30, 0x3f);
 
365
}
 
366
 
 
367
 
 
368
P12F509::P12F509(const char *_name  )
 
369
    : P12C509(_name  )
 
370
{
 
371
}
 
372
P12F509::~P12F509()
 
373
{
 
374
}
 
375
Processor * P12F509::construct(const char *name)
 
376
{
 
377
    P12F509 *p = new P12F509(name);
 
378
    p->pc->set_reset_address(0x3ff);
 
379
    p->create();
 
380
 
 
381
    return p;
 
382
}
 
383
 
 
384
//
 
385
P12F510::P12F510(const char *_name  )
 
386
    : P12F509(_name  )
 
387
{
 
388
}
 
389
P12F510::~P12F510()
 
390
{
 
391
}
 
392
 
 
393
Processor * P12F510::construct(const char *name)
 
394
{
 
395
    P12F510 *p = new P12F510(name);
 
396
    p->pc->set_reset_address(0x3ff);
 
397
    p->create();
 
398
 
 
399
    return p;
 
400
}
 
401
 
 
402
//--------------------------------------------------------
 
403
 
 
404
// construct function is identical to 12C508 version ??
 
405
Processor * P12CE518::construct(const char *name)
 
406
{
 
407
    P12CE518 *p = new P12CE518(name);
 
408
 
 
409
    p->pc->set_reset_address(0x1ff);
 
410
    p->create();
 
411
 
 
412
    return p;
 
413
}
 
414
 
 
415
 
 
416
void P12CE518::create_iopin_map()
 
417
{
 
418
    P12C508::create_iopin_map();
 
419
 
 
420
    // Define the valid I/O pins.
 
421
    //gpio.valid_iopins = 0xff;
 
422
}
 
423
 
 
424
void P12CE518::create()
 
425
{
 
426
    P12C508::create();
 
427
 
 
428
    ///m_eeprom = new P12_I2C_EE( this, 0x10 );
 
429
    ///m_eeprom->debug();
 
430
 
 
431
    // GPIO bits 6 and 7 are not bonded to physical pins, but are tied
 
432
    // to the internal I2C device.
 
433
    m_gpio->setEnableMask(0xc0 | m_gpio->getEnableMask());
 
434
 
 
435
    RegisterValue por_value(0xc0,0x00);
 
436
    m_gpio->value       = por_value;
 
437
    m_gpio->por_value   = por_value;
 
438
    m_gpio->wdtr_value  = por_value;
 
439
    m_gpio->put(0xc0);
 
440
 
 
441
    osccal.por_value = RegisterValue(0x80,0);
 
442
 
 
443
    // Kludge to force top two bits to be outputs
 
444
    m_tris->put(0x3f);
 
445
 
 
446
    ///
 
447
    /*{
 
448
    scl = new Stimulus_Node(  "EE_SCL" );
 
449
    io_scl = new IO_bi_directional_pu("gpio7");
 
450
    io_scl->update_pullup('1',true);
 
451
    io_scl->setDrivingState(true);
 
452
    io_scl->setDriving(true);
 
453
    scl->attach_stimulus( m_gpio->addPin(io_scl,7));
 
454
    scl->update();
 
455
  }
 
456
  {
 
457
    sda = new Stimulus_Node(  "EE_SDA" );
 
458
 
 
459
    io_sda = new IO_open_collector("gpio6");
 
460
    // enable the pullup resistor.
 
461
    io_sda->update_pullup('1',true);
 
462
    io_sda->setDrivingState(true);
 
463
    io_sda->setDriving(true);
 
464
    m_gpio->addPin(io_sda,6);
 
465
    sda->attach_stimulus( io_sda);
 
466
    sda->update();
 
467
  }*/
 
468
 
 
469
    //m_eeprom->attach(  scl, sda );
 
470
}
 
471
 
 
472
P12CE518::P12CE518(const char *_name  )
 
473
    : P12C508(_name  )
 
474
{
 
475
}
 
476
 
 
477
P12CE518::~P12CE518()
 
478
{
 
479
    /*delete m_eeprom;
 
480
    delete io_scl;
 
481
    delete io_sda;
 
482
    delete scl;
 
483
    delete sda;*/
 
484
}
 
485
 
 
486
void P12CE518::tris_instruction(uint tris_register)
 
487
{
 
488
    uint w_val = Wget();
 
489
    m_tris->put(  w_val & 0x3F );     // top two bits always output
 
490
}
 
491
 
 
492
 
 
493
// freqCalibrate modifies the internal RC frequency
 
494
// this version is for the 12CE518 and 12CE519 Processors but would also
 
495
// be correct for 12C508A/C509A/CR509A
 
496
// the spec sheet does not indicate the range or step size of corrections
 
497
// so this is based on +/- 12.5 % as per 16f88
 
498
void  P12CE518::freqCalibration()
 
499
{
 
500
    // If internal RC oscilator
 
501
    if((configWord &( FOSC0 | FOSC1)) == FOSC1)
 
502
    {
 
503
        int osccal_val =( osccal.get() >> 2) - 0x20;
 
504
        double freq = 4e6;
 
505
        freq *= 1. + 0.125 * osccal_val / 0x20;
 
506
        set_frequency(freq);
 
507
    }
 
508
}
 
509
//--------------------------------------------------------
 
510
 
 
511
void P12CE519::create_sfr_map()
 
512
{
 
513
}
 
514
 
 
515
Processor * P12CE519::construct(const char *name)
 
516
{
 
517
    P12CE519 *p = new P12CE519(name);
 
518
 
 
519
    cout << " 12ce519 construct\n";
 
520
 
 
521
    p->pc->set_reset_address(0x3ff);
 
522
    p->create();
 
523
 
 
524
    return p;
 
525
}
 
526
 
 
527
 
 
528
void P12CE519::create()
 
529
{
 
530
    P12CE518::create();
 
531
 
 
532
    alias_file_registers(0x00,0x0f,0x20);
 
533
    add_file_registers(0x30, 0x3f, 0);
 
534
 
 
535
    pa_bits = PA0;                 // the 519 has two code pages( i.e. PAO in status is used)
 
536
    indf->base_address_mask2 = 0x3F;  // RP - need this or INDF won't work right
 
537
}
 
538
 
 
539
 
 
540
P12CE519::P12CE519(const char *_name  )
 
541
    : P12CE518(_name  )
 
542
{
 
543
}
 
544
 
 
545
P12CE519::~P12CE519()
 
546
{
 
547
    delete_file_registers(0x30, 0x3f);
 
548
}
 
549
 
 
550
 
 
551
//--------------------------------------------------------
 
552
//
 
553
// GPIO Port
 
554
 
 
555
GPIO::GPIO(P12bitBase *pCpu, const char *pName,
 
556
           uint numIopins,
 
557
           uint enableMask,
 
558
           uint resetMask,
 
559
           uint wakeupMask,
 
560
           uint configMaskMCLRE)
 
561
    : PicPortRegister( pCpu,pName, numIopins, enableMask), m_CPU(pCpu)
 
562
    , m_resetMask(resetMask)
 
563
    , m_wakeupMask(wakeupMask)
 
564
    , m_configMaskMCLRE(configMaskMCLRE)
 
565
{
 
566
}
 
567
 
 
568
void GPIO::setbit(uint bit_number, char new_value)
 
569
{
 
570
    uint lastDrivenValue = rvDrivenValue.data;
 
571
 
 
572
    PortRegister::setbit(bit_number, new_value);
 
573
 
 
574
    // If gpio bit 0,1 or 3 changed states AND
 
575
    // ~GPWU is low( wake up on change is enabled) AND
 
576
    // the processor is sleeping.
 
577
    //    Then wake
 
578
 
 
579
    uint diff = lastDrivenValue ^ rvDrivenValue.data;
 
580
 
 
581
    if( (diff & m_resetMask) &&( m_CPU->configWord & m_configMaskMCLRE))
 
582
    {
 
583
        cpu->reset(( rvDrivenValue.data & m_resetMask) ? EXIT_RESET : MCLR_RESET);
 
584
        return;
 
585
    }
 
586
 
 
587
    if( diff & m_wakeupMask)
 
588
    {
 
589
        // If /GPWU is 0( i.e. enabled) and the processor is currently sleeping
 
590
        // then wake up the processor by resetting it.
 
591
        if(( (cpu12->option_reg->value.get() & 0x80) == 0) &&
 
592
                cpu12->getActivityState() == pic_processor::ePASleeping)
 
593
        {
 
594
            cpu->reset(IO_RESET);
 
595
        }
 
596
    }
 
597
}
 
598
 
 
599
// if bNewPU == true set weak pullups otherwise clear weak pullups
 
600
void GPIO::setPullUp(  bool bNewPU , bool mclr)
 
601
{
 
602
    m_bPU = bNewPU;
 
603
 
 
604
    // In the following do not change pullup state of internal pins
 
605
    uint mask = getEnableMask() & 0x3f;
 
606
 
 
607
    // If mclr active do not change pullup on gpio3
 
608
    if( mclr) mask &= 0x37;
 
609
 
 
610
    for( uint i=0, m = 1; mask; i++, m <<= 1)
 
611
    {
 
612
        if( mask & m)
 
613
        {
 
614
            mask ^= m;
 
615
            getPin(i)->update_pullup(  m_bPU ? '1' : '0', true );
 
616
        }
 
617
    }
 
618
}
 
619
 
 
620
 
 
621
//------------------------------------------------------------------------
 
622
void P10F200::create_iopin_map()
 
623
{
 
624
    assign_pin(1, m_gpio->addPin(new IO_bi_directional_pu("gpio0"),0));
 
625
    assign_pin(3, m_gpio->addPin(new IO_bi_directional_pu("gpio1"),1));
 
626
    assign_pin(4, m_gpio->addPin(new IO_bi_directional("gpio2"),2));
 
627
    assign_pin(6, m_gpio->addPin(new IO_bi_directional_pu("gpio3"),3));
 
628
    assign_pin(2, 0);
 
629
    assign_pin(5, 0);
 
630
 
 
631
    // gpio3 is input only, but we want pullup, so use IO_bi_directional_pu
 
632
    // but force as input pin disableing TRIS control
 
633
    m_IN_SignalControl = new IN_SignalControl;
 
634
    m_OUT_SignalControl = new OUT_SignalControl;
 
635
    m_OUT_DriveControl = new OUT_DriveControl;
 
636
    ( &(*m_gpio)[3])->setControl(m_IN_SignalControl);
 
637
}
 
638
 
 
639
void P10F200::create()
 
640
{
 
641
    create_iopin_map();
 
642
 
 
643
    _12bit_processor::create();
 
644
 
 
645
    add_file_registers(0x10, 0x1f, 0);    // 10F200 only has 16 bytes RAM
 
646
    P12bitBase::create_sfr_map();
 
647
    create_invalid_registers( );
 
648
 
 
649
    tmr0.set_cpu(this,m_gpio,2,option_reg);
 
650
    tmr0.start(0);
 
651
    osccal.set_cpu(this);
 
652
    osccal.por_value = RegisterValue(0xfe,0);
 
653
 
 
654
    pc->reset();
 
655
}
 
656
 
 
657
Processor * P10F200::construct(const char *name)
 
658
{
 
659
    P10F200 *p = new P10F200(name);
 
660
 
 
661
    p->pc->set_reset_address(0x0ff);
 
662
    p->create();
 
663
 
 
664
    return p;
 
665
}
 
666
 
 
667
P10F200::P10F200(const char *_name  )
 
668
    : P12bitBase(_name  )
 
669
{
 
670
    m_gpio = new GPIO(this,"gpio",8,0x0f);
 
671
    m_tris = new PicTrisRegister(this, "tris",m_gpio, false);
 
672
    m_tris->wdtr_value=RegisterValue(0x3f,0);
 
673
 
 
674
}
 
675
 
 
676
P10F200::~P10F200()
 
677
{
 
678
    ( &(*m_gpio)[3])->setControl(0);
 
679
    ( &(*m_gpio)[2])->setControl(0);
 
680
 
 
681
    delete m_OUT_SignalControl;
 
682
    delete m_OUT_DriveControl;
 
683
    delete_file_registers(0x10, 0x1f);
 
684
}
 
685
 
 
686
void P10F200::updateGP2Source()
 
687
{
 
688
    PinModule *pmGP2 = &(*m_gpio)[2];
 
689
 
 
690
    if( osccal.value.get() & P12_OSCCON::FOSC4 )
 
691
    {
 
692
        pmGP2->setSource(m_OUT_DriveControl);
 
693
        printf("OSCCON::FOSC4 forcing GPIO2 high on output, TODO FOSC4 toggle output\n");
 
694
    }
 
695
    else if(option_reg->value.get() & OPTION_REG::T0CS)
 
696
    {
 
697
        printf("OPTION_REG::T0CS forcing GPIO2 as input, TRIS disabled\n");
 
698
        pmGP2->setControl(m_IN_SignalControl);
 
699
        pmGP2->setSource(0);
 
700
    }
 
701
    else
 
702
    {
 
703
        // revert to default control, i.e. let TRIS control the output
 
704
        pmGP2->setControl(0);
 
705
        pmGP2->setSource(0);
 
706
        cout << "TRIS now controlling gpio2\n";
 
707
    }
 
708
    pmGP2->updatePinModule();
 
709
}
 
710
 
 
711
// freqCalibrate modifies the internal RC frequency
 
712
// this version is for the 10F2xx Processors
 
713
// the spec sheet does not indicate the range or step size of corrections
 
714
// so this is based on +/- 12.5 % as per 16f88
 
715
void  P10F200::freqCalibration()
 
716
{
 
717
    // If internal RC oscilator
 
718
    char osccal_val =( osccal.value.get() & 0xfe);
 
719
    double freq =( configWord & 1)? 8e6 : 4e6;
 
720
 
 
721
    freq *= 1. +( 0.125 * osccal_val) / 0x80;
 
722
    set_frequency(freq);
 
723
}
 
724
 
 
725
//------------------------------------------------------------------------
 
726
 
 
727
void P10F202::create()
 
728
{
 
729
    create_iopin_map();
 
730
 
 
731
    _12bit_processor::create();
 
732
 
 
733
    add_file_registers(0x08, 0x1f, 0);    // 10F202 has 24 bytes RAM
 
734
    P12bitBase::create_sfr_map();
 
735
    create_invalid_registers( );
 
736
 
 
737
    tmr0.set_cpu(this,m_gpio,2,option_reg);
 
738
    tmr0.start(0);
 
739
 
 
740
    pc->reset();
 
741
}
 
742
 
 
743
Processor * P10F202::construct(const char *name)
 
744
{
 
745
    P10F202 *p = new P10F202(name);
 
746
 
 
747
    p->pc->set_reset_address(0x1ff);
 
748
    p->create();
 
749
 
 
750
    return p;
 
751
}
 
752
 
 
753
P10F202::P10F202(const char *_name  )
 
754
    : P10F200(_name  )
 
755
{
 
756
}
 
757
 
 
758
P10F202::~P10F202()
 
759
{
 
760
    delete_file_registers(0x08, 0x0f); // Rest is deleted by P10F200
 
761
}
 
762
 
 
763
//========================================================================
 
764
// Comparator module for the 10c204 and 10c206
 
765
//
 
766
class Comparator10C20x
 
767
{
 
768
public:
 
769
    Comparator10C20x();
 
770
    ~Comparator10C20x();
 
771
};
 
772
 
 
773
class COUT_SignalSource;
 
774
 
 
775
//========================================================================
 
776
// COUT_SignalControl -- controls GPIO2's direction when the comparator is
 
777
// enabled. When the comparator is enabled, GPIO2 is an output.
 
778
 
 
779
class COUT_SignalControl : public SignalControl
 
780
{
 
781
public:
 
782
    COUT_SignalControl(){}
 
783
    ~COUT_SignalControl(){ }
 
784
    virtual char getState() { return '0'; }
 
785
    virtual void release() { delete this; }
 
786
};
 
787
 
 
788
class CIN_SignalSink;
 
789
class CMCON0 : public SfrReg
 
790
{
 
791
public:
 
792
    enum {
 
793
        CWU    = 1<<0,
 
794
        CPREF  = 1<<1,
 
795
        CNREF  = 1<<2,
 
796
        CMPON  = 1<<3,
 
797
        CMPTOCS = 1<<4,
 
798
        POL    = 1<<5,
 
799
        COUTEN = 1<<6,
 
800
        CMPOUT = 1<<7
 
801
    };
 
802
 
 
803
    CMCON0(P10F204 *pCpu, const char *pName, PinModule *CInP, PinModule *CInM, PinModule *COut);
 
804
 
 
805
    ~CMCON0();
 
806
 
 
807
    virtual void put(uint new_value);
 
808
    virtual void put_value(uint new_value);
 
809
    bool isEnabled() { return( (value.get() & COUTEN) == 0); }
 
810
 
 
811
    char getState()
 
812
    {
 
813
        char ret='Z';
 
814
        if( ( value.get() &( COUTEN | CMPON)) == CMPON)
 
815
            ret =( ((value.get() & CMPOUT)==CMPOUT) ^( (value.get() & POL)==POL)) ? '0' : '1';
 
816
 
 
817
        return ret;
 
818
    }
 
819
 
 
820
    void refresh();
 
821
 
 
822
    SignalControl *getSource() { return( SignalControl *)m_source; }
 
823
    SignalControl *getGPDirectionControl() { return m_control; }
 
824
 
 
825
    void setInputState(char newState, bool bInput);
 
826
 
 
827
private:
 
828
    P10F204 *p_F204;
 
829
    COUT_SignalControl *m_control;
 
830
    COUT_SignalSource *m_source;
 
831
    bool                        active_control;
 
832
    bool                        active_source;
 
833
    CIN_SignalSink    *m_PosInput;
 
834
    CIN_SignalSink    *m_NegInput;
 
835
 
 
836
    PinModule *m_CInP;
 
837
    PinModule *m_CInM;
 
838
    PinModule *m_COut;
 
839
 
 
840
    double m_pV, m_nV;
 
841
};
 
842
 
 
843
 
 
844
//========================================================================
 
845
// COUT_SignalSource
 
846
//
 
847
// The comparator output is driven on to the GPIO pin if the COUTEN bit in
 
848
// CMCON0 is cleared(  and if the FOSC/4 logic is not driving).
 
849
// This is implemented via COUT_SignalSource. When COUTEN bit is asserted,
 
850
// then COUT_SignalSource overides the default output driver control for
 
851
// the GPIO pin.
 
852
 
 
853
class COUT_SignalSource : public SignalControl
 
854
{
 
855
public:
 
856
    COUT_SignalSource(CMCON0 *pcmcon0)
 
857
        : m_cmcon0(pcmcon0)
 
858
    { }
 
859
    ~COUT_SignalSource() { }
 
860
 
 
861
    virtual char getState() { return m_cmcon0->getState(); }
 
862
    virtual void release() { }
 
863
 
 
864
private:
 
865
    CMCON0 *m_cmcon0;
 
866
};
 
867
 
 
868
class CIN_SignalSink : public SignalSink
 
869
{
 
870
public:
 
871
    CIN_SignalSink(CMCON0 *pcmcon0, bool binput)
 
872
        : m_cmcon0(pcmcon0),
 
873
          m_binput(binput)  // true==+input
 
874
    {}
 
875
    virtual void setSinkState(char new3State)
 
876
    {
 
877
        m_cmcon0->setInputState(new3State, m_binput);
 
878
    }
 
879
    virtual void release() {delete this; }
 
880
 
 
881
private:
 
882
    CMCON0 *m_cmcon0;
 
883
    bool m_binput;
 
884
};
 
885
 
 
886
//-----------------------------------------------------------
 
887
CMCON0::CMCON0(P10F204 *pCpu, const char *pName, PinModule *CInP, PinModule *CInM, PinModule *COut)
 
888
    : SfrReg(pCpu, pName ),
 
889
      p_F204(pCpu),
 
890
      m_CInP(CInP),
 
891
      m_CInM(CInM),
 
892
      m_COut(COut)
 
893
{
 
894
    // assign the I/O pin associated with the comparator output.
 
895
 
 
896
    m_source = new COUT_SignalSource(this);
 
897
    m_control = new COUT_SignalControl();
 
898
    m_PosInput = new CIN_SignalSink(this,true);
 
899
    m_NegInput = new CIN_SignalSink(this,false);
 
900
 
 
901
    active_source = false;
 
902
    active_control = false;
 
903
 
 
904
    CInP->addSink(m_PosInput);
 
905
    CInM->addSink(m_NegInput);
 
906
    //COut->setSource(m_source);
 
907
 
 
908
    m_pV = m_nV = 0.0;
 
909
}
 
910
 
 
911
CMCON0::~CMCON0()
 
912
{
 
913
    if( !isEnabled())
 
914
    {
 
915
        delete m_source;
 
916
        delete m_control;
 
917
    }
 
918
}
 
919
void CMCON0::put( uint new_value )
 
920
{
 
921
    uint old_value = value.get();
 
922
 
 
923
    value.put( (new_value & 0x7f )|( old_value & CMPOUT) );
 
924
 
 
925
    // If any of the control bits that afffect CMPOUT have changed, then refresh CMPOUT
 
926
    if(( old_value ^ new_value) &( CPREF | CNREF | CMPON | CMPTOCS | POL) )
 
927
        refresh();
 
928
 
 
929
    // If the output enable changed states.
 
930
    if(( old_value ^ new_value) & COUTEN ) p_F204->updateGP2Source();
 
931
 
 
932
    // If the comparator output state has changed or the polarity changed:
 
933
    if(( old_value ^ value.get()) &( CMPOUT | POL) ) m_COut->updatePinModule();
 
934
}
 
935
 
 
936
void CMCON0::refresh()
 
937
{
 
938
    if( value.get() & CMPON )
 
939
    {
 
940
        if( value.get() & CPREF ) m_pV = m_CInP->getPin().get_nodeVoltage();
 
941
        else                      m_pV = m_CInM->getPin().get_nodeVoltage();
 
942
 
 
943
        if( value.get() & CNREF ) m_nV = m_CInM->getPin().get_nodeVoltage();
 
944
        else                      m_nV = 0.6;
 
945
 
 
946
        value.put(( value.get() & 0x7f )|( (m_pV>m_nV)? CMPOUT : 0) );
 
947
    }
 
948
}
 
949
 
 
950
void CMCON0::put_value(uint new_value)
 
951
{
 
952
}
 
953
 
 
954
void CMCON0::setInputState( char newState, bool bInput )
 
955
{
 
956
    if( bInput )
 
957
    {
 
958
        if( value.get() & CPREF) m_pV = m_CInP->getPin().get_nodeVoltage();
 
959
    }
 
960
    else
 
961
    {
 
962
        if((value.get() & CPREF) == 0) m_pV = m_CInM->getPin().get_nodeVoltage();
 
963
        if( value.get() & CNREF)       m_nV = m_CInM->getPin().get_nodeVoltage();
 
964
        else                           m_nV = 0.6;
 
965
    }
 
966
    uint old_value = value.get();
 
967
 
 
968
    value.put(( old_value&0x7f) |( (m_pV>m_nV) ? CMPOUT : 0));
 
969
 
 
970
    m_COut->updatePinModule();
 
971
}
 
972
 
 
973
//========================================================================
 
974
P10F204::P10F204(const char *_name  )
 
975
    : P10F200(_name  )
 
976
{
 
977
}
 
978
 
 
979
P10F204::~P10F204()
 
980
{
 
981
    delete_SfrReg(m_cmcon0);
 
982
}
 
983
 
 
984
void P10F204::create()
 
985
{
 
986
    P10F200::create();
 
987
 
 
988
    m_cmcon0 = new CMCON0(this, "cmcon0", &(*m_gpio)[0], &(*m_gpio)[1], &(*m_gpio)[2]);
 
989
 
 
990
    RegisterValue porVal = RegisterValue(0xff,0);
 
991
    add_SfrReg(m_cmcon0, 7, porVal);
 
992
}
 
993
 
 
994
void P10F204::updateGP2Source()
 
995
{
 
996
    //    m_gpio->getIOpins(2)->setSource(m_cmcon0->getSource());
 
997
    PinModule *pmGP2 = &(*m_gpio)[2];
 
998
 
 
999
    if( osccal.get() & P12_OSCCON::FOSC4 )
 
1000
    {
 
1001
        pmGP2->setSource(m_OUT_DriveControl);
 
1002
        printf("OSCCON::FOSC4 forcing GPIO2 high on output, TODO FOSC4 toggle output\n");
 
1003
    }
 
1004
    else if( m_cmcon0->isEnabled())
 
1005
    {
 
1006
        pmGP2->setControl(m_cmcon0->getGPDirectionControl());
 
1007
        pmGP2->setSource(m_cmcon0->getSource());
 
1008
        cout << "comparator is controlling the output of GPIO2\n";
 
1009
    }
 
1010
    else if(option_reg->get() & OPTION_REG::T0CS)
 
1011
    {
 
1012
        printf("OPTION_REG::T0CS forcing GPIO2 as input, TRIS disabled\n");
 
1013
        pmGP2->setControl(m_IN_SignalControl);
 
1014
        pmGP2->setSource(0);
 
1015
    }
 
1016
    else
 
1017
    {
 
1018
        pmGP2->setControl(0);
 
1019
        pmGP2->setSource(0);
 
1020
    }
 
1021
    pmGP2->updatePinModule();
 
1022
}
 
1023
 
 
1024
//========================================================================
 
1025
Processor * P10F204::construct(const char *name)
 
1026
{
 
1027
    P10F204 *p = new P10F204(name);
 
1028
 
 
1029
    p->pc->set_reset_address(0x1ff);
 
1030
    p->create();
 
1031
 
 
1032
    return p;
 
1033
}
 
1034
//========================================================================
 
1035
P10F220::P10F220(const char *_name )
 
1036
    : P10F200(_name ),
 
1037
      adcon0(this,"adcon0" ),
 
1038
      adcon1(this,"adcon1" ),
 
1039
      adres(this,"adres" )
 
1040
{
 
1041
}
 
1042
 
 
1043
P10F220::~P10F220()
 
1044
{
 
1045
    remove_SfrReg(&adcon0);
 
1046
    remove_SfrReg(&adcon1);
 
1047
    remove_SfrReg(&adres);
 
1048
}
 
1049
 
 
1050
void P10F220::create()
 
1051
{
 
1052
    P10F200::create();
 
1053
    add_SfrReg(&adcon0,  0x07, RegisterValue(0xcc,0));
 
1054
    add_SfrReg(&adres,  0x08, RegisterValue(0,0));
 
1055
 
 
1056
    adcon1.setValidCfgBits(ADCON1::PCFG0 | ADCON1::PCFG1,0);
 
1057
    adcon1.setNumberOfChannels(4);
 
1058
    adcon1.setIOPin(0, &(*m_gpio)[0]);
 
1059
    adcon1.setIOPin(1, &(*m_gpio)[1]);
 
1060
    adcon1.setVoltRef(2, 0.6);
 
1061
    adcon1.setVoltRef(3, 0.6);
 
1062
    adcon1.setChannelConfiguration(0, 0x03);
 
1063
    adcon1.setChannelConfiguration(1, 0x03);
 
1064
    adcon1.setChannelConfiguration(2, 0x00);
 
1065
    adcon1.setChannelConfiguration(3, 0x00);
 
1066
 
 
1067
    adcon0.setChannel_Mask(3);
 
1068
    adcon0.setChannel_shift(2);
 
1069
    adcon0.setAdres(&adres);
 
1070
    adcon0.setAdresLow(0);
 
1071
    adcon0.setAdcon1(&adcon1);
 
1072
    adcon0.setA2DBits(8);
 
1073
}
 
1074
 
 
1075
//========================================================================
 
1076
Processor * P10F220::construct(const char *name)
 
1077
{
 
1078
    P10F220 *p = new P10F220(name);
 
1079
 
 
1080
    p->pc->set_reset_address(0xff);
 
1081
    p->create();
 
1082
 
 
1083
    return p;
 
1084
}
 
1085
void P10F220::enter_sleep()
 
1086
{
 
1087
    uint val;
 
1088
 
 
1089
    _12bit_processor::enter_sleep();
 
1090
 
 
1091
    status->put( status->get() & ~STATUS_GPWUF);
 
1092
    val =( adcon0.get() & ~(ADCON0_10::ADON|ADCON0_10::GO))
 
1093
            | ADCON0_10::CHS1 | ADCON0_10::CHS0;
 
1094
    adcon0.put(val);
 
1095
}
 
1096
 
 
1097
void P10F220::exit_sleep()
 
1098
{
 
1099
    _12bit_processor::exit_sleep();
 
1100
 
 
1101
    adcon0.put(adcon0.get() | ADCON0_10::ANS1 | ADCON0_10::ANS0);
 
1102
}
 
1103
 
 
1104
void  P10F220::setConfigWord(uint val, uint diff)
 
1105
{
 
1106
    PinModule *pmGP3 = &(*m_gpio)[3];
 
1107
 
 
1108
    configWord = val;
 
1109
    if( diff & WDTEN) wdt.initialize((val & WDTEN) == WDTEN);
 
1110
 
 
1111
    if( (val & MCLRE))
 
1112
    {
 
1113
        if( !(val & NOT_MCPU)) pmGP3->getPin().update_pullup('1', true);
 
1114
    }
 
1115
    if( (val & IOSCFS)) set_frequency(8e6);
 
1116
}
 
1117
//========================================================================
 
1118
P10F222::P10F222(const char *_name  )
 
1119
    : P10F220(_name  )
 
1120
{
 
1121
}
 
1122
P10F222::~P10F222()
 
1123
{
 
1124
    delete_file_registers(0x09, 0x0f);
 
1125
}
 
1126
 
 
1127
void P10F222::create()
 
1128
{
 
1129
    P10F220::create();
 
1130
    add_file_registers(0x09, 0x0f, 0);    // 10F222 has 23 bytes RAM
 
1131
}
 
1132
 
 
1133
 
 
1134
//========================================================================
 
1135
Processor * P10F222::construct(const char *name)
 
1136
{
 
1137
    P10F222 *p = new P10F222(name);
 
1138
 
 
1139
    p->pc->set_reset_address(0x1ff);
 
1140
    p->create();
 
1141
 
 
1142
    return p;
 
1143
}
 
1144
 
 
1145
//========================================================================
 
1146
// P16F505 Config Word
 
1147
 
 
1148
class P16F505ConfigWord : public ConfigWord
 
1149
{
 
1150
public:
 
1151
    enum {
 
1152
        FOSC0  = 1<<0,
 
1153
        FOSC1  = 1<<1,
 
1154
        FOSC2  = 1<<2,
 
1155
        WDTEN  = 1<<3,
 
1156
        CP     = 1<<4,
 
1157
        MCLRE  = 1<<5
 
1158
    };
 
1159
 
 
1160
    P16F505ConfigWord(P12bitBase *pCpu)
 
1161
        : ConfigWord("CONFIG", 0xfff, pCpu, 0xfff),
 
1162
          m_pCpu(pCpu)
 
1163
    {
 
1164
        assert(pCpu);
 
1165
        pCpu->wdt.initialize(true);
 
1166
    }
 
1167
 
 
1168
    virtual void set(int64_t v)
 
1169
    {
 
1170
        int64_t oldV = getVal();
 
1171
 
 
1172
        Integer::set(v);
 
1173
        if( m_pCpu)
 
1174
        {
 
1175
            int64_t diff = oldV ^ v;
 
1176
            m_pCpu->setConfigWord(v & 0x3ff, diff & 0x3ff);
 
1177
        }
 
1178
    }
 
1179
 
 
1180
    virtual string toString()
 
1181
    {
 
1182
        int64_t i64;
 
1183
        get(i64);
 
1184
        int i = i64 &0xfff;
 
1185
 
 
1186
        char buff[256];
 
1187
        const char *src;
 
1188
 
 
1189
        switch(i&(FOSC0|FOSC1|FOSC2)) {
 
1190
        case 0:
 
1191
            src = "LP";
 
1192
            break;
 
1193
        case 1:
 
1194
            src = "XT";
 
1195
            break;
 
1196
        case 2:
 
1197
            src = "HS";
 
1198
            break;
 
1199
        case 3:
 
1200
            src = "EC";
 
1201
            break;
 
1202
        case 4:
 
1203
            src = "INTRCRB4";
 
1204
            break;
 
1205
        case 5:
 
1206
            src = "INTRCCLK";
 
1207
            break;
 
1208
        case 6:
 
1209
            src = "EXTRCRB4";
 
1210
            break;
 
1211
        case 7:
 
1212
            src = "EXTRCCLK";
 
1213
            break;
 
1214
        }
 
1215
 
 
1216
        snprintf(buff, sizeof(buff),
 
1217
                 "$%3x\n"
 
1218
                 " FOSC=%d - Clk source = %s\n"
 
1219
                 " WDTEN=%d - WDT is %s\n"
 
1220
                 " CP=%d - Code protect is %s\n"
 
1221
                 " MCLRE=%d - /MCLR is %s",
 
1222
                 i,
 
1223
                 i &( FOSC0 | FOSC1), src,
 
1224
                 ( (i & WDTEN) ? 1 : 0),( (i & WDTEN) ? "enabled" : "disabled"),
 
1225
                 ( (i & CP) ? 1 : 0),( (i & CP) ? "enabled" : "disabled"),
 
1226
                 ( (i & MCLRE) ? 1 : 0),( (i & MCLRE) ? "enabled" : "disabled"));
 
1227
        return string(buff);
 
1228
    }
 
1229
 
 
1230
private:
 
1231
    P12bitBase *m_pCpu;
 
1232
};
 
1233
 
 
1234
 
 
1235
//========================================================================
 
1236
// P16F505 Implementation
 
1237
P16F505::P16F505(const char *_name  )
 
1238
    : P12bitBase(_name  )
 
1239
{
 
1240
    m_portb = new GPIO(this, "portb", 8,0x3f, 1<<3, 0x1B, 1<<5);
 
1241
    m_portc = new GPIO(this, "portc",8,0x3f, 0, 0);
 
1242
    m_trisb = new PicTrisRegister(this,"trisb", m_portb, false);
 
1243
    m_trisc = new PicTrisRegister(this,"trisc", m_portc, false);
 
1244
    m_trisb->wdtr_value=RegisterValue(0x3f,0);
 
1245
    m_trisc->wdtr_value=RegisterValue(0x3f,0);
 
1246
}
 
1247
 
 
1248
P16F505::~P16F505()
 
1249
{
 
1250
    delete_SfrReg(m_portb);
 
1251
    delete_SfrReg(m_portc);
 
1252
    delete_SfrReg(m_trisb);
 
1253
    delete_SfrReg(m_trisc);
 
1254
    delete_file_registers(0x08, 0x1f);
 
1255
    delete_file_registers(0x30, 0x3f);
 
1256
    delete_file_registers(0x50, 0x5f);
 
1257
    delete_file_registers(0x70, 0x7f);
 
1258
}
 
1259
 
 
1260
Processor * P16F505::construct(const char *name)
 
1261
{
 
1262
    P16F505 *p = new P16F505(name);
 
1263
 
 
1264
    p->pc->set_reset_address(0x3ff);
 
1265
    p->create();
 
1266
 
 
1267
    return p;
 
1268
}
 
1269
 
 
1270
void P16F505::create()
 
1271
{
 
1272
    create_iopin_map();
 
1273
 
 
1274
    _12bit_processor::create();
 
1275
 
 
1276
    add_file_registers(0x08, 0x1f, 0);
 
1277
    create_sfr_map();
 
1278
    create_invalid_registers( );
 
1279
 
 
1280
    alias_file_registers(0x00,0x0f,0x20);
 
1281
    add_file_registers(0x30, 0x3f, 0);
 
1282
 
 
1283
    alias_file_registers(0x00,0x0f,0x40);
 
1284
    add_file_registers(0x50, 0x5f, 0);
 
1285
 
 
1286
    alias_file_registers(0x00,0x0f,0x60);
 
1287
    add_file_registers(0x70, 0x7f, 0);
 
1288
 
 
1289
    pa_bits = PA0;
 
1290
    indf->base_address_mask2 = 0x7F;
 
1291
 
 
1292
    tmr0.set_cpu(this,m_portc,5,option_reg); // T0CKI pin
 
1293
    tmr0.start(0);
 
1294
 
 
1295
    pc->reset();
 
1296
}
 
1297
 
 
1298
void P16F505::create_iopin_map()
 
1299
{
 
1300
    assign_pin(1, 0);
 
1301
    assign_pin(2,  m_portb->addPin(new IO_bi_directional("portb5"),5));
 
1302
    assign_pin(3,  m_portb->addPin(new IO_bi_directional_pu("portb4"),4));
 
1303
    assign_pin(4,  m_portb->addPin(new IO_bi_directional_pu("portb3"),3));
 
1304
    assign_pin(5,  m_portc->addPin(new IO_bi_directional("portc5"),5));
 
1305
    assign_pin(6,  m_portc->addPin(new IO_bi_directional("portc4"),4));
 
1306
    assign_pin(7,  m_portc->addPin(new IO_bi_directional("portc3"),3));
 
1307
    assign_pin(8,  m_portc->addPin(new IO_bi_directional("portc2"),2));
 
1308
    assign_pin(9,  m_portc->addPin(new IO_bi_directional("portc1"),1));
 
1309
    assign_pin(10, m_portc->addPin(new IO_bi_directional("portc0"),0));
 
1310
    assign_pin(11, m_portb->addPin(new IO_bi_directional("portb2"),2));
 
1311
    assign_pin(12, m_portb->addPin(new IO_bi_directional_pu("portb1"),1));
 
1312
    assign_pin(13, m_portb->addPin(new IO_bi_directional_pu("portb0"),0));
 
1313
    assign_pin(14, 0);
 
1314
 
 
1315
    // portb3 is input only, but we want pullup, so use IO_bi_directional_pu
 
1316
    // but force as input pin disableing TRIS control
 
1317
    m_IN_SignalControl = new IN_SignalControl;
 
1318
    ( &(*m_portb)[3])->setControl(m_IN_SignalControl);
 
1319
}
 
1320
 
 
1321
void P16F505::create_sfr_map()
 
1322
{
 
1323
    RegisterValue porVal(0,0);
 
1324
 
 
1325
    add_SfrReg(indf,   0, porVal);
 
1326
    add_SfrReg(&tmr0,  1, porVal);
 
1327
    add_SfrReg(pcl,    2, RegisterValue(0xff,0));
 
1328
    add_SfrReg(status, 3, porVal);
 
1329
    add_SfrReg(fsr,    4, porVal);
 
1330
    add_SfrReg(&osccal,5, RegisterValue(0x70,0));
 
1331
    add_SfrReg(m_portb,6, porVal);
 
1332
    add_SfrReg(m_portc,7, porVal);
 
1333
    add_SfrReg(m_trisb, 0xffffffff, RegisterValue(0x3f,0));
 
1334
    add_SfrReg(m_trisc, 0xffffffff, RegisterValue(0x3f,0));
 
1335
    add_SfrReg(Wreg, 0xffffffff, porVal);
 
1336
    option_reg->set_cpu(this);
 
1337
 
 
1338
    osccal.set_cpu(this);
 
1339
}
 
1340
 
 
1341
void P16F505::create_config_memory()
 
1342
{
 
1343
    m_configMemory = new ConfigMemory(this,1);
 
1344
    m_configMemory->addConfigWord(0,new P16F505ConfigWord(this));
 
1345
}
 
1346
 
 
1347
void P16F505::tris_instruction(uint tris_register)
 
1348
{
 
1349
    if     (  tris_register == 6 ) m_trisb->put(Wget());
 
1350
    else if(  tris_register == 7 ) m_trisc->put(Wget());
 
1351
}
 
1352
 
 
1353
void  P16F505::setConfigWord(uint val, uint diff)
 
1354
{
 
1355
    PinModule *pmRB3 = &(*m_portb)[3];
 
1356
 
 
1357
    configWord = val;
 
1358
 
 
1359
    if( diff & WDTEN ) wdt.initialize((val & WDTEN) == WDTEN);
 
1360
 
 
1361
    if(( val & MCLRE) == MCLRE ) pmRB3->getPin().update_pullup('1', true);
 
1362
}
 
1363
 
 
1364
void  P16F505::updateGP2Source()
 
1365
{
 
1366
    PinModule *pmPC5 = &(*m_portc)[5];
 
1367
 
 
1368
    if(option_reg->value.get() & OPTION_REG::T0CS)
 
1369
    {
 
1370
        printf("OPTION_REG::T0CS forcing PORTC5 as input, TRIS disabled\n");
 
1371
        pmPC5->setControl(m_IN_SignalControl);
 
1372
    }
 
1373
    else
 
1374
    {
 
1375
        cout << "TRIS now controlling PORTC5\n";
 
1376
        pmPC5->setControl(0);
 
1377
    }
 
1378
}
 
1379
 
 
1380
// option_new_bits_6_7 is called from class OPTION_REG when
 
1381
// bits 5, 6, or 7 of  OPTION_REG change state
 
1382
//
 
1383
void  P16F505::option_new_bits_6_7(uint bits)
 
1384
{
 
1385
    bool bit6 =( bits & OPTION_REG::BIT6) != OPTION_REG::BIT6;
 
1386
 
 
1387
    // Weak pullup if NOT_GPPU == 0
 
1388
    m_portb->setPullUp( bit6 ,( configWord & MCLRE));
 
1389
    updateGP2Source();
 
1390
}
 
1391
 
 
1392
void P16F505::reset(RESET_TYPE r)
 
1393
{
 
1394
    m_trisb->reset(r);
 
1395
    m_trisc->reset(r);
 
1396
 
 
1397
    switch( r)
 
1398
    {
 
1399
    case IO_RESET:
 
1400
        status->put(status->value.get() | 0x80);// Set GPWUF/RBWUF flag
 
1401
 
 
1402
    default:
 
1403
        _12bit_processor::reset(r);
 
1404
    }
 
1405
}