00001 /* 00002 **************************************************************************** 00003 * 00004 * simulavr - A simulator for the Atmel AVR family of microcontrollers. 00005 * Copyright (C) 2001, 2002, 2003 Klaus Rudolph 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 * 00021 **************************************************************************** 00022 * 00023 * $Id$ 00024 */ 00025 00026 #include <limits.h> // for INT_MAX 00027 00028 #include "pin.h" 00029 #include "net.h" 00030 00031 enum { 00033 00042 TRISTATE_ANALOG_VALUE = (INT_MAX / 2) + 1 00043 }; 00044 00045 int Pin::GetAnalog(void) const { 00046 switch (outState) { 00047 case ANALOG: 00048 return analogValue; //reflext that we are self outputting an analog value 00049 00050 case HIGH: 00051 case PULLUP: 00052 return INT_MAX; 00053 00054 case TRISTATE: //if we are input! we read the analog value 00055 return analogValue; 00056 00057 case LOW: 00058 case PULLDOWN: 00059 return 0; 00060 00061 default: 00062 return 0; 00063 } 00064 } 00065 00066 void Pin::RegisterCallback(HasPinNotifyFunction *h) { 00067 notifyList.push_back(h); 00068 } 00069 00070 void Pin::SetInState(const Pin &p) { 00071 analogValue = p.analogValue; 00072 00073 if(pinOfPort != 0) { 00074 if(p) { //is (bool)(Pin) -> is LOW or HIGH for the pin 00075 *pinOfPort |= mask; 00076 } else { 00077 *pinOfPort &= 0xff - mask; 00078 } 00079 } 00080 00081 std::vector<HasPinNotifyFunction*>::iterator ii; 00082 std::vector<HasPinNotifyFunction*>::iterator ee = notifyList.end(); 00083 00084 for(ii = notifyList.begin(); ii != ee; ii++) { 00085 (*ii)->PinStateHasChanged(this); 00086 } 00087 } 00088 00089 bool Pin::CalcPin(void) { 00090 if(connectedTo == NULL) { 00091 // no net connected, transfer the output to own input 00092 SetInState(*this); 00093 return (bool)*this; 00094 } else { 00095 return connectedTo->CalcNet(); 00096 } 00097 } 00098 00099 Pin::Pin(T_Pinstate ps) { 00100 pinOfPort = 0; 00101 connectedTo = NULL; 00102 00103 outState = ps; 00104 00105 // initialisation of analog value 00106 switch (ps) { 00107 case HIGH: 00108 case PULLUP: 00109 analogValue = INT_MAX; 00110 break; 00111 00112 case LOW: 00113 case PULLDOWN: 00114 analogValue = 0; 00115 break; 00116 00117 case TRISTATE: 00118 analogValue = TRISTATE_ANALOG_VALUE; 00119 break; 00120 00121 default: 00122 analogValue = 0; 00123 } 00124 } 00125 00126 Pin::Pin() { 00127 pinOfPort = 0; 00128 connectedTo = NULL; 00129 00130 outState = TRISTATE; 00131 analogValue = TRISTATE_ANALOG_VALUE; 00132 } 00133 00134 Pin::~Pin() { 00135 // unregister myself on Net instance 00136 UnRegisterNet(connectedTo); 00137 } 00138 00139 Pin::Pin( unsigned char *parentPin, unsigned char _mask) { 00140 pinOfPort = parentPin; 00141 mask = _mask; 00142 connectedTo = NULL; 00143 00144 outState = TRISTATE; 00145 analogValue = TRISTATE_ANALOG_VALUE; 00146 } 00147 00148 Pin::Pin(const Pin& p) { 00149 pinOfPort = 0; // don't take over HWPort connection! 00150 connectedTo = NULL; // don't take over Net instance! 00151 00152 outState = p.outState; 00153 analogValue = p.analogValue; 00154 } 00155 00156 void Pin::RegisterNet(Net *n) { 00157 UnRegisterNet(connectedTo); // unregister old Net instance, if exists 00158 connectedTo = n; // register new Net instance 00159 } 00160 00161 void Pin::UnRegisterNet(Net *n) { 00162 if(connectedTo == n && connectedTo != NULL) 00163 connectedTo->Delete(this); 00164 connectedTo = NULL; 00165 } 00166 00167 Pin::operator char() const { 00168 switch(outState) { 00169 case SHORTED: return 'S'; 00170 case HIGH: return 'H'; 00171 case PULLUP: return 'h'; 00172 case TRISTATE: return 't'; 00173 case PULLDOWN: return 'l'; 00174 case LOW: return 'L'; 00175 case ANALOG: return 'a'; 00176 case ANALOG_SHORTED: return 'A'; 00177 } 00178 return 'S'; //only default, should never be reached 00179 } 00180 00181 Pin::operator bool() const { 00182 if((outState==HIGH) || (outState==PULLUP)) 00183 return true; 00184 00185 //maybe for TRISTATE not handled complete in simulavr... TODO 00186 if((outState==ANALOG) || (outState==TRISTATE)) { 00187 if(analogValue > (INT_MAX / 2)) 00188 return true; 00189 else 00190 return false; 00191 } 00192 00193 return false; 00194 } 00195 00196 Pin& Pin::operator= (char c) { 00197 switch(c) { 00198 case 'S': 00199 outState = SHORTED; 00200 analogValue = 0; 00201 break; 00202 00203 case 'H': 00204 outState = HIGH; 00205 analogValue = INT_MAX; 00206 break; 00207 00208 case 'h': 00209 outState = PULLUP; 00210 analogValue = INT_MAX; 00211 break; 00212 00213 case 't': 00214 outState = TRISTATE; 00215 analogValue = TRISTATE_ANALOG_VALUE; 00216 break; 00217 00218 case 'l': 00219 outState = PULLDOWN; 00220 analogValue = 0; 00221 break; 00222 00223 case 'L': 00224 outState = LOW; 00225 analogValue = 0; 00226 break; 00227 00228 case 'a': 00229 outState = ANALOG; 00230 analogValue = 0; 00231 break; 00232 00233 case 'A': 00234 outState = ANALOG_SHORTED; 00235 analogValue = 0; 00236 break; 00237 } 00238 00239 CalcPin(); 00240 00241 return *this; 00242 } 00243 00244 Pin& Pin::SetAnalog(int value) { 00245 //outState = ANALOG; 00246 analogValue = value; 00247 00248 CalcPin(); 00249 00250 return *this; 00251 } 00252 00253 Pin Pin::operator+= (const Pin& p) { 00254 *this = *this + p; 00255 return *this; 00256 } 00257 00258 #ifndef DISABLE_OPENDRAIN 00259 Pin::Pin(const OpenDrain &od) { 00260 bool res = (bool) od; 00261 if(res == 0) { 00262 outState = TRISTATE; 00263 analogValue = TRISTATE_ANALOG_VALUE; 00264 } else { 00265 outState = LOW; 00266 analogValue = 0; 00267 } 00268 } 00269 #endif 00270 00271 Pin Pin::operator+ (const Pin& p) { 00272 if(outState == SHORTED) 00273 return Pin(SHORTED); 00274 if(outState == ANALOG_SHORTED) 00275 return Pin(ANALOG_SHORTED); 00276 if((outState == ANALOG) && (p.outState != TRISTATE)) 00277 return Pin(ANALOG_SHORTED); 00278 switch(p.outState) { 00279 case SHORTED: 00280 return Pin(SHORTED); 00281 break; 00282 00283 case HIGH: 00284 if(outState == LOW) 00285 return Pin(SHORTED); 00286 return Pin(HIGH); 00287 break; 00288 00289 case PULLUP: 00290 if(outState == LOW) 00291 return Pin(LOW); 00292 if(outState == HIGH) 00293 return Pin(HIGH); 00294 if(outState == PULLDOWN) 00295 return Pin(TRISTATE); //any other idea? 00296 return Pin(PULLUP); 00297 break; 00298 00299 case TRISTATE: 00300 //return Pin(outState); 00301 return *this; 00302 break; 00303 00304 case PULLDOWN: 00305 if(outState == LOW) 00306 return Pin(LOW); 00307 if(outState == HIGH) 00308 return Pin(HIGH); 00309 if(outState == PULLUP) 00310 return Pin(TRISTATE); //any other idea? 00311 return Pin(PULLDOWN); 00312 break; 00313 00314 case LOW: 00315 if(outState == HIGH) 00316 return Pin(SHORTED); 00317 return Pin(LOW); 00318 break; 00319 00320 case ANALOG: 00321 if(outState != TRISTATE) 00322 return Pin(ANALOG_SHORTED); 00323 //outstate is TRISTATE and we have an anlog value so return pin ANALOG and value set 00324 return p; 00325 break; 00326 00327 case ANALOG_SHORTED: 00328 return Pin(ANALOG_SHORTED); 00329 00330 } 00331 return Pin(TRISTATE); //never used 00332 } 00333 00334 #ifndef DISABLE_OPENDRAIN 00335 00336 Pin OpenDrain::operator+= (const Pin& p) { 00337 *pin= *this+p; 00338 return *this; 00339 } 00340 00341 Pin OpenDrain::GetPin() { 00342 bool res=(bool) *pin; 00343 if (res==0) return Pin(TRISTATE); 00344 else return Pin(LOW); 00345 } 00346 00347 Pin OpenDrain::operator +(const Pin &p) { 00348 Pin dummy; 00349 bool parent=(bool)*pin; 00350 if (parent==0) dummy=Pin(TRISTATE); //if the result 00351 else dummy=Pin(LOW); 00352 00353 return dummy+p; 00354 } 00355 00356 OpenDrain::operator bool() const 00357 { 00358 return 0; 00359 } 00360 00361 #endif