Commit f6e5b259 authored by Jeroen Vreeken's avatar Jeroen Vreeken
Browse files

Working adc

parent 6d45a4f9
all:
@$(MAKE) --no-print-directory -C ../.. targets_controller/am335x
/*
Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2007
Copyright Stichting C.A. Muller Radioastronomiestation, 2007
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2014
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
......@@ -17,50 +16,79 @@
*/
#include "block_am335x_adc.h"
#include <controller/controller_block.h>
#include <log/log.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <inttypes.h>
#include <unistd.h>
struct controller_block_private {
float ain0;
float ain1;
float ain2;
float ain3;
float ain4;
float ain5;
float ain6;
float ain7;
float gain0;
float gain1;
float gain2;
float gain3;
float gain4;
float gain5;
float gain6;
float gain7;
float offset0;
float offset1;
float offset2;
float offset3;
float offset4;
float offset5;
float offset6;
float offset7;
float ain[8];
float gain[8];
float offset[8];
void *base;
};
static uint32_t adc_read(void *base, size_t reg_offset)
{
volatile uint32_t *reg = (uint32_t *)((char *)base + reg_offset);
return *reg;
}
static void adc_write(void *base, size_t reg_offset, uint32_t value)
{
volatile uint32_t *reg = (uint32_t *)((char *)base + reg_offset);
*reg = value;
}
static void adc_calculate(struct controller_block *adc)
{
// struct controller_block_private *priv = adc->private;
struct controller_block_private *priv = adc->private;
void *base = priv->base;
uint32_t data;
uint32_t count;
do {
count = adc_read(base, AM335X_ADC_REG_FIFO0COUNT);
} while (count != 8);
for (; count; count--) {
int id;
data = adc_read(base, AM335X_ADC_REG_FIFO0DATA);
id = AM335X_ADC_FIFODATA_ID_GET(data);
priv->ain[id] =
AM335X_ADC_FIFODATA_DATA_GET(data) * priv->gain[id] +
priv->offset[id];
}
adc_write(base, AM335X_ADC_REG_STEPENABLE,
AM335X_ADC_STEPENABLE_STEP1 | AM335X_ADC_STEPENABLE_STEP2 |
AM335X_ADC_STEPENABLE_STEP3 | AM335X_ADC_STEPENABLE_STEP4 |
AM335X_ADC_STEPENABLE_STEP5 | AM335X_ADC_STEPENABLE_STEP6 |
AM335X_ADC_STEPENABLE_STEP7 | AM335X_ADC_STEPENABLE_STEP8 );
}
static struct controller_block_outterm_list outterms[] = {
{ "ain0", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain0) },
{ "ain1", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain1) },
{ "ain2", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain2) },
{ "ain3", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain3) },
{ "ain4", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain4) },
{ "ain5", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain5) },
{ "ain6", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain6) },
{ "ain7", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain7) },
{ "ain0", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[0]) },
{ "ain1", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[1]) },
{ "ain2", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[2]) },
{ "ain3", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[3]) },
{ "ain4", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[4]) },
{ "ain5", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[5]) },
{ "ain6", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[6]) },
{ "ain7", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, ain[7]) },
{ NULL }
};
......@@ -88,7 +116,52 @@ static void param_set(struct controller_block *adc, int param, va_list val)
{
switch (param) {
case 0:
adc->private->gain0 = va_arg(val, double);
adc->private->gain[0] = va_arg(val, double) * AM335X_ADC_FACTOR;
break;
case 1:
adc->private->gain[1] = va_arg(val, double) * AM335X_ADC_FACTOR;
break;
case 2:
adc->private->gain[2] = va_arg(val, double) * AM335X_ADC_FACTOR;
break;
case 3:
adc->private->gain[3] = va_arg(val, double) * AM335X_ADC_FACTOR;
break;
case 4:
adc->private->gain[4] = va_arg(val, double) * AM335X_ADC_FACTOR;
break;
case 5:
adc->private->gain[5] = va_arg(val, double) * AM335X_ADC_FACTOR;
break;
case 6:
adc->private->gain[6] = va_arg(val, double) * AM335X_ADC_FACTOR;
break;
case 7:
adc->private->gain[7] = va_arg(val, double) * AM335X_ADC_FACTOR;
break;
case 8:
adc->private->offset[0] = va_arg(val, double);
break;
case 9:
adc->private->offset[1] = va_arg(val, double);
break;
case 10:
adc->private->offset[2] = va_arg(val, double);
break;
case 11:
adc->private->offset[3] = va_arg(val, double);
break;
case 12:
adc->private->offset[4] = va_arg(val, double);
break;
case 13:
adc->private->offset[5] = va_arg(val, double);
break;
case 14:
adc->private->offset[6] = va_arg(val, double);
break;
case 15:
adc->private->offset[7] = va_arg(val, double);
break;
}
}
......@@ -96,24 +169,149 @@ static void param_set(struct controller_block *adc, int param, va_list val)
struct controller_block * block_am335x_adc_create(char *name)
{
struct controller_block *adc;
int fd;
void *base;
uint32_t reg;
if (!(adc = controller_block_alloc("am355x_adc", name, sizeof(struct controller_block_private))))
if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0 ) {
log_send(LOG_T_ERROR, "Error opening /dev/mem");
close(fd);
return NULL;
}
base = mmap(NULL, AM335X_ADC_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED,
fd, AM335X_ADC_BASE);
close(fd);
if (!base) {
log_send(LOG_T_ERROR, "Mapping ADC failed");
return NULL;
}
log_send(LOG_T_DEBUG, "%s: ADC mapped @ %p", name, base);
reg = adc_read(base, AM335X_ADC_REG_REVISION);
log_send(LOG_T_DEBUG,
"%s: REVISION: 0x%" PRIx32 ": func: 0x%03x rev: %d.%d",
name, reg, AM335X_ADC_REVISION_FUNC_GET(reg),
AM335X_ADC_REVISION_X_MAJOR_GET(reg),
AM335X_ADC_REVISION_Y_MINOR_GET(reg));
if (AM335X_ADC_REVISION_FUNC_GET(reg) != AM335X_ADC_REVISION_FUNC) {
log_send(LOG_T_ERROR, "Unexpected functional number");
goto err_rev;
}
adc_write(base, AM335X_ADC_REG_CTRL, AM335X_ADC_CTRL_SC_WP_N);
adc_write(base, AM335X_ADC_REG_IRQENABLE_CLR,
AM335X_ADC_IRQENABLE_CLR_ALL);
adc_write(base, AM335X_ADC_REG_DMAENABLE_CLR,
AM335X_ADC_DMAENABLE_CLR_ALL);
adc_write(base, AM335X_ADC_REG_ADC_CLKDIV, 0);
adc_write(base, AM335X_ADC_REG_IDLECONFIG, 0);
adc_write(base, AM335X_ADC_REG_TS_CHARGE_DELAY, 1);
adc_write(base, AM335X_ADC_REG_STEPCONFIG1,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY1, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG2,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(1) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY2, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG3,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(2) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY3, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG4,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(3) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY4, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG5,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(4) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY5, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG6,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(5) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY6, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG7,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(6) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY7, 0);
adc_write(base, AM335X_ADC_REG_STEPCONFIG8,
AM335X_ADC_STEPCONFIG_SEL_RFP_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_RFM_SET(0) |
AM335X_ADC_STEPCONFIG_SEL_INP_SET(7) |
AM335X_ADC_STEPCONFIG_SEL_INM_SET(8) );
adc_write(base, AM335X_ADC_REG_STEPDELAY8, 0);
adc_write(base, AM335X_ADC_REG_CTRL,
AM335X_ADC_CTRL_SC_WP_N |
AM335X_ADC_CTRL_SID |
AM335X_ADC_CTRL_ENABLE);
adc_write(base, AM335X_ADC_REG_STEPENABLE,
AM335X_ADC_STEPENABLE_STEP1 | AM335X_ADC_STEPENABLE_STEP2 |
AM335X_ADC_STEPENABLE_STEP3 | AM335X_ADC_STEPENABLE_STEP4 |
AM335X_ADC_STEPENABLE_STEP5 | AM335X_ADC_STEPENABLE_STEP6 |
AM335X_ADC_STEPENABLE_STEP7 | AM335X_ADC_STEPENABLE_STEP8 );
if (!(adc = controller_block_alloc("am355x_adc", name, sizeof(struct controller_block_private))))
goto err_alloc;
if (controller_block_outterm_list_init(adc, outterms))
goto err_block;
goto err_outterm;
adc->private->base = base;
adc->private->gain[0] = AM335X_ADC_FACTOR;
adc->private->gain[1] = AM335X_ADC_FACTOR;
adc->private->gain[2] = AM335X_ADC_FACTOR;
adc->private->gain[3] = AM335X_ADC_FACTOR;
adc->private->gain[4] = AM335X_ADC_FACTOR;
adc->private->gain[5] = AM335X_ADC_FACTOR;
adc->private->gain[6] = AM335X_ADC_FACTOR;
adc->private->gain[7] = AM335X_ADC_FACTOR;
adc->calculate = adc_calculate;
if (controller_block_param_list_init(adc, params))
goto err_block;
goto err_param;
adc->param_set = param_set;
controller_block_add(adc);
return adc;
err_block:
err_param:
err_outterm:
controller_block_free(adc);
err_alloc:
err_rev:
munmap(base, AM335X_ADC_SIZE);
return NULL;
}
/*
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2014
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/>.
*/
#ifndef _INCLUDE_BLOCK_AM335X_ADC_
#define _INCLUDE_BLOCK_AM335X_ADC_
#define AM335X_ADC_BASE 0x44e0d000
#define AM335X_ADC_SIZE 0x00002000
#define AM335X_ADC_REG_REVISION 0x000
#define AM335X_ADC_REVISION_SCHEME_GET(x) (((x) & 0xc0000000) >> 30)
#define AM335X_ADC_REVISION_FUNC_GET(x) (((x) & 0x0fff0000) >> 16)
#define AM335X_ADC_REVISION_FUNC 0x730
#define AM335X_ADC_REVISION_X_MAJOR_GET(x) (((x) & 0x00000700) >> 8)
#define AM335X_ADC_REVISION_Y_MINOR_GET(x) (((x) & 0x0000001f) )
#define AM335X_ADC_REG_SYSCONFIG 0x010
#define AM335X_ADC_REG_IRQSTATUS_RAW 0x024
#define AM335X_ADC_REG_IRQSTATUS 0x028
#define AM335X_ADC_REG_IRQENABLE_SET 0x02c
#define AM335X_ADC_REG_IRQENABLE_CLR 0x030
#define AM335X_ADC_IRQENABLE_CLR_ALL 0xffffffff
#define AM335X_ADC_REG_IRQWAKEUP 0x034
#define AM335X_ADC_REG_DMAENABLE_SET 0x038
#define AM335X_ADC_REG_DMAENABLE_CLR 0x03c
#define AM335X_ADC_DMAENABLE_CLR_ALL 0x00000003
#define AM335X_ADC_REG_CTRL 0x040
#define AM335X_ADC_CTRL_SC_WP_N 0x00000004
#define AM335X_ADC_CTRL_SID 0x00000002
#define AM335X_ADC_CTRL_ENABLE 0x00000001
#define AM335X_ADC_REG_ADCSTAT 0x044
#define AM335X_ADC_REG_ADCRANGE 0x048
#define AM335X_ADC_REG_ADC_CLKDIV 0x04c
#define AM335X_ADC_REG_ADC_MISC 0x050
#define AM335X_ADC_REG_STEPENABLE 0x054
#define AM335X_ADC_STEPENABLE_STEP1 0x00000002
#define AM335X_ADC_STEPENABLE_STEP2 0x00000004
#define AM335X_ADC_STEPENABLE_STEP3 0x00000008
#define AM335X_ADC_STEPENABLE_STEP4 0x00000010
#define AM335X_ADC_STEPENABLE_STEP5 0x00000020
#define AM335X_ADC_STEPENABLE_STEP6 0x00000040
#define AM335X_ADC_STEPENABLE_STEP7 0x00000080
#define AM335X_ADC_STEPENABLE_STEP8 0x00000100
#define AM335X_ADC_REG_IDLECONFIG 0x058
#define AM335X_ADC_REG_TS_CHARGE_STEPCONFIG 0x05c
#define AM335X_ADC_REG_TS_CHARGE_DELAY 0x060
#define AM335X_ADC_REG_STEPCONFIG1 0x064
#define AM335X_ADC_REG_STEPDELAY1 0x068
#define AM335X_ADC_REG_STEPCONFIG2 0x06c
#define AM335X_ADC_REG_STEPDELAY2 0x070
#define AM335X_ADC_REG_STEPCONFIG3 0x074
#define AM335X_ADC_REG_STEPDELAY3 0x078
#define AM335X_ADC_REG_STEPCONFIG4 0x07c
#define AM335X_ADC_REG_STEPDELAY4 0x080
#define AM335X_ADC_REG_STEPCONFIG5 0x084
#define AM335X_ADC_REG_STEPDELAY5 0x088
#define AM335X_ADC_REG_STEPCONFIG6 0x08c
#define AM335X_ADC_REG_STEPDELAY6 0x090
#define AM335X_ADC_REG_STEPCONFIG7 0x094
#define AM335X_ADC_REG_STEPDELAY7 0x098
#define AM335X_ADC_REG_STEPCONFIG8 0x09c
#define AM335X_ADC_REG_STEPDELAY8 0x0a0
#define AM335X_ADC_REG_STEPCONFIG9 0x0a4
#define AM335X_ADC_REG_STEPDELAY9 0x0a8
#define AM335X_ADC_REG_STEPCONFIG10 0x0ac
#define AM335X_ADC_REG_STEPDELAY10 0x0b0
#define AM335X_ADC_REG_STEPCONFIG11 0x0b4
#define AM335X_ADC_REG_STEPDELAY11 0x0b8
#define AM335X_ADC_REG_STEPCONFIG12 0x0bc
#define AM335X_ADC_REG_STEPDELAY12 0x0c0
#define AM335X_ADC_REG_STEPCONFIG13 0x0c4
#define AM335X_ADC_REG_STEPDELAY13 0x0c8
#define AM335X_ADC_REG_STEPCONFIG14 0x0cc
#define AM335X_ADC_REG_STEPDELAY14 0x0d0
#define AM335X_ADC_REG_STEPCONFIG15 0x0d4
#define AM335X_ADC_REG_STEPDELAY15 0x0d8
#define AM335X_ADC_REG_STEPCONFIG16 0x0dc
#define AM335X_ADC_REG_STEPDELAY16 0x0e0
#define AM335X_ADC_STEPCONFIG_SEL_RFM_SET(x) ((x) << 23)
#define AM335X_ADC_STEPCONFIG_SEL_RFP_SET(x) ((x) << 12)
#define AM335X_ADC_STEPCONFIG_SEL_INP_SET(x) ((x) << 19)
#define AM335X_ADC_STEPCONFIG_SEL_INM_SET(x) ((x) << 15)
#define AM335X_ADC_REG_FIFO0COUNT 0x0e4
#define AM335X_ADC_REG_FIFO0THRESHOLD 0x0e8
#define AM335X_ADC_REG_DMA0REQ 0x0ec
#define AM335X_ADC_REG_FIFO1COUNT 0x0f0
#define AM335X_ADC_REG_FIFO1THRESHOLD 0x0f4
#define AM335X_ADC_REG_DMA1REQ 0x0f8
#define AM335X_ADC_REG_FIFO0DATA 0x100
#define AM335X_ADC_REG_FIFO1DATA 0x200
#define AM335X_ADC_FIFODATA_ID_GET(x) (((x) & 0x000f0000) >> 16)
#define AM335X_ADC_FIFODATA_DATA_GET(x) ((x) & 0x00000fff)
#define AM335X_ADC_FACTOR (1.8/4096.0)
#endif /* _INCLUDE_BLOCK_AM335X_ADC_ */
......@@ -7,7 +7,7 @@ BLOCK_SRCS := \
BLOCK_OBJS := $(BLOCK_SRCS:.c=.lo)
$(BLOCK_OBJS): CFLAGS += -O3 -g -Wall
$(BLOCK_OBJS): CFLAGS += -O3 -Wall
$(LIBDIR)/libam335x.la_LDFLAGS +=
$(LIBDIR)/libam335x.la: $(BLOCK_OBJS)
$(LIB_LINK)
......
......@@ -3,6 +3,7 @@
for lib in $@; do
SYMBOLS=`nm $lib |grep "block_.*_create" |cut -d' ' -f3`
if [ "${SYMBOLS}none" != "none" ]; then
echo -n "$lib "
libla=${lib/.a/.la}
echo -n "${libla/.*lib/} "
fi
done
#!/bin/sh
#!/bin/bash
for lib in $@; do
SYMBOLS=`nm $lib |grep "block_.*_create" |cut -d' ' -f3`
for symbol in $SYMBOLS; do
echo -n "-Wl,-u -Wl,${symbol} "
echo -n "-Wl,-u -Wl,${symbol} ${lib} "
done
done
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment