/* * Open HR20 * * target: ATmega169 @ 4 MHz in Honnywell Rondostat HR20E * * compiler: WinAVR-20071221 * avr-libc 1.6.0 * GCC 4.2.2 * * copyright: 2008 Dario Carluccio (hr20-at-carluccio-dot-de) * 2008 Jiri Dobry (jdobry-at-centrum-dot-cz) * * license: This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 */ /*! * \file adc.c * \brief functions to control Analog / Digtial - Converter * \author Dario Carluccio ; Jiri Dobry * \date $Date$ * $Rev$ */ // AVR LibC includes #include #include #include #include #include #include // HR20 Project includes #include "debug.h" #include "main.h" #include "adc.h" #include "task.h" #include "../common/rtc.h" #include "eeprom.h" #include "com.h" // typedefs // vars static uint8_t state_ADC; uint8_t sleep_with_ADC=0; /*! ******************************************************************************* * Ring buffer for last minute * * make average for last 15 seconds * used for calculate 1 minute difference ******************************************************************************/ static int16_t ring_buf[2][AVERAGE_LEN]; #if ! HW_WINDOW_DETECTION int16_t ring_buf_temp_avgs [AVGS_BUFFER_LEN]; uint8_t ring_buf_temp_avgs_pos; #endif static uint8_t ring_pos=0; static uint8_t ring_used=0; static int32_t ring_sum [2] = {0,0}; int16_t ring_average [2] = {0,0}; static void shift_ring(void) { ring_pos = (ring_pos+1) % AVERAGE_LEN; #if ! HW_WINDOW_DETECTION if (ring_pos==0) { ring_buf_temp_avgs[ring_buf_temp_avgs_pos]=temp_average; ring_buf_temp_avgs_pos = (ring_buf_temp_avgs_pos+1)%AVGS_BUFFER_LEN; } #endif if (ring_used=AVERAGE_LEN) { ring_average[type] = (int16_t) (ring_sum[type]/(int32_t)(AVERAGE_LEN)); } #if DEBUG_BATT_ADC COM_printStr16(PSTR("SU"),ring_sum[BAT_RING_TYPE]); COM_printStr16(PSTR("up"),ring_used*0x100+ring_pos); #endif ring_buf[type][ring_pos]=value; } /*! ******************************************************************************* * Get temperature * * \returns temperature in 1/100 degrees Celsius (1987: 19,87�C) * * \note * - measurment has been performed before using \ref ADC_Measure_Temp * - Attention: negative values are possible ******************************************************************************/ #if 0 int16_t ADC_Get_Temp_Degree(void) // Get Temperature in 1/100 Deg �C { int32_t degree; degree = ADC_Convert_To_Degree(); if (degree < INT16_MIN){ return (INT16_MIN); }else if (degree > INT16_MAX){ return (INT16_MAX); }else{ return ((int16_t) degree); } } #endif /*! ******************************************************************************* * Get battery voltage * * \returns battery voltage in mV * * \note * - measurment has been performed before using \ref ADC_Measure_Ub * - Battery voltage = (V_ref * 1024) / ADC_Val_Ub with V_ref=1.1V ******************************************************************************/ static int16_t ADC_Get_Bat_Voltage(uint16_t adc) // Get Batteriy Voltage in mV { uint32_t millivolt; millivolt = 1126400; millivolt /= adc; return ((int16_t) millivolt); } /*! ******************************************************************************* * Get battery status * * \returns false if battery is low * * \note * - none ******************************************************************************/ #if 0 bool ADC_Get_Bat_isOk(void) { return (ADC_Get_Bat_Voltage() > ADC_LOW_BATT_LEVEL); } #endif /*! ******************************************************************************* * convert ACD value to temperature * * \returns temperature in 1/100 degrees Celsius * * \todo: store values for conversion in EEPROM ******************************************************************************/ static int16_t ADC_Convert_To_Degree(int16_t adc) { int16_t dummy; uint8_t i; int16_t kx=TEMP_CAL_OFFSET+(int16_t)kx_d[0]; for (i=1; i=16 see to \ref ee_config * ADC value is <1024 (OK, only 10-bit AD converter) */ dummy = (int16_t) ( (((int32_t)(adc - kx))*(-TEMP_CAL_STEP)) /(int32_t)(kx_d[i]) ); dummy += TEMP_CAL_N*TEMP_CAL_STEP-((int16_t)(i-1))*TEMP_CAL_STEP; #if TEMP_COMPENSATE_OPTION dummy += (int16_t)config.room_temp_offset*10; #endif return (dummy); } /*! ******************************************************************************* * ADC task * \note ******************************************************************************/ void start_task_ADC(void) { state_ADC=1; // power up ADC power_up_ADC(); // set ADC control and status register ADCSRA = (1<dummy_adc+ADC_TOLERANCE)||(addummy_adc+ADC_TOLERANCE)||(ad