1 /*
2    Copyright (C) 2009 Roy R. Rankin
3 
4 This file is part of the libgpsim library of gpsim
5 
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10 
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 Lesser General Public License for more details.
15 
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, see
18 <http://www.gnu.org/licenses/lgpl-2.1.html>.
19 */
20 
21 
22 //
23 // p12f6xx
24 //
25 //  This file supports:
26 //    PIC12F629
27 //    PIC12F675
28 //    PIC12F683
29 //
30 //Note: unlike most other 12F processors these have 14bit instructions
31 
32 #include "../config.h"
33 #include "symbol.h"
34 
35 #include "stimuli.h"
36 #include "eeprom.h"
37 
38 #include "p12f6xx.h"
39 #include "pic-ioports.h"
40 
41 #include "packages.h"
42 #include "pic-registers.h"
43 #include "trace.h"
44 class Processor;
45 
46 
47 //#define DEBUG
48 #if defined(DEBUG)
49 #include "../config.h"
50 #define Dprintf(arg) {printf("%s:%d ",__FILE__,__LINE__); printf arg; }
51 #else
52 #define Dprintf(arg) {}
53 #endif
54 
55 //========================================================================
56 //
57 // Configuration Memory for the 12F6XX devices.
58 
59 class Config12F6 : public ConfigWord
60 {
61 public:
Config12F6(pic_processor * pCpu)62     explicit Config12F6(pic_processor  *pCpu)
63         : ConfigWord("CONFIG12F6", 0x3fff, "Configuration Word", pCpu, 0x2007)
64     {
65         Dprintf(("Config12F6::Config12F6 %p\n", m_pCpu));
66 
67         if (m_pCpu)
68         {
69             m_pCpu->set_config_word(0x2007, 0x3fff);
70         }
71     }
72 };
73 
74 
75 // Does not match any of 3 versions in pir.h, pir.cc
76 // If required by any other porcessors should be moved there
77 //
78 class PIR1v12f : public PIR
79 {
80 public:
PIR1v12f(Processor * pCpu,const char * pName,const char * pDesc,INTCON * _intcon,PIE * _pie)81     PIR1v12f(Processor *pCpu, const char *pName, const char *pDesc, INTCON *_intcon, PIE *_pie)
82         : PIR(pCpu, pName, pDesc, _intcon, _pie, 0)
83     {
84         valid_bits = TMR1IF | CMIF | ADIF | EEIF;
85         writable_bits = TMR1IF | CMIF | ADIF | EEIF;
86     }
87 
88     enum
89     {
90         TMR1IF 	= 1 << 0,
91         TMR2IF  = 1 << 1,	//For 12F683
92         CMIF	= 1 << 3,
93         CLC1IF  = 1 << 3,	// For 10F32x
94         NCO1IF  = 1 << 4,	// For 10F32x
95         ADIF	= 1 << 6,
96         EEIF	= 1 << 7
97     };
98 
99     //------------------------------------------------------------------------
100 
set_tmr1if()101     virtual void set_tmr1if()
102     {
103         put(get() | TMR1IF);
104     }
set_tmr2if()105     virtual void set_tmr2if()
106     {
107         put(get() | TMR2IF);
108     }
109 
set_cmif()110     virtual void set_cmif()
111     {
112         trace.raw(write_trace.get() | value.get());
113         value.put(value.get() | CMIF);
114 
115         if (value.get() & pie->value.get())
116         {
117             setPeripheralInterrupt();
118         }
119     }
120 
set_clc1if()121     virtual void set_clc1if()
122     {
123         trace.raw(write_trace.get() | value.get());
124         value.put(value.get() | CLC1IF);
125 
126         if (value.get() & pie->value.get())
127         {
128             setPeripheralInterrupt();
129         }
130     }
131 
set_nco1if()132     virtual void set_nco1if()
133     {
134         unsigned int pievalue = value.get();
135 
136         if (!(pievalue & NCO1IF))
137         {
138             trace.raw(write_trace.get() | pievalue);
139             value.put(pievalue | NCO1IF);
140         }
141 
142         if (value.get() & pie->value.get())
143         {
144             setPeripheralInterrupt();
145         }
146     }
147 
set_c1if()148     virtual void set_c1if()
149     {
150         set_cmif();
151     }
152 
set_eeif()153     virtual void set_eeif()
154     {
155         trace.raw(write_trace.get() | value.get());
156         value.put(value.get() | EEIF);
157 
158         if (value.get() & pie->value.get())
159         {
160             setPeripheralInterrupt();
161         }
162     }
163 
set_adif()164     virtual void set_adif()
165     {
166         trace.raw(write_trace.get() | value.get());
167         value.put(value.get() | ADIF);
168 
169         if (value.get() & pie->value.get())
170         {
171             setPeripheralInterrupt();
172         }
173     }
174 };
175 
176 
177 //========================================================================
178 
create_config_memory()179 void P12F629::create_config_memory()
180 {
181     m_configMemory = new ConfigMemory(this, 1);
182     m_configMemory->addConfigWord(0, new Config12F6(this));
183 }
184 
185 
set_config_word(unsigned int address,unsigned int cfg_word)186 bool P12F629::set_config_word(unsigned int address, unsigned int cfg_word)
187 {
188     enum
189     {
190         FOSC0  = 1 << 0,
191         FOSC1  = 1 << 1,
192         FOSC2  = 1 << 2,
193         WDTEN  = 1 << 3,
194         PWRTEN = 1 << 4,
195         MCLRE  = 1 << 5,
196         BOREN  = 1 << 6,
197         CP     = 1 << 7,
198         CPD    = 1 << 8,
199 
200         BG0    = 1 << 12,
201         BG1    = 1 << 13
202     };
203 
204     if (address == config_word_address())
205     {
206         if ((cfg_word & MCLRE) == MCLRE)
207         {
208             assignMCLRPin(4);  // package pin 4
209 
210         }
211         else
212         {
213             unassignMCLRPin();
214         }
215 
216         wdt.initialize((cfg_word & WDTEN) == WDTEN);
217 
218         if ((cfg_word & (FOSC2 | FOSC1)) == 0x04)   // internal RC OSC
219         {
220             osccal.set_freq(4e6);
221         }
222 
223         return (_14bit_processor::set_config_word(address, cfg_word));
224     }
225 
226     return false;
227 }
228 
229 
P12F629(const char * _name,const char * desc)230 P12F629::P12F629(const char *_name, const char *desc)
231     : _14bit_processor(_name, desc),
232       intcon_reg(this, "intcon", "Interrupt Control"),
233       comparator(this),
234       pie1(this, "PIE1", "Peripheral Interrupt Enable"),
235       t1con(this, "t1con", "TMR1 Control"),
236       tmr1l(this, "tmr1l", "TMR1 Low"),
237       tmr1h(this, "tmr1h", "TMR1 High"),
238       pcon(this, "pcon", "pcon"),
239       osccal(this, "osccal", "Oscillator Calibration Register", 0xfc),
240       int_pin(this, &intcon_reg, 0)
241 
242 {
243     m_ioc = new IOC(this, "ioc", "Interrupt-On-Change GPIO Register");
244     m_gpio = new PicPortGRegister(this, "gpio", "", &intcon_reg, m_ioc, 8, 0x3f);
245     m_trisio = new PicTrisRegister(this, "trisio", "", m_gpio, false);
246 
247     m_wpu = new WPU(this, "wpu", "Weak Pull-up Register", m_gpio, 0x37);
248     pir1 = new PIR1v12f(this, "pir1", "Peripheral Interrupt Register", &intcon_reg, &pie1);
249     tmr0.set_cpu(this, m_gpio, 4, option_reg);
250     tmr0.start(0);
251 
252     if (config_modes)
253         config_modes->valid_bits = ConfigMode::CM_FOSC0 | ConfigMode::CM_FOSC1 |
254                                    ConfigMode::CM_FOSC1x | ConfigMode::CM_WDTE | ConfigMode::CM_PWRTE;
255 }
256 
257 
~P12F629()258 P12F629::~P12F629()
259 {
260     delete_file_registers(0x20, ram_top);
261     remove_sfr_register(&tmr0);
262     remove_sfr_register(&tmr1l);
263     remove_sfr_register(&tmr1h);
264     remove_sfr_register(&pcon);
265     remove_sfr_register(&t1con);
266     remove_sfr_register(&intcon_reg);
267     remove_sfr_register(&pie1);
268     remove_sfr_register(&comparator.cmcon);
269     remove_sfr_register(&comparator.vrcon);
270     remove_sfr_register(get_eeprom()->get_reg_eedata());
271     remove_sfr_register(get_eeprom()->get_reg_eeadr());
272     remove_sfr_register(get_eeprom()->get_reg_eecon1());
273     remove_sfr_register(get_eeprom()->get_reg_eecon2());
274     remove_sfr_register(&osccal);
275     delete_sfr_register(m_gpio);
276     delete_sfr_register(m_trisio);
277     delete_sfr_register(m_wpu);
278     delete_sfr_register(m_ioc);
279     delete_sfr_register(pir1);
280     delete e;
281 }
282 
283 
construct(const char * name)284 Processor * P12F629::construct(const char *name)
285 {
286     P12F629 *p = new P12F629(name);
287     p->create(0x5f, 128);
288     p->create_invalid_registers();
289     p->create_symbols();
290     return p;
291 }
292 
293 
create_symbols()294 void P12F629::create_symbols()
295 {
296     pic_processor::create_symbols();
297     addSymbol(Wreg);
298 }
299 
300 
create_sfr_map()301 void P12F629::create_sfr_map()
302 {
303     pir_set_def.set_pir1(pir1);
304     add_sfr_register(indf,    0x00);
305     alias_file_registers(0x00, 0x00, 0x80);
306     add_sfr_register(&tmr0,   0x01, RegisterValue(0xff, 0));
307     add_sfr_register(option_reg,  0x81, RegisterValue(0xff, 0));
308     add_sfr_register(pcl,     0x02, RegisterValue(0, 0));
309     add_sfr_register(status,  0x03, RegisterValue(0x18, 0));
310     add_sfr_register(fsr,     0x04);
311     alias_file_registers(0x02, 0x04, 0x80);
312     add_sfr_register(&tmr1l,  0x0e, RegisterValue(0, 0), "tmr1l");
313     add_sfr_register(&tmr1h,  0x0f, RegisterValue(0, 0), "tmr1h");
314     add_sfr_register(&pcon,   0x8e, RegisterValue(0, 0), "pcon");
315     add_sfr_register(&t1con,  0x10, RegisterValue(0, 0));
316     add_sfr_register(m_gpio, 0x05);
317     add_sfr_register(m_trisio, 0x85, RegisterValue(0x3f, 0));
318     add_sfr_register(pclath,  0x0a, RegisterValue(0, 0));
319     add_sfr_register(&intcon_reg, 0x0b, RegisterValue(0, 0));
320     alias_file_registers(0x0a, 0x0b, 0x80);
321     intcon = &intcon_reg;
322     intcon_reg.set_pir_set(get_pir_set());
323     add_sfr_register(pir1,   0x0c, RegisterValue(0, 0), "pir1");
324     tmr1l.tmrh = &tmr1h;
325     tmr1l.t1con = &t1con;
326     tmr1l.setInterruptSource(new InterruptSource(pir1, PIR1v1::TMR1IF));
327     tmr1h.tmrl  = &tmr1l;
328     t1con.tmrl  = &tmr1l;
329     tmr1l.setIOpin(&(*m_gpio)[5]);
330     tmr1l.setGatepin(&(*m_gpio)[4]);
331     add_sfr_register(&pie1,   0x8c, RegisterValue(0, 0));
332 
333     if (pir1)
334     {
335         pir1->set_intcon(&intcon_reg);
336         pir1->set_pie(&pie1);
337     }
338 
339     pie1.setPir(pir1);
340     // Link the comparator and voltage ref to porta
341     comparator.initialize(get_pir_set(), nullptr,
342                           &(*m_gpio)[0], &(*m_gpio)[1],
343                           nullptr, nullptr,
344                           &(*m_gpio)[2], nullptr);
345     comparator.cmcon.set_configuration(1, 0, AN0, AN1, AN0, AN1, ZERO);
346     comparator.cmcon.set_configuration(1, 1, AN0, AN1, AN0, AN1, OUT0);
347     comparator.cmcon.set_configuration(1, 2, AN0, AN1, AN0, AN1, NO_OUT);
348     comparator.cmcon.set_configuration(1, 3, AN1, VREF, AN1, VREF, OUT0);
349     comparator.cmcon.set_configuration(1, 4, AN1, VREF, AN1, VREF, NO_OUT);
350     comparator.cmcon.set_configuration(1, 5, AN1, VREF, AN0, VREF, OUT0);
351     comparator.cmcon.set_configuration(1, 6, AN1, VREF, AN0, VREF, NO_OUT);
352     comparator.cmcon.set_configuration(1, 7, NO_IN, NO_IN, NO_IN, NO_IN, ZERO);
353     comparator.cmcon.set_configuration(2, 0, NO_IN, NO_IN, NO_IN, NO_IN, ZERO);
354     comparator.cmcon.set_configuration(2, 1, NO_IN, NO_IN, NO_IN, NO_IN, ZERO);
355     comparator.cmcon.set_configuration(2, 2, NO_IN, NO_IN, NO_IN, NO_IN, ZERO);
356     comparator.cmcon.set_configuration(2, 3, NO_IN, NO_IN, NO_IN, NO_IN, ZERO);
357     comparator.cmcon.set_configuration(2, 4, NO_IN, NO_IN, NO_IN, NO_IN, ZERO);
358     comparator.cmcon.set_configuration(2, 5, NO_IN, NO_IN, NO_IN, NO_IN, ZERO);
359     comparator.cmcon.set_configuration(2, 6, NO_IN, NO_IN, NO_IN, NO_IN, ZERO);
360     comparator.cmcon.set_configuration(2, 7, NO_IN, NO_IN, NO_IN, NO_IN, ZERO);
361     add_sfr_register(&comparator.cmcon, 0x19, RegisterValue(0, 0), "cmcon");
362     add_sfr_register(&comparator.vrcon, 0x99, RegisterValue(0, 0), "cvrcon");
363     add_sfr_register(get_eeprom()->get_reg_eedata(),  0x9a);
364     add_sfr_register(get_eeprom()->get_reg_eeadr(),   0x9b);
365     add_sfr_register(get_eeprom()->get_reg_eecon1(),  0x9c, RegisterValue(0, 0));
366     add_sfr_register(get_eeprom()->get_reg_eecon2(),  0x9d);
367     add_sfr_register(m_wpu, 0x95, RegisterValue(0x37, 0), "wpu");
368     add_sfr_register(m_ioc, 0x96, RegisterValue(0, 0), "ioc");
369     add_sfr_register(&osccal, 0x90, RegisterValue(0x80, 0));
370 
371     int_pin.setIOpin(&(*m_gpio)[2], 0);
372 }
373 
374 
375 //-------------------------------------------------------------------
set_out_of_range_pm(unsigned int address,unsigned int value)376 void P12F629::set_out_of_range_pm(unsigned int address, unsigned int value)
377 {
378     if ((address >= 0x2100) && (address < 0x2100 + get_eeprom()->get_rom_size()))
379     {
380         get_eeprom()->change_rom(address - 0x2100, value);
381     }
382 }
383 
384 
create_iopin_map()385 void P12F629::create_iopin_map()
386 {
387     package = new Package(8);
388 
389     // Now Create the package and place the I/O pins
390     package->assign_pin(7, m_gpio->addPin(new IO_bi_directional_pu("gpio0"), 0));
391     package->assign_pin(6, m_gpio->addPin(new IO_bi_directional_pu("gpio1"), 1));
392     package->assign_pin(5, m_gpio->addPin(new IO_bi_directional_pu("gpio2"), 2));
393     package->assign_pin(4, m_gpio->addPin(new IOPIN("gpio3"), 3));
394     package->assign_pin(3, m_gpio->addPin(new IO_bi_directional_pu("gpio4"), 4));
395     package->assign_pin(2, m_gpio->addPin(new IO_bi_directional_pu("gpio5"), 5));
396     package->assign_pin(1, 0);
397     package->assign_pin(8, 0);
398 }
399 
400 
create(int _ram_top,int eeprom_size)401 void  P12F629::create(int _ram_top, int eeprom_size)
402 {
403     ram_top = _ram_top;
404     create_iopin_map();
405     _14bit_processor::create();
406     e = new EEPROM_PIR(this, pir1);
407     e->initialize(eeprom_size);
408     e->set_intcon(&intcon_reg);
409     set_eeprom(e);
410     add_file_registers(0x20, ram_top, 0x80);
411     P12F629::create_sfr_map();
412 }
413 
414 
415 //-------------------------------------------------------------------
enter_sleep()416 void P12F629::enter_sleep()
417 {
418     tmr1l.sleep();
419     _14bit_processor::enter_sleep();
420 }
421 
422 
423 //-------------------------------------------------------------------
exit_sleep()424 void P12F629::exit_sleep()
425 {
426     tmr1l.wake();
427     _14bit_processor::exit_sleep();
428 }
429 
430 
431 //-------------------------------------------------------------------
option_new_bits_6_7(unsigned int bits)432 void P12F629::option_new_bits_6_7(unsigned int bits)
433 {
434     Dprintf(("P12F629::option_new_bits_6_7 bits=%x\n", bits));
435     m_gpio->setIntEdge((bits & OPTION_REG::BIT6) == OPTION_REG::BIT6);
436     m_wpu->set_wpu_pu((bits & OPTION_REG::BIT7) != OPTION_REG::BIT7);
437 }
438 
439 
440 //========================================================================
441 //
442 // Pic 16F675
443 //
444 
construct(const char * name)445 Processor * P12F675::construct(const char *name)
446 {
447     P12F675 *p = new P12F675(name);
448     p->create(0x5f, 128);
449     p->create_invalid_registers();
450     p->create_symbols();
451     return p;
452 }
453 
454 
P12F675(const char * _name,const char * desc)455 P12F675::P12F675(const char *_name, const char *desc)
456     : P12F629(_name, desc),
457       ansel(this, "ansel", "Analog Select"),
458       adcon0(this, "adcon0", "A2D Control 0"),
459       adcon1(this, "adcon1", "A2D Control 1"),
460       adresh(this, "adresh", "A2D Result High"),
461       adresl(this, "adresl", "A2D Result Low")
462 {
463 }
464 
465 
~P12F675()466 P12F675::~P12F675()
467 {
468     remove_sfr_register(&adresl);
469     remove_sfr_register(&adresh);
470     remove_sfr_register(&adcon0);
471     remove_sfr_register(&ansel);
472 }
473 
474 
create(int ram_top,int eeprom_size)475 void  P12F675::create(int ram_top, int eeprom_size)
476 {
477     P12F629::create(ram_top, eeprom_size);
478     create_sfr_map();
479 }
480 
481 
create_sfr_map()482 void P12F675::create_sfr_map()
483 {
484     //
485     //  adcon1 is not a register on the 12f675, but it is used internally
486     //  to perform the ADC conversions
487     //
488     add_sfr_register(&adresl,  0x9e, RegisterValue(0, 0));
489     add_sfr_register(&adresh,  0x1e, RegisterValue(0, 0));
490     add_sfr_register(&adcon0, 0x1f, RegisterValue(0, 0));
491     add_sfr_register(&ansel, 0x9f, RegisterValue(0x0f, 0));
492     ansel.setAdcon1(&adcon1);
493     ansel.setAdcon0(&adcon0);
494     adcon0.setAdresLow(&adresl);
495     adcon0.setAdres(&adresh);
496     adcon0.setAdcon1(&adcon1);
497     adcon0.setIntcon(&intcon_reg);
498     adcon0.setA2DBits(10);
499     adcon0.setPir(pir1);
500     adcon0.setChannel_Mask(3);
501     adcon0.setChannel_shift(2);
502     adcon1.setNumberOfChannels(4);
503     adcon1.setIOPin(0, &(*m_gpio)[0]);
504     adcon1.setIOPin(1, &(*m_gpio)[1]);
505     adcon1.setIOPin(2, &(*m_gpio)[2]);
506     adcon1.setIOPin(3, &(*m_gpio)[4]);
507     adcon1.setVrefHiConfiguration(2, 1);
508     /* Channel Configuration done dynamiclly based on ansel */
509     adcon1.setValidCfgBits(ADCON1::VCFG0 | ADCON1::VCFG1, 4);
510 }
511 
512 
513 //========================================================================
514 //
515 // Pic 16F683
516 //
517 
construct(const char * name)518 Processor * P12F683::construct(const char *name)
519 {
520     P12F683 *p = new P12F683(name);
521     p->create(0x7f, 256);
522     p->create_invalid_registers();
523     p->create_symbols();
524     return p;
525 }
526 
527 
P12F683(const char * _name,const char * desc)528 P12F683::P12F683(const char *_name, const char *desc)
529     : P12F675(_name, desc),
530       t2con(this, "t2con", "TMR2 Control"),
531       pr2(this, "pr2", "TMR2 Period Register"),
532       tmr2(this, "tmr2", "TMR2 Register"),
533       ccp1con(this, "ccp1con", "Capture Compare Control"),
534       ccpr1l(this, "ccpr1l", "Capture Compare 1 Low"),
535       ccpr1h(this, "ccpr1h", "Capture Compare 1 High"),
536       wdtcon(this, "wdtcon", "WDT Control", 0x1f),
537       osccon(nullptr),
538       osctune(this, "osctune", "OSC Tune")
539 
540 {
541     internal_osc = false;
542     pir1->valid_bits |= PIR1v12f::TMR2IF;
543     pir1->writable_bits |= PIR1v12f::TMR2IF;
544 }
545 
546 
~P12F683()547 P12F683::~P12F683()
548 {
549     delete_file_registers(0x20, 0x7f);
550     delete_file_registers(0xa0, 0xbf);
551     remove_sfr_register(&tmr2);
552     remove_sfr_register(&t2con);
553     remove_sfr_register(&pr2);
554     remove_sfr_register(&ccpr1l);
555     remove_sfr_register(&ccpr1h);
556     remove_sfr_register(&ccp1con);
557     remove_sfr_register(&wdtcon);
558     remove_sfr_register(osccon);
559     remove_sfr_register(&osctune);
560     remove_sfr_register(&comparator.cmcon1);
561 }
562 
563 
create(int,int eeprom_size)564 void  P12F683::create(int /* _ram_top */, int eeprom_size)
565 {
566     P12F629::create(0, eeprom_size);
567     osccon = new OSCCON(this, "osccon", "OSC Control");
568     add_file_registers(0x20, 0x6f, 0);
569     add_file_registers(0xa0, 0xbf, 0);
570     add_file_registers(0x70, 0x7f, 0x80);
571     create_sfr_map();
572 }
573 
574 
create_sfr_map()575 void P12F683::create_sfr_map()
576 {
577     P12F675::create_sfr_map();
578     add_sfr_register(&tmr2,   0x11, RegisterValue(0, 0));
579     add_sfr_register(&t2con,  0x12, RegisterValue(0, 0));
580     add_sfr_register(&pr2,    0x92, RegisterValue(0xff, 0));
581     add_sfr_register(&ccpr1l,  0x13, RegisterValue(0, 0));
582     add_sfr_register(&ccpr1h,  0x14, RegisterValue(0, 0));
583     add_sfr_register(&ccp1con, 0x15, RegisterValue(0, 0));
584     add_sfr_register(&wdtcon, 0x18, RegisterValue(0x08, 0), "wdtcon");
585     add_sfr_register(osccon, 0x8f, RegisterValue(0, 0), "osccon");
586     remove_sfr_register(&osccal);
587     add_sfr_register(&osctune, 0x90, RegisterValue(0, 0), "osctune");
588     osccon->set_osctune(&osctune);
589     osctune.set_osccon(osccon);
590     t2con.tmr2  = &tmr2;
591     tmr2.pir_set   = get_pir_set();
592     tmr2.pr2    = &pr2;
593     tmr2.t2con  = &t2con;
594     tmr2.add_ccp(&ccp1con);
595     pr2.tmr2    = &tmr2;
596     ccp1con.setCrosslinks(&ccpr1l, pir1, PIR1v1::CCP1IF, &tmr2);
597     ccp1con.setIOpin(&((*m_gpio)[2]));
598     ccpr1l.ccprh  = &ccpr1h;
599     ccpr1l.tmrl   = &tmr1l;
600     ccpr1h.ccprl  = &ccpr1l;
601     comparator.cmcon.new_name("cmcon0");
602     comparator.cmcon.set_tmrl(&tmr1l);
603     comparator.cmcon1.set_tmrl(&tmr1l);
604     add_sfr_register(&comparator.cmcon1, 0x1a, RegisterValue(2, 0), "cmcon1");
605     wdt.set_timeout(1.0 / 31000.0);
606 }
607 
608 
P10F32X(const char * _name,const char * desc)609 P10F32X::P10F32X(const char *_name, const char *desc)
610     : _14bit_processor(_name, desc),
611       intcon_reg(this, "intcon", "Interrupt Control"),
612       pie1(this, "PIE1", "Peripheral Interrupt Enable"),
613       t2con(this, "t2con", "TMR2 Control"),
614       tmr2(this, "tmr2", "TMR2 Register"),
615       pr2(this, "pr2", "Timer2 Period Register"),
616       pcon(this, "pcon", "pcon"),
617       ansela(this, "ansela", "Analog Select"),
618       fvrcon(this, "fvrcon", "Voltage reference control register", 0xf3, 0x00),
619       borcon(this, "borcon", "Brown-out reset control register"),
620       wdtcon(this, "wdtcon", "WDT Control", 0x3f),
621       adcon0(this, "adcon", "A2D Control 0"),
622       adcon1(this, "adcon1", "A2D Control 1"), // virtual register
623       adres(this, "adres", "A2D Result Low"),
624       pwm1con(this, "pwm1con", "PWM CONTROL REGISTER 1", 1),
625       pwm1dcl(this, "pwm1dcl", "PWM DUTY CYCLE LOW BITS"),
626       pwm1dch(this, "pwm1dch", "PWM DUTY CYCLE HIGH BITS"),
627       pwm2con(this, "pwm2con", "PWM CONTROL REGISTER 2", 2),
628       pwm2dcl(this, "pwm2dcl", "PWM DUTY CYCLE LOW BITS"),
629       pwm2dch(this, "pwm2dch", "PWM DUTY CYCLE HIGH BITS"),
630       pm_rw(this), cwg(this), nco(this), clcdata(this),
631       clc1(this, 0, &clcdata),
632       vregcon(this, "vregcon", "Voltage Regulator Control Register")
633 
634 {
635     m_iocaf = new IOCxF(this, "iocaf", "Interrupt-On-Change flag Register", 0x0f);
636     m_iocap = new IOC(this, "iocap", "Interrupt-On-Change positive edge", 0x0f);
637     m_iocan = new IOC(this, "iocan", "Interrupt-On-Change negative edge", 0x0f);
638     m_porta = new PicPortIOCRegister(this, "porta", "", &intcon_reg, m_iocap, m_iocan, m_iocaf, 8, 0x0f);
639     m_trisa = new PicTrisRegister(this, "trisa", "", m_porta, false, 0x07);
640     m_lata  = new PicLatchRegister(this, "lata", "", m_porta, 0x07);
641     m_wpu = new WPU(this, "wpua", "Weak Pull-up Register", m_porta, 0x0f);
642     pir1 = new PIR1v12f(this, "pir1", "Peripheral Interrupt Register", &intcon_reg, &pie1);
643     pir1->valid_bits |= PIR1v12f::TMR2IF | PIR1v12f::NCO1IF;
644     pir1->valid_bits &= ~(PIR1v12f::EEIF | PIR1v12f::TMR1IF);
645     pir1->writable_bits = pir1->valid_bits;
646     m_cpu_temp = new CPU_Temp("cpu_temperature", 30.0, "CPU die temperature");
647     osccon = new OSCCON_HS2(this, "osccon", "Oscillator Control Register");
648     tmr0.set_cpu(this, m_porta, 3, option_reg);
649     tmr0.start(0);
650     clc1.set_dxs_data(1, 8, lcxdx);
651     clc1.set_dxs_data(2, 8, lcxdx);
652     clc1.set_dxs_data(3, 8, lcxdx);
653     clc1.set_dxs_data(4, 8, lcxdx);
654 }
655 
656 
~P10F32X()657 P10F32X::~P10F32X()
658 {
659     delete_file_registers(0x40, ram_top);
660     remove_sfr_register(&tmr2);
661     remove_sfr_register(&t2con);
662     remove_sfr_register(&pr2);
663     remove_sfr_register(&pcon);
664     remove_sfr_register(&intcon_reg);
665     remove_sfr_register(&pie1);
666     remove_sfr_register(&ansela);
667     remove_sfr_register(&fvrcon);
668     remove_sfr_register(&tmr0);
669     remove_sfr_register(&borcon);
670     remove_sfr_register(&wdtcon);
671     remove_sfr_register(&adcon0);
672     remove_sfr_register(&adcon1);
673     remove_sfr_register(&adres);
674     remove_sfr_register(&pwm1dcl);
675     remove_sfr_register(&pwm1dch);
676     remove_sfr_register(&pwm1con);
677     remove_sfr_register(&pwm2dcl);
678     remove_sfr_register(&pwm2dch);
679     remove_sfr_register(&pwm2con);
680     remove_sfr_register(pm_rw.get_reg_pmadr());
681     remove_sfr_register(pm_rw.get_reg_pmadrh());
682     remove_sfr_register(pm_rw.get_reg_pmdata());
683     remove_sfr_register(pm_rw.get_reg_pmdath());
684     remove_sfr_register(pm_rw.get_reg_pmcon1_rw());
685     remove_sfr_register(pm_rw.get_reg_pmcon2());
686     remove_sfr_register(&nco.nco1accl);
687     remove_sfr_register(&nco.nco1acch);
688     remove_sfr_register(&nco.nco1accu);
689     remove_sfr_register(&nco.nco1incl);
690     remove_sfr_register(&nco.nco1inch);
691     remove_sfr_register(&nco.nco1con);
692     remove_sfr_register(&nco.nco1clk);
693     remove_sfr_register(&clc1.clcxcon);
694     remove_sfr_register(&clc1.clcxpol);
695     remove_sfr_register(&clc1.clcxsel0);
696     remove_sfr_register(&clc1.clcxsel1);
697     remove_sfr_register(&clc1.clcxgls0);
698     remove_sfr_register(&clc1.clcxgls1);
699     remove_sfr_register(&clc1.clcxgls2);
700     remove_sfr_register(&clc1.clcxgls3);
701     remove_sfr_register(&cwg.cwg1con0);
702     remove_sfr_register(&cwg.cwg1con1);
703     remove_sfr_register(&cwg.cwg1con2);
704     remove_sfr_register(&cwg.cwg1dbr);
705     remove_sfr_register(&cwg.cwg1dbf);
706     remove_sfr_register(&vregcon);
707     delete_sfr_register(m_porta);
708     delete_sfr_register(m_trisa);
709     delete_sfr_register(m_lata);
710     delete_sfr_register(m_wpu);
711     delete_sfr_register(m_iocaf);
712     delete_sfr_register(m_iocap);
713     delete_sfr_register(m_iocan);
714     delete_sfr_register(pir1);
715     delete_sfr_register(osccon);
716     delete m_cpu_temp;
717 }
718 
719 
create()720 void  P10F32X::create()
721 {
722     ram_top = 0x7f;
723     P10F32X::create_iopin_map();
724     _14bit_processor::create();
725     status->write_mask &= ~0xe0; // IRP RP0 RP1 read only
726     add_file_registers(0x40, ram_top, 0x00);
727     P10F32X::create_sfr_map();
728 }
729 
730 
option_new_bits_6_7(unsigned int bits)731 void P10F32X::option_new_bits_6_7(unsigned int bits)
732 {
733     Dprintf(("P10F32X::option_new_bits_6_7 bits=%x\n", bits));
734     m_porta->setIntEdge((bits & OPTION_REG::BIT6));
735     m_wpu->set_wpu_pu(!(bits & OPTION_REG::BIT7));
736 }
737 
738 
create_symbols()739 void P10F32X::create_symbols()
740 {
741     pic_processor::create_symbols();
742     addSymbol(Wreg);
743 }
744 
745 
create_sfr_map()746 void P10F32X::create_sfr_map()
747 {
748     pir_set_def.set_pir1(pir1);
749     add_sfr_register(indf,    0x00);
750     add_sfr_register(&tmr0,   0x01, RegisterValue(0xff, 0));
751     add_sfr_register(option_reg,  0x0e, RegisterValue(0xff, 0));
752     add_sfr_register(pcl,     0x02, RegisterValue(0, 0));
753     add_sfr_register(status,  0x03, RegisterValue(0x18, 0));
754     add_sfr_register(fsr,     0x04);
755     add_sfr_register(m_porta,  0x05, RegisterValue(0x0, 0));
756     add_sfr_register(m_trisa,  0x06, RegisterValue(0x0f, 0));
757     add_sfr_register(m_lata,  0x07, RegisterValue(0x00, 0));
758     add_sfr_registerR(&ansela, 0x08, RegisterValue(0x07, 0));
759     add_sfr_registerR(m_wpu, 0x09, RegisterValue(0x0f, 0), "wpu");
760     add_sfr_registerR(pclath,  0x0a, RegisterValue(0, 0));
761     add_sfr_registerR(&intcon_reg, 0x0b, RegisterValue(0, 0));
762     intcon = &intcon_reg;
763     intcon_reg.set_pir_set(get_pir_set());
764     add_sfr_register(pir1,   0x0c, RegisterValue(0, 0), "pir1");
765     add_sfr_registerR(&pie1,   0x0d, RegisterValue(0, 0));
766     add_sfr_register(&pcon,   0x0f, RegisterValue(0, 0), "pcon");
767     add_sfr_registerR(osccon,   0x10, RegisterValue(0x60, 0));
768     add_sfr_registerR(&tmr2,     0x11, RegisterValue(0, 0));
769     add_sfr_registerR(&pr2,      0x12, RegisterValue(0xff, 0));
770     add_sfr_registerR(&t2con,    0x13, RegisterValue(0, 0));
771     add_sfr_register(&pwm1dcl,  0x14, RegisterValue(0, 0));
772     add_sfr_register(&pwm1dch,  0x15, RegisterValue(0, 0));
773     add_sfr_registerR(&pwm1con,  0x16, RegisterValue(0, 0));
774     add_sfr_register(&pwm2dcl,  0x17, RegisterValue(0, 0));
775     add_sfr_register(&pwm2dch,  0x18, RegisterValue(0, 0));
776     add_sfr_registerR(&pwm2con,  0x19, RegisterValue(0, 0));
777     add_sfr_registerR(m_iocap,   0x1a, RegisterValue(0, 0));
778     add_sfr_registerR(m_iocan,   0x1b, RegisterValue(0, 0));
779     add_sfr_registerR(m_iocaf,   0x1c, RegisterValue(0, 0));
780     add_sfr_registerR(&fvrcon,   0x1d, RegisterValue(0, 0));
781     add_sfr_register(&adres,    0x1e, RegisterValue(0, 0));
782     add_sfr_registerR(&adcon0,   0x1f, RegisterValue(0, 0));
783     add_sfr_registerR(pm_rw.get_reg_pmadr(),  0x20);
784     add_sfr_registerR(pm_rw.get_reg_pmadrh(), 0x21);
785     add_sfr_register(pm_rw.get_reg_pmdata(), 0x22);
786     add_sfr_register(pm_rw.get_reg_pmdath(), 0x23);
787     add_sfr_registerR(pm_rw.get_reg_pmcon1_rw(), 0x24);
788     add_sfr_registerR(pm_rw.get_reg_pmcon2(), 0x25);
789     add_sfr_registerR(&nco.nco1accl, 0x27, RegisterValue(0, 0));
790     add_sfr_registerR(&nco.nco1acch, 0x28, RegisterValue(0, 0));
791     add_sfr_registerR(&nco.nco1accu, 0x29, RegisterValue(0, 0));
792     add_sfr_registerR(&nco.nco1incl, 0x2a, RegisterValue(1, 0));
793     add_sfr_registerR(&nco.nco1inch, 0x2b, RegisterValue(0, 0));
794     add_sfr_registerR(&nco.nco1con,  0x2d, RegisterValue(0, 0));
795     add_sfr_registerR(&nco.nco1clk,  0x2e, RegisterValue(0, 0));
796     add_sfr_registerR(&wdtcon,   0x30, RegisterValue(0x16, 0));
797     add_sfr_registerR(&clc1.clcxcon, 0x31, RegisterValue(0, 0), "clc1con");
798     add_sfr_register(&clc1.clcxpol, 0x32, RegisterValue(0, 0), "clc1pol");
799     add_sfr_register(&clc1.clcxsel0, 0x33, RegisterValue(0, 0), "clc1sel0");
800     add_sfr_register(&clc1.clcxsel1, 0x34, RegisterValue(0, 0), "clc1sel1");
801     add_sfr_register(&clc1.clcxgls0, 0x35, RegisterValue(0, 0), "clc1gls0");
802     add_sfr_register(&clc1.clcxgls1, 0x36, RegisterValue(0, 0), "clc1gls1");
803     add_sfr_register(&clc1.clcxgls2, 0x37, RegisterValue(0, 0), "clc1gls2");
804     add_sfr_register(&clc1.clcxgls3, 0x38, RegisterValue(0, 0), "clc1gls3");
805     add_sfr_registerR(&cwg.cwg1con0, 0x39, RegisterValue(0, 0));
806     add_sfr_register(&cwg.cwg1con1, 0x3a);
807     add_sfr_register(&cwg.cwg1con2, 0x3b);
808     add_sfr_register(&cwg.cwg1dbr, 0x3c);
809     add_sfr_register(&cwg.cwg1dbf, 0x3d);
810     add_sfr_registerR(&vregcon, 0x3e, RegisterValue(1, 0));
811     add_sfr_register(&borcon,   0x3f, RegisterValue(0x80, 0));
812 
813     if (pir1)
814     {
815         pir1->set_intcon(&intcon_reg);
816         pir1->set_pie(&pie1);
817     }
818 
819     pie1.setPir(pir1);
820     ansela.setValidBits(0x07);
821     ansela.setAdcon1(&adcon1);
822     ansela.config(7, 0);
823     adcon1.setNumberOfChannels(8);
824     adcon0.setAdres(&adres);
825     adcon0.setAdcon1(&adcon1);
826     adcon0.setIntcon(&intcon_reg);
827     adcon0.setA2DBits(8);
828     adcon0.setPir(pir1);
829     adcon0.setChannel_Mask(7);
830     adcon0.setChannel_shift(2);
831     adcon1.setIOPin(0, &(*m_porta)[0]);
832     adcon1.setIOPin(1, &(*m_porta)[1]);
833     adcon1.setIOPin(2, &(*m_porta)[2]);
834     fvrcon.set_adcon1(&adcon1);
835     fvrcon.set_VTemp_AD_chan(6);
836     fvrcon.set_FVRAD_AD_chan(7);
837     t2con.tmr2  = &tmr2;
838     tmr2.pir_set   = get_pir_set();
839     tmr2.pr2    = &pr2;
840     tmr2.t2con  = &t2con;
841     tmr2.add_ccp(&pwm1con);
842     tmr2.add_ccp(&pwm2con);
843     pr2.tmr2    = &tmr2;
844     pwm1con.set_pwmdc(&pwm1dcl, &pwm1dch);
845     pwm1con.setIOPin1(&(*m_porta)[0]);
846     pwm1con.set_tmr2(&tmr2);
847     pwm1con.set_cwg(&cwg);
848     pwm1con.set_clc(&clc1, 0);
849     pwm2con.set_pwmdc(&pwm2dcl, &pwm2dch);
850     pwm2con.setIOPin1(&(*m_porta)[1]);
851     pwm2con.set_tmr2(&tmr2);
852     pwm2con.set_cwg(&cwg);
853     pwm2con.set_clc(&clc1, 0);
854     cwg.set_IOpins(&(*m_porta)[0], &(*m_porta)[1], &(*m_porta)[2]);
855     clc1.p_nco = &nco;
856     clc1.set_clcPins(&(*m_porta)[1], &(*m_porta)[0], &(*m_porta)[2]);
857     tmr0.set_clc(&clc1, 0);
858     clc1.setInterruptSource(new InterruptSource(pir1, (1 << 3)));
859     nco.setIOpins(&(*m_porta)[1], &(*m_porta)[2]);
860     nco.pir = pir1;
861 }
862 
863 
create_iopin_map()864 void P10F32X::create_iopin_map()
865 {
866     package = new Package(8);
867 
868     // Now Create the package and place the I/O pins
869     package->assign_pin(5, m_porta->addPin(new IO_bi_directional_pu("ra0"), 0));
870     package->assign_pin(4, m_porta->addPin(new IO_bi_directional_pu("ra1"), 1));
871     package->assign_pin(3, m_porta->addPin(new IO_bi_directional_pu("ra2"), 2));
872     package->assign_pin(8, m_porta->addPin(new IO_bi_directional_pu("ra3"), 3));
873     package->assign_pin(1, 0);
874     package->assign_pin(2, 0);
875     package->assign_pin(6, 0);
876     package->assign_pin(7, 0);
877 }
878 
879 
create_config_memory()880 void P10F32X::create_config_memory()
881 {
882     m_configMemory = new ConfigMemory(this, 1);
883     m_configMemory->addConfigWord(0, new Config12F6(this));
884 }
885 
886 
set_config_word(unsigned int address,unsigned int cfg_word)887 bool P10F32X::set_config_word(unsigned int address, unsigned int cfg_word)
888 {
889     enum
890     {
891         FOSC  = 1 << 0,
892         BOREN  = 1 << 1,
893         BOREN1  = 1 << 2,
894         WDTEN0  = 1 << 3,
895         WDTEN1  = 1 << 4,
896         MCLRE  = 1 << 6,
897         CP     = 1 << 7,
898         LVP    = 1 << 8,
899 
900     };
901     Dprintf(("P10F32X::set_config_word address 0x%x cfg=0x%x\n", address, cfg_word));
902 
903     if (address == config_word_address())
904     {
905         if ((cfg_word & MCLRE))
906         {
907             assignMCLRPin(8);  // package pin 8
908 
909         }
910         else
911         {
912             unassignMCLRPin();
913         }
914 
915         wdt_flag = (cfg_word & (WDTEN0 | WDTEN1)) >> 3;
916         wdt.set_timeout(1.0 / 31000.0);
917         wdt.initialize(wdt_flag & 2, false);
918 
919         if (cfg_word & FOSC)   // EC on CLKIN
920         {
921             m_porta->getPin(1)->newGUIname("CKIN");
922             set_int_osc(false);
923 
924         }
925         else  	     // INTRC
926         {
927             m_porta->getPin(1)->newGUIname(m_porta->getPin(1)->name().c_str());
928             set_int_osc(true);
929             osccon->set_rc_frequency();
930         }
931 
932         return (_14bit_processor::set_config_word(address, cfg_word));
933     }
934 
935     return false;
936 }
937 
938 
939 //-------------------------------------------------------------------
enter_sleep()940 void P10F32X::enter_sleep()
941 {
942     tmr0.sleep();
943 
944     if (wdt_flag == 2)          // WDT is suspended during sleep
945     {
946         wdt.initialize(false);
947     }
948 
949     pic_processor::enter_sleep();
950 }
951 
952 
exit_sleep()953 void P10F32X::exit_sleep()
954 {
955     if (m_ActivityState == ePASleeping)
956     {
957         tmr0.wake();
958 
959         if (wdt_flag == 2)
960         {
961             wdt.initialize(true);
962         }
963 
964         pic_processor::exit_sleep();
965     }
966 }
967 
968 
P10F320(const char * _name,const char * desc)969 P10F320::P10F320(const char *_name, const char *desc)
970     : P10F32X(_name, desc)
971 {
972 }
973 
974 
~P10F320()975 P10F320::~P10F320()
976 {
977 }
978 
979 
construct(const char * name)980 Processor * P10F320::construct(const char *name)
981 {
982     P10F320 *p = new P10F320(name);
983     p->create();
984     p->create_invalid_registers();
985     p->create_symbols();
986     return p;
987 }
988 
989 
construct(const char * name)990 Processor * P10LF320::construct(const char *name)
991 {
992     P10LF320 *p = new P10LF320(name);
993     p->create();
994     p->create_invalid_registers();
995     p->create_symbols();
996     return p;
997 }
998 
999 
P10F322(const char * _name,const char * desc)1000 P10F322::P10F322(const char *_name, const char *desc)
1001     : P10F32X(_name, desc)
1002 {
1003 }
1004 
1005 
~P10F322()1006 P10F322::~P10F322()
1007 {
1008 }
1009 
1010 
construct(const char * name)1011 Processor * P10F322::construct(const char *name)
1012 {
1013     P10F322 *p = new P10F322(name);
1014     p->create();
1015     p->create_invalid_registers();
1016     p->create_symbols();
1017     return p;
1018 }
1019 
1020 
construct(const char * name)1021 Processor * P10LF322::construct(const char *name)
1022 {
1023     P10LF322 *p = new P10LF322(name);
1024     p->create();
1025     p->create_invalid_registers();
1026     p->create_symbols();
1027     return p;
1028 }
1029