Compare commits

...

2 commits

Author SHA1 Message Date
Stephan I. Böttcher
6d5e8152aa ads8688: implement adc readout 2024-11-01 21:39:45 +01:00
Stephan I. Böttcher
63d3bf4bc8 ltc2656: deassert ssel before assert 2024-11-01 21:37:12 +01:00
6 changed files with 224 additions and 1 deletions

View file

@ -147,7 +147,7 @@ sources = irena mainloop parser message isr crc \
usb controlpipe usbconfig dma stream \
enc28j60 net udp \
expression variables display \
pressure gpio ltc2656 \
pressure gpio ltc2656 ads8688 \
adc rtc \
plugin \
nomalloc strtol uart uart1 base85

196
ads8688.c Normal file
View file

@ -0,0 +1,196 @@
#include "ads8688.h"
#include "ssp.h"
#include "expression.h"
#include "message.h"
#include <string.h>
#define N 4
static unsigned int timeout = 1000;
static int nread = 2;
static struct ads8688_data {
unsigned short last;
unsigned char feature;
unsigned char alarm;
unsigned char range[8];
unsigned short data[N];
unsigned short first[N];
unsigned int n;
unsigned int sum[N];
int square[N];
} data;
const struct keywords ads8688_variable_names[] = {
VARIABLE("adc_timeout", &timeout),
VARIABLE("adc_nread", &nread),
VARIABLE("adc_last", &data.last),
VARIABLE("adc_range", &data.range),
VARIABLE("adc_data", &data.data),
VARIABLE("adc_avr", &data.n),
VARIABLE("adc_sum", &data.sum),
VARIABLE("adc_square", &data.square),
VARIABLE("ssp_adc", &ssp_conf_adc),
KW_END
};
int ads8688(unsigned short *frame, int n, int flags, int timeout)
{
if (flags & adc_f_init)
ssp_init(&ssp_conf_adc);
else
ssp_deassert_ssel();
ssp_assert_ssel();
ssp_set_buffer(data.data, N);
ssp_set_read(1, n);
ssp_submit(frame, 1, n, 0);
int r = ssp_wait(timeout);
if (!r)
ssp_deassert_ssel();
return r;
}
int adc_cmd(struct command *cmd, const struct command_par *par)
{
static const struct keywords kw[] = {
FLAG_VAL("continue", 0x0000),
FLAG_VAL("standby", 0x8200),
FLAG_VAL("powerdown", 0x8300),
FLAG_VAL("reset", 0x8500),
FLAG_VAL("autochannel",0xa000),
FLAG_VAL("channel", 0xc000),
FLAG_VAL("aux", 0xe000),
FLAG_VAL("autoseqen", 0x0200),
FLAG_VAL("pdown", 0x0400),
FLAG_VAL("feature", 0x0600),
FLAG_VAL("range", 0x0a00),
FLAG_VAL("b10d24", 0x0b00),
FLAG_VAL("u10d24", 0x0b05),
FLAG_VAL("b5d12", 0x0b01),
FLAG_VAL("u5d12", 0x0b06),
FLAG_VAL("b2d56", 0x0b02),
FLAG_VAL("u2d56", 0x0b07),
FLAG_VAL("b1d28", 0x0b03),
FLAG_VAL("u1d28", 0x0b0f),
FLAG_VAL("b0d64", 0x0b0b),
FLAG_VAL("readback", 0x7e00),
FLAG_VAL("alarms", 0x2000),
FLAG_VAL("tripped", 0x2200),
FLAG_VAL("active", 0x2400),
FLAG_VAL("hysteresis", 0x2a00),
FLAG_VAL("highmsb", 0x2c00),
FLAG_VAL("highlsb", 0x2e00),
FLAG_VAL("lowmsb", 0x3000),
FLAG_VAL("lowlsb", 0x3200),
FLAG_VAL("send", 0x10000),
KW_END };
const struct keywords *k;
error_msg_t e = parse_flag(cmd, kw, &k, 2);
unsigned int ch = 0;
unsigned int val = 0;
unsigned int flags = adc_f_init;
unsigned int code = par->code;
unsigned short frame = 0;
unsigned int send = 0;
if (k) {
frame = k->val;
send = k->val & 0xffff0000;
if (send)
e = parse_flag(cmd, kw, &k, 2);
}
// adc/send/«cmd» [«n»] [«timeout»] «value» zero or one value
if (!e)
e = parse_expression_square(cmd, &ch, 1);
if (!e && ch > 8)
e = &parser_value_error;
if (e)
return parser_error_message(cmd, e);
e = parse_expression(cmd, &val);
int r = 0;
if (frame & 0x8000) {
if (frame == 0xc000)
frame |= ch << 10;
if (e)
val = nread;
r = ads8688(&frame, val, flags, timeout);
data.last = frame;
goto done;
}
if (!frame) {
if (nread > N)
nread = N;
memset(&data.n, 0, sizeof(int)*(2*N+1));
if (e || val >= 0x1000)
val = 0x1000;
while (data.n < val) {
r = ads8688(&frame, nread, flags, timeout);
flags = 0;
if (r)
break;
if (!data.n)
memcpy(data.first, data.data, sizeof(data.first));
for (int i=0; i < nread; i++) {
data.sum[i] += data.data[i];
int diff = data.data[i] - data.first[i];
data.square[i] += diff*diff;
}
data.n++;
}
if (!data.n)
goto done;
if (send)
for (int i=0; i < nread; i++)
printf("A %d %d %d 0x%04x %u %d\n",
ch, i, data.n, data.first[i], data.sum[i], data.square[i]);
parser_format_message(cmd, "%03d adc[%u] → [%d] %d %04x %04x %04x %04x\n",
code, ch, r, data.n,
data.sum[0], data.sum[1],
data.sum[2], data.sum[3] );
return code;
}
if (frame == 0x0a00)
frame += ch << 9;
if (frame >= 0x2a00 && frame <= 0x3200)
frame += (5*ch) << 9;
if (frame >= 0x2200 && frame <= 0x2400)
frame += (ch & 4) << 7;
if (!e)
frame |= 0x100 | val & 0xff;
r = ads8688(&frame, 1, flags, timeout);
if (r)
goto done;
if ((frame & 0xff00) == 0x0700)
data.feature = val;
if (frame >= 0x0b00 && frame < 0x1a00 && frame & 0x100)
data.range[((frame>>9)-5)&7] = val;
if (frame == 0x2000)
data.alarm = data.data[0] >> 8;
done:
if (r)
code++;
if (send)
printf("AF 0x%04x %u %d 0x%04x 0x%04x 0x%04x 0x%04x\n",
frame, val, r,
data.data[0], data.data[1],
data.data[2], data.data[3] );
parser_format_message(cmd, "%03d adc 0x%04x → [%d] %04x %04x %04x %04x\n",
code, frame, r,
data.data[0], data.data[1],
data.data[2], data.data[3] );
return code;
}

