diff --git a/BSP/linux-kernel/drivers/iio/adc/nvt_adc.c b/BSP/linux-kernel/drivers/iio/adc/nvt_adc.c index 3c8dec601..3e21d97bb 100755 --- a/BSP/linux-kernel/drivers/iio/adc/nvt_adc.c +++ b/BSP/linux-kernel/drivers/iio/adc/nvt_adc.c @@ -20,12 +20,17 @@ #include #include #include - +#include +#include #include #include #include -#define DRV_VERSION "1.03.000" +#include +#include +#include + +#define DRV_VERSION "1.06.003" #ifdef CONFIG_NVT_FPGA_EMULATION #define CALI_VDDADC 3300 @@ -43,7 +48,7 @@ .indexed = 1, \ .channel = num, \ .address = num, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ .scan_index = num, \ .scan_type = { \ @@ -55,11 +60,13 @@ .datasheet_name = id, \ } +static UINT8 debug_adc = 0; + static uint nvt_adc_poll_mode = 1; module_param(nvt_adc_poll_mode, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(nvt_adc_poll_mode, "1:poll mode, 0:irq mode"); -static uint nvt_adc_pow2div = 1; +static uint nvt_adc_pow2div = 7; module_param(nvt_adc_pow2div, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(nvt_adc_pow2div, "adc sample clock pow2 div"); @@ -75,8 +82,54 @@ struct nvt_adc_state { struct clk *clk; unsigned long trim_value; u32 cali_value; + struct delayed_work adc_avg_work;// cal adc mid work + struct proc_dir_entry *pproc_adc; + }; +// ADC Average func // +// data 0 +static UINT32 *t_data = NULL; +static UINT32 t_data_now = 0; // store t_data amount +static UINT32 adc_mid_val = 0; // store average value +static UINT32 adc_mid_vol = 0; // store average voltage +static UINT32 adc_mid = 0; +static UINT32 adc_mid_first = 0; // first read ready + +// data_1 +static UINT32 *t_data1 = NULL; +static UINT32 t_data_now1 = 0; // store t_data amount +static UINT32 adc_mid1_val = 0; // store average value +static UINT32 adc_mid1_vol = 0; // store average voltage +static UINT32 adc_mid1 = 0; +static UINT32 adc_mid1_first = 0; // mid2 first read ready + +// data_2 +static UINT32 *t_data2 = NULL; +static UINT32 t_data_now2 = 0; // store t_data amount +static UINT32 adc_mid2_val = 0; // store average value +static UINT32 adc_mid2_vol = 0; // store average voltage +static UINT32 adc_mid2 = 0; +static UINT32 adc_mid2_first = 0; // mid2 first read ready + +// data_3 +static UINT32 *t_data3 = NULL; +static UINT32 t_data_now3 = 0; // store t_data amount +static UINT32 adc_mid3_val = 0; // store average value +static UINT32 adc_mid3_vol = 0; // store average voltage +static UINT32 adc_mid3 = 0; +static UINT32 adc_mid3_first = 0; // mid2 first read ready +// + +static u32 adc_base = 0; +static UINT32 adc_trim = 0; + +static UINT32 adc_avg_times = 50; +static UINT32 filter = 3 ; +static UINT32 avg_sel = 3; +static UINT32 avg_sel_sts = 0; + + static u32 adc_getreg(struct nvt_adc_state *adc, u32 offset) { return nvt_readl(adc->base + offset); @@ -121,10 +174,414 @@ static void adc_set_default_hw(struct nvt_adc_state *adc) ctrl_reg.bit.clkdiv = nvt_adc_pow2div; ctrl_reg.bit.sampavg = 0; ctrl_reg.bit.extsamp_cnt = nvt_adc_plusdiv; - ctrl_reg.bit.adc_en = 0; + ctrl_reg.bit.adc_en = 1; adc_setreg(adc, ADC_CTRL_REG_OFS, ctrl_reg.reg); } +#if 1 +static int nvt_adc_read_avg_int(void) +{ + t_data = (int*)kmalloc(sizeof(int) * adc_avg_times , GFP_KERNEL); + memset(t_data ,0, adc_avg_times*sizeof(int)); + + t_data1 = (int*)kmalloc(sizeof(int) * adc_avg_times , GFP_KERNEL); + memset(t_data1 ,0, adc_avg_times*sizeof(int)); + + t_data2 = (int*)kmalloc(sizeof(int) * adc_avg_times , GFP_KERNEL); + memset(t_data2 ,0, adc_avg_times*sizeof(int)); + + t_data3 = (int*)kmalloc(sizeof(int) * adc_avg_times , GFP_KERNEL); + memset(t_data3 ,0, adc_avg_times*sizeof(int)); + + return 1; +} + +static void nvt_adc_read_avg(struct work_struct *work) //(struct nvt_adc_state *adc, u8 channel) +{ + UINT32 adc_data = 0; + UINT32 i = 0, temp = 0; + UINT32 channel = 0; + + struct nvt_adc_state *adc = container_of(work, struct nvt_adc_state, + adc_avg_work.work); + + //adc_mid_val = adc_mid; + //adc_mid_vol = (adc_mid +CALI_OFFSET)*adc_trim/511; + //printk("\n adc_mid = %d , adc_mid_val = %d , adc_mid_vol = %d \r\n\n", adc_mid, adc_mid_val, adc_mid_vol); + if (adc_mid3_first == 0) { + //schedule_delayed_work(&adc->adc_avg_work, msecs_to_jiffies(10)); + goto adc_avg_work ; + } + + // data 0 + if( avg_sel == 0 ){ + + if (adc_mid_first == 0 ){ // firstly ready + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + adc_mid = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + + }else{ + adc_mid_val = adc_mid; + adc_mid_vol = (adc_mid + CALI_OFFSET)*adc_trim/511; + adc_mid_first++ ; + } + + }else { + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + temp = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + + }else { + + if( (temp <= (adc_mid + filter)) && (temp >= (adc_mid - filter) ) ){ + t_data[t_data_now] = temp; + t_data_now++; + } + if (t_data_now != 0 && debug_adc){ + printk("0.temp = %d, t_data[t_data_now = %d] = %d , adc_mid = %u, filter = %u\r\n",temp, t_data_now-1, t_data[t_data_now-1], adc_mid, filter); + } + + // calculate average + if (t_data_now >= adc_avg_times ){ + adc_data = 0; + for( i = 0 ; i < adc_avg_times ; i++ ){ + adc_data += t_data[i]; + } + + adc_data = adc_data / adc_avg_times ; + + adc_mid_val = adc_data; + adc_mid = adc_data; + t_data_now = 0 ; + + adc_mid_val = adc_mid; + adc_mid_vol = (adc_mid +CALI_OFFSET)*adc_trim/511; + + printk("reset0 adc_mid_val = %d, adc_mid_vol = %d \r\n",adc_mid_val, adc_mid_vol); + } + } + } + + + // data 1 + } else if( avg_sel == 1 ) { + + if (adc_mid1_first == 0 ){ // firstly ready + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + adc_mid1 = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } else { + adc_mid1_val = adc_mid1; + adc_mid1_vol = (adc_mid1 + CALI_OFFSET)*adc_trim/511; + adc_mid1_first++ ; + } + + + }else{ + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + temp = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + + } else { + if( (temp <= (adc_mid1 + filter)) && (temp >= (adc_mid1 - filter) ) ){ + t_data1[t_data_now1] = temp; + t_data_now1++; + } + + if (t_data_now1 != 0 && debug_adc){ + printk("1.temp = %d, t_data1[t_data_now1 = %d] = %d \r\n",temp ,t_data_now1-1, t_data1[t_data_now1-1]); + } + + // calculate average + if (t_data_now1 >= adc_avg_times ){ + adc_data = 0; + for( i = 0 ; i < adc_avg_times ; i++ ){ + adc_data += t_data1[i]; + } + + adc_data = adc_data / adc_avg_times ; + + adc_mid1_val = adc_data; + adc_mid1 = adc_data; + t_data_now1 = 0 ; + + adc_mid1_val = adc_mid1; + adc_mid1_vol = (adc_mid1 +CALI_OFFSET)*adc_trim/511; + + printk("reset1 adc_mid1 = %d, adc_mid1_vol = %d \r\n",adc_mid1, adc_mid1_val); + } + } + } + + // data 2 + } else if( avg_sel == 2 ) { + + if (adc_mid2_first == 0 ){ // firstly ready + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + adc_mid2 = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } else { + adc_mid2_val = adc_mid2; + adc_mid2_vol = (adc_mid2 + CALI_OFFSET)*adc_trim/511; + adc_mid2_first++ ; + } + + + }else{ + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + temp = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + + } else { + if( (temp <= (adc_mid2 + filter)) && (temp >= (adc_mid2 - filter) ) ){ + t_data2[t_data_now2] = temp; + t_data_now2++; + } + + if (t_data_now2 != 0 && debug_adc){ + printk("2.temp = %d, t_data2[t_data_now2 = %d] = %d \r\n",temp ,t_data_now2-1, t_data2[t_data_now2-1]); + } + + // calculate average + if (t_data_now2 >= adc_avg_times ){ + adc_data = 0; + for( i = 0 ; i < adc_avg_times ; i++ ){ + adc_data += t_data2[i]; + } + + adc_data = adc_data / adc_avg_times ; + + adc_mid2_val = adc_data; + adc_mid2 = adc_data; + t_data_now2 = 0 ; + + adc_mid2_val = adc_mid2; + adc_mid2_vol = (adc_mid2 +CALI_OFFSET)*adc_trim/511; + + printk("reset2 adc_mid2 = %d, adc_mid2_vol = %d \r\n",adc_mid2, adc_mid2_val); + } + } + } + + // data 3 + } else if( avg_sel == 3 ) { + + if (adc_mid3_first == 0 ){ // firstly ready + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + adc_mid3 = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } else { + adc_mid3_val = adc_mid3; + adc_mid3_vol = (adc_mid3 + CALI_OFFSET)*adc_trim/511; + adc_mid3_first++ ; + } + + + }else{ + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + } + temp = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + channel*4); + + if (avg_sel_sts == 1 ){ + mdelay(1); + avg_sel_sts = 0; + + } else { + if( (temp <= (adc_mid3 + filter)) && (temp >= (adc_mid3 - filter) ) ){ + t_data3[t_data_now3] = temp; + t_data_now3++; + } + + if (t_data_now3 != 0 && debug_adc){ + printk("3.temp = %d, t_data3[t_data_now3 = %d] = %d \r\n",temp ,t_data_now3-1, t_data3[t_data_now3-1]); + } + + // calculate average + if (t_data_now3 >= adc_avg_times ){ + adc_data = 0; + for( i = 0 ; i < adc_avg_times ; i++ ){ + adc_data += t_data3[i]; + } + + adc_data = adc_data / adc_avg_times ; + + adc_mid3_val = adc_data; + adc_mid3 = adc_data; + t_data_now3 = 0 ; + + adc_mid3_val = adc_mid3; + adc_mid3_vol = (adc_mid3 +CALI_OFFSET)*adc_trim/511; + + printk("reset3 adc_mid3 = %d, adc_mid3_vol = %d adc_mid3_vol=%u\r\n",adc_mid3, adc_mid3_val, adc_mid3_vol); + } + } + } + } + + adc_avg_work : + schedule_delayed_work(&adc->adc_avg_work, msecs_to_jiffies(5)); +} +#endif +#if 1 + +#define MAX_CMD_LENGTH 10 +static ssize_t data_proc_cmd_write(struct file *file, const char __user *buf, + size_t size, loff_t *off) +{ + int val; + int len = size; + char cmd_line[MAX_CMD_LENGTH]; + char *cmdstr = cmd_line; + const char delimiters[] = {' ', 0x0A, 0x0D, '\0'}; + char *p_arg; + union ADC_CTRL_REG ctrl_reg; + UINT32 temp; + + // check command length + if (len > (MAX_CMD_LENGTH - 1)) { + printk("%s: Command length %d is too long\n", __func__, len); + return -EINVAL; + } + + // copy command string from user space + if (copy_from_user(cmd_line, buf, len)) { + return -EINVAL; + } + + if (len == 0) + cmd_line[0] = '\0'; + else + cmd_line[len - 1] = '\0'; + + p_arg = strsep(&cmdstr, delimiters); + sscanf(p_arg, "%x", &val); + + // set avg_sel = 0 or 1 for 1 CH connect two device + avg_sel = val; + avg_sel_sts = 1; + + printk("avg_sel = %d \n", avg_sel); + + if ( avg_sel == 5 ){ + + // Check ADC is Enable + ctrl_reg.reg = nvt_readl(adc_base + ADC_CTRL_REG_OFS); + if(!ctrl_reg.bit.adc_en){ + ctrl_reg.reg = nvt_readl(adc_base + ADC_CTRL_REG_OFS); + ctrl_reg.bit.adc_en = 1; + nvt_writel(ctrl_reg.reg, adc_base + ADC_CTRL_REG_OFS); + } + + // second value + temp = nvt_readl(adc_base + ADC_AIN0_DATA_REG_OFS + 0*4); + printk("ch0 second val = %d \n", temp); + + // cal second trim2 + if(temp) + adc_trim = adc_mid3_vol * 511 / temp ; + else{ + adc_trim = 511; + printk("!!!!!!!!! temp is zero\n"); + } + + printk("adc_trim = %d \n", adc_trim); + + t_data3[t_data_now3] = temp; + t_data_now3++; + adc_mid3 = temp; + adc_mid3_val = adc_mid3; + adc_mid3_vol = (adc_mid3 + CALI_OFFSET)*adc_trim/511; + + adc_mid3_first = 1 ; + + } + + return size; +} + + +static int adc_proc_show(struct seq_file *seq, void *v) +{ + UINT32 volt = 0 ; + //printk("adc_avg_value = %d, adc_avg_voltage = %d \n", adc_mid_val, adc_mid_vol); + //printk("adc_avg2 value = %d, adc2_avg_voltage = %d \n", adc_mid1_val, adc_mid1_vol); + if ( avg_sel == 0 ){ + //printk("%d\n", adc_mid_vol); + volt = adc_mid_vol; + }else if ( avg_sel == 1 ){ + //printk("%d\n", adc_mid1_vol); + volt = adc_mid1_vol; + }else if ( avg_sel == 2 ){ + //printk("%d\n", adc_mid2_vol); + volt = adc_mid2_vol; + }else if ( avg_sel == 3 ){ + printk("adc_mid3_vol = %d\n", adc_mid3_vol); + volt = adc_mid3_vol; + } + seq_printf(seq,"%d\n",volt); + + return 0; +} + +static int adc_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, adc_proc_show, NULL); +} + +static struct file_operations proc_adc_fops = { + .owner = THIS_MODULE, + .open = adc_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = data_proc_cmd_write, +}; + + + + +#endif + static u32 nvt_adc_get_value(struct nvt_adc_state *adc, u8 channel) { u16 adc_data; @@ -150,6 +607,16 @@ static int nvt_adc_read_raw(struct iio_dev *iio, *value = nvt_adc_get_value(adc, channel->address); return IIO_VAL_INT; + // Read Average + case IIO_CHAN_INFO_AVERAGE_RAW: + if ( avg_sel == 0 ){ + *value = adc_mid_vol; + }else{ + *value = adc_mid1_vol; + } + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: printk("IIO_CHAN_INFO_SCALE\n"); return IIO_VAL_FRACTIONAL_LOG2; @@ -188,7 +655,7 @@ static ssize_t nvt_adc_enable(struct device *dev, ret = kstrtoul(buf, 10, &input); if (ret < 0) return ret; - + adc_set_enable(adc, input); return len; @@ -408,6 +875,8 @@ static void nvt_adc_get_trimdata(struct nvt_adc_state *adc) } } #endif + adc_trim = adc->cali_value; + //printk("adc_trim = %d \r\n",adc_trim); } #endif @@ -415,9 +884,15 @@ static int nvt_adc_probe(struct platform_device *pdev) { struct iio_dev *iio; struct nvt_adc_state *adc; - int err = 0, irq; + int err = 0, irq , i=0; struct resource *res; struct thermal_zone_device *thermal_zone = NULL; + int ret_avg = 0; + struct proc_dir_entry *pentry = NULL; + + union ADC_AIN0_DATA_REG data_reg; + union ADC_STATUS_REG sts_reg; + #ifdef CONFIG_OF const struct of_device_id *of_id; @@ -426,19 +901,19 @@ static int nvt_adc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "[NVT ADC] OF not found\n"); return -EINVAL; } - //pr_info("%s %d: of_id->compatible = %s\n", __func__, __LINE__, of_id->compatible); #endif - - adc = kzalloc(sizeof(struct nvt_adc_state), GFP_KERNEL); - if (!adc) - return -ENOMEM; - - iio = iio_device_alloc(sizeof(*adc)); - if (!iio) +printk("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + iio = iio_device_alloc(sizeof(struct nvt_adc_state) ); + if (!iio){ return -ENOMEM; + } adc = iio_priv(iio); + if (!adc ){ + err = -ENOMEM; + goto iio_free; + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -450,6 +925,8 @@ static int nvt_adc_probe(struct platform_device *pdev) if (!adc->base) goto iio_free; + adc_base = (u32)adc->base; + adc->clk = clk_get(&pdev->dev, dev_name(&pdev->dev)); if (!IS_ERR(adc->clk)) { clk_prepare(adc->clk); @@ -485,7 +962,7 @@ static int nvt_adc_probe(struct platform_device *pdev) adc->sample_rate = (clk_get_rate(adc->clk) / (2 * (nvt_adc_pow2div + 1))) / (4 * (26 + nvt_adc_plusdiv)); adc_set_default_hw(adc); - + iio->name = "nvt_adc"; iio->modes = INDIO_DIRECT_MODE; iio->info = &nvt_adc_info; @@ -503,12 +980,83 @@ static int nvt_adc_probe(struct platform_device *pdev) pr_info("%s: %s done voltage %d ver %s\n", __func__, dev_name(&pdev->dev), adc->cali_value, DRV_VERSION); + udelay(30); + + // if data ready + for( i = 0 ; i< 5 ; i++ ){ + sts_reg.reg = adc_getreg(adc, ADC_STATUS_REG_OFS); + if(sts_reg.bit.ain0_datardy ==1 ){ + break; + } + udelay(50); + } + + if (i==5){ + printk("\n adc ready timout !!\r\n"); + } + data_reg.reg = adc_getreg(adc, ADC_AIN0_DATA_REG_OFS); + + // read first value + adc_mid3_first = 0; + if ( avg_sel == 0 ){ + adc_mid = data_reg.reg; + adc_mid_first = 1 ; // already get firstly value + adc_mid_val = adc_mid; + adc_mid_vol = (adc_mid +CALI_OFFSET)*adc_trim/511; + + printk("adc_mid first value = %u\n", adc_mid_val); + + }else if(avg_sel == 1 ) { + adc_mid1 = data_reg.reg; + adc_mid1_first = 1 ; // already get firstly value + adc_mid1_val = adc_mid1; + adc_mid1_vol = (adc_mid1 +CALI_OFFSET)*adc_trim/511; + + printk("adc_mid1 first value = %u\n", adc_mid1_val); + + }else if(avg_sel == 2 ) { + adc_mid2 = data_reg.reg; + adc_mid2_first = 1 ; // already get firstly value + adc_mid2_val = adc_mid2; + adc_mid2_vol = (adc_mid2 +CALI_OFFSET)*adc_trim/511; + + printk("adc_mid2 first value = %u\n", adc_mid2_val); + + }else if(avg_sel == 3 ) { + adc_mid3 = data_reg.reg; +// adc_mid3_first = 1 ; // already get firstly value + adc_mid3_val = adc_mid3; + adc_mid3_vol = (adc_mid3 +CALI_OFFSET)*adc_trim/511; + + printk("adc_mid3 first value = %u\n", adc_mid3_val); + } + + +#if 1 + // ADC Average data + /* tempeture compensation */ + ret_avg = nvt_adc_read_avg_int(); + + if(ret_avg){ + INIT_DELAYED_WORK(&adc->adc_avg_work, nvt_adc_read_avg); + schedule_delayed_work(&adc->adc_avg_work, msecs_to_jiffies(1)); + } + + pentry = proc_create("adc", 0, NULL, &proc_adc_fops); + if (pentry == NULL) { + dev_err(&pdev->dev, "failed to create adc proc!\n"); + err = -EINVAL; + goto t_data_free; + } + adc->pproc_adc = pentry; +#endif thermal_zone = thermal_zone_device_register("nvt_thermal", 0, 0, adc, &ops, NULL, 0, 0); if (IS_ERR(thermal_zone)) { dev_err(&pdev->dev, "thermal zone device is NULL\n"); - return PTR_ERR(thermal_zone); + err = PTR_ERR(thermal_zone); + goto t_data_free; } thermal_get_trimdata(adc); @@ -518,7 +1066,14 @@ static int nvt_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, thermal_zone); return 0; - + +t_data_free: + cancel_delayed_work(&adc->adc_avg_work); + kfree(t_data); + kfree(t_data1); + kfree(t_data2); + kfree(t_data3); + iio_free: iio_device_free(iio); @@ -527,10 +1082,16 @@ iio_free: static int nvt_adc_remove(struct platform_device *pdev) { - struct iio_dev *iio = platform_get_drvdata(pdev);; + struct iio_dev *iio = platform_get_drvdata(pdev); + struct nvt_adc_state *adc ; + adc = iio_priv(iio); + + cancel_delayed_work(&adc->adc_avg_work); iio_device_unregister(iio); iio_device_free(iio); + remove_proc_entry("adc", NULL); + kfree(t_data); return 0; } diff --git a/code/lib/include/io/adc.h b/code/lib/include/io/adc.h index ab00c8513..a12312e36 100755 --- a/code/lib/include/io/adc.h +++ b/code/lib/include/io/adc.h @@ -379,6 +379,7 @@ extern UINT32 adc_readData(ADC_CHANNEL Channel); extern BOOL adc_isDataReady(ADC_CHANNEL Channel); extern void adc_clearDataReady(ADC_CHANNEL Channel); extern UINT32 adc_readVoltage(ADC_CHANNEL Channel); +extern UINT32 adc_readVoltage_channel0_avg(UINT32 device_id, UINT32 delay_time_ms); extern UINT32 adc_thermal_read_data(void); extern UINT32 adc_thermal_read_voltage(void); diff --git a/code/lib/source/io/libio.a b/code/lib/source/io/libio.a old mode 100644 new mode 100755 index 8ef69015f..2a596557a Binary files a/code/lib/source/io/libio.a and b/code/lib/source/io/libio.a differ diff --git a/code/lib/source/io/libio.so b/code/lib/source/io/libio.so index a4bbdcfcb..580629639 100755 Binary files a/code/lib/source/io/libio.so and b/code/lib/source/io/libio.so differ