1 /*
2    Copyright (C) 2006 T. Scott Dattalo
3    Copyright (C) 2009, 2013, 2015 Roy R. Rankin
4 
5 This file is part of the libgpsim library of gpsim
6 
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11 
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, see
19 <http://www.gnu.org/licenses/lgpl-2.1.html>.
20 */
21 
22 #ifndef SRC_A2DCONVERTER_H_
23 #define SRC_A2DCONVERTER_H_
24 
25 #include "ioports.h"
26 #include "registers.h"
27 #include "trigger.h"
28 #include "stimuli.h"
29 #include "comparator.h"
30 
31 class ADCON0;
32 class ADCON2_DIF;
33 class ANSEL_H;
34 class CPSCON0;
35 class ComparatorModule2;
36 class DACCON0;
37 class INTCON;
38 class PIR;
39 class Processor;
40 
41 
42 //---------------------------------------------------------
43 // ADRES
44 //
45 /*
46 class ADRES : public sfr_register
47 {
48 public:
49 
50   void put(int new_value);
51 };
52 */
53 
54 /*
55 	AD_IN_SignalControl is used to set an ADC pin as input
56 	regardless of the setting to the TRIS register
57 */
58 class AD_IN_SignalControl : public SignalControl
59 {
60 public:
AD_IN_SignalControl()61     AD_IN_SignalControl() {}
~AD_IN_SignalControl()62     ~AD_IN_SignalControl() {}
getState()63     char getState()
64     {
65         return '1';
66     }
release()67     void release() {}
68 };
69 
70 
71 //---------------------------------------------------------
72 // ADCON1
73 //
74 
75 class ADCON1 : public sfr_register
76 {
77 public:
78 
79     enum PCFG_bits
80     {
81         PCFG0 = 1 << 0,
82         PCFG1 = 1 << 1,
83         PCFG2 = 1 << 2,
84         PCFG3 = 1 << 3, // 16f87x etc.
85         VCFG0 = 1 << 4, // 16f88
86         VCFG1 = 1 << 5, // 16f88
87         ADCS2 = 1 << 6,
88         ADFM  = 1 << 7  // Format Result select bit
89     };
90 
91     ADCON1(Processor *pCpu, const char *pName, const char *pDesc);
92     ~ADCON1();
93 
94     virtual void put(unsigned int new_value);
95     virtual void put_value(unsigned int new_value);
96     void setChannelConfiguration(unsigned int cfg, unsigned int bitMask);
97     void setVrefLoConfiguration(unsigned int cfg, unsigned int channel);
98     void setVrefHiConfiguration(unsigned int cfg, unsigned int channel);
99     unsigned int getVrefHiChannel(unsigned int cfg);
100     unsigned int getVrefLoChannel(unsigned int cfg);
101 
102     double getChannelVoltage(unsigned int channel);
103     virtual double getVrefHi();
104     virtual double getVrefLo();
105 
106     void setValidCfgBits(unsigned int m, unsigned int s);
107     void setNumberOfChannels(unsigned int);
getNumberOfChannels()108     unsigned int getNumberOfChannels()
109     {
110         return (m_nAnalogChannels);
111     }
112     void setIOPin(unsigned int, PinModule *);
113     void setVoltRef(unsigned int, float);
114     int  get_cfg(unsigned int);
115     virtual unsigned int get_adc_configmask(unsigned int);
set_cfg_index(unsigned int index)116     virtual void set_cfg_index(unsigned int index)
117     {
118         cfg_index = index;
119     }
120 
121     void set_channel_in(unsigned int channel, bool on);
122     void setADCnames();
setValidBits(unsigned int mask)123     void setValidBits(unsigned int mask)
124     {
125         valid_bits = mask;
126     }
getADFM()127     bool getADFM()
128     {
129         return adfm;
130     }
getMaxCfg()131     unsigned int getMaxCfg()
132     {
133         return cMaxConfigurations;
134     }
135 
136 protected:
137     unsigned int valid_bits;
138     bool		adfm = false;
139     PinModule **m_AnalogPins = nullptr;
140     float	*m_voltageRef = nullptr;
141     unsigned int m_nAnalogChannels = 0;
142     unsigned int mValidCfgBits = 0;
143     unsigned int mCfgBitShift = 0;
144     unsigned int mIoMask = 0;
145     unsigned int cfg_index = 0;
146 
147     static const unsigned int cMaxConfigurations = 16;
148 
149     /* Vrefhi/lo_position - this is an array that tells which
150      * channel the A/D converter's  voltage reference(s) are located.
151      * The index into the array is formed from the PCFG bits.
152      * The encoding is as follows:
153      *   0-7:  analog channel containing Vref(s)
154      *     8:  The reference is internal (i.e. Vdd)
155      *  0xff:  The analog inputs are configured as digital inputs
156      */
157     unsigned int Vrefhi_position[cMaxConfigurations];
158     unsigned int Vreflo_position[cMaxConfigurations];
159 
160     /* configuration bits is an array of 8-bit masks definining whether or not
161      * a given channel is analog or digital
162      */
163     unsigned int m_configuration_bits[cMaxConfigurations];
164 
165     // used bt setControl to set pin direction as input
166     AD_IN_SignalControl *m_ad_in_ctl = nullptr;
167 };
168 
169 
170 //---------------------------------------------------------
171 // ADCON1_16F
172 //
173 
174 class ADCON1_16F : public ADCON1
175 {
176 public:
177 
178     enum
179     {
180         ADPREF0 = (1 << 0),
181         ADPREF1 = (1 << 1),
182         ADNREF  = (1 << 2),
183         ADCS0   = (1 << 4),
184         ADCS1   = (1 << 5),
185         ADCS2   = (1 << 6),
186         ADFM    = (1 << 7)
187     };
188 
189     ADCON1_16F(Processor *pCpu, const char *pName, const char *pDesc);
190 
191     virtual void put_value(unsigned int new_value);
setAdcon0(ADCON0 * _adcon0)192     void setAdcon0(ADCON0 *_adcon0)
193     {
194         adcon0 = _adcon0;
195     }
196     virtual double getVrefHi();
197     virtual double getVrefLo();
set_FVR_chan(unsigned int chan)198     void set_FVR_chan(unsigned int chan)
199     {
200         FVR_chan = chan;
201     }
202 
203 private:
204     ADCON0 *adcon0 = nullptr;
205     unsigned int FVR_chan;
206 };
207 
208 
209 //---------------------------------------------------------
210 // ADCON0
211 //
212 
213 class ADCON0 : public sfr_register, public TriggerObject
214 {
215 public:
216 
217     enum
218     {
219         ADON = 1 << 0,
220         ADIF = 1 << 1,
221         GO   = 1 << 2,
222         CHS0 = 1 << 3,
223         CHS1 = 1 << 4,
224         CHS2 = 1 << 5,
225         ADCS0 = 1 << 6,
226         ADCS1 = 1 << 7,
227 
228     };
229 
230     enum AD_states
231     {
232         AD_IDLE,
233         AD_ACQUIRING,
234         AD_CONVERTING
235     };
236 
237     ADCON0(Processor *pCpu, const char *pName, const char *pDesc);
238 
239     void start_conversion();
240     void stop_conversion();
241     virtual void set_interrupt();
242     virtual void callback();
243     void put(unsigned int new_value);
244     virtual void put_conversion();
245 
getADIF()246     bool getADIF()
247     {
248         return (value.get() & ADIF) != 0;
249     }
250     void setAdres(sfr_register *);
251     void setAdresLow(sfr_register *);
252     void setAdcon1(ADCON1 *);
253     void setIntcon(INTCON *);
254     virtual void setPir(PIR *);
255     void setA2DBits(unsigned int);
setChannel_Mask(unsigned int ch_mask)256     void setChannel_Mask(unsigned int ch_mask)
257     {
258         channel_mask = ch_mask;
259     }
setChannel_shift(unsigned int ch_shift)260     void setChannel_shift(unsigned int ch_shift)
261     {
262         channel_shift = ch_shift;
263     }
setGo(unsigned int go)264     void setGo(unsigned int go)
265     {
266         GO_bit = (1 << go);
267     }
get_ADFM()268     virtual bool get_ADFM()
269     {
270         return adcon1->getADFM();
271     }
272     virtual void set_Tad(unsigned int);
getChannelVoltage(unsigned int channel)273     virtual double getChannelVoltage(unsigned int channel)
274     {
275         return (adcon1->getChannelVoltage(channel));
276     }
getVrefHi()277     virtual double getVrefHi()
278     {
279         return (m_dSampledVrefHi  = adcon1->getVrefHi());
280     }
getVrefLo()281     virtual double getVrefLo()
282     {
283         return (m_dSampledVrefLo  = adcon1->getVrefLo());
284     }
285 
setValidBits(unsigned int mask)286     void setValidBits(unsigned int mask)
287     {
288         valid_bits = mask;
289     }
290 
291 private:
292     friend class ADCON0_10;
293     friend class ADCON0_12F;
294     friend class ADCON0_32X;
295     friend class ADCON0_DIF;
296 
297     sfr_register *adres = nullptr;
298     sfr_register *adresl = nullptr;
299     ADCON1 *adcon1 = nullptr;
300     INTCON *intcon = nullptr;
301     PIR    *m_pPir = nullptr;
302 
303     double m_dSampledVoltage = 0.0;
304     double m_dSampledVrefHi = 0.0;
305     double m_dSampledVrefLo = 0.0;
306     unsigned int m_A2DScale = 0;
307     unsigned int m_nBits = 0;
308     guint64 future_cycle = 0;
309     unsigned int ad_state;
310     unsigned int Tad = 0;
311     unsigned int channel_mask;
312     unsigned int channel_shift;
313     unsigned int GO_bit;
314     unsigned int valid_bits = 0;
315 };
316 
317 
318 class ADCON0_91X : public ADCON0
319 {
320 public:
321     enum
322     {
323         ADON = 1 << 0,
324         GO   = 1 << 1,
325         CHS0 = 1 << 2,
326         CHS1 = 1 << 3,
327         CHS2 = 1 << 4,
328         VCFG0 = 1 << 5,	// P16f91x
329         VCFG1 = 1 << 6,	// P16f91x
330         ADFM  = 1 << 7,	// P16f91x
331 
332     };
333 
ADCON0_91X(Processor * pCpu,const char * pName,const char * pDesc)334     ADCON0_91X(Processor *pCpu, const char *pName, const char *pDesc) : ADCON0(pCpu, pName, pDesc) {}
335 
get_ADFM()336     virtual bool get_ADFM()
337     {
338         return value.get() & ADFM;
339     }
340     virtual double getVrefHi();
341     virtual double getVrefLo();
342 
343     unsigned int Vrefhi_position = 0;
344     unsigned int Vreflo_position = 0;
345 };
346 
347 
348 /* A/D converter with 12 or 10 bit differential input with ADCON2
349    32 possible input channels
350  */
351 
352 class ADCON0_DIF : public ADCON0
353 {
354     enum
355     {
356         ADON = 1 << 0,
357         GO   = 1 << 1,
358         CHS0 = 1 << 2,
359         CHS1 = 1 << 3,
360         CHS2 = 1 << 4,
361         CHS3 = 1 << 5,
362         CHS4 = 1 << 6,
363         ADRMD = 1 << 7
364     };
365 
366 public:
367     ADCON0_DIF(Processor *pCpu, const char *pName, const char *pDesc);
368 
369     virtual void put(unsigned int new_value);
370     virtual void put_conversion(void);
setAdcon2(ADCON2_DIF * _adcon2)371     void	setAdcon2(ADCON2_DIF * _adcon2)
372     {
373         adcon2 = _adcon2;
374     }
375 
376 private:
377     ADCON2_DIF *adcon2;
378 };
379 
380 
381 //---------------------------------------------------------
382 // ADCON0_10 register for 10f22x A2D
383 //
384 
385 class ADCON0_10 : public ADCON0
386 {
387 public:
388 
389     enum
390     {
391         ADON = 1 << 0,
392         GO   = 1 << 1,
393         CHS0 = 1 << 2,
394         CHS1 = 1 << 3,
395         ANS0 = 1 << 6,
396         ANS1 = 1 << 7
397     };
398     void put(unsigned int new_value);
399     ADCON0_10(Processor *pCpu, const char *pName, const char *pDesc);
400 
401 private:
402     AD_IN_SignalControl ad_pin_input;
403 };
404 
405 
406 //---------------------------------------------------------
407 // ANSEL
408 //
409 
410 class ANSEL : public sfr_register
411 {
412 public:
413     enum
414     {
415         ANS0 = 1 << 0,
416         ANS1 = 1 << 1,
417         ANS2 = 1 << 2,
418         ANS3 = 1 << 3,
419         ANS4 = 1 << 4,
420         ANS5 = 1 << 5,
421         ANS6 = 1 << 6,
422         ANS7 = 1 << 7
423     };
424 
425     ANSEL(Processor *pCpu, const char *pName, const char *pDesc);
426 
427     void setAdcon1(ADCON1 *new_adcon1);
setAnselh(ANSEL_H * new_anselh)428     void setAnselh(ANSEL_H *new_anselh)
429     {
430         anselh = new_anselh;
431     }
432     void put(unsigned int new_val);
setValidBits(unsigned int mask)433     void setValidBits(unsigned int mask)
434     {
435         valid_bits = mask;
436     }
437 
438 private:
439     ADCON1 *adcon1 = nullptr;
440     ANSEL_H *anselh = nullptr;
441     unsigned int valid_bits;
442 };
443 
444 
445 //---------------------------------------------------------
446 // ANSEL_H
447 //
448 
449 class ANSEL_H : public sfr_register
450 {
451 public:
452     enum
453     {
454         ANS8 = 1 << 0,
455         ANS9 = 1 << 1,
456         ANS10 = 1 << 2,
457         ANS11 = 1 << 3,
458         ANS12 = 1 << 4,
459         ANS13 = 1 << 5,
460     };
461 
462     ANSEL_H(Processor *pCpu, const char *pName, const char *pDesc);
463 
464     void setAdcon1(ADCON1 *new_adcon1);
setAnsel(ANSEL * new_ansel)465     void setAnsel(ANSEL *new_ansel)
466     {
467         ansel = new_ansel;
468     }
469     void put(unsigned int new_val);
setValidBits(unsigned int mask)470     void setValidBits(unsigned int mask)
471     {
472         valid_bits = mask;
473     }
474 
475 private:
476     ADCON1 *adcon1 = nullptr;
477     ANSEL *ansel = nullptr;
478     unsigned int valid_bits;
479 };
480 
481 
482 //
483 //	ANSEL_P is an analog select register associated
484 //	with a port.
485 class ANSEL_P : public sfr_register
486 {
487 public:
488     ANSEL_P(Processor *pCpu, const char *pName, const char *pDesc);
489 
490     void setAdcon1(ADCON1 *new_adcon1);
491     void setAnsel(ANSEL_P *new_ansel);
492     void put(unsigned int new_val);
setValidBits(unsigned int mask)493     void setValidBits(unsigned int mask) { valid_bits = mask; }
config(unsigned int pins,unsigned int first_chan)494     void config(unsigned int pins, unsigned int first_chan)
495     {
496         analog_pins = pins;
497         first_channel = first_chan;
498     }
get_mask()499     unsigned int get_mask() { return cfg_mask; }
500 
501 private:
502     ADCON1 *adcon1 = nullptr;
503     ANSEL_P *ansel = nullptr;
504     unsigned int valid_bits;	// register bit mask
505     unsigned int analog_pins = 0;	// bit map of analog port pins
506     unsigned int first_channel = 0;	// channel number for LSB of analog_pins
507     unsigned int cfg_mask = 0;	// A2D mask this port only
508     std::list<ANSEL_P *> ansel_list;
509 };
510 
511 
512 //---------------------------------------------------------
513 // ADCON0_12F register for 12f675 A2D
514 //
515 
516 class ADCON0_12F : public ADCON0
517 {
518 public:
519 
520     enum
521     {
522         ADON = 1 << 0,
523         GO   = 1 << 1,
524         CHS0 = 1 << 2,
525         CHS1 = 1 << 3,
526         CHS2 = 1 << 4,
527         VCFG = 1 << 6,
528         ADFM = 1 << 7
529     };
530     void put(unsigned int new_value);
get_ADFM()531     virtual bool get_ADFM()
532     {
533         return (value.get() & ADFM);
534     }
set_Tad(unsigned int _tad)535     virtual void set_Tad(unsigned int _tad)
536     {
537         Tad = _tad;
538     }
539     ADCON0_12F(Processor *pCpu, const char *pName, const char *pDesc);
540 
541 private:
542     AD_IN_SignalControl ad_pin_input;
543 };
544 
545 
546 //---------------------------------------------------------
547 // ADCON0_32X register for 10f320 A2D
548 //
549 
550 class ADCON0_32X : public ADCON0
551 {
552 public:
553 
554     enum
555     {
556         ADON = 1 << 0,
557         GO   = 1 << 1,
558         CHS0 = 1 << 2,
559         CHS1 = 1 << 3,
560         CHS2 = 1 << 4,
561         ADCS0 = 1 << 5,
562         ADCS1 = 1 << 6,
563         ADCS2 = 1 << 7,
564     };
565     void put(unsigned int new_value);
566 
567     ADCON0_32X(Processor *pCpu, const char *pName, const char *pDesc);
568 
569 private:
570     AD_IN_SignalControl ad_pin_input;
571 };
572 
573 
574 //---------------------------------------------------------
575 // ANSEL_12F
576 //
577 
578 class ANSEL_12F : public sfr_register
579 {
580 public:
581     enum
582     {
583         ANS0 = 1 << 0,
584         ANS1 = 1 << 1,
585         ANS2 = 1 << 2,
586         ANS3 = 1 << 3,
587         ADCS0 = 1 << 4,
588         ADCS1 = 1 << 5,
589         ADCS2 = 1 << 6
590     };
591 
592     ANSEL_12F(Processor *pCpu, const char *pName, const char *pDesc);
593 
setAdcon0(ADCON0_12F * new_adcon0)594     void setAdcon0(ADCON0_12F *new_adcon0)
595     {
596         adcon0 = new_adcon0;
597     }
setAdcon1(ADCON1 * new_adcon1)598     void setAdcon1(ADCON1 *new_adcon1)
599     {
600         adcon1 = new_adcon1;
601     }
602     void put(unsigned int new_val);
603     void set_tad(unsigned int);
604 
605 private:
606     ADCON1 *adcon1 = nullptr;
607     ADCON0_12F *adcon0 = nullptr;
608 };
609 
610 
611 // set voltage from stimulus
612 class a2d_stimulus : public stimulus
613 {
614 public:
615     a2d_stimulus(ADCON1 *arg, int chan, const char *n = nullptr,
616                  double _Vth = 0.0, double _Zth = 1e12
617                 );
618 
619     ADCON1 *_adcon1;
620     int	   channel;
621 
622     virtual void   set_nodeVoltage(double v);
623 };
624 
625 
626 //---------------------------------------------------------
627 // FVRCON register for Fixed Voltage Reference
628 //
629 
630 
631 class FVRCON : public sfr_register
632 {
633 public:
634 
635     enum
636     {
637         ADFVR0 	= 1 << 0,
638         ADFVR1 	= 1 << 1,
639         CDAFVR0 = 1 << 2,
640         CDAFVR1 = 1 << 3,
641         TSRNG	= 1 << 4,
642         TSEN	= 1 << 5,
643         FVRRDY	= 1 << 6,
644         FVREN	= 1 << 7,
645     };
646     FVRCON(Processor *, const char *pName, const char *pDesc = nullptr, unsigned int bitMask = 0xff, unsigned int alwaysOne = 0);
647 
648     virtual void put(unsigned int new_value);
649     virtual void put_value(unsigned int new_value);
set_adcon1(ADCON1 * _adcon1)650     void set_adcon1(ADCON1 *_adcon1)
651     {
652         adcon1 = _adcon1;
653     }
set_cmModule(ComparatorModule2 * _cmModule)654     void set_cmModule(ComparatorModule2 *_cmModule)
655     {
656         cmModule = _cmModule;
657     }
set_daccon0(DACCON0 * _daccon0)658     void set_daccon0(DACCON0 *_daccon0)
659     {
660         daccon0_list.push_back(_daccon0);
661     }
set_cpscon0(CPSCON0 * _cpscon0)662     void set_cpscon0(CPSCON0 *_cpscon0)
663     {
664         cpscon0 = _cpscon0;
665     }
set_VTemp_AD_chan(unsigned int _chan)666     void set_VTemp_AD_chan(unsigned int _chan)
667     {
668         VTemp_AD_chan = _chan;
669     }
set_FVRAD_AD_chan(unsigned int _chan)670     void set_FVRAD_AD_chan(unsigned int _chan)
671     {
672         FVRAD_AD_chan = _chan;
673     }
674 
675 private:
676     double compute_VTemp(unsigned int);	//Voltage of core temperature setting
677     double compute_FVR_AD(unsigned int);	//Voltage reference for ADC
678     double compute_FVR_CDA(unsigned int);	//Voltage reference for Comparators, DAC, CPS
679     ADCON1 *adcon1 = nullptr;
680     DACCON0 *daccon0 = nullptr;
681     std::vector<DACCON0 *> daccon0_list;
682     ComparatorModule2 *cmModule = nullptr;
683     CPSCON0 *cpscon0 = nullptr;
684     unsigned int VTemp_AD_chan = 0;
685     unsigned int FVRAD_AD_chan = 0;
686     unsigned int mask_writable;
687     unsigned int always_one;	// bits in register that are always 1
688 };
689 
690 
691 //
692 //  DAC module
693 //
694 
695 class DACCON0 : public sfr_register
696 {
697 public:
698     enum
699     {
700         DACNSS  = (1 << 0),	// Negative source select bit (18f26k22)
701         DACPSS0	= (1 << 2),
702         DACPSS1	= (1 << 3),
703         DACOE2	= (1 << 4),
704         DACOE	= (1 << 5),
705         DACLPS  = (1 << 6),
706         DACEN	= (1 << 7),
707     };
708 
709     DACCON0(Processor *, const char *pName, const char *pDesc = nullptr, unsigned int bitMask = 0xe6, unsigned int bit_res = 32);
710 
711     virtual void put(unsigned int new_value);
712     virtual void put_value(unsigned int new_value);
set_adcon1(ADCON1 * _adcon1)713     virtual void set_adcon1(ADCON1 *_adcon1)
714     {
715         adcon1 = _adcon1;
716     }
set_cpscon0(CPSCON0 * _cpscon0)717     void set_cpscon0(CPSCON0 *_cpscon0)
718     {
719         cpscon0 = _cpscon0;
720     }
set_cmModule(ComparatorModule2 * _cmModule)721     void set_cmModule(ComparatorModule2 *_cmModule)
722     {
723         cmModule = _cmModule;
724     }
set_FVRCDA_AD_chan(unsigned int _chan)725     void set_FVRCDA_AD_chan(unsigned int _chan)
726     {
727         FVRCDA_AD_chan = _chan;
728     }
729     void set_dcaccon1_reg(unsigned int reg);
set_FVR_CDA_volt(double volt)730     void set_FVR_CDA_volt(double volt)
731     {
732         FVR_CDA_volt = volt;
733     }
734     void setDACOUT(PinModule *pin1, PinModule *pin2 = nullptr)
735     {
736         output_pin[0] = pin1;
737         output_pin[1] = pin2;
738     }
739     virtual void	compute_dac(unsigned int value);
740     virtual double get_Vhigh(unsigned int value);
741 
742 protected:
743     void  set_dacoutpin(bool output_enabled, int chan, double Vout);
744     ADCON1	*adcon1 = nullptr;
745     ComparatorModule2 *cmModule = nullptr;
746     std::vector<ComparatorModule2 *> cmModule_list;
747     CPSCON0	*cpscon0 = nullptr;
748     unsigned int  FVRCDA_AD_chan = 0;
749     unsigned int  bit_mask;
750     unsigned int  bit_resolution;
751     unsigned int  daccon1_reg = 0;
752     double	FVR_CDA_volt = 0.0;
753     bool		Pin_Active[2];
754     double	Vth[2];
755     double	Zth[2];
756     bool		driving[2];
757     PinModule	*output_pin[2];
758     IOPIN *pin = nullptr;
759 };
760 
761 
762 class DACCON1 : public sfr_register
763 {
764 public:
765     DACCON1(Processor *, const char *pName, const char *pDesc = nullptr, unsigned int bitMask = 0x1f, DACCON0 *_daccon0 = nullptr);
766 
767     virtual void put(unsigned int new_value);
768     virtual void put_value(unsigned int new_value);
set_daccon0(DACCON0 * _daccon0)769     void set_daccon0(DACCON0 *_daccon0)
770     {
771         daccon0 = _daccon0;
772     }
773 
774 private:
775     unsigned int bit_mask;
776     DACCON0	*daccon0;
777 };
778 
779 
780 // Differential input and trigger conversion start
781 class ADCON2_DIF : public sfr_register, public TriggerObject
782 {
783 public:
784 
785     enum
786     {
787         CHSNS0   = 1 << 0,
788         CHSNS1   = 1 << 1,
789         CHSNS2   = 1 << 2,
790         CHSNS3   = 1 << 3,
791         TRIGSEL0 = 1 << 4,
792         TRIGSEL1 = 1 << 5,
793         TRIGSEL2 = 1 << 6,
794         TRIGSEL3 = 1 << 7,
795     };
796 
797     ADCON2_DIF(Processor *pCpu, const char *pName, const char *pDesc);
798 };
799 
800 
801 #ifdef RRR
802 // A2D up to 32 channels
803 class ADCON0_32 : public ADCON0
804 {
805     enum
806     {
807         ADON = 1 << 0,
808         GO   = 1 << 1,
809         CHS0 = 1 << 2,
810         CHS1 = 1 << 3,
811         CHS2 = 1 << 4,
812         CHS3 = 1 << 5,
813         CHS4 = 1 << 6,
814     };
815 
816 public:
817     ADCON0_32(Processor *pCpu, const char *pName, const char *pDesc);
818     virtual void put(unsigned int new_value);
819     virtual void put_conversion();
820 };
821 
822 
823 #endif //RRR
824 //
825 //
826 // Trigger conversion start (16f1503)
827 class ADCON2_TRIG : public sfr_register
828 {
829 public:
830 
831     enum
832     {
833         TRIGSEL0 = 1 << 4,
834         TRIGSEL1 = 1 << 5,
835         TRIGSEL2 = 1 << 6,
836         TRIGSEL3 = 1 << 7,
837     };
838 
839     ADCON2_TRIG(Processor *pCpu, const char *pName, const char *pDesc);
840 
841     virtual void put(unsigned int new_value);
setValidBits(unsigned int mask)842     void setValidBits(unsigned int mask)
843     {
844         valid_bits = mask;
845     }
setAdcon0(ADCON0 * _adcon0)846     void setAdcon0(ADCON0 *_adcon0)
847     {
848         m_adcon0 = _adcon0;
849     }
850     void setCMxsync(unsigned int cm, bool output);
851     void t0_overflow();
852 
853 private:
854     unsigned int 	valid_bits;
855     bool 		CMxsync[4];
856     ADCON0	*m_adcon0 = nullptr;
857 };
858 
859 
860 #endif // __A2DCONVERTER_H__
861