BeRTOS
|
00001 00043 #include "adc_avr.h" 00044 00045 #include "cfg/cfg_adc.h" 00046 #include "cfg/cfg_proc.h" 00047 #include "cfg/cfg_signal.h" 00048 #include <cfg/macros.h> 00049 #include <cfg/compiler.h> 00050 00051 #include <cpu/irq.h> // IRQ_ASSERT_ENABLED() 00052 00053 #include <drv/adc.h> 00054 00055 #include <avr/io.h> 00056 #include <avr/interrupt.h> 00057 00064 #define ADC_AVR_AREF 0 00065 #define ADC_AVR_AVCC 1 00066 #define ADC_AVR_INT256 2 00067 /* \} */ 00068 00069 #if CONFIG_KERN 00070 #include <cfg/module.h> 00071 #include <kern/proc.h> 00072 #include <kern/signal.h> 00073 00074 00075 #if !CONFIG_KERN_SIGNALS 00076 #error Signals must be active to use the ADC with kernel 00077 #endif 00078 00079 /* Signal adc convertion end */ 00080 #define SIG_ADC_COMPLETE SIG_SINGLE 00081 00082 /* ADC waiting process */ 00083 static struct Process *adc_process; 00084 00089 ISR(ADC_vect) 00090 { 00091 sig_post(adc_process, SIG_ADC_COMPLETE); 00092 } 00093 #endif /* CONFIG_KERN */ 00094 00099 void adc_hw_select_ch(uint8_t ch) 00100 { 00101 /* Set to 0 all mux registers */ 00102 #if CPU_AVR_ATMEGA8 || CPU_AVR_ATMEGA328P || CPU_AVR_ATMEGA168 00103 ADMUX &= ~(BV(MUX3) | BV(MUX2) | BV(MUX1) | BV(MUX0)); 00104 #elif CPU_AVR_ATMEGA32 || CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281 \ 00105 || CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560 00106 ADMUX &= ~(BV(MUX4) | BV(MUX3) | BV(MUX2) | BV(MUX1) | BV(MUX0)); 00107 #if CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560 00108 ADCSRB &= ~(BV(MUX5)); 00109 #endif 00110 #else 00111 #error Unknown CPU 00112 #endif 00113 00114 /* Select channel, only first 8 channel modes are supported */ 00115 ADMUX |= (ch & 0x07); 00116 00117 #if CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560 00118 /* Select channel, all 16 channels are supported */ 00119 if (ch > 0x07) 00120 ADCSRB |= BV(MUX5); 00121 00122 #endif 00123 00124 } 00125 00126 00132 uint16_t adc_hw_read(void) 00133 { 00134 // Ensure another convertion is not running. 00135 ASSERT(!(ADCSRA & BV(ADSC))); 00136 00137 // Start convertion 00138 ADCSRA |= BV(ADSC); 00139 00140 #if CONFIG_KERN 00141 // Ensure IRQs enabled. 00142 IRQ_ASSERT_ENABLED(); 00143 adc_process = proc_current(); 00144 sig_wait(SIG_ADC_COMPLETE); 00145 #else 00146 //Wait in polling until is done 00147 while (ADCSRA & BV(ADSC)) ; 00148 #endif 00149 00150 return(ADC); 00151 } 00152 00156 void adc_hw_init(void) 00157 { 00158 /* 00159 * Select channel 0 as default, 00160 * result right adjusted. 00161 */ 00162 ADMUX = 0; 00163 00164 #if CONFIG_ADC_AVR_REF == ADC_AVR_AREF 00165 /* External voltage at AREF as analog ref source */ 00166 /* None */ 00167 #elif CONFIG_ADC_AVR_REF == ADC_AVR_AVCC 00168 /* AVCC as analog ref source */ 00169 ADMUX |= BV(REFS0); 00170 #elif CONFIG_ADC_AVR_REF == ADC_AVR_INT256 00171 /* Internal 2.56V as ref source */ 00172 ADMUX |= BV(REFS1) | BV(REFS0); 00173 #else 00174 #error Unsupported ADC ref value. 00175 #endif 00176 00177 #if defined(ADCSRB) 00178 /* Disable Auto trigger source: ADC in Free running mode. */ 00179 ADCSRB = 0; 00180 #endif 00181 00182 /* Enable ADC, disable autotrigger mode. */ 00183 ADCSRA = BV(ADEN); 00184 00185 #if CONFIG_KERN 00186 MOD_CHECK(proc); 00187 ADCSRA |= BV(ADIE); 00188 #endif 00189 00190 /* Set convertion frequency */ 00191 #if CONFIG_ADC_AVR_DIVISOR == 2 00192 ADCSRA |= BV(ADPS0); 00193 #elif CONFIG_ADC_AVR_DIVISOR == 4 00194 ADCSRA |= BV(ADPS1); 00195 #elif CONFIG_ADC_AVR_DIVISOR == 8 00196 ADCSRA |= BV(ADPS1) | BV(ADPS0); 00197 #elif CONFIG_ADC_AVR_DIVISOR == 16 00198 ADCSRA |= BV(ADPS2); 00199 #elif CONFIG_ADC_AVR_DIVISOR == 32 00200 ADCSRA |= BV(ADPS2) | BV(ADPS0); 00201 #elif CONFIG_ADC_AVR_DIVISOR == 64 00202 ADCSRA |= BV(ADPS2) | BV(ADPS1); 00203 #elif CONFIG_ADC_AVR_DIVISOR == 128 00204 ADCSRA |= BV(ADPS2) | BV(ADPS1) | BV(ADPS0); 00205 #else 00206 #error Unsupported ADC prescaler value. 00207 #endif 00208 00209 /* Start a convertion to init ADC hw */ 00210 adc_hw_read(); 00211 }