Sigma: Add triggers support for 100 and 200 MHz.

This commit is contained in:
Håvard Espeland 2010-04-30 22:18:10 +02:00
parent ed09fd07f7
commit 57bbf56b84
2 changed files with 175 additions and 29 deletions

View File

@ -35,6 +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"
static GSList *device_instances = NULL; static GSList *device_instances = NULL;
@ -46,6 +47,11 @@ static struct timeval start_tv;
static int cur_firmware = -1; static int cur_firmware = -1;
static int num_probes = 0; static int num_probes = 0;
static int samples_per_event = 0; static int samples_per_event = 0;
static int capture_ratio = 50;
/* Single-pin trigger support */
static uint8_t triggerpin = 1;
static uint8_t triggerfall = 0;
static uint64_t supported_samplerates[] = { static uint64_t supported_samplerates[] = {
KHZ(200), KHZ(200),
@ -71,6 +77,8 @@ static struct samplerates samplerates = {
static int capabilities[] = { static int capabilities[] = {
HWCAP_LOGIC_ANALYZER, HWCAP_LOGIC_ANALYZER,
HWCAP_SAMPLERATE, HWCAP_SAMPLERATE,
HWCAP_CAPTURE_RATIO,
HWCAP_PROBECONFIG,
/* These are really implemented in the driver, not the hardware. */ /* These are really implemented in the driver, not the hardware. */
HWCAP_LIMIT_MSEC, HWCAP_LIMIT_MSEC,
@ -198,6 +206,13 @@ static int sigma_read_pos(uint32_t *stoppos, uint32_t *triggerpos)
*triggerpos = result[0] | (result[1] << 8) | (result[2] << 16); *triggerpos = result[0] | (result[1] << 8) | (result[2] << 16);
*stoppos = result[3] | (result[4] << 8) | (result[5] << 16); *stoppos = result[3] | (result[4] << 8) | (result[5] << 16);
/* Not really sure why this must be done, but according to spec. */
if ((--*stoppos & 0x1ff) == 0x1ff)
stoppos -= 64;
if ((*--triggerpos & 0x1ff) == 0x1ff)
triggerpos -= 64;
return 1; return 1;
} }
@ -495,6 +510,39 @@ static int set_samplerate(struct sigrok_device_instance *sdi, uint64_t samplerat
return ret; return ret;
} }
/* Only trigger on single pin supported (in 100-200 MHz modes) */
static int configure_probes(GSList *probes)
{
struct probe *probe;
GSList *l;
int trigger_set = 0;
for (l = probes; l; l = l->next) {
probe = (struct probe *)l->data;
if (!probe->enabled || !probe->trigger)
continue;
if (trigger_set) {
g_warning("Asix Sigma only supports a single pin trigger"
" in 100 and 200 MHz mode.");
return SIGROK_ERR;
}
/* Found trigger */
if (probe->trigger[0] == 'f')
triggerfall = 1;
else
triggerfall = 0;
triggerpin = probe->index - 1;
trigger_set = 1;
}
return SIGROK_OK;
}
static void hw_closedev(int device_index) static void hw_closedev(int device_index)
{ {
device_index = device_index; device_index = device_index;
@ -527,7 +575,7 @@ static void *hw_get_device_info(int device_index, int device_info_id)
info = &samplerates; info = &samplerates;
break; break;
case DI_TRIGGER_TYPES: case DI_TRIGGER_TYPES:
info = 0; info = (char *)TRIGGER_TYPES;
break; break;
case DI_CUR_SAMPLERATE: case DI_CUR_SAMPLERATE:
info = &cur_samplerate; info = &cur_samplerate;
@ -564,10 +612,15 @@ static int hw_set_configuration(int device_index, int capability, void *value)
if (capability == HWCAP_SAMPLERATE) { if (capability == HWCAP_SAMPLERATE) {
ret = set_samplerate(sdi, *(uint64_t*) value); ret = set_samplerate(sdi, *(uint64_t*) value);
} else if (capability == HWCAP_PROBECONFIG) { } else if (capability == HWCAP_PROBECONFIG) {
ret = SIGROK_OK; ret = configure_probes(value);
} else if (capability == HWCAP_LIMIT_MSEC) { } else if (capability == HWCAP_LIMIT_MSEC) {
limit_msec = strtoull(value, NULL, 10); limit_msec = strtoull(value, NULL, 10);
ret = SIGROK_OK; ret = SIGROK_OK;
} else if (capability == HWCAP_CAPTURE_RATIO) {
capture_ratio = strtoull(value, NULL, 10);
ret = SIGROK_OK;
} else if (capability == HWCAP_PROBECONFIG) {
ret = configure_probes((GSList *) value);
} else { } else {
ret = SIGROK_ERR; ret = SIGROK_ERR;
} }
@ -585,7 +638,7 @@ static int hw_set_configuration(int device_index, int capability, void *value)
* spread 20 ns apart. * spread 20 ns apart.
*/ */
static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts, static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts,
uint16_t *lastsample, void *user_data) uint16_t *lastsample, int triggerpos, void *user_data)
{ {
uint16_t tsdiff, ts; uint16_t tsdiff, ts;
uint16_t samples[65536 * samples_per_event]; uint16_t samples[65536 * samples_per_event];
@ -595,6 +648,11 @@ static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts,
int clustersize = EVENTS_PER_CLUSTER * samples_per_event; int clustersize = EVENTS_PER_CLUSTER * samples_per_event;
uint16_t *event; uint16_t *event;
uint16_t cur_sample; uint16_t cur_sample;
int triggerts = -1;
/* Find in which cluster the trigger occured */
if (triggerpos != -1)
triggerts = (triggerpos / 7);
/* For each ts */ /* For each ts */
for (i = 0; i < 64; ++i) { for (i = 0; i < 64; ++i) {
@ -611,8 +669,21 @@ static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts,
n = numpad; n = numpad;
} }
event = (uint16_t *) &buf[i * 16 + 2]; /* Send samples between previous and this timestamp to sigrok. */
sent = 0;
while (sent < n) {
tosend = MIN(2048, n - sent);
packet.type = DF_LOGIC16;
packet.length = tosend * sizeof(uint16_t);
packet.payload = samples + sent;
session_bus(user_data, &packet);
sent += tosend;
}
n = 0;
event = (uint16_t *) &buf[i * 16 + 2];
cur_sample = 0; cur_sample = 0;
/* For each event in cluster. */ /* For each event in cluster. */
@ -634,18 +705,39 @@ static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts,
*lastsample = samples[n - 1]; *lastsample = samples[n - 1];
/* Send to sigrok. */ /* Send data up to trigger point (if triggered) */
sent = 0; sent = 0;
while (sent < n) { if (i == triggerts) {
tosend = MIN(2048, n - sent); /*
* Trigger is presumptively only accurate to event, i.e.
* for 100 and 200 MHz, where multiple samples are coded
* in a single event, the trigger does not match the
* exact sample.
*/
tosend = (triggerpos % 7) - 3;
packet.type = DF_LOGIC16; if (tosend > 0) {
packet.length = tosend * sizeof(uint16_t); packet.type = DF_LOGIC16;
packet.payload = samples + sent; packet.length = tosend * sizeof(uint16_t);
packet.payload = samples;
session_bus(user_data, &packet);
sent += tosend;
}
packet.type = DF_TRIGGER;
packet.length = 0;
packet.payload = 0;
session_bus(user_data, &packet); session_bus(user_data, &packet);
sent += tosend;
} }
/* Send rest of the chunk to sigrok */
tosend = n - sent;
packet.type = DF_LOGIC16;
packet.length = tosend * sizeof(uint16_t);
packet.payload = samples + sent;
session_bus(user_data, &packet);
} }
return SIGROK_OK; return SIGROK_OK;
@ -661,6 +753,8 @@ static int receive_data(int fd, int revents, void *user_data)
struct timeval tv; struct timeval tv;
uint16_t lastts = 0; uint16_t lastts = 0;
uint16_t lastsample = 0; uint16_t lastsample = 0;
uint8_t modestatus;
int triggerchunk = -1;
fd = fd; fd = fd;
revents = revents; revents = revents;
@ -686,8 +780,11 @@ static int receive_data(int fd, int revents, void *user_data)
/* Get the current position. */ /* Get the current position. */
sigma_read_pos(&stoppos, &triggerpos); sigma_read_pos(&stoppos, &triggerpos);
/* Read mode status. We will care for this later. */ /* Check if trigger has fired */
sigma_get_register(READ_MODE); modestatus = sigma_get_register(READ_MODE);
if (modestatus & 0x20) {
triggerchunk = triggerpos / 512;
}
/* Download sample data. */ /* Download sample data. */
for (curchunk = 0; curchunk < numchunks;) { for (curchunk = 0; curchunk < numchunks;) {
@ -704,8 +801,14 @@ static int receive_data(int fd, int revents, void *user_data)
/* Decode chunks and send them to sigrok. */ /* Decode chunks and send them to sigrok. */
for (i = 0; i < newchunks; ++i) { for (i = 0; i < newchunks; ++i) {
decode_chunk_ts(buf + (i * CHUNK_SIZE), if (curchunk + i == triggerchunk)
&lastts, &lastsample, user_data); decode_chunk_ts(buf + (i * CHUNK_SIZE),
&lastts, &lastsample,
triggerpos & 0x1ff, user_data);
else
decode_chunk_ts(buf + (i * CHUNK_SIZE),
&lastts, &lastsample,
-1, user_data);
} }
curchunk += newchunks; curchunk += newchunks;
@ -724,9 +827,10 @@ static int hw_start_acquisition(int device_index, gpointer session_device_id)
struct sigrok_device_instance *sdi; struct sigrok_device_instance *sdi;
struct datafeed_packet packet; struct datafeed_packet packet;
struct datafeed_header header; struct datafeed_header header;
uint8_t trigger_option[2] = { 0x38, 0x00 };
struct clockselect_50 clockselect; struct clockselect_50 clockselect;
int frac; int frac;
uint8_t triggerselect;
struct triggerinout triggerinout_conf;
session_device_id = session_device_id; session_device_id = session_device_id;
@ -739,15 +843,34 @@ static int hw_start_acquisition(int device_index, gpointer session_device_id)
if (cur_firmware == -1) if (cur_firmware == -1)
set_samplerate(sdi, MHZ(50)); set_samplerate(sdi, MHZ(50));
/* Setup trigger (by trigger-in). */ /* Enter trigger programming mode */
sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20); sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20);
/* More trigger setup. */ /* 100 and 200 MHz mode */
sigma_write_register(WRITE_TRIGGER_OPTION, if (cur_samplerate >= MHZ(100)) {
trigger_option, sizeof(trigger_option)); sigma_set_register(WRITE_TRIGGER_SELECT1, 0x81);
/* Trigger normal (falling edge). */ triggerselect = (1 << LEDSEL1) | (triggerfall << 3) |
sigma_set_register(WRITE_TRIGGER_SELECT1, 0x08); (triggerpin & 0x7);
/* All other modes */
} else if (cur_samplerate <= MHZ(50)) {
sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20);
triggerselect = (1 << LEDSEL1) | (1 << LEDSEL0);
}
/* Setup trigger in and out pins to default values */
memset(&triggerinout_conf, 0, sizeof(struct triggerinout));
triggerinout_conf.trgout_bytrigger = 1;
triggerinout_conf.trgout_enable = 1;
sigma_write_register(WRITE_TRIGGER_OPTION,
(uint8_t *) &triggerinout_conf,
sizeof(struct triggerinout));
/* Go back to normal mode */
sigma_set_register(WRITE_TRIGGER_SELECT1, triggerselect);
/* Set clock select register. */ /* Set clock select register. */
if (cur_samplerate == MHZ(200)) if (cur_samplerate == MHZ(200))
@ -773,17 +896,12 @@ static int hw_start_acquisition(int device_index, gpointer session_device_id)
} }
/* Setup maximum post trigger time. */ /* Setup maximum post trigger time. */
sigma_set_register(WRITE_POST_TRIGGER, 0xff); sigma_set_register(WRITE_POST_TRIGGER, (capture_ratio * 256) / 100);
/* Start acqusition (software trigger start). */ /* Start acqusition (software trigger start). */
gettimeofday(&start_tv, 0); gettimeofday(&start_tv, 0);
sigma_set_register(WRITE_MODE, 0x0d); sigma_set_register(WRITE_MODE, 0x0d);
/* Add capture source. */
source_add(0, G_IO_IN, 10, receive_data, session_device_id);
receive_data(0, 1, session_device_id);
/* Send header packet to the session bus. */ /* Send header packet to the session bus. */
packet.type = DF_HEADER; packet.type = DF_HEADER;
packet.length = sizeof(struct datafeed_header); packet.length = sizeof(struct datafeed_header);
@ -795,6 +913,9 @@ static int hw_start_acquisition(int device_index, gpointer session_device_id)
header.num_probes = num_probes; header.num_probes = num_probes;
session_bus(session_device_id, &packet); session_bus(session_device_id, &packet);
/* Add capture source. */
source_add(0, G_IO_IN, 10, receive_data, session_device_id);
return SIGROK_OK; return SIGROK_OK;
} }

