simulavr  1.1.0
pin.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 <limits.h> // for INT_MAX
27 #include <assert.h>
28 
29 #include "pin.h"
30 #include "net.h"
31 #include "rwmem.h"
32 
33 float AnalogValue::getA(float vcc) {
34  switch(dState) {
35  case ST_GND:
36  return 0.0;
37  case ST_FLOATING:
38  return REL_FLOATING_POTENTIAL * vcc;
39  case ST_VCC:
40  return vcc;
41  case ST_ANALOG:
42  // check for valid value range
43  if(aValue < 0.0)
44  return 0.0;
45  if(aValue > vcc)
46  return vcc;
47  return aValue;
48  }
49 
50  //remove warning only:
51  return 0;
52 }
53 
54 int Pin::GetAnalog(void) {
55  float vcc = 5.0; // assume a fixed Vcc with 5.0V!
56 
57  return (int)(((double)GetAnalogValue(vcc) * INT_MAX) / (double)vcc);
58 }
59 
61  notifyList.push_back(h);
62 }
63 
64 void Pin::SetInState(const Pin &p) {
65  analogVal = p.analogVal;
66 
67  if(pinOfPort != nullptr) {
68  if(p) { //is (bool)(Pin) -> is LOW or HIGH for the pin
69  *pinOfPort |= mask;
70  } else {
71  *pinOfPort &= 0xff - mask;
72  }
73  if(pinRegOfPort != nullptr)
74  pinRegOfPort->hardwareChange(*pinOfPort);
75  }
76 
77  std::vector<HasPinNotifyFunction*>::iterator ii;
78  std::vector<HasPinNotifyFunction*>::iterator ee = notifyList.end();
79 
80  for(ii = notifyList.begin(); ii != ee; ii++) {
81  (*ii)->PinStateHasChanged(this);
82  }
83 }
84 
85 bool Pin::CalcPin(void) {
86  if(connectedTo == nullptr) {
87  // no net connected, transfer the output to own input
88  SetInState(*this);
89  return (bool)*this;
90  } else {
91  return connectedTo->CalcNet();
92  }
93 }
94 
96  pinOfPort = nullptr;
97  pinRegOfPort = nullptr;
98  connectedTo = nullptr;
99  mask = 0;
100 
101  outState = ps;
102 
103  // Initialization of analog value
104  switch (ps) {
105  case HIGH:
106  case PULLUP:
107  analogVal.setD(AnalogValue::ST_VCC);
108  break;
109 
110  case LOW:
111  case PULLDOWN:
112  analogVal.setD(AnalogValue::ST_GND);
113  break;
114 
115  case TRISTATE:
116  analogVal.setD(AnalogValue::ST_FLOATING);
117  break;
118 
119  default:
120  analogVal.setD(AnalogValue::ST_GND); // is this right? Which cases use this?
121  break;
122  }
123 }
124 
126  pinOfPort = nullptr;
127  pinRegOfPort = nullptr;
128  connectedTo = nullptr;
129  mask = 0;
130 
131  outState = TRISTATE;
132 }
133 
135  // unregister myself on Net instance
136  UnRegisterNet(connectedTo);
137 }
138 
139 Pin::Pin(unsigned char *parentPin, unsigned char _mask) {
140  pinOfPort = parentPin;
141  pinRegOfPort = nullptr;
142  mask = _mask;
143  connectedTo = nullptr;
144 
145  outState = TRISTATE;
146 }
147 
148 Pin::Pin(const Pin& p) {
149  pinOfPort = nullptr; // don't take over HWPort connection!
150  pinRegOfPort = nullptr;
151  connectedTo = nullptr; // don't take over Net instance!
152  mask = 0;
153 
154  outState = p.outState;
155  analogVal = p.analogVal;
156 }
157 
158 Pin::Pin(float analog) {
159  mask = 0;
160  pinOfPort = nullptr;
161  pinRegOfPort = nullptr;
162  connectedTo = nullptr;
163  analogVal.setA(analog);
164 
165  outState = ANALOG;
166 }
167 
169  UnRegisterNet(connectedTo); // unregister old Net instance, if exists
170  connectedTo = n; // register new Net instance
171 }
172 
174  if(connectedTo == n && connectedTo != nullptr)
175  connectedTo->Delete(this);
176  connectedTo = nullptr;
177 }
178 
179 Pin::operator char() const {
180  switch(outState) {
181  case SHORTED: return 'S';
182  case HIGH: return 'H';
183  case PULLUP: return 'h';
184  case TRISTATE: return 't';
185  case PULLDOWN: return 'l';
186  case LOW: return 'L';
187  case ANALOG: return 'a';
188  case ANALOG_SHORTED: return 'A';
189  }
190  return 'S'; // only default, should never be reached
191 }
192 
193 Pin::operator bool() const {
194  if(outState==HIGH)
195  return true;
196 
197  // maybe for TRISTATE not handled complete in simulavr... TODO
198  if((outState==TRISTATE) || (outState==PULLUP)) {
199  // fix, because in SetInState the output state of connected pin is only transfered to analogVal!
200  if((analogVal.getD() == AnalogValue::ST_VCC) || (analogVal.getD() == AnalogValue::ST_FLOATING))
201  return true;
202  else if(analogVal.getD() == AnalogValue::ST_GND)
203  return false;
204  else // could this happen?
205  return false;
206  }
207  if(outState==ANALOG) {
208  if(analogVal.analogValid()) // this part of condition isn't really correct, because it depends on Vcc level
209  // and this isn't known here!
210  return true;
211  else
212  // could this happen?
213  return false;
214  }
215 
216  return false;
217 }
218 
220  switch(c) {
221  case 'S':
222  outState = SHORTED;
223  analogVal.setD(AnalogValue::ST_GND);
224  break;
225 
226  case 'H':
227  outState = HIGH;
228  analogVal.setD(AnalogValue::ST_VCC);
229  break;
230 
231  case 'h':
232  outState = PULLUP;
233  analogVal.setD(AnalogValue::ST_VCC);
234  break;
235 
236  case 't':
237  outState = TRISTATE;
238  analogVal.setD(AnalogValue::ST_FLOATING);
239  break;
240 
241  case 'l':
242  outState = PULLDOWN;
243  analogVal.setD(AnalogValue::ST_GND);
244  break;
245 
246  case 'L':
247  outState = LOW;
248  analogVal.setD(AnalogValue::ST_GND);
249  break;
250 
251  case 'a':
252  outState = ANALOG;
253  analogVal.setD(AnalogValue::ST_FLOATING); // set to floating state, analog value, but not set
254  break;
255 
256  case 'A':
257  outState = ANALOG_SHORTED;
258  analogVal.setD(AnalogValue::ST_GND);
259  break;
260  }
261 
262  CalcPin();
263 
264  return *this;
265 }
266 
267 Pin& Pin::SetAnalogValue(float value) {
268  analogVal.setA(value);
269 
270  CalcPin();
271 
272  return *this;
273 }
274 
276  *this = *this + p;
277  return *this;
278 }
279 
281  if(outState == SHORTED)
282  return Pin(SHORTED);
283  if(outState == ANALOG_SHORTED)
284  return Pin(ANALOG_SHORTED);
285  if((outState == ANALOG) && (p.outState != TRISTATE))
286  return Pin(ANALOG_SHORTED);
287  switch(p.outState) {
288  case SHORTED:
289  return Pin(SHORTED);
290  break;
291 
292  case HIGH:
293  if(outState == LOW)
294  return Pin(SHORTED);
295  return Pin(HIGH);
296  break;
297 
298  case PULLUP:
299  if(outState == LOW)
300  return Pin(LOW);
301  if(outState == HIGH)
302  return Pin(HIGH);
303  if(outState == PULLDOWN)
304  return Pin(TRISTATE); // any other idea?
305  return Pin(PULLUP);
306  break;
307 
308  case TRISTATE:
309  return *this;
310  break;
311 
312  case PULLDOWN:
313  if(outState == LOW)
314  return Pin(LOW);
315  if(outState == HIGH)
316  return Pin(HIGH);
317  if(outState == PULLUP)
318  return Pin(TRISTATE); // any other idea?
319  return Pin(PULLDOWN);
320  break;
321 
322  case LOW:
323  if(outState == HIGH)
324  return Pin(SHORTED);
325  return Pin(LOW);
326  break;
327 
328  case ANALOG:
329  if(outState != TRISTATE)
330  return Pin(ANALOG_SHORTED);
331  // outState is TRISTATE and we have an analog value so return pin ANALOG and value set
332  return p;
333  break;
334 
335  case ANALOG_SHORTED:
336  return Pin(ANALOG_SHORTED);
337 
338  }
339  return Pin(TRISTATE); // never used
340 }
341 
343  // get back state of output side
344  bool input = (bool)*pin;
345  if(input)
346  return Pin(LOW);
347  else
348  return Pin(TRISTATE);
349 }
350 
352  pin = p;
353 }
354 
356  regCount = 0;
357  outState = TRISTATE;
358 
359  ResetOverride();
360 }
361 
363  // unregister myself on Net instance
364  UnRegisterNet(connectedTo);
365 }
366 
368  DDOE = DDOV = 0;
369  PVOE = PVOV = PVOEwDDR = 0;
370  PUOE = PUOV = 0;
371 }
372 
374  assert(regCount < (sizeof(DDOV) * 8)); // bit count is used!
375  return regCount++;
376 }
377 
378 void PortPin::SetDDOV(bool val, int index) {
379  if(val)
380  DDOV |= 1 << index;
381  else
382  DDOV &= ~(1 << index);
383 }
384 
385 void PortPin::SetDDOE(bool val, int index) {
386  if(val)
387  DDOE |= 1 << index;
388  else
389  DDOE &= ~(1 << index);
390 }
391 
392 void PortPin::SetPVOV(bool val, int index) {
393  if(val)
394  PVOV |= 1 << index;
395  else
396  PVOV &= ~(1 << index);
397 }
398 
399 void PortPin::SetPVOE(bool val, int index) {
400  if(val)
401  PVOE |= 1 << index;
402  else
403  PVOE &= ~(1 << index);
404 }
405 
406 void PortPin::SetPVOE_WithDDR(bool val, int index) {
407  if(val)
408  PVOEwDDR |= 1 << index;
409  else
410  PVOEwDDR &= ~(1 << index);
411 }
412 
413 void PortPin::SetPUOV(bool val, int index) {
414  if(val)
415  PUOV |= 1 << index;
416  else
417  PUOV &= ~(1 << index);
418 }
419 
420 void PortPin::SetPUOE(bool val, int index) {
421  if(val)
422  PUOE |= 1 << index;
423  else
424  PUOE &= ~(1 << index);
425 }
426 
427 bool PortPin::CalcPinOverride(bool ddr, bool port, bool pud) {
428  unsigned char ddov = DDOE & DDOV; // masking values
429  unsigned char pvov = PVOE & PVOV;
430  unsigned char pvovwddr = PVOEwDDR & PVOV;
431  bool resultingDDR = (!DDOE && ddr) || (DDOE && ddov);
432  bool resultingPort = (!(PVOE || PVOEwDDR) && port) || (PVOE && pvov) || (PVOEwDDR && pvovwddr && ddr);
433  bool pu = !pud && !ddr && port;
434  bool resultingPU = (!PUOE && pu) || (PUOE && PUOV);
435 
436  if(resultingDDR) {
437  if(resultingPort)
438  outState = Pin::HIGH;
439  else
440  outState = Pin::LOW;
441  } else {
442  if(resultingPU)
443  outState = Pin::PULLUP;
444  else
445  outState = Pin::TRISTATE;
446  }
447 
448  return CalcPin();
449 }
450 
451 /* EOF */
virtual ~PortPin()
pin destructor, breaks save connection to other pins, if necessary
Definition: pin.cpp:362
int GetAnalog(void)
Get analog value as integer from 0 to INT_MAX (for backward compatibility, will be deprecated later) ...
Definition: pin.cpp:54
virtual ~Pin()
pin destructor, breaks save connection to other pins, if necessary
Definition: pin.cpp:134
PortPin(void)
common constructor, initial output state is tristate
Definition: pin.cpp:355
float getA(float vcc)
calculate real voltage potential, needs value of Vcc potential
Definition: pin.cpp:33
virtual Pin operator+=(const Pin &p)
calculate common state from connected other pin to this pin
Definition: pin.cpp:275
Pin class, handles input and output to external parts.
Definition: pin.h:98
digital state, Vcc potential
Definition: pin.h:64
Pin & SetAnalogValue(float value)
Sets the pin to an real analog value.
Definition: pin.cpp:267
void SetPVOE(bool val, int index=0)
set port override enable
Definition: pin.cpp:399
void SetPVOV(bool val, int index=0)
set port override value
Definition: pin.cpp:392
float aValue
analog value from setA method or constructor (not checked to valid range!)
Definition: pin.h:58
virtual Pin & operator=(char)
set output stage to (digital) state, set value for ANALOG state separately
Definition: pin.cpp:219
virtual Pin operator+(const Pin &p)
calculate common state from 2 connected pins
Definition: pin.cpp:280
int dState
digital state and validity of aValue
Definition: pin.h:57
T_Pinstate
Possible PIN states.
Definition: pin.h:115
digital state, ground potential
Definition: pin.h:62
Definition: pin.h:116
T_Pinstate outState
discrete value of output stage
Definition: pin.h:126
virtual Pin GetPin()
"cast method" to get back a Pin instance
Definition: pin.cpp:342
bool CalcPinOverride(bool ddr, bool port, bool pud)
calculate pin outState with override functionality
Definition: pin.cpp:427
bool CalcPin(void)
Update input values from output values.
Definition: pin.cpp:85
void ResetOverride(void)
reset override states
Definition: pin.cpp:367
valid analog value between ground and Vcc (and included)
Definition: pin.h:65
int RegisterAlternateUse(void)
register an alternate function to pin
Definition: pin.cpp:373
void RegisterCallback(HasPinNotifyFunction *)
Definition: pin.cpp:60
void SetPUOE(bool val, int index=0)
set pullup override enable
Definition: pin.cpp:420
virtual void UnRegisterNet(Net *n)
deletes Net instance registration for pin
Definition: pin.cpp:173
floating potential, not connected or tristate, assumed as FLOATING_POTENTIAL
Definition: pin.h:63
virtual void RegisterNet(Net *n)
registers Net instance on pin
Definition: pin.cpp:168
Pin(void)
common constructor, initial output state is tristate
Definition: pin.cpp:125
virtual void SetInState(const Pin &p)
handles the input value from net
Definition: pin.cpp:64
void SetDDOV(bool val, int index=0)
set data direction override value
Definition: pin.cpp:378
void SetDDOE(bool val, int index=0)
set data direction override enable
Definition: pin.cpp:385
#define REL_FLOATING_POTENTIAL
Definition: pin.h:37
OpenDrain(Pin *p)
Definition: pin.cpp:351
Definition: pin.h:117
void SetPUOV(bool val, int index=0)
set pullup override value
Definition: pin.cpp:413
void SetPVOE_WithDDR(bool val, int index=0)
set port override enable, if DDR is set
Definition: pin.cpp:406
AnalogValue analogVal
"real" analog voltage value
Definition: pin.h:104
Connect Pins to each other and transfers a output change from a pin to input values for all pins...
Definition: net.h:34