2
Copyright( C) 1998 T. Scott Dattalo
4
This file is part of the libgpsim library of gpsim
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.
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.
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>.
25
// This file supports:
26
// PIC12C508 PIC12C509
27
// PIC12CE518 PIC12CE519
28
// PIC10F200 PIC10F202 PIC10F204
29
// PIC10F220 PIC10F222
39
//========================================================================
40
// Generic Configuration word for the midrange family.
42
class Generic12bitConfigWord : public ConfigWord
45
Generic12bitConfigWord(P12bitBase *pCpu)
46
: ConfigWord("CONFIG", 0xfff, pCpu, 0xfff), m_pCpu(pCpu)
49
pCpu->wdt.initialize(true);
60
virtual void set(int64_t v)
62
int64_t oldV = getVal();
67
int64_t diff = oldV ^ v;
68
m_pCpu->setConfigWord(v & 0x3ff, diff & 0x3ff);
71
virtual string toString()
79
snprintf(buff,sizeof(buff),
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",
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"));
98
void P12_OSCCON::put(uint new_value)
100
uint old = value.get();
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();
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
115
P12_I2C_EE(pic_processor *, uint _rom_size);
119
P12_I2C_EE::P12_I2C_EE(pic_processor* pcpu, uint _rom_size)
120
: I2C_EE(pcpu,_rom_size)
122
if(pcpu) pcpu->ema.set_Registers(rom, rom_size);
125
P12_I2C_EE::~P12_I2C_EE()
129
//-------------------------------------------------------------------
131
P12bitBase::P12bitBase(const char *_name)
132
: _12bit_processor(_name ),
135
osccal (this, "osccal" )
142
P12bitBase::~P12bitBase()
146
( &(*m_gpio)[3])->setControl(0);
147
( &(*m_gpio)[2])->setControl(0);
149
delete m_IN_SignalControl;
150
delete_SfrReg(m_gpio);
151
delete_SfrReg(m_tris);
152
remove_SfrReg(&tmr0);
153
remove_SfrReg(&osccal);
156
void P12bitBase::create_config_memory()
158
m_configMemory = new ConfigMemory(this,1);
159
m_configMemory->addConfigWord( 0, new Generic12bitConfigWord(this) );
162
//========================================================================
163
void P12bitBase::create_iopin_map()
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));
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);
180
//--------------------------------------------------------
181
void P12bitBase::reset( RESET_TYPE r )
185
if( r == IO_RESET) status->put(status->value.get() | 0x80); // Set GPWUF flag
187
_12bit_processor::reset(r);
190
//------------------------------------------------------------------------
191
#define STATUS_GPWUF 0x80
193
void P12bitBase::enter_sleep()
195
pic_processor::enter_sleep();
197
status->put( status->value.get() & ~STATUS_GPWUF);
198
cout << "enter sleep status="<<hex <<status->get()<<endl;
201
void P12bitBase::updateGP2Source()
203
PinModule *pmGP2 = &(*m_gpio)[2];
205
if(option_reg->value.get() & OPTION_REG::T0CS)
207
printf("OPTION_REG::T0CS forcing GPIO2 as input, TRIS disabled\n");
208
pmGP2->setControl( m_IN_SignalControl );
212
cout << "TRIS now controlling gpio2\n";
213
pmGP2->setControl(0);
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()
222
// If internal RC oscilator
223
if((configWord &( FOSC0 | FOSC1)) == FOSC1)
225
int osccal_val =( osccal.get() >> 4) - 0x07;
226
double freq = get_frequency();
227
freq *= 1. + 0.125 * osccal_val / 0x08;
231
// option_new_bits_6_7 is called from class OPTION_REG when
232
// bits 5, 6, or 7 of OPTION_REG change state
234
void P12bitBase::option_new_bits_6_7(uint bits)
236
// Weak pullup if NOT_GPPU == 0
237
m_gpio->setPullUp( ( bits & OPTION_REG::BIT6) != OPTION_REG::BIT6 ,( configWord & MCLRE));
241
void P12bitBase::create_sfr_map()
243
RegisterValue porVal(0,0);
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);
256
osccal.set_cpu(this);
259
void P12bitBase::setConfigWord(uint val, uint diff)
261
PinModule *pmGP3 = &(*m_gpio)[3];
264
if( diff & WDTEN) wdt.initialize((val & WDTEN) == WDTEN);
266
if( (val & MCLRE) == MCLRE) pmGP3->getPin().update_pullup('1', true);
269
void P12bitBase::tris_instruction(uint tris_register)
274
void P12C508::create()
278
_12bit_processor::create();
280
add_file_registers(0x07, 0x1f, 0);
281
P12bitBase::create_sfr_map();
282
create_invalid_registers( );
284
tmr0.set_cpu(this,m_gpio,2,option_reg);
291
Processor * P12C508::construct(const char *name)
293
P12C508 *p = new P12C508(name);
295
p->pc->set_reset_address(0x1ff);
301
P12C508::P12C508( const char *_name )
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);
311
delete_file_registers(0x07, 0x1f);
314
P12F508::P12F508(const char *_name )
322
Processor * P12F508::construct(const char *name)
324
P12F508 *p = new P12F508(name);
325
p->pc->set_reset_address(0x1ff);
330
//--------------------------------------------------------
332
void P12C509::create_sfr_map()
336
Processor * P12C509::construct(const char *name)
338
P12C509 *p = new P12C509(name);
340
p->pc->set_reset_address(0x3ff);
346
void P12C509::create()
350
alias_file_registers(0x00,0x0f,0x20);
351
add_file_registers(0x30, 0x3f, 0);
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
357
P12C509::P12C509(const char *_name )
364
delete_file_registers(0x30, 0x3f);
368
P12F509::P12F509(const char *_name )
375
Processor * P12F509::construct(const char *name)
377
P12F509 *p = new P12F509(name);
378
p->pc->set_reset_address(0x3ff);
385
P12F510::P12F510(const char *_name )
393
Processor * P12F510::construct(const char *name)
395
P12F510 *p = new P12F510(name);
396
p->pc->set_reset_address(0x3ff);
402
//--------------------------------------------------------
404
// construct function is identical to 12C508 version ??
405
Processor * P12CE518::construct(const char *name)
407
P12CE518 *p = new P12CE518(name);
409
p->pc->set_reset_address(0x1ff);
416
void P12CE518::create_iopin_map()
418
P12C508::create_iopin_map();
420
// Define the valid I/O pins.
421
//gpio.valid_iopins = 0xff;
424
void P12CE518::create()
428
///m_eeprom = new P12_I2C_EE( this, 0x10 );
429
///m_eeprom->debug();
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());
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;
441
osccal.por_value = RegisterValue(0x80,0);
443
// Kludge to force top two bits to be outputs
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));
457
sda = new Stimulus_Node( "EE_SDA" );
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);
469
//m_eeprom->attach( scl, sda );
472
P12CE518::P12CE518(const char *_name )
477
P12CE518::~P12CE518()
486
void P12CE518::tris_instruction(uint tris_register)
489
m_tris->put( w_val & 0x3F ); // top two bits always output
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()
500
// If internal RC oscilator
501
if((configWord &( FOSC0 | FOSC1)) == FOSC1)
503
int osccal_val =( osccal.get() >> 2) - 0x20;
505
freq *= 1. + 0.125 * osccal_val / 0x20;
509
//--------------------------------------------------------
511
void P12CE519::create_sfr_map()
515
Processor * P12CE519::construct(const char *name)
517
P12CE519 *p = new P12CE519(name);
519
cout << " 12ce519 construct\n";
521
p->pc->set_reset_address(0x3ff);
528
void P12CE519::create()
532
alias_file_registers(0x00,0x0f,0x20);
533
add_file_registers(0x30, 0x3f, 0);
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
540
P12CE519::P12CE519(const char *_name )
545
P12CE519::~P12CE519()
547
delete_file_registers(0x30, 0x3f);
551
//--------------------------------------------------------
555
GPIO::GPIO(P12bitBase *pCpu, const char *pName,
560
uint configMaskMCLRE)
561
: PicPortRegister( pCpu,pName, numIopins, enableMask), m_CPU(pCpu)
562
, m_resetMask(resetMask)
563
, m_wakeupMask(wakeupMask)
564
, m_configMaskMCLRE(configMaskMCLRE)
568
void GPIO::setbit(uint bit_number, char new_value)
570
uint lastDrivenValue = rvDrivenValue.data;
572
PortRegister::setbit(bit_number, new_value);
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.
579
uint diff = lastDrivenValue ^ rvDrivenValue.data;
581
if( (diff & m_resetMask) &&( m_CPU->configWord & m_configMaskMCLRE))
583
cpu->reset(( rvDrivenValue.data & m_resetMask) ? EXIT_RESET : MCLR_RESET);
587
if( diff & m_wakeupMask)
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)
594
cpu->reset(IO_RESET);
599
// if bNewPU == true set weak pullups otherwise clear weak pullups
600
void GPIO::setPullUp( bool bNewPU , bool mclr)
604
// In the following do not change pullup state of internal pins
605
uint mask = getEnableMask() & 0x3f;
607
// If mclr active do not change pullup on gpio3
608
if( mclr) mask &= 0x37;
610
for( uint i=0, m = 1; mask; i++, m <<= 1)
615
getPin(i)->update_pullup( m_bPU ? '1' : '0', true );
621
//------------------------------------------------------------------------
622
void P10F200::create_iopin_map()
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));
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);
639
void P10F200::create()
643
_12bit_processor::create();
645
add_file_registers(0x10, 0x1f, 0); // 10F200 only has 16 bytes RAM
646
P12bitBase::create_sfr_map();
647
create_invalid_registers( );
649
tmr0.set_cpu(this,m_gpio,2,option_reg);
651
osccal.set_cpu(this);
652
osccal.por_value = RegisterValue(0xfe,0);
657
Processor * P10F200::construct(const char *name)
659
P10F200 *p = new P10F200(name);
661
p->pc->set_reset_address(0x0ff);
667
P10F200::P10F200(const char *_name )
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);
678
( &(*m_gpio)[3])->setControl(0);
679
( &(*m_gpio)[2])->setControl(0);
681
delete m_OUT_SignalControl;
682
delete m_OUT_DriveControl;
683
delete_file_registers(0x10, 0x1f);
686
void P10F200::updateGP2Source()
688
PinModule *pmGP2 = &(*m_gpio)[2];
690
if( osccal.value.get() & P12_OSCCON::FOSC4 )
692
pmGP2->setSource(m_OUT_DriveControl);
693
printf("OSCCON::FOSC4 forcing GPIO2 high on output, TODO FOSC4 toggle output\n");
695
else if(option_reg->value.get() & OPTION_REG::T0CS)
697
printf("OPTION_REG::T0CS forcing GPIO2 as input, TRIS disabled\n");
698
pmGP2->setControl(m_IN_SignalControl);
703
// revert to default control, i.e. let TRIS control the output
704
pmGP2->setControl(0);
706
cout << "TRIS now controlling gpio2\n";
708
pmGP2->updatePinModule();
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()
717
// If internal RC oscilator
718
char osccal_val =( osccal.value.get() & 0xfe);
719
double freq =( configWord & 1)? 8e6 : 4e6;
721
freq *= 1. +( 0.125 * osccal_val) / 0x80;
725
//------------------------------------------------------------------------
727
void P10F202::create()
731
_12bit_processor::create();
733
add_file_registers(0x08, 0x1f, 0); // 10F202 has 24 bytes RAM
734
P12bitBase::create_sfr_map();
735
create_invalid_registers( );
737
tmr0.set_cpu(this,m_gpio,2,option_reg);
743
Processor * P10F202::construct(const char *name)
745
P10F202 *p = new P10F202(name);
747
p->pc->set_reset_address(0x1ff);
753
P10F202::P10F202(const char *_name )
760
delete_file_registers(0x08, 0x0f); // Rest is deleted by P10F200
763
//========================================================================
764
// Comparator module for the 10c204 and 10c206
766
class Comparator10C20x
773
class COUT_SignalSource;
775
//========================================================================
776
// COUT_SignalControl -- controls GPIO2's direction when the comparator is
777
// enabled. When the comparator is enabled, GPIO2 is an output.
779
class COUT_SignalControl : public SignalControl
782
COUT_SignalControl(){}
783
~COUT_SignalControl(){ }
784
virtual char getState() { return '0'; }
785
virtual void release() { delete this; }
788
class CIN_SignalSink;
789
class CMCON0 : public SfrReg
803
CMCON0(P10F204 *pCpu, const char *pName, PinModule *CInP, PinModule *CInM, PinModule *COut);
807
virtual void put(uint new_value);
808
virtual void put_value(uint new_value);
809
bool isEnabled() { return( (value.get() & COUTEN) == 0); }
814
if( ( value.get() &( COUTEN | CMPON)) == CMPON)
815
ret =( ((value.get() & CMPOUT)==CMPOUT) ^( (value.get() & POL)==POL)) ? '0' : '1';
822
SignalControl *getSource() { return( SignalControl *)m_source; }
823
SignalControl *getGPDirectionControl() { return m_control; }
825
void setInputState(char newState, bool bInput);
829
COUT_SignalControl *m_control;
830
COUT_SignalSource *m_source;
833
CIN_SignalSink *m_PosInput;
834
CIN_SignalSink *m_NegInput;
844
//========================================================================
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
853
class COUT_SignalSource : public SignalControl
856
COUT_SignalSource(CMCON0 *pcmcon0)
859
~COUT_SignalSource() { }
861
virtual char getState() { return m_cmcon0->getState(); }
862
virtual void release() { }
868
class CIN_SignalSink : public SignalSink
871
CIN_SignalSink(CMCON0 *pcmcon0, bool binput)
873
m_binput(binput) // true==+input
875
virtual void setSinkState(char new3State)
877
m_cmcon0->setInputState(new3State, m_binput);
879
virtual void release() {delete this; }
886
//-----------------------------------------------------------
887
CMCON0::CMCON0(P10F204 *pCpu, const char *pName, PinModule *CInP, PinModule *CInM, PinModule *COut)
888
: SfrReg(pCpu, pName ),
894
// assign the I/O pin associated with the comparator output.
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);
901
active_source = false;
902
active_control = false;
904
CInP->addSink(m_PosInput);
905
CInM->addSink(m_NegInput);
906
//COut->setSource(m_source);
919
void CMCON0::put( uint new_value )
921
uint old_value = value.get();
923
value.put( (new_value & 0x7f )|( old_value & CMPOUT) );
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) )
929
// If the output enable changed states.
930
if(( old_value ^ new_value) & COUTEN ) p_F204->updateGP2Source();
932
// If the comparator output state has changed or the polarity changed:
933
if(( old_value ^ value.get()) &( CMPOUT | POL) ) m_COut->updatePinModule();
936
void CMCON0::refresh()
938
if( value.get() & CMPON )
940
if( value.get() & CPREF ) m_pV = m_CInP->getPin().get_nodeVoltage();
941
else m_pV = m_CInM->getPin().get_nodeVoltage();
943
if( value.get() & CNREF ) m_nV = m_CInM->getPin().get_nodeVoltage();
946
value.put(( value.get() & 0x7f )|( (m_pV>m_nV)? CMPOUT : 0) );
950
void CMCON0::put_value(uint new_value)
954
void CMCON0::setInputState( char newState, bool bInput )
958
if( value.get() & CPREF) m_pV = m_CInP->getPin().get_nodeVoltage();
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();
966
uint old_value = value.get();
968
value.put(( old_value&0x7f) |( (m_pV>m_nV) ? CMPOUT : 0));
970
m_COut->updatePinModule();
973
//========================================================================
974
P10F204::P10F204(const char *_name )
981
delete_SfrReg(m_cmcon0);
984
void P10F204::create()
988
m_cmcon0 = new CMCON0(this, "cmcon0", &(*m_gpio)[0], &(*m_gpio)[1], &(*m_gpio)[2]);
990
RegisterValue porVal = RegisterValue(0xff,0);
991
add_SfrReg(m_cmcon0, 7, porVal);
994
void P10F204::updateGP2Source()
996
// m_gpio->getIOpins(2)->setSource(m_cmcon0->getSource());
997
PinModule *pmGP2 = &(*m_gpio)[2];
999
if( osccal.get() & P12_OSCCON::FOSC4 )
1001
pmGP2->setSource(m_OUT_DriveControl);
1002
printf("OSCCON::FOSC4 forcing GPIO2 high on output, TODO FOSC4 toggle output\n");
1004
else if( m_cmcon0->isEnabled())
1006
pmGP2->setControl(m_cmcon0->getGPDirectionControl());
1007
pmGP2->setSource(m_cmcon0->getSource());
1008
cout << "comparator is controlling the output of GPIO2\n";
1010
else if(option_reg->get() & OPTION_REG::T0CS)
1012
printf("OPTION_REG::T0CS forcing GPIO2 as input, TRIS disabled\n");
1013
pmGP2->setControl(m_IN_SignalControl);
1014
pmGP2->setSource(0);
1018
pmGP2->setControl(0);
1019
pmGP2->setSource(0);
1021
pmGP2->updatePinModule();
1024
//========================================================================
1025
Processor * P10F204::construct(const char *name)
1027
P10F204 *p = new P10F204(name);
1029
p->pc->set_reset_address(0x1ff);
1034
//========================================================================
1035
P10F220::P10F220(const char *_name )
1037
adcon0(this,"adcon0" ),
1038
adcon1(this,"adcon1" ),
1039
adres(this,"adres" )
1045
remove_SfrReg(&adcon0);
1046
remove_SfrReg(&adcon1);
1047
remove_SfrReg(&adres);
1050
void P10F220::create()
1053
add_SfrReg(&adcon0, 0x07, RegisterValue(0xcc,0));
1054
add_SfrReg(&adres, 0x08, RegisterValue(0,0));
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);
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);
1075
//========================================================================
1076
Processor * P10F220::construct(const char *name)
1078
P10F220 *p = new P10F220(name);
1080
p->pc->set_reset_address(0xff);
1085
void P10F220::enter_sleep()
1089
_12bit_processor::enter_sleep();
1091
status->put( status->get() & ~STATUS_GPWUF);
1092
val =( adcon0.get() & ~(ADCON0_10::ADON|ADCON0_10::GO))
1093
| ADCON0_10::CHS1 | ADCON0_10::CHS0;
1097
void P10F220::exit_sleep()
1099
_12bit_processor::exit_sleep();
1101
adcon0.put(adcon0.get() | ADCON0_10::ANS1 | ADCON0_10::ANS0);
1104
void P10F220::setConfigWord(uint val, uint diff)
1106
PinModule *pmGP3 = &(*m_gpio)[3];
1109
if( diff & WDTEN) wdt.initialize((val & WDTEN) == WDTEN);
1113
if( !(val & NOT_MCPU)) pmGP3->getPin().update_pullup('1', true);
1115
if( (val & IOSCFS)) set_frequency(8e6);
1117
//========================================================================
1118
P10F222::P10F222(const char *_name )
1124
delete_file_registers(0x09, 0x0f);
1127
void P10F222::create()
1130
add_file_registers(0x09, 0x0f, 0); // 10F222 has 23 bytes RAM
1134
//========================================================================
1135
Processor * P10F222::construct(const char *name)
1137
P10F222 *p = new P10F222(name);
1139
p->pc->set_reset_address(0x1ff);
1145
//========================================================================
1146
// P16F505 Config Word
1148
class P16F505ConfigWord : public ConfigWord
1160
P16F505ConfigWord(P12bitBase *pCpu)
1161
: ConfigWord("CONFIG", 0xfff, pCpu, 0xfff),
1165
pCpu->wdt.initialize(true);
1168
virtual void set(int64_t v)
1170
int64_t oldV = getVal();
1175
int64_t diff = oldV ^ v;
1176
m_pCpu->setConfigWord(v & 0x3ff, diff & 0x3ff);
1180
virtual string toString()
1189
switch(i&(FOSC0|FOSC1|FOSC2)) {
1216
snprintf(buff, sizeof(buff),
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",
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);
1235
//========================================================================
1236
// P16F505 Implementation
1237
P16F505::P16F505(const char *_name )
1238
: P12bitBase(_name )
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);
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);
1260
Processor * P16F505::construct(const char *name)
1262
P16F505 *p = new P16F505(name);
1264
p->pc->set_reset_address(0x3ff);
1270
void P16F505::create()
1274
_12bit_processor::create();
1276
add_file_registers(0x08, 0x1f, 0);
1278
create_invalid_registers( );
1280
alias_file_registers(0x00,0x0f,0x20);
1281
add_file_registers(0x30, 0x3f, 0);
1283
alias_file_registers(0x00,0x0f,0x40);
1284
add_file_registers(0x50, 0x5f, 0);
1286
alias_file_registers(0x00,0x0f,0x60);
1287
add_file_registers(0x70, 0x7f, 0);
1290
indf->base_address_mask2 = 0x7F;
1292
tmr0.set_cpu(this,m_portc,5,option_reg); // T0CKI pin
1298
void P16F505::create_iopin_map()
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));
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);
1321
void P16F505::create_sfr_map()
1323
RegisterValue porVal(0,0);
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);
1338
osccal.set_cpu(this);
1341
void P16F505::create_config_memory()
1343
m_configMemory = new ConfigMemory(this,1);
1344
m_configMemory->addConfigWord(0,new P16F505ConfigWord(this));
1347
void P16F505::tris_instruction(uint tris_register)
1349
if ( tris_register == 6 ) m_trisb->put(Wget());
1350
else if( tris_register == 7 ) m_trisc->put(Wget());
1353
void P16F505::setConfigWord(uint val, uint diff)
1355
PinModule *pmRB3 = &(*m_portb)[3];
1359
if( diff & WDTEN ) wdt.initialize((val & WDTEN) == WDTEN);
1361
if(( val & MCLRE) == MCLRE ) pmRB3->getPin().update_pullup('1', true);
1364
void P16F505::updateGP2Source()
1366
PinModule *pmPC5 = &(*m_portc)[5];
1368
if(option_reg->value.get() & OPTION_REG::T0CS)
1370
printf("OPTION_REG::T0CS forcing PORTC5 as input, TRIS disabled\n");
1371
pmPC5->setControl(m_IN_SignalControl);
1375
cout << "TRIS now controlling PORTC5\n";
1376
pmPC5->setControl(0);
1380
// option_new_bits_6_7 is called from class OPTION_REG when
1381
// bits 5, 6, or 7 of OPTION_REG change state
1383
void P16F505::option_new_bits_6_7(uint bits)
1385
bool bit6 =( bits & OPTION_REG::BIT6) != OPTION_REG::BIT6;
1387
// Weak pullup if NOT_GPPU == 0
1388
m_portb->setPullUp( bit6 ,( configWord & MCLRE));
1392
void P16F505::reset(RESET_TYPE r)
1400
status->put(status->value.get() | 0x80);// Set GPWUF/RBWUF flag
1403
_12bit_processor::reset(r);