simulavr  1.1.0
hwacomp.cpp
Go to the documentation of this file.
1 /*
2  ****************************************************************************
3  *
4  * simulavr - A simulator for the Atmel AVR family of microcontrollers.
5  * Copyright (C) 2001, 2002, 2003 Klaus Rudolph
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program 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
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  ****************************************************************************
22  *
23  * $Id$
24  */
25 
26 #include "hwacomp.h"
27 
28 #include "irqsystem.h"
29 #include "hwad.h"
30 #include "hwtimer/hwtimer.h"
31 
33  HWIrqSystem *irqsys,
34  PinAtPort ain0,
35  PinAtPort ain1,
36  unsigned int _irqVec,
37  HWAd *_ad,
38  BasicTimerUnit *_timerA,
39  IOSpecialReg *_sfior,
40  BasicTimerUnit *_timerB,
41  bool _useBG):
42  Hardware(core),
43  TraceValueRegister(core, "ACOMP"),
44  irqSystem(irqsys),
45  pinAin0(ain0),
46  pinAin1(ain1),
47  useBG(_useBG),
48  acme_sfior(false),
49  enabled(true),
50  irqVec(_irqVec),
51  timerA(_timerA),
52  timerB(_timerB),
53  ad(_ad),
54  sfior(_sfior),
55  acsr_reg(this, "ACSR", this, &HWAcomp::GetAcsr, &HWAcomp::SetAcsr)
56 {
57  // just check right assignment of IRQ vector number
59  // register callback for pin changes
60  ain0.GetPin().RegisterCallback(this);
61  ain1.GetPin().RegisterCallback(this);
62  // vcc voltage and bandgap reference voltage
63  v_cc = &(core->v_supply);
64  v_bg = &(core->v_bandgap);
65  // register to timer for input capture source, if available
66  if(timerA != NULL)
68  if(timerB != NULL)
70  // register to ad to get signal changes from ADC multiplexer
71  if(ad != NULL)
72  ad->RegisterNotifyClient(this);
73  // register for SFIOR, if set
74  if(sfior != NULL)
75  sfior->connectSRegClient(this);
76 
77  Reset();
78 }
79 
81  if(ad != NULL)
83 }
84 
86  acsr = 0;
87  enabled = true;
88  acme_sfior = false; // this assumes, that SFIOR register is also reseted
89  if(GetIn0() > GetIn1())
90  acsr |= ACO;
91 }
92 
93 void HWAcomp::SetAcsr(unsigned char val) {
94  unsigned char old = acsr & (ACO|ACI);
95  bool old_acic = (acsr & ACIC) == ACIC;
96  bool old_bg = (acsr & ACBG) == ACBG;
97  if(!useBG)
98  val &= ~ACBG; // delete ACBG bit, if not available
99  // store data
100  acsr = val & ~(ACO|ACI); // mask out new bits
101  acsr |= old; // and restore old bits
102  // if AIN0 source is changed, calculate comparator state
103  bool bg = (acsr & ACBG) == ACBG;
104  if(old_bg != bg)
105  PinStateHasChanged(NULL);
106  if(val & ACI)
107  acsr &= ~ACI; // reset ACI if ACI in val is set to 1
108  enabled = (acsr & ACD) == 0; // disabled, if ACD is 1!
109  // reflect ACIC state to timer, if available
110  bool acic = (acsr & ACIC) == ACIC;
111  if(acic != old_acic) {
112  if(timerA != NULL)
113  timerA->SetACIC(acic);
114  if(timerB != NULL)
115  timerB->SetACIC(acic);
116  }
117  // if interrupt enabled and ACI is asserted, then fire interrupt
118  if(enabled) {
119  if((acsr & ( ACI|ACIE)) == (ACI|ACIE))
120  irqSystem->SetIrqFlag(this, irqVec);
121  else
123  }
124 }
125 
126 float HWAcomp::GetIn0(void) {
127  if(useBG && ((acsr & ACBG) == ACBG))
128  return v_bg->GetRawAnalog();
129  else
131 }
132 
133 float HWAcomp::GetIn1(void) {
134  float vcc = v_cc->GetRawAnalog();
135  if(isSetACME())
136  return ad->GetADMuxValue(vcc);
137  else
138  return pinAin1.GetAnalogValue(vcc);
139 }
140 
142  // get old comparator state and IRQ mode
143  bool old = (acsr & ACO);
144  unsigned char irqmode = acsr & (ACIS1|ACIS0);
145 
146  // if unit is disabled (to save power), do not check state
147  if(!enabled)
148  return;
149 
150  // calculate state
151  if(GetIn0() > GetIn1()) {
152  // set output to high
153  if(old == false) {
154  // rising edge
155  acsr |= ACO;
156  // fire IRQ, if necessary
157  if((irqmode == 0) || (irqmode == (ACIS1|ACIS0))) {
158  acsr |= ACI;
159  if(acsr & ACIE) irqSystem->SetIrqFlag(this, irqVec);
160  }
161  }
162  } else {
163  // set output to low
164  if (old == true) {
165  // falling edge
166  acsr &= ~ACO;
167  // fire IRQ, if necessary
168  if((irqmode == 0) || (irqmode == ACIS1)) {
169  acsr |= ACI;
170  if(acsr & ACIE) irqSystem->SetIrqFlag(this, irqVec);
171  }
172  }
173  }
174 }
175 
177  // just start notify functionality
178  if(isSetACME())
179  PinStateHasChanged(NULL);
180 }
181 
182 void HWAcomp::ClearIrqFlag(unsigned int vector){
183  if (vector == irqVec) {
184  acsr &= ~ACI;
186  }
187 }
188 
189 unsigned char HWAcomp::set_from_reg(const IOSpecialReg* reg, unsigned char nv) {
190  // check, if ACME bit is set
191  acme_sfior = (nv & 0x08) == 0x08;
192  // check comparator state
193  PinStateHasChanged(NULL);
194  return nv;
195 }
196 
197 bool HWAcomp::isSetACME(void) {
198  // ACME feature is only available, if a ADC exists and ADC isn't enabled!
199  if(ad != NULL && !ad->IsADEnabled()) {
200  // check from SFIOR register, if available
201  if(sfior != NULL)
202  return acme_sfior;
203  // or check from ADC unit (there in ADCSRB register)
204  return ad->IsSetACME();
205  } else
206  // otherwise ACME isn't available or not enabled
207  return false;
208 }
Pin & GetPin()
Definition: pinatport.cpp:45
Basic AVR device, contains the core functionality.
Definition: avrdevice.h:66
HWIrqSystem * irqSystem
connection to IRQ controller
Definition: hwacomp.h:49
bool useBG
has ADBG register bit and can switch In0 to bandgap ref
Definition: hwacomp.h:54
void RegisterNotifyClient(AnalogSignalChange *client)
Register analog comparator for notification of multiplexer signal change.
Definition: hwad.h:302
Pin * v_cc
get access to voltage supply level
Definition: hwacomp.h:53
BasicTimerUnit * timerB
connection to timerB for input capture event. NULL, if not available
Definition: hwacomp.h:60
void UnregisterNotifyClient(void)
Unregister client for signal change notification.
Definition: hwad.h:304
float GetIn0(void)
Get analog value for comparator input 0.
Definition: hwacomp.cpp:126
Pin class, handles input and output to external parts.
Definition: pin.h:98
bool enabled
analog comparator is enabled
Definition: hwacomp.h:56
float GetIn1(void)
Get analog value for comparator input 1.
Definition: hwacomp.cpp:133
void SetAcsr(unsigned char val)
Set method for ACSR register.
Definition: hwacomp.cpp:93
unsigned char acsr
ACSR register value.
Definition: hwacomp.h:57
void connectSRegClient(IOSpecialRegClient *c)
Registers a client to this IO register to inform this client on read or write access.
Definition: rwmem.h:429
void PinStateHasChanged(Pin *)
Get informed about input pin change.
Definition: hwacomp.cpp:141
void ClearIrqFlag(unsigned int vec)
Reflect irq processing, reset interrupt source.
Definition: hwacomp.cpp:182
BasicTimerUnit * timerA
connection to timerA for input capture event. NULL, if not available
Definition: hwacomp.h:59
Basic timer unit.
Definition: hwtimer.h:48
void Reset()
Reset the unit.
Definition: hwacomp.cpp:85
Build a register for TraceValue's.
Definition: traceval.h:442
PinAtPort pinAin1
port pin AIN1
Definition: hwacomp.h:51
void SetACIC(bool acic)
reflect ACIC flag to input capture source
Definition: hwtimer.h:88
void SetIrqFlag(Hardware *, unsigned int vector_index)
Definition: irqsystem.cpp:243
bool acme_sfior
ACME flag in SFIOR register is set.
Definition: hwacomp.h:55
unsigned int irqVec
stores the IRQ vector number
Definition: hwacomp.h:58
void RegisterCallback(HasPinNotifyFunction *)
Definition: pin.cpp:60
HWAd * ad
connection to ADC for analog input mux. NULL, if not available
Definition: hwacomp.h:61
unsigned char set_from_reg(const IOSpecialReg *reg, unsigned char nv)
Definition: hwacomp.cpp:189
void RegisterACompForICapture(HWAcomp *acomp)
register analog comparator unit for input capture source
Definition: hwtimer.cpp:573
Pin * v_bg
get access to bandgap reference
Definition: hwacomp.h:52
bool isSetACME(void)
Check, if ACME flag is set (from ADC or SFIOR register)
Definition: hwacomp.cpp:197
Pin v_supply
represents supply voltage level, needed for analog peripherals
Definition: avrdevice.h:112
bool IsADEnabled(void)
Check, if ADC is enabled.
Definition: hwad.h:296
float GetADMuxValue(float vcc)
Get analog value from ADC multiplexer.
Definition: hwad.h:300
Pin v_bandgap
represents bandgap (ref) voltage level, needed for analog peripherals
Definition: avrdevice.h:113
void DebugVerifyInterruptVector(unsigned int vector_index, const Hardware *source)
In datasheets RESET vector is index 1 but we use 0! And not a byte address.
Definition: irqsystem.cpp:297
~HWAcomp()
Definition: hwacomp.cpp:80
IOSpecialReg * sfior
connection to SFIOR register, if necessary. NULL, if not used
Definition: hwacomp.h:62
HWAcomp(AvrDevice *core, HWIrqSystem *irqsys, PinAtPort ain0, PinAtPort ain1, unsigned int irqVec, HWAd *_ad, BasicTimerUnit *_timerA, IOSpecialReg *_sfior=NULL, BasicTimerUnit *_timerB=NULL, bool _useBG=true)
constructor to instantiate a analog comparator peripheral
Definition: hwacomp.cpp:32
void NotifySignalChanged(void)
Definition: hwacomp.cpp:176
bool IsSetACME(void)
Check, if ACME bit is set, return false, if not available.
Definition: hwad.h:298
void ClearIrqFlag(unsigned int vector_index)
Definition: irqsystem.cpp:258
Definition: hwad.h:204
PinAtPort pinAin0
port pin AIN0
Definition: hwacomp.h:50
float GetRawAnalog(void) const
get back raw analog value (just variable content!)
Definition: pin.h:149
float GetAnalogValue(float vcc)
Get pin analog voltage level.
Definition: pinatport.cpp:55
Analog comparator peripheral.
Definition: hwacomp.h:42