| /*************************************************************************** |
| * __________ __ ___. |
| * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| * \/ \/ \/ \/ \/ |
| * $Id$ |
| * |
| * Copyright (C) 2007 by Dave Chapman |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ****************************************************************************/ |
| #include "config.h" |
| #include "cpu.h" |
| #include "system.h" |
| #include "kernel.h" |
| #include "thread.h" |
| #include "string.h" |
| #include "adc.h" |
| |
| static unsigned short adcdata[8]; |
| |
| #ifndef BOOTLOADER |
| |
| /* Tick task */ |
| static void adc_tick(void) |
| { |
| int i; |
| |
| PCLK_ADC |= PCK_EN; /* Enable ADC clock */ |
| |
| /* Start converting the first 4 channels */ |
| for (i = 0; i < 4; i++) |
| ADCCON = i; |
| |
| } |
| |
| /* IRQ handler */ |
| void ADC(void) |
| { |
| int num; |
| uint32_t adc_status; |
| |
| do |
| { |
| adc_status = ADCSTATUS; |
| num = (adc_status>>24) & 7; |
| if (num) adcdata[(adc_status >> 16) & 0x7] = adc_status & 0x3ff; |
| } while (num); |
| |
| PCLK_ADC &= ~PCK_EN; /* Disable ADC clock */ |
| } |
| #endif /* BOOTLOADER */ |
| |
| |
| unsigned short adc_read(int channel) |
| { |
| #ifdef BOOTLOADER |
| /* IRQs aren't enabled in the bootloader - just do the read directly */ |
| int i; |
| uint32_t adc_status; |
| |
| PCLK_ADC |= PCK_EN; /* Enable ADC clock */ |
| |
| /* Start converting the first 4 channels */ |
| for (i = 0; i < 4; i++) |
| ADCCON = i; |
| |
| /* Now read the values back */ |
| for (i=0; i < 4; i++) |
| { |
| /* Wait for data to become stable */ |
| while ((ADCDATA & 0x1) == 0); |
| |
| adc_status = ADCSTATUS; |
| adcdata[(adc_status >> 16) & 0x7] = adc_status & 0x3ff; |
| } |
| |
| PCLK_ADC &= ~PCK_EN; /* Disable ADC clock */ |
| #endif |
| |
| return adcdata[channel]; |
| } |
| |
| void adc_init(void) |
| { |
| /* consider configuring PCK_ADC source here */ |
| |
| ADCCON = (1<<4); /* Enter standby mode */ |
| ADCCFG |= 0x00000003; /* Single-mode, auto power-down */ |
| |
| #ifndef BOOTLOADER |
| ADCCFG |= (1<<3); /* Request IRQ on ADC completion */ |
| IEN |= ADC_IRQ_MASK; /* Unmask ADC IRQs */ |
| |
| tick_add_task(adc_tick); |
| |
| sleep(2); /* Ensure valid readings when adc_init returns */ |
| #endif |
| } |