X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fdemo%2Fprotocol.c;h=eea3c9b8e7e622a72941ca23be952aa2e54c30e4;hb=7f0463840ab5d6a85daaa76850558d2b71e596cf;hp=8db7cbbfacaf3e85776a1bd0edaeee27e1989867;hpb=94f364ec11c938934f68cde067ee590218177140;p=libsigrok.git diff --git a/src/hardware/demo/protocol.c b/src/hardware/demo/protocol.c index 8db7cbbf..eea3c9b8 100644 --- a/src/hardware/demo/protocol.c +++ b/src/hardware/demo/protocol.c @@ -173,77 +173,92 @@ static const uint8_t pattern_squid[128][128 / 8] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, }; -SR_PRIV void demo_generate_analog_pattern(struct analog_gen *ag, uint64_t sample_rate) +SR_PRIV void demo_generate_analog_pattern(struct dev_context *devc) { double t, frequency; - float value; + float amplitude, offset; + struct analog_pattern *pattern; unsigned int num_samples, i; + float value; int last_end; - sr_dbg("Generating %s pattern.", analog_pattern_str[ag->pattern]); - num_samples = ANALOG_BUFSIZE / sizeof(float); + frequency = (double) devc->cur_samplerate / ANALOG_SAMPLES_PER_PERIOD; + amplitude = DEFAULT_ANALOG_AMPLITUDE; + offset = DEFAULT_ANALOG_OFFSET; + + /* + * FIXME: We actually need only one period. A ringbuffer would be + * useful here. + * Make sure the number of samples we put out is an integer + * multiple of our period size. + */ - switch (ag->pattern) { - case PATTERN_SQUARE: - value = ag->amplitude; - last_end = 0; - for (i = 0; i < num_samples; i++) { - if (i % 5 == 0) - value = -value; - if (i % 10 == 0) - last_end = i; - ag->pattern_data[i] = value; - } - ag->num_samples = last_end; - break; - case PATTERN_SINE: - frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD; - - /* Make sure the number of samples we put out is an integer - * multiple of our period size */ - /* FIXME we actually need only one period. A ringbuffer would be - * useful here. */ - while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0) - num_samples--; - - for (i = 0; i < num_samples; i++) { - t = (double) i / (double) sample_rate; - ag->pattern_data[i] = ag->amplitude * - sin(2 * G_PI * frequency * t); - } - - ag->num_samples = num_samples; - break; - case PATTERN_TRIANGLE: - frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD; - - while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0) - num_samples--; - - for (i = 0; i < num_samples; i++) { - t = (double) i / (double) sample_rate; - ag->pattern_data[i] = (2 * ag->amplitude / G_PI) * - asin(sin(2 * G_PI * frequency * t)); - } - - ag->num_samples = num_samples; - break; - case PATTERN_SAWTOOTH: - frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD; - - while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0) - num_samples--; - - for (i = 0; i < num_samples; i++) { - t = (double) i / (double) sample_rate; - ag->pattern_data[i] = 2 * ag->amplitude * - ((t * frequency) - floor(0.5f + t * frequency)); - } - - ag->num_samples = num_samples; - break; + /* PATTERN_SQUARE: */ + sr_dbg("Generating %s pattern.", analog_pattern_str[PATTERN_SQUARE]); + pattern = g_malloc(sizeof(struct analog_pattern)); + value = amplitude; + last_end = 0; + for (i = 0; i < num_samples; i++) { + if (i % 5 == 0) + value = -value; + if (i % 10 == 0) + last_end = i; + pattern->data[i] = value + offset; + } + pattern->num_samples = last_end; + devc->analog_patterns[PATTERN_SQUARE] = pattern; + + /* Readjusting num_samples for all other patterns. */ + while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0) + num_samples--; + + /* PATTERN_SINE: */ + sr_dbg("Generating %s pattern.", analog_pattern_str[PATTERN_SINE]); + pattern = g_malloc(sizeof(struct analog_pattern)); + for (i = 0; i < num_samples; i++) { + t = (double) i / (double) devc->cur_samplerate; + pattern->data[i] = sin(2 * G_PI * frequency * t) * amplitude + offset; + } + pattern->num_samples = last_end; + devc->analog_patterns[PATTERN_SINE] = pattern; + + /* PATTERN_TRIANGLE: */ + sr_dbg("Generating %s pattern.", analog_pattern_str[PATTERN_TRIANGLE]); + pattern = g_malloc(sizeof(struct analog_pattern)); + for (i = 0; i < num_samples; i++) { + t = (double) i / (double) devc->cur_samplerate; + pattern->data[i] = (2 / G_PI) * asin(sin(2 * G_PI * frequency * t)) * + amplitude + offset; } + pattern->num_samples = last_end; + devc->analog_patterns[PATTERN_TRIANGLE] = pattern; + + /* PATTERN_SAWTOOTH: */ + sr_dbg("Generating %s pattern.", analog_pattern_str[PATTERN_SAWTOOTH]); + pattern = g_malloc(sizeof(struct analog_pattern)); + for (i = 0; i < num_samples; i++) { + t = (double) i / (double) devc->cur_samplerate; + pattern->data[i] = 2 * ((t * frequency) - floor(0.5f + t * frequency)) * + amplitude + offset; + } + pattern->num_samples = last_end; + devc->analog_patterns[PATTERN_SAWTOOTH] = pattern; + + /* PATTERN_ANALOG_RANDOM */ + /* Data not filled here, will be generated in send_analog_packet(). */ + pattern = g_malloc(sizeof(struct analog_pattern)); + pattern->num_samples = last_end; + devc->analog_patterns[PATTERN_ANALOG_RANDOM] = pattern; +} + +SR_PRIV void demo_free_analog_pattern(struct dev_context *devc) +{ + g_free(devc->analog_patterns[PATTERN_SQUARE]); + g_free(devc->analog_patterns[PATTERN_SINE]); + g_free(devc->analog_patterns[PATTERN_TRIANGLE]); + g_free(devc->analog_patterns[PATTERN_SAWTOOTH]); + g_free(devc->analog_patterns[PATTERN_ANALOG_RANDOM]); } static uint64_t encode_number_to_gray(uint64_t nr) @@ -390,9 +405,12 @@ static void send_analog_packet(struct analog_gen *ag, { struct sr_datafeed_packet packet; struct dev_context *devc; + struct analog_pattern *pattern; uint64_t sending_now, to_avg; int ag_pattern_pos; unsigned int i; + float amplitude, offset, value; + float *data; if (!ag->ch || !ag->ch->enabled) return; @@ -401,11 +419,13 @@ static void send_analog_packet(struct analog_gen *ag, packet.type = SR_DF_ANALOG; packet.payload = &ag->packet; + pattern = devc->analog_patterns[ag->pattern]; + ag->packet.meaning->channels = g_slist_append(NULL, ag->ch); ag->packet.meaning->mq = ag->mq; ag->packet.meaning->mqflags = ag->mq_flags; - /* Set a unit for the given quantity */ + /* Set a unit for the given quantity. */ if (ag->mq == SR_MQ_VOLTAGE) ag->packet.meaning->unit = SR_UNIT_VOLT; else if (ag->mq == SR_MQ_CURRENT) @@ -476,22 +496,55 @@ static void send_analog_packet(struct analog_gen *ag, ag->packet.meaning->unit = SR_UNIT_UNITLESS; if (!devc->avg) { - ag_pattern_pos = analog_pos % ag->num_samples; - sending_now = MIN(analog_todo, ag->num_samples - ag_pattern_pos); - ag->packet.data = ag->pattern_data + ag_pattern_pos; + ag_pattern_pos = analog_pos % pattern->num_samples; + sending_now = MIN(analog_todo, pattern->num_samples - ag_pattern_pos); + if (ag->amplitude != DEFAULT_ANALOG_AMPLITUDE || + ag->offset != DEFAULT_ANALOG_OFFSET || + ag->pattern == PATTERN_ANALOG_RANDOM) { + /* + * Amplitude or offset changed (or we are generating + * random data), modify each sample. + */ + if (ag->pattern == PATTERN_ANALOG_RANDOM) { + amplitude = ag->amplitude / 500.0; + offset = ag->offset - DEFAULT_ANALOG_OFFSET - ag->amplitude; + } else { + amplitude = ag->amplitude / DEFAULT_ANALOG_AMPLITUDE; + offset = ag->offset - DEFAULT_ANALOG_OFFSET; + } + data = ag->packet.data; + for (i = 0; i < sending_now; i++) { + if (ag->pattern == PATTERN_ANALOG_RANDOM) + data[i] = (rand() % 1000) * amplitude + offset; + else + data[i] = pattern->data[ag_pattern_pos + i] * amplitude + offset; + } + } else { + /* Amplitude and offset unchanged, use the fast way. */ + ag->packet.data = pattern->data + ag_pattern_pos; + } ag->packet.num_samples = sending_now; sr_session_send(sdi, &packet); /* Whichever channel group gets there first. */ *analog_sent = MAX(*analog_sent, sending_now); } else { - ag_pattern_pos = analog_pos % ag->num_samples; - to_avg = MIN(analog_todo, ag->num_samples - ag_pattern_pos); + ag_pattern_pos = analog_pos % pattern->num_samples; + to_avg = MIN(analog_todo, pattern->num_samples - ag_pattern_pos); + if (ag->pattern == PATTERN_ANALOG_RANDOM) { + amplitude = ag->amplitude / 500.0; + offset = ag->offset - DEFAULT_ANALOG_OFFSET - ag->amplitude; + } else { + amplitude = ag->amplitude / DEFAULT_ANALOG_AMPLITUDE; + offset = ag->offset - DEFAULT_ANALOG_OFFSET; + } for (i = 0; i < to_avg; i++) { - ag->avg_val = (ag->avg_val + - *(ag->pattern_data + - ag_pattern_pos + i)) / 2; + if (ag->pattern == PATTERN_ANALOG_RANDOM) + value = (rand() % 1000) * amplitude + offset; + else + value = *(pattern->data + ag_pattern_pos + i) * amplitude + offset; + ag->avg_val = (ag->avg_val + value) / 2; ag->num_avgs++; /* Time to send averaged data? */ if ((devc->avg_samples > 0) && (ag->num_avgs >= devc->avg_samples)) @@ -499,7 +552,8 @@ static void send_analog_packet(struct analog_gen *ag, } if (devc->avg_samples == 0) { - /* We're averaging all the samples, so wait with + /* + * We're averaging all the samples, so wait with * sending until the very end. */ *analog_sent = ag->num_avgs; @@ -660,7 +714,7 @@ SR_PRIV int demo_prepare_data(int fd, int revents, void *cb_data) devc->spent_us += todo_us; if (devc->limit_frames && devc->sent_frame_samples >= SAMPLES_PER_FRAME) { - std_session_send_frame_end(sdi); + std_session_send_df_frame_end(sdi); devc->sent_frame_samples = 0; devc->limit_frames--; if (!devc->limit_frames) { @@ -688,7 +742,7 @@ SR_PRIV int demo_prepare_data(int fd, int revents, void *cb_data) sr_dev_acquisition_stop(sdi); } else if (devc->limit_frames) { if (devc->sent_frame_samples == 0) - std_session_send_frame_begin(sdi); + std_session_send_df_frame_begin(sdi); } return G_SOURCE_CONTINUE;