Compare commits
4 commits
0feba685ea
...
6ad8702936
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ad8702936 | ||
|
|
131d90dd9d | ||
|
|
d6be6f5afe | ||
|
|
dfbbb088d2 |
8 changed files with 466 additions and 144 deletions
462
ads8688.c
462
ads8688.c
|
|
@ -5,34 +5,340 @@
|
|||
#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),
|
||||
KW_END
|
||||
struct ads8688_control;
|
||||
typedef int (*adc_callback_t)(struct ads8688_control *);
|
||||
static struct ads8688_control {
|
||||
unsigned int status;
|
||||
unsigned short frame;
|
||||
unsigned short frame2;
|
||||
unsigned short channels;
|
||||
unsigned short nbuf;
|
||||
unsigned short nchannels;
|
||||
unsigned short tchannels;
|
||||
unsigned int gains;
|
||||
unsigned int first[10];
|
||||
unsigned int sum[10];
|
||||
int square[10];
|
||||
unsigned int navg[10];
|
||||
struct ssp_job job;
|
||||
struct ssp_match match;
|
||||
adc_callback_t callback;
|
||||
} ads8688_control;
|
||||
|
||||
void ads8688_readings(struct ads8688_control *c, unsigned int cc, int i, int ii)
|
||||
{
|
||||
unsigned short first = ssp_buffer[0];
|
||||
unsigned int sum = first;
|
||||
int square = 0;
|
||||
int n = 1;
|
||||
unsigned short sdo = 0;
|
||||
if (!i && ii > 1)
|
||||
sdo = ssp_buffer[1];
|
||||
while (i < c->nbuf) {
|
||||
int d = ssp_buffer[i];
|
||||
sum += d;
|
||||
d -= first;
|
||||
square += d*d;
|
||||
n++;
|
||||
i += ii;
|
||||
}
|
||||
if (cc > 9)
|
||||
cc = 9;
|
||||
c->sum[cc] = sum;
|
||||
c->square[cc] = square;
|
||||
c->navg[cc] = n;
|
||||
c->first[cc] = sdo<<16 | first;
|
||||
cc = 1<<cc;
|
||||
c->nchannels |= cc;
|
||||
c->tchannels |= cc;
|
||||
c->status |= 0x10000 | cc<<8;
|
||||
}
|
||||
|
||||
static inline int tcnh_cb(struct ads8688_control *c)
|
||||
{
|
||||
c->status |= 0xE0000000;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int alldone_cb(struct ads8688_control *c)
|
||||
{
|
||||
c->status |= 0xD0000000;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_cb(struct ads8688_control *c)
|
||||
{
|
||||
c->status = c->status & 0xff | 0x300;
|
||||
if ((c->frame & 0xf0ff) != 0xc000)
|
||||
return tcnh_cb(c);
|
||||
unsigned int cc = c->frame >> 8 & 0xf;
|
||||
if (cc <= 8) {
|
||||
ads8688_readings(c, cc, 0, c->match.read_count);
|
||||
cc++;
|
||||
}
|
||||
if (cc == 15)
|
||||
cc = 0;
|
||||
while (cc <= 8 && !(c->channels & 1<<cc))
|
||||
cc++;
|
||||
if (cc > 8)
|
||||
return alldone_cb(c);
|
||||
c->frame = 0xc000 | cc;
|
||||
ssp_set_buffer(0, c->nbuf);
|
||||
return ssp_submit_batch(&c->frame, 1, 2, 0, 0);
|
||||
}
|
||||
|
||||
static int read_auto_cb(struct ads8688_control *c)
|
||||
{
|
||||
c->status = c->status & 0xff | 0x400;
|
||||
if (c->frame == 0xa000) {
|
||||
int ii = 0;
|
||||
int i = 0;
|
||||
unsigned int cc = c->channels;
|
||||
while (cc) {
|
||||
cc >>= 1;
|
||||
ii++;
|
||||
}
|
||||
for (cc=0; cc<8; cc++)
|
||||
if (c->channels & 1<<cc)
|
||||
ads8688_readings(c, cc, i++, ii);
|
||||
return alldone_cb(c);
|
||||
}
|
||||
if (c->frame == 0)
|
||||
c->frame = 0x0300 | c->channels & 0xff;
|
||||
else if ((c->frame & 0xff) == 0x03)
|
||||
c->frame = 0xa000;
|
||||
else
|
||||
return tcnh_cb(c);
|
||||
ssp_set_buffer(0, c->nbuf);
|
||||
return ssp_submit_batch(&c->frame, 1, 2, 0, 0);
|
||||
}
|
||||
|
||||
inline static
|
||||
unsigned int save_gain(unsigned short frame, unsigned short data, unsigned int *gains)
|
||||
{
|
||||
unsigned int cc = (frame >> 9) - 5 & 15;
|
||||
if (cc > 8 || frame & 0x100)
|
||||
return cc;
|
||||
unsigned int g = data >> 8 & 15;
|
||||
*gains &= ~(0xf << 4*cc);
|
||||
*gains |= g << 4*cc;
|
||||
return cc;
|
||||
}
|
||||
|
||||
static int gains_cb(struct ads8688_control *c)
|
||||
{
|
||||
c->status = c->status & ~0xf00 | 0x500;
|
||||
unsigned short f = c->frame;
|
||||
if (f & 0x1e00)
|
||||
return tcnh_cb(c);
|
||||
unsigned int cc = save_gain(f, *ssp_buffer, &c->gains);
|
||||
if (cc == 11)
|
||||
cc = 0;
|
||||
else if (cc >= 8)
|
||||
return alldone_cb(c);
|
||||
else
|
||||
c->status |= 0x10000 | cc<<8;
|
||||
c->frame = cc + 5 << 9;
|
||||
if (f & 0x100)
|
||||
c->frame |= 0x100 | c->gains >> 4*cc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ads8688_cb(const struct ssp_batch *b)
|
||||
{
|
||||
struct ads8688_control *c = b->data;
|
||||
c->status = c->status + 1 & 0xff | 0x200;
|
||||
return c->callback(c);
|
||||
}
|
||||
|
||||
static const struct ssp_batch ads8688_batch[] = {
|
||||
[0] = {
|
||||
.flags = ssp_b_config,
|
||||
{ .ssel = &ssp_conf_adc },
|
||||
},
|
||||
[1] = {
|
||||
.flags = ssp_b_call,
|
||||
{ .callback = ads8688_cb },
|
||||
{ .data = &ads8688_control },
|
||||
},
|
||||
[2] {
|
||||
.flags = ssp_b_job
|
||||
| SSP_B_REPEAT(256) | ssp_b_whilebuf
|
||||
| ssp_b_deassert | ssp_b_assert | SSP_B_DELAY(10),
|
||||
{ .job = &ads8688_control.job},
|
||||
{ .match = &ads8688_control.match},
|
||||
},
|
||||
[3] {
|
||||
.flags = ssp_b_goto | SSP_B_JUMP(-2) | ssp_b_stop,
|
||||
},
|
||||
};
|
||||
|
||||
static int ads8688_start(int nskip, int nread)
|
||||
{
|
||||
struct ads8688_control *c = &ads8688_control;
|
||||
c->status = 0x100;
|
||||
c->job.command = &c->frame;
|
||||
c->job.count = 1 + nskip + nread;
|
||||
c->job.idle_frame = 0;
|
||||
c->match.frame_count = nskip;
|
||||
c->match.read_count = nread;
|
||||
return ssp_start_batch(ads8688_batch, 0);
|
||||
}
|
||||
|
||||
int adc_gains_cmd(struct command *cmd, const struct command_par *par)
|
||||
{
|
||||
static const struct keywords kw[] = { FLAG_VAL("read", 0), {}};
|
||||
const struct keywords *k;
|
||||
error_msg_t e = parse_flag(cmd, kw, &k, 2);
|
||||
if (e)
|
||||
return parser_error_message(cmd, e);
|
||||
|
||||
struct ads8688_control *c = &ads8688_control;
|
||||
c->frame = 0; // read
|
||||
unsigned int oldgains = c->gains;
|
||||
if (!k) {
|
||||
parse_expression(cmd, &c->gains);
|
||||
c->frame = 0x0100; // write
|
||||
}
|
||||
unsigned int newgains = c->gains; // volatile
|
||||
|
||||
c->nbuf = 8;
|
||||
c->job.cmd_count = 1;
|
||||
c->callback = gains_cb;
|
||||
int r = ads8688_start(1, 1);
|
||||
int code = par->code;
|
||||
if (r)
|
||||
code++;
|
||||
parser_format_message(cmd, "%03d gains[%04x/%d] 0x%08x → 0x%08x\n",
|
||||
code, c->frame, r, oldgains, newgains);
|
||||
return code;
|
||||
}
|
||||
|
||||
int adc_read_cmd(struct command *cmd, const struct command_par *par)
|
||||
{
|
||||
static const struct keywords kw[] = { FLAG_VAL("auto", 0), {}};
|
||||
const struct keywords *k;
|
||||
error_msg_t e = parse_flag(cmd, kw, &k, 2);
|
||||
if (e)
|
||||
return parser_error_message(cmd, e);
|
||||
|
||||
struct ads8688_control *c = &ads8688_control;
|
||||
parse_expression(cmd, (unsigned int *)&c->channels); // { nbuf, aidx, ch}
|
||||
int aidx = c->channels >> 12;
|
||||
|
||||
if (!k) {
|
||||
c->frame = 0xcf00;
|
||||
c->callback = read_cb;
|
||||
}
|
||||
else {
|
||||
c->frame = 0x0000;
|
||||
c->callback = read_auto_cb;
|
||||
}
|
||||
c->job.cmd_count = 0; // idle_frame = continue command
|
||||
int r = ads8688_start(aidx+1, 1);
|
||||
int code = par->code;
|
||||
if (r)
|
||||
code++;
|
||||
parser_format_message(cmd, "%03d adc read (%d) 0x%04x 0x%08x\n",
|
||||
code, r, c->channels, c->status);
|
||||
return code;
|
||||
}
|
||||
|
||||
int adc_print_cmd(struct command *cmd, const struct command_par *par)
|
||||
{
|
||||
struct ads8688_control *c = &ads8688_control;
|
||||
|
||||
int code = par->code;
|
||||
static const struct keywords kw[] = {
|
||||
FLAG_VAL("status", 0x01000000),
|
||||
FLAG_VAL("wait", 0x02000000),
|
||||
FLAG_VAL("send", 0x00010000),
|
||||
FLAG_VAL("msg", 0x00020000),
|
||||
FLAG_VAL("force", 0x00100000),
|
||||
FLAG_VAL("all", 0x000001ff),
|
||||
FLAG_VAL("aux", 0x00000100),
|
||||
FLAG_VAL("abort", 0x04000000),
|
||||
{}
|
||||
};
|
||||
unsigned int chs = 0;
|
||||
error_msg_t e = parse_flags(cmd, kw, &chs);
|
||||
if (e)
|
||||
return parser_error_message(cmd, e);
|
||||
unsigned int what = chs;
|
||||
|
||||
if (what & 0x07000000) {
|
||||
int r = 0;
|
||||
if (what & 0x02000000) {
|
||||
parse_expression_square(cmd, &timeout, 1);
|
||||
r = ssp_wait(timeout);
|
||||
}
|
||||
else
|
||||
r = ssp_busy();
|
||||
if (r && what & 0x04000000) {
|
||||
int rr = ssp_abort_batch(ads8688_batch);
|
||||
if (rr==-1)
|
||||
c->status |= 0xF0000000;
|
||||
else
|
||||
c->status |= 0xA0000000 | rr<<20;
|
||||
}
|
||||
if (what & 0x01000000 || c) {
|
||||
if (r)
|
||||
code++;
|
||||
parser_format_message(cmd, "%03d busy: 0x%x status: 0x%08x\n",
|
||||
code, r, c->status);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
parse_expression(cmd, &chs);
|
||||
|
||||
unsigned int ach = c->tchannels;
|
||||
if (!(what & 0x00010000) || !ach)
|
||||
ach = c->nchannels;
|
||||
if (!(chs &= 0x1ff))
|
||||
chs = ach & ~(ach-1);
|
||||
else if (ach & chs && !(what & 0x00100000))
|
||||
chs = ach;
|
||||
chs &= 0x1ff;
|
||||
if (!chs) {
|
||||
code ++;
|
||||
parser_format_message(cmd, "%03d no adc data\n", code);
|
||||
return code;
|
||||
}
|
||||
if (what & 0x00010000)
|
||||
c->tchannels &=~ chs;
|
||||
|
||||
unsigned int aidx = c->channels >> 8 & 0xf0;
|
||||
int ch = 0;
|
||||
unsigned int ccc = chs;
|
||||
int n = 0;
|
||||
while (ccc) {
|
||||
while (!(ccc & 1)) {
|
||||
ccc >>= 1;
|
||||
ch++;
|
||||
}
|
||||
static const char fmt[] = "%03d ADS %x %d 0x%04x %u %u\n";
|
||||
if (what & 0x00010000)
|
||||
printf(0, fmt+5, aidx+ch, c->navg[ch], c->first[ch], c->sum[ch], c->square[ch]);
|
||||
if (what & 0x00020000)
|
||||
message(MSG_PRIO_INFO, fmt+5, aidx+ch, c->navg[ch], c->first[ch], c->sum[ch], c->square[ch]);
|
||||
if (!n++) {
|
||||
parser_format_message(cmd, fmt, code, aidx+ch, c->navg[ch], c->first[ch], c->sum[ch], c->square[ch]);
|
||||
c->nchannels &= ~(1<<ch);
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
#define N 4
|
||||
static struct ads8688_data {
|
||||
unsigned short data[N];
|
||||
unsigned short frame;
|
||||
unsigned short nread;
|
||||
} data;
|
||||
|
||||
int ads8688(unsigned short *frame, int n, int flags, int timeout)
|
||||
{
|
||||
if (flags & adc_f_init)
|
||||
|
|
@ -49,7 +355,7 @@ int ads8688(unsigned short *frame, int n, int flags, int timeout)
|
|||
return r;
|
||||
}
|
||||
|
||||
int adc_cmd(struct command *cmd, const struct command_par *par)
|
||||
int adc_frame_cmd(struct command *cmd, const struct command_par *par)
|
||||
{
|
||||
static const struct keywords kw[] = {
|
||||
FLAG_VAL("continue", 0x0000),
|
||||
|
|
@ -81,7 +387,7 @@ int adc_cmd(struct command *cmd, const struct command_par *par)
|
|||
FLAG_VAL("highlsb", 0x2e00),
|
||||
FLAG_VAL("lowmsb", 0x3000),
|
||||
FLAG_VAL("lowlsb", 0x3200),
|
||||
FLAG_VAL("send", 0x10000),
|
||||
FLAG_VAL("unipolar", 0x0b04),
|
||||
KW_END };
|
||||
|
||||
const struct keywords *k;
|
||||
|
|
@ -91,14 +397,10 @@ int adc_cmd(struct command *cmd, const struct command_par *par)
|
|||
unsigned int flags = adc_f_init;
|
||||
unsigned int code = par->code;
|
||||
unsigned short frame = 0;
|
||||
unsigned int send = 0;
|
||||
if (k) {
|
||||
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
|
||||
|
||||
// adc/«cmd» [«n»] «value» zero or one value
|
||||
|
||||
if (!e)
|
||||
e = parse_expression_square(cmd, &ch, 1);
|
||||
|
|
@ -110,86 +412,60 @@ int adc_cmd(struct command *cmd, const struct command_par *par)
|
|||
e = parse_expression(cmd, &val);
|
||||
|
||||
int r = 0;
|
||||
int n = 1;
|
||||
|
||||
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(0, "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 (!e)
|
||||
data.nread = val;
|
||||
n = data.nread;
|
||||
goto send;
|
||||
}
|
||||
|
||||
if (frame == 0x0a00)
|
||||
frame += ch << 9;
|
||||
if (frame >= 0x2a00 && frame <= 0x3200)
|
||||
frame += (5*ch) << 9;
|
||||
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:
|
||||
send:
|
||||
data.frame = frame;
|
||||
r = ads8688(&data.frame, n, flags, timeout);
|
||||
if (r)
|
||||
code++;
|
||||
|
||||
if (send)
|
||||
printf(0, "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;
|
||||
}
|
||||
|
||||
const struct keywords ads8688_variable_names[] = {
|
||||
VARIABLE("adc_timeout", &timeout),
|
||||
VARIABLE("adc_navg", ads8688_control.navg),
|
||||
VARIABLE("adc_nread", &data.nread),
|
||||
VARIABLE("adc_data", &data.data),
|
||||
VARIABLE("adc_dframe", &data.frame),
|
||||
VARIABLE("adc_frame", &ads8688_control.frame),
|
||||
VARIABLE("adc_channels", &ads8688_control.channels),
|
||||
VARIABLE("adc_nbuffer", &ads8688_control.nbuf),
|
||||
VARIABLE("adc_gains", &ads8688_control.gains),
|
||||
VARIABLE("adc_first", ads8688_control.first),
|
||||
VARIABLE("adc_sum", ads8688_control.sum),
|
||||
VARIABLE("adc_square", ads8688_control.square),
|
||||
VARIABLE("adc_status", &ads8688_control.status),
|
||||
KW_END
|
||||
};
|
||||
|
||||
const struct keywords adc_commands[] = {
|
||||
CMD_KW("frame", adc_frame_cmd, 370, 0),
|
||||
CMD_KW("gains", adc_gains_cmd, 372, 0),
|
||||
CMD_KW("read", adc_read_cmd, 374, 0),
|
||||
CMD_KW("print", adc_print_cmd, 376, 0),
|
||||
CMD_END
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,5 +11,6 @@ enum adc_flags {
|
|||
};
|
||||
|
||||
extern const struct keywords ads8688_variable_names[];
|
||||
extern const struct keywords adc_commands[];
|
||||
|
||||
#endif
|
||||
|
|
|
|||
4
isr.h
4
isr.h
|
|
@ -8,13 +8,13 @@ void init_vic(void);
|
|||
static inline unsigned int cpsr(void)
|
||||
{
|
||||
unsigned int r;
|
||||
__asm__ __volatile__ ("MRS %0, CPSR" : "=r" (r));
|
||||
__asm__ __volatile__ ("MRS %0, CPSR" : "=r" (r) :: "memory");
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void cpsr_c(unsigned int r)
|
||||
{
|
||||
__asm__ __volatile__ ("MSR CPSR_c, %0" :: "r" (r));
|
||||
__asm__ __volatile__ ("MSR CPSR_c, %0" :: "r" (r) : "memory");
|
||||
}
|
||||
|
||||
static inline unsigned int disable_irq(unsigned int flag)
|
||||
|
|
|
|||
|
|
@ -520,7 +520,7 @@ static const struct keywords main_command_table[] = {
|
|||
CMD_KW("pressure", pressure_cmd, 366, 0),
|
||||
CMD_KW("bate", bate_cmd, 368, 0),
|
||||
CMD_KW("dac", dac_cmd, 364, 0),
|
||||
CMD_KW("adc", adc_cmd, 362, 0),
|
||||
CMD_KW("adc", parse_sub_command, 909, adc_commands),
|
||||
CMD_KW("ssp", parse_sub_command, 909, ssp_commands),
|
||||
{"flash", {.par=&flash_command}},
|
||||
{"dma", {.par=&usb_command}},
|
||||
|
|
|
|||
5
parser.c
5
parser.c
|
|
@ -81,10 +81,7 @@ error_msg_t expect_char(struct command *cmd, char what)
|
|||
{
|
||||
if (parse_char(cmd, what))
|
||||
return 0;
|
||||
static char mes[] = ". expected\n";
|
||||
static ERRORMESSAGE(error, 709, mes);
|
||||
mes[0] = what;
|
||||
return &error;
|
||||
return error_printf(709, "%c expected\n", what);
|
||||
}
|
||||
|
||||
const struct keywords *parse_keyword(struct command *cmd, const struct keywords *table)
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ int pressure_cmd(struct command *cmd, const struct command_par *par)
|
|||
if (what & 0x0020) {
|
||||
ssp_conf_bate = ssp_confs_bate[!!idx];
|
||||
bate_status = 2;
|
||||
int c = ssp_submit_batch(bate_batch, 0);
|
||||
int c = ssp_start_batch(bate_batch, 0);
|
||||
if (!c) {
|
||||
parser_format_message(cmd, "%03d bate[%d] triggered\n",
|
||||
code, idx);
|
||||
|
|
|
|||
93
ssp.c
93
ssp.c
|
|
@ -15,7 +15,6 @@ static volatile struct ssp_job job;
|
|||
struct ssp_match ssp_match;
|
||||
unsigned int ssp_bits;
|
||||
int (*ssp_callback)();
|
||||
volatile unsigned int ssp_lastword;
|
||||
unsigned int ssp_ssel_mask = SSP_SSEL_MASK0 | SSP_SSEL_MASK1;
|
||||
|
||||
unsigned short *ssp_buffer;
|
||||
|
|
@ -24,12 +23,13 @@ volatile int ssp_frames_read;
|
|||
|
||||
unsigned short ssp_scratch[256];
|
||||
|
||||
void ssp_set_buffer(short *buf, int size)
|
||||
void ssp_set_buffer(short *buf, unsigned int size)
|
||||
{
|
||||
unsigned int iflg = disable_irq(INT_DISABLE);
|
||||
volatile struct ssp_job *j=&job;
|
||||
if (!(size && buf)) {
|
||||
if (!buf) {
|
||||
buf = ssp_scratch;
|
||||
if (!size || size > sizeof(ssp_scratch)/2)
|
||||
size = sizeof(ssp_scratch)/2;
|
||||
}
|
||||
ssp_buffer = (unsigned short *)buf;
|
||||
|
|
@ -65,7 +65,6 @@ static void ssp_isr(void)
|
|||
unsigned int dr = SSPDR;
|
||||
sr=SSPSR;
|
||||
nread++;
|
||||
ssp_lastword = ssp_lastword << ssp_bits | dr;
|
||||
if (ssp_frames_read++ >= ssp_match.frame_count
|
||||
&& !rc
|
||||
&& (dr & ssp_match.mask) == ssp_match.value) {
|
||||
|
|
@ -94,11 +93,12 @@ static void ssp_isr(void)
|
|||
goto outic;
|
||||
else {
|
||||
SSPIMSC = 0;
|
||||
if (ssp_callback)
|
||||
ssp_callback();
|
||||
int (*cb)() = ssp_callback;
|
||||
ssp_callback = 0;
|
||||
if (cb)
|
||||
cb();
|
||||
goto out;
|
||||
}
|
||||
|
||||
else if (!(sr & (SSPSR_BSY|SSPSR_RNE)))
|
||||
nread = 8;
|
||||
|
||||
|
|
@ -154,18 +154,41 @@ int ssp_submit(const unsigned short *cmd, short cmd_size, unsigned short ic, uns
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ssp_submit_batch(const unsigned short *cmd, short cmd_size,
|
||||
unsigned short ic, unsigned short rc, unsigned short fc)
|
||||
{
|
||||
volatile struct ssp_job *j=&job;
|
||||
unsigned int iflg = disable_irq(INT_DISABLE);
|
||||
j->command = cmd;
|
||||
j->cmd_count = cmd_size;
|
||||
j->count = ic;
|
||||
if (!fc) {
|
||||
j->read_count = rc;
|
||||
ssp_match.frame_count = 0;
|
||||
ssp_match.read_count = 0;
|
||||
}
|
||||
else {
|
||||
j->read_count = 0;
|
||||
ssp_match.frame_count = fc;
|
||||
ssp_match.read_count = rc;
|
||||
}
|
||||
ssp_frames_sent = 0;
|
||||
ssp_frames_read = 0;
|
||||
ssp_callback = ssp_run_batch;
|
||||
enable_irq(iflg);
|
||||
ssp_poll();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ssp_submit_job(const struct ssp_job *jj)
|
||||
{
|
||||
unsigned int iflg = disable_irq(INT_DISABLE);
|
||||
size_t n = sizeof(job);
|
||||
if (!jj->buf_ptr) {
|
||||
n -= 8;
|
||||
if (jj->buf_count)
|
||||
ssp_set_buffer(0, 0);
|
||||
}
|
||||
memcpy((void*)&job, jj, n);
|
||||
memcpy((void*)&job, jj, sizeof(job)-8);
|
||||
if (jj->buf_ptr || jj->buf_count)
|
||||
ssp_set_buffer(0, jj->buf_count);
|
||||
ssp_frames_sent = 0;
|
||||
ssp_frames_read = 0;
|
||||
ssp_callback = ssp_run_batch;
|
||||
enable_irq(iflg);
|
||||
ssp_poll();
|
||||
return 0;
|
||||
|
|
@ -280,8 +303,9 @@ const struct ssp_batch *ssp_batch;
|
|||
static inline
|
||||
void ssel_delay(int delay)
|
||||
{
|
||||
delay &= ssp_b_delay;
|
||||
delay >>= ssp_b_dshift;
|
||||
while (delay-->0) __asm__("");
|
||||
while (delay-->0) __asm__ volatile ("");
|
||||
}
|
||||
|
||||
// called first by `ssp_submit_batch()`
|
||||
|
|
@ -308,27 +332,31 @@ int ssp_run_batch()
|
|||
if (c == ssp_b_config)
|
||||
ssp_init(batch->ssel);
|
||||
|
||||
if (f & ssp_b_scratch)
|
||||
ssp_set_buffer(0, 0);
|
||||
|
||||
if (c == ssp_b_buffer)
|
||||
ssp_set_buffer(batch->buffer, f & 0xffff);
|
||||
|
||||
if (f & ssp_b_deassert) {
|
||||
ssp_deassert_ssel();
|
||||
if (c == ssp_b_job)
|
||||
ssel_delay(f & ssp_b_delay);
|
||||
ssel_delay(f);
|
||||
}
|
||||
if (f & ssp_b_assert || c == ssp_b_config) {
|
||||
ssp_assert_ssel();
|
||||
if (c == ssp_b_job)
|
||||
ssel_delay(f & ssp_b_delay);
|
||||
}
|
||||
|
||||
static unsigned int repeats;
|
||||
if (c != ssp_b_job && c != ssp_b_gosub
|
||||
|| repeats++ >= f & ssp_b_repeat) {
|
||||
// we did all repeats … advance to the next job
|
||||
repeats = 0;
|
||||
ssp_batch++;
|
||||
ssel_delay(f);
|
||||
}
|
||||
|
||||
static const struct ssp_batch *gosub_return;
|
||||
static int gosub_repeats;
|
||||
static unsigned int repeats, gosub_repeats;
|
||||
if (c != ssp_b_job && c != ssp_b_gosub
|
||||
|| repeats++ >= f & ssp_b_repeat
|
||||
|| ssp_b_whilebuf & !job.buf_count) {
|
||||
// we did all repeats … advance to the next job
|
||||
repeats = 0;
|
||||
ssp_batch++;
|
||||
|
||||
if (f & ssp_b_stop)
|
||||
ssp_batch = 0;
|
||||
|
|
@ -338,6 +366,7 @@ int ssp_run_batch()
|
|||
repeats = gosub_repeats;
|
||||
gosub_return = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == ssp_b_call) {
|
||||
int c = batch->callback(batch);
|
||||
|
|
@ -350,18 +379,24 @@ int ssp_run_batch()
|
|||
gosub_return = ssp_batch;
|
||||
gosub_repeats = repeats;
|
||||
}
|
||||
short jmp = f; // sign extend (f & 0xffff)
|
||||
if (batch->batch) {
|
||||
short jmp = (f & ssp_b_jump) >> ssp_b_jshift;
|
||||
if (f & ssp_b_jsign)
|
||||
jmp -= 1 + (ssp_b_jump >> ssp_b_jshift);
|
||||
if (batch->batch)
|
||||
ssp_batch = batch->batch;
|
||||
else
|
||||
ssp_batch = batch;
|
||||
ssp_batch += jmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == ssp_b_job) {
|
||||
if (batch->match)
|
||||
ssp_match = *batch->match;
|
||||
else
|
||||
memset(&ssp_match, 0, sizeof(ssp_match));
|
||||
if (batch->job && batch->job->count)
|
||||
return ssp_submit_job(batch->job);
|
||||
}
|
||||
|
||||
|
|
@ -400,19 +435,17 @@ doit:
|
|||
return n;
|
||||
}
|
||||
|
||||
int ssp_submit_batch(const struct ssp_batch *batch, int timeout)
|
||||
int ssp_start_batch(const struct ssp_batch *batch, int timeout)
|
||||
{
|
||||
unsigned int c = ssp_wait(timeout);
|
||||
if (c)
|
||||
return c;
|
||||
ssp_batch = batch;
|
||||
ssp_callback = ssp_run_batch;
|
||||
return ssp_run_batch();
|
||||
}
|
||||
|
||||
const struct keywords ssp_variable_names[] = {
|
||||
VARIABLE("ssp_buffer", ssp_scratch),
|
||||
VARIABLE("ssp_response", (void *)&ssp_lastword),
|
||||
VARIABLE("ssp_match", &ssp_match),
|
||||
VARIABLE("ssp_ssel_mask", &ssp_ssel_mask),
|
||||
VARIABLE("ssp_frames_sent", (void *)&ssp_frames_sent),
|
||||
|
|
|
|||
25
ssp.h
25
ssp.h
|
|
@ -8,14 +8,14 @@
|
|||
|
||||
void ssp_reset(void);
|
||||
|
||||
void ssp_set_buffer(short *buf, int size);
|
||||
void ssp_set_buffer(short *buf, unsigned int size);
|
||||
void ssp_poll(void);
|
||||
int ssp_submit(const unsigned short *cmd, short cmd_size, unsigned short ic, unsigned short rc);
|
||||
unsigned int ssp_busy(void);
|
||||
int ssp_wait(int timeout);
|
||||
|
||||
extern unsigned int ssp_bits;
|
||||
extern volatile unsigned int ssp_lastword;
|
||||
unsigned short *ssp_buffer;
|
||||
extern unsigned int ssp_ssel_mask;
|
||||
extern unsigned int ssp_ssel;
|
||||
extern unsigned int ssp_read_size;
|
||||
|
|
@ -25,7 +25,8 @@ extern unsigned int ssp_match_value;
|
|||
extern unsigned int ssp_match_count;
|
||||
extern volatile int ssp_frames_sent;
|
||||
extern volatile int ssp_frames_read;
|
||||
extern unsigned short ssp_scratch[256];
|
||||
#define NSCRATCH 256
|
||||
extern unsigned short ssp_scratch[NSCRATCH];
|
||||
extern int (*ssp_callback)();
|
||||
|
||||
extern struct ssp_config {
|
||||
|
|
@ -96,9 +97,11 @@ struct ssp_batch {
|
|||
const struct timer_wait *wait;
|
||||
ssp_batch_callback_t callback;
|
||||
const struct ssp_batch *batch;
|
||||
unsigned short *buffer;
|
||||
};
|
||||
union {
|
||||
const struct ssp_match *match;
|
||||
unsigned int value;
|
||||
void *data;
|
||||
};
|
||||
} *ssp_batch;
|
||||
|
|
@ -106,14 +109,20 @@ struct ssp_batch {
|
|||
enum ssp_batch_flags {
|
||||
ssp_b_count = 0x00ffffff,
|
||||
ssp_b_repeat = 0x00000fff,
|
||||
ssp_b_delay = 0x00fff000,
|
||||
ssp_b_delay = 0x007ff000,
|
||||
ssp_b_dshift = 12,
|
||||
ssp_b_jump = 0x000ff000,
|
||||
ssp_b_jsign = 0x00080000,
|
||||
ssp_b_jshift = 12,
|
||||
ssp_b_scratch = 0x00800000,
|
||||
ssp_b_whilebuf = 0x00400000,
|
||||
ssp_b_job = 0x01000000,
|
||||
ssp_b_config = 0x02000000,
|
||||
ssp_b_wait = 0x03000000,
|
||||
ssp_b_call = 0x04000000,
|
||||
ssp_b_goto = 0x05000000,
|
||||
ssp_b_gosub = 0x06000000,
|
||||
ssp_b_buffer = 0x07000000,
|
||||
ssp_b_what = 0x0f000000,
|
||||
ssp_b_assert = 0x10000000,
|
||||
ssp_b_deassert = 0x20000000,
|
||||
|
|
@ -121,6 +130,10 @@ enum ssp_batch_flags {
|
|||
ssp_b_return = 0x80000000,
|
||||
};
|
||||
|
||||
#define SSP_B_DELAY(m) (((m)<<ssp_b_dshift)&ssp_b_delay)
|
||||
#define SSP_B_REPEAT(c) (((c)-1)&ssp_b_repeat)
|
||||
#define SSP_B_JUMP(r) (((r)<<ssp_b_jshift)&ssp_b_jump)
|
||||
|
||||
// skip `count` frames before recording `size` frames.
|
||||
static inline
|
||||
void ssp_set_read(unsigned short count, unsigned short size)
|
||||
|
|
@ -130,7 +143,9 @@ void ssp_set_read(unsigned short count, unsigned short size)
|
|||
}
|
||||
|
||||
int ssp_submit_job(const struct ssp_job *jj);
|
||||
int ssp_submit_batch(const struct ssp_batch *batch, int timeout);
|
||||
int ssp_submit_batch(const unsigned short *cmd, short cmd_size,
|
||||
unsigned short ic, unsigned short rc, unsigned short fc);
|
||||
int ssp_start_batch(const struct ssp_batch *batch, int timeout);
|
||||
int ssp_run_batch();
|
||||
int ssp_abort_batch(const struct ssp_batch *batch);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue