/*
avr_adc.c
- Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
+ Copyright 2008, 2010 Michel Pollet <buserror@gmail.com>
This file is part of simavr.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "sim_time.h"
#include "avr_adc.h"
static avr_cycle_count_t avr_adc_int_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
uint8_t muxi = avr_regbit_get_array(avr, p->mux, ARRAY_SIZE(p->mux));
avr_adc_mux_t mux = p->muxmode[muxi];
// optional shift left/right
- uint8_t shift = avr_regbit_get(avr, p->adlar) ? 0 : 6;
+ uint8_t shift = avr_regbit_get(avr, p->adlar) ? 6 : 0; // shift LEFT
uint32_t reg = 0;
switch (mux.kind) {
case ADC_MUX_REF:
reg = mux.src; // reference voltage
break;
+ case ADC_MUX_VCC4:
+ if ( !avr->vcc) {
+ AVR_LOG(avr, LOG_WARNING, "ADC: missing VCC analog voltage\n");
+ } else
+ reg = avr->vcc / 4;
+ break;
}
uint32_t vref = 3300;
switch (ref) {
+ case ADC_VREF_VCC:
+ if (!avr->vcc)
+ AVR_LOG(avr, LOG_WARNING, "ADC: missing VCC analog voltage\n");
+ else
+ vref = avr->vcc;
+ break;
case ADC_VREF_AREF:
if (!avr->aref)
- printf("ADC Warning : missing AREF analog voltage\n");
+ AVR_LOG(avr, LOG_WARNING, "ADC: missing AREF analog voltage\n");
else
vref = avr->aref;
break;
case ADC_VREF_AVCC:
if (!avr->avcc)
- printf("ADC Warning : missing AVCC analog voltage\n");
+ AVR_LOG(avr, LOG_WARNING, "ADC: missing AVCC analog voltage\n");
else
vref = avr->avcc;
break;
reg = (reg * 0x3ff) / vref; // scale to 10 bits ADC
// printf("ADC to 10 bits 0x%x %d\n", reg, reg);
if (reg > 0x3ff) {
- printf("ADC Warning channel %d clipped %u/%u VREF %d\n", mux.kind, reg, 0x3ff, vref);
+ AVR_LOG(avr, LOG_WARNING, "ADC: channel %d clipped %u/%u VREF %d\n", mux.kind, reg, 0x3ff, vref);
reg = 0x3ff;
}
reg <<= shift;
if (!aden && avr_regbit_get(avr, p->aden)) {
// first conversion
p->first = 1;
- printf("ADC Start AREF %d AVCC %d\n", avr->aref, avr->avcc);
+ AVR_LOG(avr, LOG_TRACE, "ADC: Start AREF %d AVCC %d\n", avr->aref, avr->avcc);
}
if (aden && !avr_regbit_get(avr, p->aden)) {
// stop ADC
avr_cycle_timer_cancel(avr, avr_adc_int_raise, p);
avr_regbit_clear(avr, p->adsc);
+ v = avr->data[p->adsc.reg]; // Peter Ross pross@xvid.org
}
if (!adsc && avr_regbit_get(avr, p->adsc)) {
// start one!
div = avr->frequency >> div;
if (p->first)
- printf("ADC starting at %uKHz\n", div / 13 / 100);
+ AVR_LOG(avr, LOG_TRACE, "ADC: starting at %uKHz\n", div / 13 / 100);
div /= p->first ? 25 : 13; // first cycle is longer
avr_cycle_timer_register(avr,
avr_irq_register_notify(p->io.irq + i, avr_adc_irq_notify, p);
}
+static const char * irq_names[ADC_IRQ_COUNT] = {
+ [ADC_IRQ_ADC0] = "16<adc0",
+ [ADC_IRQ_ADC1] = "16<adc1",
+ [ADC_IRQ_ADC2] = "16<adc2",
+ [ADC_IRQ_ADC3] = "16<adc3",
+ [ADC_IRQ_ADC4] = "16<adc4",
+ [ADC_IRQ_ADC5] = "16<adc5",
+ [ADC_IRQ_ADC6] = "16<adc6",
+ [ADC_IRQ_ADC7] = "16<adc7",
+ [ADC_IRQ_ADC8] = "16<adc0",
+ [ADC_IRQ_ADC9] = "16<adc9",
+ [ADC_IRQ_ADC10] = "16<adc10",
+ [ADC_IRQ_ADC11] = "16<adc11",
+ [ADC_IRQ_ADC12] = "16<adc12",
+ [ADC_IRQ_ADC13] = "16<adc13",
+ [ADC_IRQ_ADC14] = "16<adc14",
+ [ADC_IRQ_ADC15] = "16<adc15",
+ [ADC_IRQ_TEMP] = "16<temp",
+ [ADC_IRQ_IN_TRIGGER] = "<trigger_in",
+ [ADC_IRQ_OUT_TRIGGER] = ">trigger_out",
+};
+
static avr_io_t _io = {
.kind = "adc",
.reset = avr_adc_reset,
+ .irq_names = irq_names,
};
void avr_adc_init(avr_t * avr, avr_adc_t * p)
{
p->io = _io;
- // allocate this module's IRQ
- p->io.irq_count = ADC_IRQ_COUNT;
- p->io.irq = avr_alloc_irq(0, p->io.irq_count);
- p->io.irq_ioctl_get = AVR_IOCTL_ADC_GETIRQ;
-
avr_register_io(avr, &p->io);
avr_register_vector(avr, &p->adc);
+ // allocate this module's IRQ
+ avr_io_setirqs(&p->io, AVR_IOCTL_ADC_GETIRQ, ADC_IRQ_COUNT, NULL);
avr_register_io_write(avr, p->r_adcsra, avr_adc_write, p);
avr_register_io_read(avr, p->r_adcl, avr_adc_read_l, p);