4 Copyright 2008, 2010 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
8 simavr is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 simavr is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with simavr. If not, see <http://www.gnu.org/licenses/>.
28 static avr_cycle_count_t avr_adc_int_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
30 avr_adc_t * p = (avr_adc_t *)param;
31 if (avr_regbit_get(avr, p->aden)) {
32 // if the interrupts are not used, still raised the UDRE and TXC flag
33 avr_raise_interrupt(avr, &p->adc);
34 avr_regbit_clear(avr, p->adsc);
41 static uint8_t avr_adc_read_l(struct avr_t * avr, avr_io_addr_t addr, void * param)
43 avr_adc_t * p = (avr_adc_t *)param;
45 if (p->read_status) // conversion already done
46 return avr_core_watch_read(avr, addr);
48 uint8_t refi = avr_regbit_get_array(avr, p->ref, ARRAY_SIZE(p->ref));
49 uint16_t ref = p->ref_values[refi];
50 uint8_t muxi = avr_regbit_get_array(avr, p->mux, ARRAY_SIZE(p->mux));
51 avr_adc_mux_t mux = p->muxmode[muxi];
52 // optional shift left/right
53 uint8_t shift = avr_regbit_get(avr, p->adlar) ? 6 : 0; // shift LEFT
58 reg = p->adc_values[mux.src];
63 reg = ((uint32_t)p->adc_values[mux.src] * mux.gain) -
64 ((uint32_t)p->adc_values[mux.diff] * mux.gain);
67 reg = p->temp; // assumed to be already calibrated somehow
70 reg = mux.src; // reference voltage
74 printf("ADC Warning : missing VCC analog voltage\n");
83 printf("ADC Warning : missing VCC analog voltage\n");
89 printf("ADC Warning : missing AREF analog voltage\n");
95 printf("ADC Warning : missing AVCC analog voltage\n");
102 // printf("ADCL %d:%3d:%3d read %4d vref %d:%d=%d\n",
103 // mux.kind, mux.diff, mux.src,
104 // reg, refi, ref, vref);
105 reg = (reg * 0x3ff) / vref; // scale to 10 bits ADC
106 // printf("ADC to 10 bits 0x%x %d\n", reg, reg);
108 printf("ADC Warning channel %d clipped %u/%u VREF %d\n", mux.kind, reg, 0x3ff, vref);
112 // printf("ADC to 10 bits %x shifted %d\n", reg, shift);
113 avr->data[p->r_adcl] = reg;
114 avr->data[p->r_adch] = reg >> 8;
116 return avr_core_watch_read(avr, addr);
121 * "When ADCL is read, the ADC Data Register is not updated until ADCH is read.
122 * Consequently, if the result is left adjusted and no more than 8-bit
123 * precision is required, it is sufficient to read ADCH.
124 * Otherwise, ADCL must be read first, then ADCH."
125 * So here if the H is read before the L, we still call the L to update the
128 static uint8_t avr_adc_read_h(struct avr_t * avr, avr_io_addr_t addr, void * param)
130 avr_adc_t * p = (avr_adc_t *)param;
131 // no "break" here on purpose
132 switch (p->read_status) {
134 avr_adc_read_l(avr, p->r_adcl, param);
138 return avr_core_watch_read(avr, addr);
142 static void avr_adc_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
144 avr_adc_t * p = (avr_adc_t *)param;
145 uint8_t adsc = avr_regbit_get(avr, p->adsc);
146 uint8_t aden = avr_regbit_get(avr, p->aden);
148 avr->data[p->adsc.reg] = v;
150 // can't write zero to adsc
151 if (adsc && !avr_regbit_get(avr, p->adsc)) {
152 avr_regbit_set(avr, p->adsc);
153 v = avr->data[p->adsc.reg];
155 if (!aden && avr_regbit_get(avr, p->aden)) {
158 printf("ADC Start AREF %d AVCC %d\n", avr->aref, avr->avcc);
160 if (aden && !avr_regbit_get(avr, p->aden)) {
162 avr_cycle_timer_cancel(avr, avr_adc_int_raise, p);
163 avr_regbit_clear(avr, p->adsc);
164 v = avr->data[p->adsc.reg]; // Peter Ross pross@xvid.org
166 if (!adsc && avr_regbit_get(avr, p->adsc)) {
168 uint8_t muxi = avr_regbit_get_array(avr, p->mux, ARRAY_SIZE(p->mux));
172 } e = { .mux = p->muxmode[muxi] };
173 avr_raise_irq(p->io.irq + ADC_IRQ_OUT_TRIGGER, e.v);
175 // clock prescaler are just a bit shift.. and 0 means 1
176 uint32_t div = avr_regbit_get_array(avr, p->adps, ARRAY_SIZE(p->adps));
179 div = avr->frequency >> div;
181 printf("ADC starting at %uKHz\n", div / 13 / 100);
182 div /= p->first ? 25 : 13; // first cycle is longer
184 avr_cycle_timer_register(avr,
185 avr_hz_to_cycles(avr, div),
186 avr_adc_int_raise, p);
188 avr_core_watch_write(avr, addr, v);
191 static void avr_adc_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
193 avr_adc_t * p = (avr_adc_t *)param;
194 avr_t * avr = p->io.avr;
197 case ADC_IRQ_ADC0 ... ADC_IRQ_ADC7: {
198 p->adc_values[irq->irq] = value;
203 case ADC_IRQ_IN_TRIGGER: {
204 if (avr_regbit_get(avr, p->adate)) {
205 // start a conversion
211 static void avr_adc_reset(avr_io_t * port)
213 avr_adc_t * p = (avr_adc_t *)port;
216 avr_cycle_timer_cancel(p->io.avr, avr_adc_int_raise, p);
217 avr_regbit_clear(p->io.avr, p->adsc);
219 for (int i = 0; i < ADC_IRQ_COUNT; i++)
220 avr_irq_register_notify(p->io.irq + i, avr_adc_irq_notify, p);
223 static const char * irq_names[ADC_IRQ_COUNT] = {
224 [ADC_IRQ_ADC0] = "16<adc0",
225 [ADC_IRQ_ADC1] = "16<adc1",
226 [ADC_IRQ_ADC2] = "16<adc2",
227 [ADC_IRQ_ADC3] = "16<adc3",
228 [ADC_IRQ_ADC4] = "16<adc4",
229 [ADC_IRQ_ADC5] = "16<adc5",
230 [ADC_IRQ_ADC6] = "16<adc6",
231 [ADC_IRQ_ADC7] = "16<adc7",
232 [ADC_IRQ_TEMP] = "16<temp",
233 [ADC_IRQ_IN_TRIGGER] = "<trigger_in",
234 [ADC_IRQ_OUT_TRIGGER] = ">trigger_out",
237 static avr_io_t _io = {
239 .reset = avr_adc_reset,
240 .irq_names = irq_names,
243 void avr_adc_init(avr_t * avr, avr_adc_t * p)
247 avr_register_io(avr, &p->io);
248 avr_register_vector(avr, &p->adc);
249 // allocate this module's IRQ
250 avr_io_setirqs(&p->io, AVR_IOCTL_ADC_GETIRQ, ADC_IRQ_COUNT, NULL);
252 avr_register_io_write(avr, p->r_adcsra, avr_adc_write, p);
253 avr_register_io_read(avr, p->r_adcl, avr_adc_read_l, p);
254 avr_register_io_read(avr, p->r_adch, avr_adc_read_h, p);