15
ads8688.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef _ads8688_h_
#define _ads8688_h_
#include "parser.h"
int ads8688(unsigned short *frame, int n, int flags, int timeout);
int adc_cmd(struct command *cmd, const struct command_par *par);
enum adc_flags {
adc_f_init = 1,
};
extern const struct keywords ads8688_variable_names[];
#endif

View file

@ -7,6 +7,8 @@ int ltc2656(unsigned int frame, int flags, int timeout)
{
if (flags & dac_f_init)
ssp_init(&ssp_conf_dac);
else
ssp_deassert_ssel();
ssp_assert_ssel();
ssp_set_buffer(0,0);
unsigned short cmd[2] = { frame >> 16, frame & 0xffff };

View file

@ -27,6 +27,7 @@
#include "plugin.h"
#include "pressure.h"
#include "ltc2656.h"
#include "ads8688.h"
#include "display.h"
// collect command submissions from various sources
@ -525,6 +526,7 @@ static const struct keywords main_command_table[] = {
{"spi", {.par=&plugin_command}},
CMD_KW("pressure", bate_cmd, 360, 0),
CMD_KW("dac", dac_cmd, 362, 0),
CMD_KW("adc", adc_cmd, 364, 0),
{"uart", {.par=&uart_par}},
CMD_KW("uart1", uart1_command, 196, 0),
{"usb", {.par=&usb_command}},
@ -883,6 +885,7 @@ const struct keywords *variable_names[] = {
script_variable_names,
eth_variable_names,
pressure_variable_names,
ads8688_variable_names,
0
};

7
ssp.h
View file

@ -68,4 +68,11 @@ void ssp_set_match(unsigned int mask, unsigned int value,
ssp_read_size = size;
}
static inline
void ssp_set_read(unsigned int count, unsigned int size)
{
ssp_match_count = count;
ssp_read_size = size;
}
#endif