/*! \file a2d.c \brief Analog-to-Digital converter function library. */
//*****************************************************************************
//
// File Name : 'a2d.c'
// Title : Analog-to-digital converter functions
// Author : Pascal Stang - Copyright (C) 2002
// Created : 2002-04-08
// Revised : 2002-09-30
// Version : 1.1
// Target MCU : Atmel AVR series
// Editor Tabs : 4
//
// This code is distributed under the GNU Public License
// which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************
#include <avr/io.h>
#include <avr/interrupt.h>
#include "global.h"
#include "a2d.h"
// global variables
//! Software flag used to indicate when
/// the a2d conversion is complete.
volatile unsigned char a2dCompleteFlag;
// functions
// initialize a2d converter
void a2dInit(void)
{
sbi(ADCSR, ADEN); // enable ADC (turn on ADC power)
cbi(ADCSR, ADFR); // default to single sample convert mode
a2dSetPrescaler(ADC_PRESCALE); // set default prescaler
a2dSetReference(ADC_REFERENCE); // set default reference
cbi(ADMUX, ADLAR); // set to right-adjusted result
sbi(ADCSR, ADIE); // enable ADC interrupts
a2dCompleteFlag = FALSE; // clear conversion complete flag
sei(); // turn on interrupts (if not already on)
}
// turn off a2d converter
void a2dOff(void)
{
cbi(ADCSR, ADIE); // disable ADC interrupts
cbi(ADCSR, ADEN); // disable ADC (turn off ADC power)
}
// configure A2D converter clock division (prescaling)
void a2dSetPrescaler(unsigned char prescale)
{
outb(ADCSR, ((inb(ADCSR) & ~ADC_PRESCALE_MASK) | prescale));
}
// configure A2D converter voltage reference
void a2dSetReference(unsigned char ref)
{
outb(ADMUX, ((inb(ADMUX) & ~ADC_REFERENCE_MASK) | (ref<<6)));
}
// sets the a2d input channel
void a2dSetChannel(unsigned char ch)
{
outb(ADMUX, (inb(ADMUX) & ~ADC_MUX_MASK) | (ch & ADC_MUX_MASK)); // set channel
}
// start a conversion on the current a2d input channel
void a2dStartConvert(void)
{
sbi(ADCSR, ADIF); // clear hardware "conversion complete" flag
sbi(ADCSR, ADSC); // start conversion
}
// return TRUE if conversion is complete
u08 a2dIsComplete(void)
{
return bit_is_set(ADCSR, ADSC);
}
// Perform a 10-bit conversion
// starts conversion, waits until conversion is done, and returns result
unsigned short a2dConvert10bit(unsigned char ch)
{
a2dCompleteFlag = FALSE; // clear conversion complete flag
outb(ADMUX, (inb(ADMUX) & ~ADC_MUX_MASK) | (ch & ADC_MUX_MASK)); // set channel
sbi(ADCSR, ADIF); // clear hardware "conversion complete" flag
sbi(ADCSR, ADSC); // start conversion
//while(!a2dCompleteFlag); // wait until conversion complete
//while( bit_is_clear(ADCSR, ADIF) ); // wait until conversion complete
while( bit_is_set(ADCSR, ADSC) ); // wait until conversion complete
// CAUTION: MUST READ ADCL BEFORE ADCH!!!
return (inb(ADCL) | (inb(ADCH)<<8)); // read ADC (full 10 bits);
}
// Perform a 8-bit conversion.
// starts conversion, waits until conversion is done, and returns result
unsigned char a2dConvert8bit(unsigned char ch)
{
// do 10-bit conversion and return highest 8 bits
return a2dConvert10bit(ch)>>2; // return ADC MSB byte
}
//! Interrupt handler for ADC complete interrupt.
SIGNAL(SIG_ADC)
{
// set the a2d conversion flag to indicate "complete"
a2dCompleteFlag = TRUE;
}