Sigma: Value/mask trigger support in 50 MHz mode.

This commit is contained in:
Håvard Espeland 2010-05-01 22:38:43 +02:00
parent eec5275e2f
commit ee492173a1
2 changed files with 181 additions and 26 deletions

View File

@ -35,7 +35,7 @@
#define USB_VENDOR_NAME "ASIX" #define USB_VENDOR_NAME "ASIX"
#define USB_MODEL_NAME "SIGMA" #define USB_MODEL_NAME "SIGMA"
#define USB_MODEL_VERSION "" #define USB_MODEL_VERSION ""
#define TRIGGER_TYPES "rf" #define TRIGGER_TYPES "rf10"
static GSList *device_instances = NULL; static GSList *device_instances = NULL;
@ -49,10 +49,14 @@ static int num_probes = 0;
static int samples_per_event = 0; static int samples_per_event = 0;
static int capture_ratio = 50; static int capture_ratio = 50;
/* Single-pin trigger support. */ /* Single-pin trigger support (100 and 200 MHz).*/
static uint8_t triggerpin = 1; static uint8_t triggerpin = 1;
static uint8_t triggerfall = 0; static uint8_t triggerfall = 0;
/* Simple trigger support (<= 50 MHz). */
static uint16_t triggermask = 1;
static uint16_t triggervalue = 1;
static uint64_t supported_samplerates[] = { static uint64_t supported_samplerates[] = {
KHZ(200), KHZ(200),
KHZ(250), KHZ(250),
@ -245,6 +249,64 @@ static int sigma_read_dram(uint16_t startchunk, size_t numchunks, uint8_t *data)
return sigma_read(data, numchunks * CHUNK_SIZE); return sigma_read(data, numchunks * CHUNK_SIZE);
} }
/* Upload trigger look-up tables to Sigma */
static int sigma_write_trigger_lut(struct triggerlut *lut)
{
int i;
uint8_t tmp[2];
uint16_t bit;
/* Transpose the table and send to Sigma. */
for (i = 0; i < 16; ++i) {
bit = 1 << i;
tmp[0] = tmp[1] = 0;
if (lut->m2d[0] & bit)
tmp[0] |= 0x01;
if (lut->m2d[1] & bit)
tmp[0] |= 0x02;
if (lut->m2d[2] & bit)
tmp[0] |= 0x04;
if (lut->m2d[3] & bit)
tmp[0] |= 0x08;
if (lut->m3 & bit)
tmp[0] |= 0x10;
if (lut->m3s & bit)
tmp[0] |= 0x20;
if (lut->m4 & bit)
tmp[0] |= 0x40;
if (lut->m0d[0] & bit)
tmp[1] |= 0x01;
if (lut->m0d[1] & bit)
tmp[1] |= 0x02;
if (lut->m0d[2] & bit)
tmp[1] |= 0x04;
if (lut->m0d[3] & bit)
tmp[1] |= 0x08;
if (lut->m1d[0] & bit)
tmp[1] |= 0x10;
if (lut->m1d[1] & bit)
tmp[1] |= 0x20;
if (lut->m1d[2] & bit)
tmp[1] |= 0x40;
if (lut->m1d[3] & bit)
tmp[1] |= 0x80;
sigma_write_register(WRITE_TRIGGER_SELECT0, tmp, sizeof(tmp));
sigma_set_register(WRITE_TRIGGER_SELECT1, 0x30 | i);
}
/* Send the parameters */
sigma_write_register(WRITE_TRIGGER_SELECT0, (uint8_t *) &lut->params,
sizeof(lut->params));
return SIGROK_OK;
}
/* Generate the bitbang stream for programming the FPGA. */ /* Generate the bitbang stream for programming the FPGA. */
static int bin2bitbang(const char *filename, static int bin2bitbang(const char *filename,
unsigned char **buf, size_t *buf_size) unsigned char **buf, size_t *buf_size)
@ -515,11 +577,8 @@ static int configure_probes(GSList *probes)
GSList *l; GSList *l;
int trigger_set = 0; int trigger_set = 0;
if (cur_samplerate <= MHZ(50)) { triggermask = 0;
g_warning("Trigger support only implemented " triggervalue = 0;
"in 100 and 200 MHz mode.");
return SIGROK_ERR;
}
for (l = probes; l; l = l->next) { for (l = probes; l; l = l->next) {
probe = (struct probe *)l->data; probe = (struct probe *)l->data;
@ -527,20 +586,43 @@ static int configure_probes(GSList *probes)
if (!probe->enabled || !probe->trigger) if (!probe->enabled || !probe->trigger)
continue; continue;
if (trigger_set) { if (cur_samplerate >= MHZ(100)) {
g_warning("Asix Sigma only supports a single pin trigger " /* Fast trigger support */
"in 100 and 200 MHz mode."); if (trigger_set) {
return SIGROK_ERR; g_warning("Asix Sigma only supports a single pin trigger "
"in 100 and 200 MHz mode.");
return SIGROK_ERR;
}
if (probe->trigger[0] == 'f')
triggerfall = 1;
else if (probe->trigger[0] == 'r')
triggerfall = 0;
else {
g_warning("Asix Sigma only supports "
"rising/falling trigger in 100 "
"and 200 MHz mode.");
return SIGROK_ERR;
}
triggerpin = probe->index - 1;
} else {
/* Normal trigger support */
triggermask |= 1 << (probe->index - 1);
if (probe->trigger[0] == '1')
triggervalue |= 1 << (probe->index - 1);
else if (probe->trigger[0] == '0')
triggervalue |= 0 << (probe->index - 1);
else {
g_warning("Asix Sigma only supports "
"trigger values in <= 50"
" MHz mode.");
return SIGROK_ERR;
}
} }
/* Found trigger. */ ++trigger_set;
if (probe->trigger[0] == 'f')
triggerfall = 1;
else
triggerfall = 0;
triggerpin = probe->index - 1;
trigger_set = 1;
} }
return SIGROK_OK; return SIGROK_OK;
@ -652,10 +734,20 @@ static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts,
uint16_t *event; uint16_t *event;
uint16_t cur_sample; uint16_t cur_sample;
int triggerts = -1; int triggerts = -1;
int triggeroff = 0;
/* Find in which cluster the trigger occured. */ if (triggerpos != -1) {
if (triggerpos != -1) if (cur_samplerate <= MHZ(50))
triggerts = (triggerpos / 7); triggerpos -= EVENTS_PER_CLUSTER;
else
triggeroff = 3;
if (triggerpos < 0)
triggerpos = 0;
/* Find in which cluster the trigger occured. */
triggerts = triggerpos / 7;
}
/* For each ts. */ /* For each ts. */
for (i = 0; i < 64; ++i) { for (i = 0; i < 64; ++i) {
@ -706,8 +798,6 @@ static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts,
} }
} }
*lastsample = samples[n - 1];
/* Send data up to trigger point (if triggered). */ /* Send data up to trigger point (if triggered). */
sent = 0; sent = 0;
if (i == triggerts) { if (i == triggerts) {
@ -717,7 +807,7 @@ static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts,
* in a single event, the trigger does not match the * in a single event, the trigger does not match the
* exact sample. * exact sample.
*/ */
tosend = (triggerpos % 7) - 3; tosend = (triggerpos % 7) - triggeroff;
if (tosend > 0) { if (tosend > 0) {
packet.type = DF_LOGIC16; packet.type = DF_LOGIC16;
@ -741,6 +831,8 @@ static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts,
packet.length = tosend * sizeof(uint16_t); packet.length = tosend * sizeof(uint16_t);
packet.payload = samples + sent; packet.payload = samples + sent;
session_bus(user_data, &packet); session_bus(user_data, &packet);
*lastsample = samples[n - 1];
} }
return SIGROK_OK; return SIGROK_OK;
@ -825,6 +917,46 @@ static int receive_data(int fd, int revents, void *user_data)
return TRUE; return TRUE;
} }
/*
* Build trigger LUTs used by 50 MHz and lower sample rates for supporting
* simple pin change and state triggers. Only two transitions (rise/fall) can be
* set at any time, but a full mask and value can be set (0/1).
*/
static int build_basic_trigger(struct triggerlut *lut)
{
int i, j, k, bit;
memset(lut, 0, sizeof(struct triggerlut));
/* Unknown */
lut->m4 = 0xa000;
/* Set the LUT for controlling value/maske trigger */
for (i = 0; i < 4; ++i) {
lut->m2d[i] = 0xffff;
for (j = 0; j < 16; ++j)
for (k = 0; k < 4; ++k) {
bit = 1 << (i * 4 + k);
if ((triggermask & bit) &&
(triggervalue & bit) != (j & (1 << k))) {
lut->m2d[i] &= ~(1 << j);
}
}
}
/* Unused when not triggering on transitions */
lut->m3 = 0xffff;
/* Triggertype: event */
lut->params.selres = 3;
return SIGROK_OK;
}
static int hw_start_acquisition(int device_index, gpointer session_device_id) static int hw_start_acquisition(int device_index, gpointer session_device_id)
{ {
struct sigrok_device_instance *sdi; struct sigrok_device_instance *sdi;
@ -834,6 +966,7 @@ static int hw_start_acquisition(int device_index, gpointer session_device_id)
int frac; int frac;
uint8_t triggerselect; uint8_t triggerselect;
struct triggerinout triggerinout_conf; struct triggerinout triggerinout_conf;
struct triggerlut lut;
session_device_id = session_device_id; session_device_id = session_device_id;
@ -858,7 +991,9 @@ static int hw_start_acquisition(int device_index, gpointer session_device_id)
/* All other modes. */ /* All other modes. */
} else if (cur_samplerate <= MHZ(50)) { } else if (cur_samplerate <= MHZ(50)) {
sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20); build_basic_trigger(&lut);
sigma_write_trigger_lut(&lut);
triggerselect = (1 << LEDSEL1) | (1 << LEDSEL0); triggerselect = (1 << LEDSEL1) | (1 << LEDSEL0);
} }

View File

@ -102,4 +102,24 @@ struct triggerinout {
uint8_t trgin_enable : 1; uint8_t trgin_enable : 1;
}; };
struct triggerlut {
/* The actual LUTs. */
uint16_t m0d[4], m1d[4], m2d[4];
uint16_t m3, m3s, m4;
/* Paramters should be sent as a single register write. */
struct {
uint8_t selc : 2;
uint8_t selpresc : 6;
uint8_t selinc : 2;
uint8_t selres : 2;
uint8_t sela : 2;
uint8_t selb : 2;
uint16_t cmpb;
uint16_t cmpa;
} params;
};
#endif #endif