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 <limits.h>
00027 #include "hwad.h"
00028
00029 #include "irqsystem.h"
00030 #include "avrerror.h"
00031
00032 #define MUX0 0x01
00033 #define MUX1 0x02
00034 #define MUX2 0x04
00035 #define ADCBG 0x40 //currently not supported
00036
00037 using namespace std;
00038
00039 HWAdmux::HWAdmux(
00040 AvrDevice* c,
00041 Pin* _ad0,
00042 Pin* _ad1,
00043 Pin* _ad2,
00044 Pin* _ad3,
00045 Pin* _ad4,
00046 Pin* _ad5,
00047 Pin* _ad6,
00048 Pin* _ad7
00049 ) :
00050 Hardware(c),
00051 TraceValueRegister(c, "ADMUX"),
00052 core(c),
00053 admux_reg(this, "ADMUX", this, &HWAdmux::GetAdmux, &HWAdmux::SetAdmux)
00054 {
00055 ad[0]=_ad0;
00056 ad[1]=_ad1;
00057 ad[2]=_ad2;
00058 ad[3]=_ad3;
00059 ad[4]=_ad4;
00060 ad[5]=_ad5;
00061 ad[6]=_ad6;
00062 ad[7]=_ad7;
00063
00064 Reset();
00065 }
00066
00067 void HWAdmux::Reset() {
00068 admux=0;
00069 }
00070
00071 void HWAdmux::SetAdmux(unsigned char val) {
00072 admux=val;
00073 }
00074
00075 unsigned char HWAdmux::GetAdmux() {
00076 return admux;
00077 }
00078
00079 int HWAdmux::GetMuxOutput() {
00080
00081 int pin = admux&(MUX2|MUX1|MUX0);
00082 Pin* p = ad[pin];
00083 if(!p){
00084 cerr << "HWAdmux::GetMuxOutput null pin on " << pin << endl;
00085 return 0;
00086 }
00087 return p->GetAnalog();
00088 }
00089
00090
00091 #define ADEN 0x80
00092 #define ADSC 0x40
00093 #define ADFR 0x20
00094 #define ADIF 0x10
00095 #define ADIE 0x08
00096 #define ADPS2 0x04
00097 #define ADPS1 0x02
00098 #define ADPS0 0x01
00099 #define ADLAR (1<<5)
00100
00101 HWAd::HWAd( AvrDevice *c, HWAdmux *a, HWIrqSystem *i, Pin& _aref, unsigned int iv) :
00102 Hardware(c),
00103 TraceValueRegister(c, "AD"),
00104 core(c),
00105 admux(a),
00106 irqSystem(i),
00107 aref(_aref),
00108 irqVec(iv),
00109 adch_reg(this, "ADCH", this, &HWAd::GetAdch, 0),
00110 adcl_reg(this, "ADCL", this, &HWAd::GetAdcl, 0),
00111 adcsr_reg(this, "ADCSR", this, &HWAd::GetAdcsr, &HWAd::SetAdcsr)
00112 {
00113 irqSystem->DebugVerifyInterruptVector(irqVec, this);
00114 core->AddToCycleList(this);
00115
00116
00117 Reset();
00118 }
00119
00120 void HWAd::Reset() {
00121 adcsr=0;
00122 state=IDLE;
00123 prescaler=0;
00124 clk=0;
00125 usedBefore=false;
00126 adchLocked=false;
00127 }
00128
00129 unsigned char HWAd::GetAdch() { adchLocked=false; return adch; }
00130 unsigned char HWAd::GetAdcl() { adchLocked=true; return adcl; }
00131 unsigned char HWAd::GetAdcsr() {
00132 return adcsr;
00133 }
00134
00135 void HWAd::SetAdcsr(unsigned char val) {
00136 unsigned char old=adcsr&(ADIF|ADSC);
00137 if (val & ADIF ) old&= ~ADIF;
00138 adcsr= old|(val& (~(ADIF)));
00139
00140 if ((adcsr&(ADIE|ADIF))==(ADIE|ADIF)) {
00141 irqSystem->SetIrqFlag(this, irqVec);
00142 } else {
00143 irqSystem->ClearIrqFlag(irqVec);
00144 }
00145 }
00146
00147
00148 void HWAd::ClearIrqFlag(unsigned int vector){
00149 if (vector==irqVec) {
00150 adcsr&=~ADIF;
00151 irqSystem->ClearIrqFlag( irqVec);
00152 }
00153 }
00154
00155
00156 unsigned int HWAd::CpuCycle() {
00157 if (adcsr&ADEN) {
00158 prescaler++;
00159 if (prescaler>=128) prescaler=0;
00160
00161
00162
00163
00164
00165 unsigned char oldClk=clk;
00166
00167 switch ( adcsr & ( ADPS2|ADPS1|ADPS0)) {
00168 case 0:
00169 case ADPS0:
00170 if ((prescaler%1)==0) clk++;
00171 break;
00172
00173 case ADPS1:
00174 if ((prescaler%2)==0) clk++;
00175 break;
00176
00177 case (ADPS1|ADPS0):
00178 if ((prescaler%4)==0) clk++;
00179 break;
00180
00181 case (ADPS2):
00182 if ((prescaler%8)==0) clk++;
00183 break;
00184
00185 case (ADPS2|ADPS0):
00186 if ((prescaler%16)==0) clk++;
00187 break;
00188
00189 case (ADPS2|ADPS1):
00190 if ((prescaler%32)==0) clk++;
00191 break;
00192
00193 case (ADPS2|ADPS1|ADPS0):
00194 if ((prescaler%64)==0) clk++;
00195 break;
00196
00197 }
00198
00199 if (clk!=oldClk) {
00200
00201 switch (state) {
00202 case IDLE:
00203 clk=0;
00204 if (adcsr&ADSC) {
00205 if (usedBefore) {
00206 state=RUNNING;
00207 } else {
00208 state=INIT;
00209 }
00210 }
00211 break;
00212
00213 case INIT:
00214
00215 if (clk==13*2) {
00216 state = RUNNING;
00217 clk=1*2;
00218
00219
00220
00221 usedBefore=true;
00222 }
00223 break;
00224
00225 case RUNNING:
00226 if (clk==1.5*2) {
00227 adSample= admux->GetMuxOutput();
00228 int adref= aref.GetAnalog();
00229 if (adSample>adref) adSample=adref;
00230 if (adref==0) {
00231 adSample=INT_MAX;
00232 } else {
00233 adSample= (int)((float)adSample/(float)adref*INT_MAX);
00234 }
00235
00236 } else if ( clk== 13*2) {
00237
00238 if(admux->GetAdmux() & ADLAR){
00239 adSample <<= (16-10);
00240 }
00241
00242 if (adchLocked) {
00243 if (core->trace_on) {
00244 traceOut<< "AD-Result lost adch is locked!" << endl;
00245 } else {
00246 cerr << "AD-Result lost adch is locked!" << endl;
00247 }
00248 } else {
00249 adch=adSample>>8;
00250 }
00251 adcl=adSample&0xff;
00252 adcsr|=ADIF;
00253 if ((adcsr&(ADIE|ADIF))==(ADIE|ADIF)) {
00254 irqSystem->SetIrqFlag(this, irqVec);
00255 }
00256
00257 if (adcsr& ADFR) {
00258 clk=0;
00259 } else {
00260 adcsr&=~ADSC;
00261 }
00262 } else if (clk==14*2) {
00263 clk=0;
00264 state = IDLE;
00265 }
00266 break;
00267
00268 }
00269 }
00270
00271 } else {
00272 prescaler=0;
00273 clk=0;
00274 }
00275
00276 return 0;
00277 }
00278