From: HÃ¥vard Espeland Date: Fri, 30 Apr 2010 20:18:10 +0000 (+0200) Subject: Sigma: Add triggers support for 100 and 200 MHz. X-Git-Tag: libsigrok-0.1.0~539 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=57bbf56b8420e75bcad45b417c0d36c0a55a3910;p=libsigrok.git Sigma: Add triggers support for 100 and 200 MHz. --- diff --git a/hardware/asix-sigma/asix-sigma.c b/hardware/asix-sigma/asix-sigma.c index dfaca10c..c5797cf4 100644 --- a/hardware/asix-sigma/asix-sigma.c +++ b/hardware/asix-sigma/asix-sigma.c @@ -35,6 +35,7 @@ #define USB_VENDOR_NAME "ASIX" #define USB_MODEL_NAME "SIGMA" #define USB_MODEL_VERSION "" +#define TRIGGER_TYPES "rf" static GSList *device_instances = NULL; @@ -46,6 +47,11 @@ static struct timeval start_tv; static int cur_firmware = -1; static int num_probes = 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[] = { KHZ(200), @@ -71,6 +77,8 @@ static struct samplerates samplerates = { static int capabilities[] = { HWCAP_LOGIC_ANALYZER, HWCAP_SAMPLERATE, + HWCAP_CAPTURE_RATIO, + HWCAP_PROBECONFIG, /* These are really implemented in the driver, not the hardware. */ 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); *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; } @@ -495,6 +510,39 @@ static int set_samplerate(struct sigrok_device_instance *sdi, uint64_t samplerat 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) { device_index = device_index; @@ -527,7 +575,7 @@ static void *hw_get_device_info(int device_index, int device_info_id) info = &samplerates; break; case DI_TRIGGER_TYPES: - info = 0; + info = (char *)TRIGGER_TYPES; break; case DI_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) { ret = set_samplerate(sdi, *(uint64_t*) value); } else if (capability == HWCAP_PROBECONFIG) { - ret = SIGROK_OK; + ret = configure_probes(value); } else if (capability == HWCAP_LIMIT_MSEC) { limit_msec = strtoull(value, NULL, 10); 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 { ret = SIGROK_ERR; } @@ -585,7 +638,7 @@ static int hw_set_configuration(int device_index, int capability, void *value) * spread 20 ns apart. */ 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 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; uint16_t *event; uint16_t cur_sample; + int triggerts = -1; + + /* Find in which cluster the trigger occured */ + if (triggerpos != -1) + triggerts = (triggerpos / 7); /* For each ts */ for (i = 0; i < 64; ++i) { @@ -611,8 +669,21 @@ static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts, 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; /* For each event in cluster. */ @@ -634,18 +705,39 @@ static int decode_chunk_ts(uint8_t *buf, uint16_t *lastts, *lastsample = samples[n - 1]; - /* Send to sigrok. */ + /* Send data up to trigger point (if triggered) */ sent = 0; - while (sent < n) { - tosend = MIN(2048, n - sent); + if (i == triggerts) { + /* + * 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; + + if (tosend > 0) { + packet.type = DF_LOGIC16; + packet.length = tosend * sizeof(uint16_t); + packet.payload = samples; + session_bus(user_data, &packet); + + sent += tosend; + } - packet.type = DF_LOGIC16; - packet.length = tosend * sizeof(uint16_t); - packet.payload = samples + sent; + packet.type = DF_TRIGGER; + packet.length = 0; + packet.payload = 0; 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; @@ -661,6 +753,8 @@ static int receive_data(int fd, int revents, void *user_data) struct timeval tv; uint16_t lastts = 0; uint16_t lastsample = 0; + uint8_t modestatus; + int triggerchunk = -1; fd = fd; revents = revents; @@ -686,8 +780,11 @@ static int receive_data(int fd, int revents, void *user_data) /* Get the current position. */ sigma_read_pos(&stoppos, &triggerpos); - /* Read mode status. We will care for this later. */ - sigma_get_register(READ_MODE); + /* Check if trigger has fired */ + modestatus = sigma_get_register(READ_MODE); + if (modestatus & 0x20) { + triggerchunk = triggerpos / 512; + } /* Download sample data. */ 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. */ for (i = 0; i < newchunks; ++i) { - decode_chunk_ts(buf + (i * CHUNK_SIZE), - &lastts, &lastsample, user_data); + if (curchunk + i == triggerchunk) + 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; @@ -724,9 +827,10 @@ static int hw_start_acquisition(int device_index, gpointer session_device_id) struct sigrok_device_instance *sdi; struct datafeed_packet packet; struct datafeed_header header; - uint8_t trigger_option[2] = { 0x38, 0x00 }; struct clockselect_50 clockselect; int frac; + uint8_t triggerselect; + struct triggerinout triggerinout_conf; 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) set_samplerate(sdi, MHZ(50)); - /* Setup trigger (by trigger-in). */ + /* Enter trigger programming mode */ sigma_set_register(WRITE_TRIGGER_SELECT1, 0x20); - /* More trigger setup. */ + /* 100 and 200 MHz mode */ + if (cur_samplerate >= MHZ(100)) { + sigma_set_register(WRITE_TRIGGER_SELECT1, 0x81); + + triggerselect = (1 << LEDSEL1) | (triggerfall << 3) | + (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, - trigger_option, sizeof(trigger_option)); + (uint8_t *) &triggerinout_conf, + sizeof(struct triggerinout)); - /* Trigger normal (falling edge). */ - sigma_set_register(WRITE_TRIGGER_SELECT1, 0x08); + /* Go back to normal mode */ + sigma_set_register(WRITE_TRIGGER_SELECT1, triggerselect); /* Set clock select register. */ 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. */ - sigma_set_register(WRITE_POST_TRIGGER, 0xff); + sigma_set_register(WRITE_POST_TRIGGER, (capture_ratio * 256) / 100); /* Start acqusition (software trigger start). */ gettimeofday(&start_tv, 0); 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. */ packet.type = DF_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; session_bus(session_device_id, &packet); + /* Add capture source. */ + source_add(0, G_IO_IN, 10, receive_data, session_device_id); + return SIGROK_OK; } diff --git a/hardware/asix-sigma/asix-sigma.h b/hardware/asix-sigma/asix-sigma.h index af569275..2d38294e 100644 --- a/hardware/asix-sigma/asix-sigma.h +++ b/hardware/asix-sigma/asix-sigma.h @@ -65,6 +65,9 @@ enum sigma_read_register { #define REG_DRAM_BLOCK_BEGIN (8 << 4) #define REG_DRAM_BLOCK_DATA (10 << 4) +#define LEDSEL0 6 +#define LEDSEL1 7 + #define NEXT_REG 1 #define EVENTS_PER_CLUSTER 7 @@ -77,4 +80,26 @@ struct clockselect_50 { 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