39 #include "avrmalloc.h" 68 static void adc_iadd_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
70 static uint8_t adc_intr_read (VDevice *dev,
int addr);
71 static void adc_intr_write (VDevice *dev,
int addr, uint8_t val);
72 static void adc_intr_reset (VDevice *dev);
73 static int adc_intr_cb (uint64_t time, AvrClass *data);
74 static int adc_clk_incr_cb (uint64_t ck, AvrClass *data);
81 return (VDevice *)adc_intr_new (addr, name, rel_addr);
85 adc_intr_new (
int addr,
char *name,
int rel_addr)
105 adc_intr_reset, adc_iadd_addr);
108 adc->rel_addr = rel_addr;
109 adc_iadd_addr ((VDevice *)adc, addr, name, 0, NULL);
111 adc_intr_reset ((VDevice *)adc);
115 adc_iadd_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
void *data)
117 ADCIntr_T *adc = (ADCIntr_T *)vdev;
119 if (strncmp (
"ADCSR", name, 5) == 0)
121 adc->adcsr_addr = addr;
124 else if (strncmp (
"ADMUX", name, 5) == 0)
126 adc->admux_addr = addr;
131 avr_error (
"invalid ADC register name: '%s' @ 0x%04x", name, addr);
147 adc_intr_read (VDevice *dev,
int addr)
149 ADCIntr_T *adc = (ADCIntr_T *)dev;
151 if (addr == adc->adcsr_addr)
154 else if (addr == adc->admux_addr)
164 adc_intr_write (VDevice *dev,
int addr, uint8_t val)
166 ADCIntr_T *adc = (ADCIntr_T *)dev;
175 if (addr == adc->adcsr_addr)
178 adc->adcsr = val & ~mask_ADIF;
182 if ((val & mask_ADSC) && (val & mask_ADEN))
184 if ((adc->intr_cb == NULL))
187 cb = callback_new (adc_intr_cb, (AvrClass *)adc);
191 if ((adc_d->clk_cb == NULL))
194 cb = callback_new (adc_clk_incr_cb, (AvrClass *)adc_d);
199 adc_d->adc_count = 13;
200 switch ((adc->adcsr) & (mask_ADPS0 | mask_ADPS1 | mask_ADPS2))
222 adc_d->divisor = 128;
235 else if (addr == adc->admux_addr)
247 adc_intr_reset (VDevice *dev)
249 ADCIntr_T *adc = (ADCIntr_T *)dev;
258 adc_intr_cb (uint64_t time, AvrClass *data)
260 ADCIntr_T *adc = (ADCIntr_T *)data;
262 if (adc->intr_cb == NULL)
263 return CB_RET_REMOVE;
265 if ((adc->adcsr & mask_ADEN) && (adc->adcsr & mask_ADIE)
266 && (adc->adcsr & mask_ADIF))
271 adc->adcsr &= ~mask_ADIF;
274 return CB_RET_RETAIN;
283 static void adc_add_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
285 static uint8_t adc_read (VDevice *dev,
int addr);
286 static void adc_write (VDevice *dev,
int addr, uint8_t val);
287 static void adc_reset (VDevice *dev);
294 uint8_t *data_ptr = (uint8_t *) data;
296 return (VDevice *)adc_new (addr, name, (uint8_t) * data_ptr,
299 avr_error (
"Attempted A/D create with NULL data pointer");
304 adc_new (
int addr,
char *name, uint8_t uier,
int rel_addr)
318 adc_construct (ADC_T *adc,
int addr,
char *name, uint8_t uier,
int rel_addr)
327 adc->rel_addr = rel_addr;
328 adc_add_addr ((VDevice *)adc, addr, name, 0, NULL);
330 adc_reset ((VDevice *)adc);
331 adc->u_divisor = uier ? 12 : 1;
334 adc_add_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
void *data)
336 ADC_T *adc = (ADC_T *)vdev;
338 if (strncmp (
"ADCL", name, 4) == 0)
340 adc->adcl_addr = addr;
343 else if (strncmp (
"ADCH", name, 4) == 0)
345 adc->adch_addr = addr;
350 avr_error (
"invalid ADC register name: '%s' @ 0x%04x", name, addr);
366 adc_read (VDevice *dev,
int addr)
368 ADC_T *adc = (ADC_T *)dev;
370 if (addr == adc->adcl_addr)
373 else if (addr == adc->adch_addr)
383 adc_write (VDevice *dev,
int addr, uint8_t val)
385 avr_error (
"Bad ADC write address: 0x%04x", addr);
389 adc_reset (VDevice *dev)
391 ADC_T *adc = (ADC_T *)dev;
404 adc_clk_incr_cb (uint64_t ck, AvrClass *data)
406 ADC_T *adc = (ADC_T *)data;
407 uint8_t last = adc->adc_count;
416 if (adc->clk_cb == NULL)
417 return CB_RET_REMOVE;
419 if (adc->divisor <= 0)
420 avr_error (
"Bad divisor value: %d", adc->divisor);
423 adc->adc_count -= ((ck % (adc->divisor * adc->u_divisor)) == 0);
425 if (adc->adc_count != last)
427 if (adc->adc_count == 0)
429 adc_ti->adcsr |= mask_ADIF;
430 adc_ti->adcsr &= ~mask_ADSC;
431 adc->adc_in = adc_port_rd (adc_ti->admux);
432 adc->adcl = (adc->adc_in) & 0xff;
434 adc->adch = ((adc->adc_in) >> 8) & 0x03;
435 if (adc_ti->adcsr & mask_ADFR)
440 return CB_RET_REMOVE;
444 return CB_RET_RETAIN;
451 adc_port_rd (uint8_t mux)
458 fprintf (stderr,
"\nEnter data to read into the ADC for channel %d: ",
462 if (fgets (line,
sizeof (line), stdin) == NULL)
466 if (sscanf (line,
"%d\n", &data) != 1)
471 return (uint16_t) (data & 0x3ff);
475 adc_port_wr (uint8_t val)
477 fprintf (stderr,
"wrote 0x%02x to ADC\n", val);
#define avr_new(type, count)
Macro for allocating memory.
VDevice * adc_int_create(int addr, char *name, int rel_addr, void *data)
Allocate a new ADC interrupt.
void avr_core_async_cb_add(AvrCore *core, CallBack *cb)
Add a new asynchronous callback to list.
VDevice * avr_core_get_vdev_by_addr(AvrCore *core, int addr)
Returns the VDevice which handles the address addr.
void vdev_destroy(void *dev)
Destructor for a VDevice.
void adc_destroy(void *adc)
Destructor for ADC object.
void avr_core_irq_raise(AvrCore *core, unsigned int irq)
Raises an irq by adding it's data to the irq_pending list.
AvrClass * vdev_get_core(VDevice *dev)
Get the core field.
void vdev_construct(VDevice *dev, VDevFP_Read rd, VDevFP_Write wr, VDevFP_Reset reset, VDevFP_AddAddr add_addr)
Constructor for a VDevice.
void adc_construct(ADC_T *adc, int addr, char *name, uint8_t uier, int rel_addr)
Constructor for ADC object.
#define avr_error(fmt, args...)
Print an error message to stderr and terminate program.
void adc_intr_destroy(void *adc)
Destructor for adc interrupt object.
void avr_core_clk_cb_add(AvrCore *core, CallBack *cb)
Add a new clock callback to list.
void adc_intr_construct(ADCIntr_T *adc, int addr, char *name, int rel_addr)
Constructor for adc interrupt object.
VDevice * adc_create(int addr, char *name, int rel_addr, void *data)
Allocate a new ADC structure.
void class_overload_destroy(AvrClass *klass, AvrClassFP_Destroy destroy)
Overload the default destroy method.