00001
00034 #include <ioavr.h>
00035 #include <inavr.h>
00036
00037 #include "structs.h"
00038
00039 #include "main.h"
00040 #include "ADC.h"
00041
00042
00043
00044
00045
00046
00048 ADC_Status_t ADCS;
00049
00050
00072
00073 __eeprom unsigned char VBAT_RANGE = 1;
00074
00075
00076
00077
00078
00113 #pragma vector=ADC_vect
00114 __interrupt void ADC_ISR(void)
00115 {
00116 static unsigned char avgIndex = 0;
00117 unsigned char i, Next, Signed;
00118 signed int temp = 0;
00119
00120 Signed = FALSE;
00121 ADCSRA &= ~(1<<ADEN);
00122
00123
00124
00125
00126 switch (ADCS.MUX){
00127
00128 case 0x01:
00129 ADCS.rawNTC = ADC;
00130 Next=0x02;
00131 break;
00132
00133
00134
00135 case 0x02:
00136 ADCS.rawRID = ADC;
00137 Next=0x03;
00138 break;
00139
00140
00141
00142 case 0x03:
00143
00144 ADCS.VIN = ScaleU(4, (unsigned int)ADC);
00145
00146
00147 if (ADCS.VIN < VIN_MIN) {
00148 ADCS.Mains = FALSE;
00149 } else {
00150 ADCS.Mains = TRUE;
00151 }
00152
00153 Next=0x05;
00154 break;
00155
00156
00157
00158 case 0x05:
00159 ADCS.rawVBAT = ADC;
00160
00161
00162 ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC);
00163 Next=0x17;
00164
00165 break;
00166
00167
00168 case 0x17:
00169
00170
00171
00172
00173 if (ADC > 511) {
00174 ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE,
00175 (1024 - (ADC-ADCS.ADC5_G20_OS)));
00176 } else if (ADC > 0) {
00177 ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS));
00178 } else {
00179 ADCS.IBAT = 0;
00180 }
00181
00182
00183
00184
00185
00186 ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;
00187 for (i = 0; i < 4 ; i++) {
00188 temp += ADCS.discIBAT[i];
00189 }
00190
00191 ADCS.avgIBAT = (temp / 4);
00192
00193 ADCS.Flag = TRUE;
00194 Next=0x01;
00195 Signed = FALSE;
00196 break;
00197
00198
00199 default:
00200 Next=0x01;
00201 break;
00202 }
00203
00204
00205
00206 ADCS.MUX = Next;
00207 ADMUX = (1<<REFS0) + ADCS.MUX;
00208
00209 if (Signed) {
00210 ADCSRB |= (1<<BIN);
00211 } else {
00212 ADCSRB &= ~(1<<BIN);
00213 }
00214
00215
00216
00217 if (!((ADCS.Halt) && (ADCS.Flag))) {
00218 ADCSRA |= (1<<ADEN)|(1<<ADSC);
00219 }
00220 }
00221
00222
00246 unsigned int ScaleU(unsigned char setting, unsigned int data)
00247 {
00248
00249 unsigned int scaled = 0;
00250
00251
00252 if (setting == 3) {
00253 scaled = 29 * data;
00254 scaled += (data >> 2);
00255 scaled += (data >> 4);
00256 } else {
00257
00258 scaled = 39 * data;
00259 scaled += (data >> 4);
00260
00261 if (setting <3) {
00262
00263
00264
00265 scaled = (scaled >> (3-setting));
00266 }
00267 }
00268
00269 return(scaled);
00270 }
00271
00272
00297 unsigned int ScaleI(unsigned char setting, unsigned int data)
00298 {
00299
00300 unsigned int scaled = 0;
00301
00302
00303 if (setting == 3) {
00304 scaled = 21 * data;
00305 scaled -= (data >> 4);
00306 scaled += (data >> 7);
00307 } else {
00308 scaled = 28 * data;
00309 scaled -= (data >> 3);
00310 scaled += (data >> 5);
00311
00312 if (setting <3) {
00313
00314
00315
00316 scaled = (scaled >> (3-setting));
00317 }
00318 }
00319
00320 return(scaled);
00321 }
00322
00323
00330 void ADC_Wait(void)
00331 {
00332
00333 ADCS.Flag = FALSE;
00334 do {
00335 } while (ADCS.Flag == FALSE);
00336
00337
00338 ADCS.Flag = FALSE;
00339 do {
00340 } while (ADCS.Flag == FALSE);
00341 }
00342
00343
00369 void ADC_Init(void)
00370 {
00371 unsigned char i;
00372
00373 __disable_interrupt();
00374
00375 ADCS.Halt = FALSE;
00376
00377
00378 DDRA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
00379 PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
00380
00381
00382 ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);
00383
00384 ADCSRB = 0;
00385
00386
00387 ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER;
00388
00389 do {
00390 } while (!(ADCSRA & (1<<ADIF)));
00391
00392 ADCSRA |= (1<<ADIF);
00393
00394 ADCS.ADC3_G20_OS = ADC;
00395
00396 ADMUX = (1<<REFS0) | 0x16;
00397
00398
00399 ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER;
00400
00401 do {
00402 } while (!(ADCSRA & (1<<ADIF)));
00403
00404 ADCSRA |= (1<<ADIF);
00405
00406 ADCS.ADC5_G20_OS = ADC;
00407
00408
00409 ADCS.Flag = FALSE;
00410 ADCS.MUX = 0x01;
00411 ADMUX = (1<<REFS0) | ADCS.MUX;
00412
00413
00414 ADCS.avgIBAT = 0;
00415
00416 for (i = 0; i < 4; i++) {
00417 ADCS.discIBAT[i] = 0;
00418 }
00419
00420
00421 ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|ADC_PRESCALER;
00422
00423 __enable_interrupt();
00424
00425
00426 ADC_Wait();
00427 }