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