Ajout FishPeper
This commit is contained in:
172
OpenSky/arch/cc251x/hal_adc.c
Normal file
172
OpenSky/arch/cc251x/hal_adc.c
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
Copyright 2017 fishpepper <AT> gmail.com
|
||||
|
||||
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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http:// www.gnu.org/licenses/>.
|
||||
|
||||
author: fishpepper <AT> gmail.com
|
||||
*/
|
||||
|
||||
#include "hal_adc.h"
|
||||
#include "hal_defines.h"
|
||||
#include "hal_cc25xx.h"
|
||||
#include "portmacros.h"
|
||||
#include "config.h"
|
||||
#include "hal_dma.h"
|
||||
#include "debug.h"
|
||||
#include "delay.h"
|
||||
#include "wdt.h"
|
||||
|
||||
|
||||
// adc results
|
||||
__xdata uint16_t hal_adc_data[2];
|
||||
|
||||
void hal_adc_init(void) {
|
||||
hal_adc_data[0] = 0;
|
||||
hal_adc_data[1] = 0;
|
||||
|
||||
// pin config -> dir = input
|
||||
PORT2DIR(ADC_PORT) &= ~((1 << ADC1) | (1 << ADC0));
|
||||
|
||||
// set special function ADC for those pins:
|
||||
ADCCFG = (1 << ADC1) | (1 << ADC0);
|
||||
|
||||
// set up adc:
|
||||
// - external vref (avcc)
|
||||
// - 10bit adc
|
||||
// - stop on AIN7
|
||||
ADCCON2 = ADCCON2_SREF_AVDD | ADCCON2_SDIV_10BIT | ADCCON2_SCH_AIN7;
|
||||
|
||||
// full speed, start conversion (bit0+1 always write as 1...)
|
||||
ADCCON1 = ADCCON1_ST | ADCCON1_STSEL_FULL_SPEED | 0b11;
|
||||
|
||||
// configure DMA1 + DMA2:
|
||||
hal_adc_dma_init(1, &hal_adc_data[0], DMA_TRIG_ADC_CH0 + ADC0);
|
||||
hal_adc_dma_init(2, &hal_adc_data[1], DMA_TRIG_ADC_CH0 + ADC1);
|
||||
|
||||
// set pointer to the DMA configuration struct into DMA-channel 1-4
|
||||
// configuration
|
||||
SET_WORD(DMA1CFGH, DMA1CFGL, &hal_dma_config[1]);
|
||||
|
||||
hal_adc_dma_arm();
|
||||
|
||||
// for testing only, do not use under normal use
|
||||
#if ADC_DO_TEST
|
||||
adc_test();
|
||||
#endif // ADC_DO_TEST
|
||||
}
|
||||
|
||||
void hal_adc_dma_arm(void) {
|
||||
DMAARM = (DMA_ARM_CH1 | DMA_ARM_CH2);
|
||||
}
|
||||
|
||||
void hal_adc_process(void) {
|
||||
if (hal_adc_dma_done()) {
|
||||
// THIS OUTPUT BREAKS CONNECTIVITY! USE FOR DEBUGGING ONLY.
|
||||
// fine, arm dma:
|
||||
hal_adc_dma_arm();
|
||||
} else {
|
||||
// oops this should not happen
|
||||
debug_putc('D');
|
||||
// cancel and re arm dma
|
||||
// DMAARM = DMA_ARM_ABORT | (DMA_ARM_CH1 | DMA_ARM_CH2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hal_adc_dma_init(uint8_t dma_id, uint16_t __xdata *dest_adr, uint8_t trig) {
|
||||
hal_dma_config[dma_id].PRIORITY = DMA_PRI_LOW; // example used high...
|
||||
hal_dma_config[dma_id].M8 = DMA_M8_USE_7_BITS;
|
||||
hal_dma_config[dma_id].IRQMASK = DMA_IRQMASK_DISABLE;
|
||||
hal_dma_config[dma_id].TRIG = trig;
|
||||
hal_dma_config[dma_id].TMODE = DMA_TMODE_BLOCK;
|
||||
hal_dma_config[dma_id].WORDSIZE = DMA_WORDSIZE_BYTE;
|
||||
|
||||
SET_WORD(hal_dma_config[dma_id].SRCADDRH, hal_dma_config[dma_id].SRCADDRL, &X_ADCL);
|
||||
SET_WORD(hal_dma_config[dma_id].DESTADDRH, hal_dma_config[dma_id].DESTADDRL, dest_adr);
|
||||
hal_dma_config[dma_id].VLEN = DMA_VLEN_USE_LEN;
|
||||
|
||||
SET_WORD(hal_dma_config[dma_id].LENH, hal_dma_config[dma_id].LENL, 2);
|
||||
hal_dma_config[dma_id].SRCINC = DMA_SRCINC_1;
|
||||
hal_dma_config[dma_id].DESTINC = DMA_DESTINC_1;
|
||||
}
|
||||
|
||||
uint8_t hal_adc_dma_done(void) {
|
||||
return ((DMAIRQ & (DMA_ARM_CH1 | DMA_ARM_CH2)) == (DMA_ARM_CH1 | DMA_ARM_CH2));
|
||||
}
|
||||
|
||||
uint8_t hal_adc_get_scaled(uint8_t ch) {
|
||||
uint16_t adc_data;
|
||||
// adc data is HHHHHHHHLLLL0000 -> shift >>6 to get 10bit
|
||||
// the cc2510 is _ALWAYS_ outputting data in two's complement format
|
||||
// thus we shift >>7 to get 9 bit two's complement
|
||||
// NOTE: the chip seems to have a bug, in contrast to the datasheet
|
||||
// measuring a signal close to GND seems to deliver negative values (!)
|
||||
// therefore we have to check for negative numbers and set them to zero
|
||||
if (ch == 0) {
|
||||
// convert to 8 bit (see above)
|
||||
adc_data = hal_adc_data[1] >> 7;
|
||||
if (adc_data & (1 << 8)) adc_data = 0; // bugfix: handle negative numbers
|
||||
// return fixed value
|
||||
return adc_data;
|
||||
} else {
|
||||
adc_data = hal_adc_data[0] >> 7;
|
||||
if (adc_data & (1 << 8)) adc_data = 0; // bugfix: handle negative numbers
|
||||
#ifdef ADC1_USE_ACS712
|
||||
// acs712 is connected to ADC1
|
||||
// when powered by 5V we can use a trick
|
||||
// to get a good resolution:
|
||||
// use inverted power inputs to get
|
||||
// 0A = 2.5V
|
||||
// 30A = 0.0V
|
||||
return 255-(adc_data);
|
||||
#else
|
||||
return adc_data;
|
||||
#endif // ADC1_USE_ACS712
|
||||
}
|
||||
}
|
||||
|
||||
#if ADC_DO_TEST
|
||||
void hal_adc_test(void) {
|
||||
debug("adc: running test\n"); debug_flush();
|
||||
|
||||
while (1) {
|
||||
debug("adc: re-arming adc\n"); debug_flush();
|
||||
hal_adc_dma_arm();
|
||||
|
||||
debug("adc: waiting for adc completion\n"); debug_flush();
|
||||
while (!hal_adc_dma_done()) {
|
||||
debug_putc('.');
|
||||
delay_ms(1);
|
||||
}
|
||||
debug("\nadc: done. res[0] = "); debug_flush();
|
||||
|
||||
debug_put_uint16(hal_adc_data[0]>>4);
|
||||
debug_putc('x'); debug_put_hex8(hal_adc_data[0]>>12);
|
||||
debug_put_hex8((hal_adc_data[0]>>4)&0xff);
|
||||
|
||||
debug(", res[1] = "); debug_flush();
|
||||
|
||||
debug_put_uint16(hal_adc_data[1]>>4);
|
||||
debug_putc('x'); debug_put_hex8(hal_adc_data[1]>>12);
|
||||
debug_put_hex8((hal_adc_data[1]>>4)&0xff);
|
||||
|
||||
debug_put_newline();
|
||||
|
||||
delay_ms(100);
|
||||
|
||||
// reset wdt
|
||||
wdt_reset();
|
||||
}
|
||||
}
|
||||
#endif // ADC_DO_TEST
|
||||
Reference in New Issue
Block a user