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
00027
00028
00029
00030
00031
00032 #include <config.h>
00033
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037
00038 #include "avrerror.h"
00039 #include "avrmalloc.h"
00040 #include "avrclass.h"
00041 #include "utils.h"
00042 #include "callback.h"
00043 #include "op_names.h"
00044
00045 #include "storage.h"
00046 #include "flash.h"
00047
00048 #include "vdevs.h"
00049 #include "memory.h"
00050 #include "stack.h"
00051 #include "register.h"
00052 #include "sram.h"
00053 #include "eeprom.h"
00054 #include "timers.h"
00055 #include "ports.h"
00056 #include "adc.h"
00057
00058 #include "avrcore.h"
00059
00060 #include "intvects.h"
00061
00062
00063
00064
00065
00066
00067
00068 static void adc_iadd_addr (VDevice *vdev, int addr, char *name, int rel_addr,
00069 void *data);
00070 static uint8_t adc_intr_read (VDevice *dev, int addr);
00071 static void adc_intr_write (VDevice *dev, int addr, uint8_t val);
00072 static void adc_intr_reset (VDevice *dev);
00073 static int adc_intr_cb (uint64_t time, AvrClass *data);
00074 static int adc_clk_incr_cb (uint64_t ck, AvrClass *data);
00075
00076
00077
00078 VDevice *
00079 adc_int_create (int addr, char *name, int rel_addr, void *data)
00080 {
00081 return (VDevice *)adc_intr_new (addr, name, rel_addr);
00082 }
00083
00084 ADCIntr_T *
00085 adc_intr_new (int addr, char *name, int rel_addr)
00086 {
00087 ADCIntr_T *adc;
00088
00089 adc = avr_new (ADCIntr_T, 1);
00090 adc_intr_construct (adc, addr, name, rel_addr);
00091 class_overload_destroy ((AvrClass *)adc, adc_intr_destroy);
00092
00093 return adc;
00094 }
00095
00096
00097
00098 void
00099 adc_intr_construct (ADCIntr_T *adc, int addr, char *name, int rel_addr)
00100 {
00101 if (adc == NULL)
00102 avr_error ("passed null ptr");
00103
00104 vdev_construct ((VDevice *)adc, adc_intr_read, adc_intr_write,
00105 adc_intr_reset, adc_iadd_addr);
00106
00107 if (rel_addr)
00108 adc->rel_addr = rel_addr;
00109 adc_iadd_addr ((VDevice *)adc, addr, name, 0, NULL);
00110
00111 adc_intr_reset ((VDevice *)adc);
00112 }
00113
00114 static void
00115 adc_iadd_addr (VDevice *vdev, int addr, char *name, int rel_addr, void *data)
00116 {
00117 ADCIntr_T *adc = (ADCIntr_T *)vdev;
00118
00119 if (strncmp ("ADCSR", name, 5) == 0)
00120 {
00121 adc->adcsr_addr = addr;
00122 }
00123
00124 else if (strncmp ("ADMUX", name, 5) == 0)
00125 {
00126 adc->admux_addr = addr;
00127 }
00128
00129 else
00130 {
00131 avr_error ("invalid ADC register name: '%s' @ 0x%04x", name, addr);
00132 }
00133 }
00134
00135
00136
00137 void
00138 adc_intr_destroy (void *adc)
00139 {
00140 if (adc == NULL)
00141 return;
00142
00143 vdev_destroy (adc);
00144 }
00145
00146 static uint8_t
00147 adc_intr_read (VDevice *dev, int addr)
00148 {
00149 ADCIntr_T *adc = (ADCIntr_T *)dev;
00150
00151 if (addr == adc->adcsr_addr)
00152 return (adc->adcsr);
00153
00154 else if (addr == adc->admux_addr)
00155 return (adc->admux);
00156
00157 else
00158 avr_error ("Bad address: 0x%04x", addr);
00159
00160 return 0;
00161 }
00162
00163 static void
00164 adc_intr_write (VDevice *dev, int addr, uint8_t val)
00165 {
00166 ADCIntr_T *adc = (ADCIntr_T *)dev;
00167 CallBack *cb;
00168 ADC_T *adc_d;
00169
00170 adc_d =
00171 (ADC_T *)avr_core_get_vdev_by_addr ((AvrCore *)
00172 vdev_get_core ((VDevice *)adc),
00173 adc->rel_addr);
00174
00175 if (addr == adc->adcsr_addr)
00176 {
00177 if (val & mask_ADIF)
00178 adc->adcsr = val & ~mask_ADIF;
00179 else
00180 adc->adcsr = val;
00181
00182 if ((val & mask_ADSC) && (val & mask_ADEN))
00183 {
00184 if ((adc->intr_cb == NULL))
00185 {
00186
00187 cb = callback_new (adc_intr_cb, (AvrClass *)adc);
00188 adc->intr_cb = cb;
00189 avr_core_async_cb_add ((AvrCore *)vdev_get_core (dev), cb);
00190 }
00191 if ((adc_d->clk_cb == NULL))
00192 {
00193
00194 cb = callback_new (adc_clk_incr_cb, (AvrClass *)adc_d);
00195 adc_d->clk_cb = cb;
00196 avr_core_clk_cb_add ((AvrCore *)
00197 vdev_get_core ((VDevice *)adc_d), cb);
00198 }
00199 adc_d->adc_count = 13;
00200 switch ((adc->adcsr) & (mask_ADPS0 | mask_ADPS1 | mask_ADPS2))
00201 {
00202 case ADC_CK_0:
00203 case ADC_CK_2:
00204 adc_d->divisor = 2;
00205 break;
00206 case ADC_CK_4:
00207 adc_d->divisor = 4;
00208 break;
00209 case ADC_CK_8:
00210 adc_d->divisor = 8;
00211 break;
00212 case ADC_CK_16:
00213 adc_d->divisor = 16;
00214 break;
00215 case ADC_CK_32:
00216 adc_d->divisor = 32;
00217 break;
00218 case ADC_CK_64:
00219 adc_d->divisor = 64;
00220 break;
00221 case ADC_CK_128:
00222 adc_d->divisor = 128;
00223 break;
00224 default:
00225 avr_error ("The impossible happened!");
00226 }
00227 }
00228 else
00229 {
00230 adc->intr_cb = NULL;
00231
00232 }
00233 }
00234
00235 else if (addr == adc->admux_addr)
00236 {
00237 adc->admux = val;
00238 }
00239
00240 else
00241 {
00242 avr_error ("Bad address: 0x%04x", addr);
00243 }
00244 }
00245
00246 static void
00247 adc_intr_reset (VDevice *dev)
00248 {
00249 ADCIntr_T *adc = (ADCIntr_T *)dev;
00250
00251 adc->intr_cb = NULL;
00252
00253 adc->adcsr = 0;
00254 adc->admux = 0;
00255 }
00256
00257 static int
00258 adc_intr_cb (uint64_t time, AvrClass *data)
00259 {
00260 ADCIntr_T *adc = (ADCIntr_T *)data;
00261
00262 if (adc->intr_cb == NULL)
00263 return CB_RET_REMOVE;
00264
00265 if ((adc->adcsr & mask_ADEN) && (adc->adcsr & mask_ADIE)
00266 && (adc->adcsr & mask_ADIF))
00267 {
00268
00269 AvrCore *core = (AvrCore *)vdev_get_core ((VDevice *)adc);
00270 avr_core_irq_raise (core, irq_vect_table_index (ADC));
00271 adc->adcsr &= ~mask_ADIF;
00272 }
00273
00274 return CB_RET_RETAIN;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283 static void adc_add_addr (VDevice *vdev, int addr, char *name, int rel_addr,
00284 void *data);
00285 static uint8_t adc_read (VDevice *dev, int addr);
00286 static void adc_write (VDevice *dev, int addr, uint8_t val);
00287 static void adc_reset (VDevice *dev);
00288
00289
00290
00291 VDevice *
00292 adc_create (int addr, char *name, int rel_addr, void *data)
00293 {
00294 uint8_t *data_ptr = (uint8_t *) data;
00295 if (data)
00296 return (VDevice *)adc_new (addr, name, (uint8_t) * data_ptr,
00297 rel_addr);
00298 else
00299 avr_error ("Attempted A/D create with NULL data pointer");
00300 return 0;
00301 }
00302
00303 ADC_T *
00304 adc_new (int addr, char *name, uint8_t uier, int rel_addr)
00305 {
00306 ADC_T *adc;
00307
00308 adc = avr_new (ADC_T, 1);
00309 adc_construct (adc, addr, name, uier, rel_addr);
00310 class_overload_destroy ((AvrClass *)adc, adc_destroy);
00311
00312 return adc;
00313 }
00314
00315
00316
00317 void
00318 adc_construct (ADC_T *adc, int addr, char *name, uint8_t uier, int rel_addr)
00319 {
00320 if (adc == NULL)
00321 avr_error ("passed null ptr");
00322
00323 vdev_construct ((VDevice *)adc, adc_read, adc_write, adc_reset,
00324 adc_add_addr);
00325
00326 if (rel_addr)
00327 adc->rel_addr = rel_addr;
00328 adc_add_addr ((VDevice *)adc, addr, name, 0, NULL);
00329
00330 adc_reset ((VDevice *)adc);
00331 adc->u_divisor = uier ? 12 : 1;
00332 }
00333 static void
00334 adc_add_addr (VDevice *vdev, int addr, char *name, int rel_addr, void *data)
00335 {
00336 ADC_T *adc = (ADC_T *)vdev;
00337
00338 if (strncmp ("ADCL", name, 4) == 0)
00339 {
00340 adc->adcl_addr = addr;
00341 }
00342
00343 else if (strncmp ("ADCH", name, 4) == 0)
00344 {
00345 adc->adch_addr = addr;
00346 }
00347
00348 else
00349 {
00350 avr_error ("invalid ADC register name: '%s' @ 0x%04x", name, addr);
00351 }
00352 }
00353
00354
00355
00356 void
00357 adc_destroy (void *adc)
00358 {
00359 if (adc == NULL)
00360 return;
00361
00362 vdev_destroy (adc);
00363 }
00364
00365 static uint8_t
00366 adc_read (VDevice *dev, int addr)
00367 {
00368 ADC_T *adc = (ADC_T *)dev;
00369
00370 if (addr == adc->adcl_addr)
00371 return adc->adcl;
00372
00373 else if (addr == adc->adch_addr)
00374 return adc->adch;
00375
00376 else
00377 avr_error ("Bad address: 0x%04x", addr);
00378
00379 return 0;
00380 }
00381
00382 static void
00383 adc_write (VDevice *dev, int addr, uint8_t val)
00384 {
00385 avr_error ("Bad ADC write address: 0x%04x", addr);
00386 }
00387
00388 static void
00389 adc_reset (VDevice *dev)
00390 {
00391 ADC_T *adc = (ADC_T *)dev;
00392
00393 adc->clk_cb = NULL;
00394
00395 adc->adcl = 0;
00396 adc->adch = 0;
00397
00398 adc->adc_count = 0;
00399 adc->adc_in = 0;
00400 adc->divisor = 0;
00401 }
00402
00403 static int
00404 adc_clk_incr_cb (uint64_t ck, AvrClass *data)
00405 {
00406 ADC_T *adc = (ADC_T *)data;
00407 uint8_t last = adc->adc_count;
00408 ADCIntr_T *adc_ti;
00409
00410 adc_ti =
00411 (ADCIntr_T *)avr_core_get_vdev_by_addr ((AvrCore *)
00412 vdev_get_core ((VDevice *)
00413 adc),
00414 adc->rel_addr);
00415
00416 if (adc->clk_cb == NULL)
00417 return CB_RET_REMOVE;
00418
00419 if (adc->divisor <= 0)
00420 avr_error ("Bad divisor value: %d", adc->divisor);
00421
00422
00423 adc->adc_count -= ((ck % (adc->divisor * adc->u_divisor)) == 0);
00424
00425 if (adc->adc_count != last)
00426 {
00427 if (adc->adc_count == 0)
00428 {
00429 adc_ti->adcsr |= mask_ADIF;
00430 adc_ti->adcsr &= ~mask_ADSC;
00431 adc->adc_in = adc_port_rd (adc_ti->admux);
00432 adc->adcl = (adc->adc_in) & 0xff;
00433
00434 adc->adch = ((adc->adc_in) >> 8) & 0x03;
00435 if (adc_ti->adcsr & mask_ADFR)
00436 adc->adc_count = 13;
00437 else
00438 {
00439 adc->clk_cb = NULL;
00440 return CB_RET_REMOVE;
00441 }
00442 }
00443 }
00444 return CB_RET_RETAIN;
00445 }
00446
00447
00448
00449
00450 uint16_t
00451 adc_port_rd (uint8_t mux)
00452 {
00453 int data;
00454 char line[80];
00455
00456 while (1)
00457 {
00458 fprintf (stderr, "\nEnter data to read into the ADC for channel %d: ",
00459 mux);
00460
00461
00462 if (fgets (line, sizeof (line), stdin) == NULL)
00463 continue;
00464
00465
00466 if (sscanf (line, "%d\n", &data) != 1)
00467 continue;
00468
00469 break;
00470 }
00471 return (uint16_t) (data & 0x3ff);
00472 }
00473
00474 void
00475 adc_port_wr (uint8_t val)
00476 {
00477 fprintf (stderr, "wrote 0x%02x to ADC\n", val);
00478 }