general: Introduce two new headers
[simavr] / simavr / sim / avr_adc.c
1 /*
2         avr_adc.c
3
4         Copyright 2008, 2010 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
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.
12
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.
17
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/>.
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include "sim_time.h"
26 #include "avr_adc.h"
27
28 static avr_cycle_count_t avr_adc_int_raise(struct avr_t * avr, avr_cycle_count_t when, void * param)
29 {
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);
35                 p->first = 0;
36                 p->read_status = 0;
37         }
38         return 0;
39 }
40
41 static uint8_t avr_adc_read_l(struct avr_t * avr, avr_io_addr_t addr, void * param)
42 {
43         avr_adc_t * p = (avr_adc_t *)param;
44
45         if (p->read_status)     // conversion already done
46                 return avr_core_watch_read(avr, addr);
47
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
54
55         uint32_t reg = 0;
56         switch (mux.kind) {
57                 case ADC_MUX_SINGLE:
58                         reg = p->adc_values[mux.src];
59                         break;
60                 case ADC_MUX_DIFF:
61                         if (mux.gain == 0)
62                                 mux.gain = 1;
63                         reg = ((uint32_t)p->adc_values[mux.src] * mux.gain) -
64                                         ((uint32_t)p->adc_values[mux.diff] * mux.gain);
65                         break;
66                 case ADC_MUX_TEMP:
67                         reg = p->temp; // assumed to be already calibrated somehow
68                         break;
69                 case ADC_MUX_REF:
70                         reg = mux.src; // reference voltage
71                         break;
72                 case ADC_MUX_VCC4:
73                         if ( !avr->vcc) {
74                                 printf("ADC Warning : missing VCC analog voltage\n");
75                         } else
76                                 reg = avr->vcc / 4;
77                         break;
78         }
79         uint32_t vref = 3300;
80         switch (ref) {
81                 case ADC_VREF_VCC:
82                         if (!avr->vcc)
83                                 printf("ADC Warning : missing VCC analog voltage\n");
84                         else
85                                 vref = avr->vcc;
86                         break;
87                 case ADC_VREF_AREF:
88                         if (!avr->aref)
89                                 printf("ADC Warning : missing AREF analog voltage\n");
90                         else
91                                 vref = avr->aref;
92                         break;
93                 case ADC_VREF_AVCC:
94                         if (!avr->avcc)
95                                 printf("ADC Warning : missing AVCC analog voltage\n");
96                         else
97                                 vref = avr->avcc;
98                         break;
99                 default:
100                         vref = ref;
101         }
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);
107         if (reg > 0x3ff) {
108                 printf("ADC Warning channel %d clipped %u/%u VREF %d\n", mux.kind, reg, 0x3ff, vref);
109                 reg = 0x3ff;
110         }
111         reg <<= shift;
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;
115         p->read_status = 1;
116         return avr_core_watch_read(avr, addr);
117 }
118
119 /*
120  * From Datasheet:
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
126  * register value.
127  */
128 static uint8_t avr_adc_read_h(struct avr_t * avr, avr_io_addr_t addr, void * param)
129 {
130         avr_adc_t * p = (avr_adc_t *)param;
131         // no "break" here on purpose
132         switch (p->read_status) {
133                 case 0:
134                         avr_adc_read_l(avr, p->r_adcl, param);
135                 case 1:
136                         p->read_status = 2;
137                 default:
138                         return avr_core_watch_read(avr, addr);
139         }
140 }
141
142 static void avr_adc_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
143 {
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);
147
148         avr->data[p->adsc.reg] = v;
149
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];
154         }
155         if (!aden && avr_regbit_get(avr, p->aden)) {
156                 // first conversion
157                 p->first = 1;
158                 printf("ADC Start AREF %d AVCC %d\n", avr->aref, avr->avcc);
159         }
160         if (aden && !avr_regbit_get(avr, p->aden)) {
161                 // stop ADC
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
165         }
166         if (!adsc && avr_regbit_get(avr, p->adsc)) {
167                 // start one!
168                 uint8_t muxi = avr_regbit_get_array(avr, p->mux, ARRAY_SIZE(p->mux));
169                 union {
170                         avr_adc_mux_t mux;
171                         uint32_t v;
172                 } e = { .mux = p->muxmode[muxi] };
173                 avr_raise_irq(p->io.irq + ADC_IRQ_OUT_TRIGGER, e.v);
174
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));
177                 if (!div) div++;
178
179                 div = avr->frequency >> div;
180                 if (p->first)
181                         printf("ADC starting at %uKHz\n", div / 13 / 100);
182                 div /= p->first ? 25 : 13;      // first cycle is longer
183
184                 avr_cycle_timer_register(avr,
185                                 avr_hz_to_cycles(avr, div),
186                                 avr_adc_int_raise, p);
187         }
188         avr_core_watch_write(avr, addr, v);
189 }
190
191 static void avr_adc_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
192 {
193         avr_adc_t * p = (avr_adc_t *)param;
194         avr_t * avr = p->io.avr;
195
196         switch (irq->irq) {
197                 case ADC_IRQ_ADC0 ... ADC_IRQ_ADC7: {
198                         p->adc_values[irq->irq] = value;
199                 }       break;
200                 case ADC_IRQ_TEMP: {
201                         p->temp = value;
202                 }       break;
203                 case ADC_IRQ_IN_TRIGGER: {
204                         if (avr_regbit_get(avr, p->adate)) {
205                                 // start a conversion
206                         }
207                 }       break;
208         }
209 }
210
211 static void avr_adc_reset(avr_io_t * port)
212 {
213         avr_adc_t * p = (avr_adc_t *)port;
214
215         // stop ADC
216         avr_cycle_timer_cancel(p->io.avr, avr_adc_int_raise, p);
217         avr_regbit_clear(p->io.avr, p->adsc);
218
219         for (int i = 0; i < ADC_IRQ_COUNT; i++)
220                 avr_irq_register_notify(p->io.irq + i, avr_adc_irq_notify, p);
221 }
222
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",
235 };
236
237 static  avr_io_t        _io = {
238         .kind = "adc",
239         .reset = avr_adc_reset,
240         .irq_names = irq_names,
241 };
242
243 void avr_adc_init(avr_t * avr, avr_adc_t * p)
244 {
245         p->io = _io;
246
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);
251
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);
255 }