/***************************************************************************** * * File Name : wm_adc.c * * Description: adc Driver Module * * Copyright (c) 2014 Winner Microelectronics Co., Ltd. * All rights reserved. * * Author : dave * * Date : 2014-8-15 *****************************************************************************/ #include #include #include #include "wm_regs.h" #include "wm_adc.h" #include "wm_dma.h" #include "misc.h" #include "wm_io.h" #include "wm_irq.h" static u16 adc_offset = 0; volatile ST_ADC gst_adc; volatile u8 adc_irq_flag = 0; void ADC_IRQHandler(void) { u16 adcvalue; int reg; reg = tls_reg_read32(HR_SD_ADC_CONFIG_REG); if(reg & CONFIG_ADC_INT) //ADC�ж� { adc_irq_flag = 1; tls_adc_clear_irq(ADC_INT_TYPE_ADC); adcvalue = tls_read_adc_result(); if(gst_adc.adc_cb) gst_adc.adc_cb(&adcvalue,1); } if(reg & CONFIG_ADC_INT_CMP) { tls_adc_clear_irq(ADC_INT_TYPE_ADC_COMP); if(gst_adc.adc_bigger_cb) gst_adc.adc_bigger_cb(NULL, 0); } } static void adc_dma_isr_callbk(void) { if(gst_adc.adc_dma_cb) gst_adc.adc_dma_cb((u16 *)(ADC_DEST_BUFFER_DMA), gst_adc.valuelen); } void tls_adc_init(u8 ifusedma,u8 dmachannel) { tls_reg_write32(HR_SD_ADC_CONFIG_REG, 0x0); tls_irq_enable(ADC_IRQn); //ע���жϺ�channel�йأ�������Ҫ������ if(ifusedma) { gst_adc.dmachannel = tls_dma_request(dmachannel, 0); //����dma����Ҫֱ��ָ������Ϊ�����dma���ܻᱻ�������ʹ�� tls_dma_irq_register(gst_adc.dmachannel, (void(*)(void*))adc_dma_isr_callbk, NULL, TLS_DMA_IRQ_TRANSFER_DONE); } //printf("\ndma channel = %d\n",gst_adc.dmachannel); } void tls_adc_clear_irq(int inttype) { int reg; reg = tls_reg_read32(HR_SD_ADC_CONFIG_REG); if(ADC_INT_TYPE_ADC == inttype) { reg |= CONFIG_ADC_INT; tls_reg_write32(HR_SD_ADC_CONFIG_REG, reg); } else if(ADC_INT_TYPE_ADC_COMP== inttype) { reg |= CONFIG_ADC_INT_CMP; tls_reg_write32(HR_SD_ADC_CONFIG_REG, reg); } else if(ADC_INT_TYPE_DMA == inttype) { tls_dma_irq_clr(gst_adc.dmachannel, TLS_DMA_IRQ_TRANSFER_DONE); } } void tls_adc_irq_register(int inttype, void (*callback)(u16 *buf, u16 len)) { if(ADC_INT_TYPE_ADC == inttype) { gst_adc.adc_cb = callback; } else if(ADC_INT_TYPE_DMA == inttype) { gst_adc.adc_dma_cb = callback; } else if(ADC_INT_TYPE_ADC_COMP == inttype) { gst_adc.adc_bigger_cb = callback; } } u16 tls_read_adc_result(void) { u32 value; u16 ret; value = tls_reg_read32(HR_SD_ADC_RESULT_REG); ret = value&0x3fff; return ret; } void tls_adc_start_with_cpu(int Channel) { u32 value; Channel &= CONFIG_ADC_CHL_MASK; /* Stop adc first */ value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value &= ~CONFIG_ADC_DMA_MASK; value &= ~CONFIG_ADC_START; value |= Channel; tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value |= CONFIG_ADC_START; value |= CONFIG_ADC_INT_MASK; if(Channel < 8) { value |= CONFIG_ADC_G_CTRL12; value &= ~ CONFIG_ADC_VCM(0x3F); value |= CONFIG_ADC_VCM(0x1F); } tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); } void tls_adc_enable_calibration_buffer_offset(void) { u32 value; /* Stop adc first */ value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value &= ~CONFIG_ADC_DMA_MASK; value &= ~CONFIG_ADC_START; tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value |= CONFIG_ADC_CHL_OFFSET; value |= CONFIG_ADC_START; value |= CONFIG_ADC_INT_MASK; value |= CONFIG_ADC_EN_CAL; value |= CONFIG_ADC_G_CTRL12; tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); } void tls_adc_temp_offset_with_cpu(u8 calTemp12) { u32 value; value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value &= ~CONFIG_ADC_DMA_MASK; value &= ~CONFIG_ADC_START; tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value |= CONFIG_ADC_CHL_TEMP; value |= CONFIG_ADC_START; value |= CONFIG_ADC_INT_MASK; if(calTemp12) { value |= CONFIG_ADC_CAL_OFFSET_TEMP12; } else { value &= ~CONFIG_ADC_CAL_OFFSET_TEMP12; } value &= ~CONFIG_ADC_G_CTRL12; value |= CONFIG_ADC_TEMP_ON; value |= CONFIG_ADC_G_TEMP12(3); tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ } void tls_adc_voltage_start_with_cpu(void) { u32 value; value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value &= ~CONFIG_ADC_DMA_MASK; value &= ~CONFIG_ADC_START; tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value |= CONFIG_ADC_CHL_VOLT; value |= CONFIG_ADC_START; value |= CONFIG_ADC_INT_MASK; value |= CONFIG_ADC_G_CTRL12; tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ } void tls_adc_start_with_dma(int Channel, int Length) { u32 value; int len; if(Channel < 0 || Channel > 11) return; if(Length > ADC_DEST_BUFFER_SIZE) len = ADC_DEST_BUFFER_SIZE; else len = Length; gst_adc.valuelen = len; Channel &= CONFIG_ADC_CHL_MASK; value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value &= ~CONFIG_ADC_START; //stop tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /* Stop dma if necessary */ while(DMA_CHNLCTRL_REG(gst_adc.dmachannel) & 1) { DMA_CHNLCTRL_REG(gst_adc.dmachannel) = 2; } DMA_SRCADDR_REG(gst_adc.dmachannel) = HR_SD_ADC_RESULT_REG; DMA_DESTADDR_REG(gst_adc.dmachannel) = ADC_DEST_BUFFER_DMA; /* Hard, Normal, adc_req */ value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); if (Channel == 8){ DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (0+6)<<2); value |= (0x1 << 11); } else if (Channel == 9){ DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (2+6)<<2); value |= (0x1 << 13); } else if (Channel == 10){ DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (4+6)<<2); value |= (0x1 << 15); } else if (Channel == 11){ DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (6+6)<<2); value |= (0x1 << 17); } else{ DMA_MODE_REG(gst_adc.dmachannel) = (0x01 | (Channel+6)<<2); value |= (0x1 << (11 + Channel)); } tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /* Dest_add_inc, halfword, */ DMA_CTRL_REG(gst_adc.dmachannel) = (1<<3)|(1<<5)|((len*2)<<8); DMA_INTMASK_REG &= ~(0x01 << (gst_adc.dmachannel *2 + 1)); DMA_CHNLCTRL_REG(gst_adc.dmachannel) = 1; /* Enable dma */ value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value |= CONFIG_ADC_START; value |= Channel; if(Channel < 8) { value |= CONFIG_ADC_G_CTRL12; value &= ~ CONFIG_ADC_VCM(0x3F); value |= CONFIG_ADC_VCM(0x1F); } // printf("config value==%x\n", value); tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ } void tls_adc_stop(int ifusedma) { u32 value; value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value &= ~CONFIG_ADC_START; tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); if(ifusedma) tls_dma_free(gst_adc.dmachannel); } void tls_adc_config_cmp_reg(int cmp_data, int cmp_pol) { u32 value; cmp_data &= 0x3FFF; value = tls_reg_read32(HR_SD_ADC_RESULT_REG); value &= ~(0x3FFF<<14); value |= (cmp_data<<14); tls_reg_write32(HR_SD_ADC_RESULT_REG, value); value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value |= CONFIG_ADC_CMP_INT_MASK; if(cmp_pol) { value |= CONFIG_ADC_CMP_POL; } else { value &= ~CONFIG_ADC_CMP_POL; } tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); } void tls_adc_cmp_start(int Channel, int cmp_data, int cmp_pol) { u32 value; Channel &= CONFIG_ADC_CHL_MASK; /* Stop adc first */ value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value &= ~CONFIG_ADC_DMA_MASK; value &= ~CONFIG_ADC_START; value |= Channel; tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); tls_adc_config_cmp_reg(cmp_data, cmp_pol); value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); value |= CONFIG_ADC_START; if(Channel < 8) { value |= CONFIG_ADC_G_CTRL12; value &= ~ CONFIG_ADC_VCM(0x3F); value |= CONFIG_ADC_VCM(0x1F); } tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); /*start adc*/ } void tls_adc_reference_sel(int ref) { u32 value; value = tls_reg_read32(HR_SD_ADC_CONFIG_REG); if(ADC_REFERENCE_EXTERNAL == ref) { value &= ~CONFIG_ADC_REF_SEL; value |= CONFIG_ADC_BUF_BYPASS; } else if(ADC_REFERENCE_INTERNAL == ref) { value |= CONFIG_ADC_REF_SEL; value &= ~CONFIG_ADC_BUF_BYPASS; } tls_reg_write32(HR_SD_ADC_CONFIG_REG, value); } void tls_adc_set_clk(int div) { u32 value; value = tls_reg_read32(HR_CLK_DIV_CTL); value &= ~(0xffff<<12); value |= (div << 12); value |= ((u32)0x1<<31); tls_reg_write32(HR_CLK_DIV_CTL, value); } void signedToUnsignedData(u16 *adcValue, u16 *offset) { // s16 temp = 0; if(*adcValue >= 8192) { *adcValue -= 8192; } else { *adcValue += 8192; } /* if (*offset >=8192) { temp =((*offset-1)&0x1FFF) - 8192; }else{ temp = *offset; } *adcValue -= temp; */ } static void waitForAdcDone(void) { while(1) { if(adc_irq_flag) //ADC�ж� { adc_irq_flag = 0; break; } } } static void waitForStable(void) { volatile u32 count; count = 2000; while( count-- ); } u16 adc_get_offset(void) { tls_adc_init(0, 0); tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); adc_irq_flag = 0; waitForStable(); tls_adc_enable_calibration_buffer_offset(); //ʹ��У׼���� waitForAdcDone(); adc_offset = tls_read_adc_result(); //��ȡadcת����� tls_adc_stop(0); //printf("\r\noffset:%d", adc_offset); return adc_offset; } u32 adc_get_interTemp(void) { u16 code2, code1, realCode; u32 tem; tls_adc_init(0, 0); tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); adc_irq_flag = 0; waitForStable(); tls_adc_temp_offset_with_cpu(1); //code2 waitForAdcDone(); code2 = tls_read_adc_result(); tls_adc_stop(0); signedToUnsignedData(&code2, &adc_offset); adc_irq_flag = 0; waitForStable(); tls_adc_temp_offset_with_cpu(0); //code1 waitForAdcDone(); code1 = tls_read_adc_result(); tls_adc_stop(0); signedToUnsignedData(&code1, &adc_offset); realCode = ( (code1-code2)/2+8192 ); //printf("code1:%d, code2:%d, realCode:%d\r\n", code1, code2, realCode); //printf("\r\nTEMP:%.1f", realCode*0.12376-1294.58); //return (realCode*0.12376-1294.58); tem = realCode*124-1294580; //printf("tem:%d\r\n", tem); return tem; } u16 adc_get_inputVolt(u8 channel) { u16 average = 0; /*calibration*/ adc_get_offset(); /*get value*/ tls_adc_init(0, 0); tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); adc_irq_flag = 0; waitForStable(); tls_adc_start_with_cpu(channel); waitForAdcDone(); average = tls_read_adc_result(); tls_adc_stop(0); signedToUnsignedData(&average, &adc_offset); //printf("ch[%d]inputVolt:%.3f\r\n", channel+1, ((average-8192.0)/8192*2.25/1.2 + 1.584)); return average; } u16 adc_get_interVolt(void) { u16 voltValue; /*calibration*/ adc_get_offset(); /*get value*/ tls_adc_init(0, 0); tls_adc_reference_sel(ADC_REFERENCE_INTERNAL); adc_irq_flag = 0; waitForStable(); tls_adc_voltage_start_with_cpu(); waitForAdcDone(); voltValue = tls_read_adc_result(); tls_adc_stop(0); signedToUnsignedData(&voltValue, &adc_offset); float voltage = ( 1.214 - ((float)voltValue-8192)/8192*2.25/1.2 )*2; printf("interVolt:%.2f\r\n", voltage); return voltValue; } u32 adc_temp(void) { u32 tem; adc_get_offset(); tem = adc_get_interTemp(); return tem; }