View File

@ -65,6 +65,9 @@ enum sigma_read_register {
#define REG_DRAM_BLOCK_BEGIN (8 << 4) #define REG_DRAM_BLOCK_BEGIN (8 << 4)
#define REG_DRAM_BLOCK_DATA (10 << 4) #define REG_DRAM_BLOCK_DATA (10 << 4)
#define LEDSEL0 6
#define LEDSEL1 7
#define NEXT_REG 1 #define NEXT_REG 1
#define EVENTS_PER_CLUSTER 7 #define EVENTS_PER_CLUSTER 7
@ -77,4 +80,26 @@ struct clockselect_50 {
uint16_t disabled_probes; uint16_t disabled_probes;
}; };
/* The effect of all these are still a bit unclear. */
struct triggerinout {
uint8_t trgout_resistor_enable : 1;
uint8_t trgout_resistor_pullup : 1;
uint8_t reserved1 : 1;
uint8_t trgout_bytrigger : 1;
uint8_t trgout_byevent : 1;
uint8_t trgout_bytriggerin : 1;
uint8_t reserved2 : 2;
/* Should be set same as the first two */
uint8_t trgout_resistor_enable2 : 1;
uint8_t trgout_resistor_pullup2 : 1;
uint8_t reserved3 : 1;
uint8_t trgout_long : 1;
uint8_t trgout_pin : 1; /* Use 1k resistor. Pullup? */
uint8_t trgin_negate : 1;
uint8_t trgout_enable : 1;
uint8_t trgin_enable : 1;
};
#endif #endif