00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <iostream>
00027 using namespace std;
00028
00029 #include "hwport.h"
00030 #include "avrdevice.h"
00031 #include "avrerror.h"
00032 #include <assert.h>
00033
00034 HWPort::HWPort(AvrDevice *core, const string &name, bool portToggle, int size):
00035 Hardware(core),
00036 TraceValueRegister(core, "PORT" + name),
00037 myName(name),
00038 portToggleFeature(portToggle),
00039 port_reg(this, "PORT",
00040 this, &HWPort::GetPort, &HWPort::SetPort),
00041 pin_reg(this, "PIN",
00042 this, &HWPort::GetPin, &HWPort::SetPin),
00043 ddr_reg(this, "DDR",
00044 this, &HWPort::GetDdr, &HWPort::SetDdr)
00045 {
00046 if(size > 8 || size < 1)
00047 size = 8;
00048 portSize = size;
00049 portMask = (unsigned char)((1 << size) - 1);
00050
00051 Reset();
00052
00053 for(int tt = 0; tt < portSize; tt++) {
00054 string dummy = name + (char)('0' + tt);
00055 core->RegisterPin(dummy, &p[tt]);
00056 p[tt].mask = 1 << tt;
00057 p[tt].pinOfPort= &pin;
00058 }
00059 }
00060
00061 void HWPort::Reset(void) {
00062 port = 0;
00063 pin = 0;
00064 ddr = 0;
00065
00066 alternateDdr = 0;
00067 useAlternateDdr = 0;
00068
00069 alternatePort = 0;
00070 useAlternatePort = 0;
00071
00072 useAlternatePortIfDdrSet = 0;
00073
00074 CalcOutputs();
00075 }
00076
00077 Pin& HWPort::GetPin(unsigned char pinNo) {
00078 return p[pinNo];
00079 }
00080
00081 void HWPort::CalcPin(void) {
00082
00083 pin = 0;
00084 for(int tt = 0; tt < portSize; tt++) {
00085 if(p[tt].CalcPin()) pin |= (1 << tt);
00086 }
00087 }
00088
00089 void HWPort::CalcOutputs(void) {
00090 for(int actualBitNo = 0; actualBitNo < portSize; actualBitNo++) {
00091 unsigned char actualBit = 1 << actualBitNo;
00092 unsigned char workingPort = 0;
00093 unsigned char workingDdr = 0;
00094
00095 if(useAlternatePortIfDdrSet & actualBit) {
00096 if(ddr & actualBit) {
00097 workingPort |= alternatePort & actualBit;
00098 workingDdr |= actualBit;
00099 } else
00100 workingPort |= port & actualBit;
00101 } else {
00102 if(useAlternateDdr & actualBit)
00103 workingDdr |= alternateDdr & actualBit;
00104 else
00105 workingDdr |= ddr & actualBit;
00106
00107 if(useAlternatePort & actualBit)
00108 workingPort |= alternatePort & actualBit;
00109 else
00110 workingPort |= port & actualBit;
00111 }
00112
00113 if(workingDdr & actualBit) {
00114 if(workingPort & actualBit)
00115 p[actualBitNo].outState = Pin::HIGH;
00116 else
00117 p[actualBitNo].outState = Pin::LOW;
00118 } else {
00119 if(workingPort & actualBit)
00120 p[actualBitNo].outState = Pin::PULLUP;
00121 else
00122 p[actualBitNo].outState = Pin::TRISTATE;
00123 }
00124 }
00125
00126 CalcPin();
00127 }
00128
00129 string HWPort::GetPortString(void) {
00130 string dummy;
00131 dummy.resize(portSize);
00132 assert(portSize < sizeof(p)/sizeof(p[0]));
00133 for(int tt = 0; tt < portSize; tt++)
00134 dummy[portSize - 1 - tt] = p[tt];
00135
00136 return dummy;
00137 }
00138
00139 void HWPort::SetPin(unsigned char val) {
00140 if(portToggleFeature) {
00141 port ^= val;
00142 CalcOutputs();
00143 } else
00144 avr_warning("Writing of 'PORT%s.PIN' (with %d) is not supported.", myName.c_str(), val);
00145 }
00146