*/
#include "protocol.h"
+#include <time.h>
+#include <sys/timerfd.h>
SR_PRIV struct sr_dev_driver baylibre_acme_driver_info;
static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
{
struct dev_context *devc;
+ struct itimerspec tspec = {
+ .it_interval = { 0, 0 },
+ .it_value = { 0, 0 }
+ };
(void)cb_data;
devc = sdi->priv;
devc->samples_read = 0;
+ devc->samples_missed = 0;
+ devc->timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (devc->timer_fd < 0) {
+ sr_err("Error creating timer fd");
+ return SR_ERR;
+ }
- if (pipe(devc->pipe_fds)) {
- sr_err("Error setting up pipe");
+ tspec.it_interval.tv_sec = 0;
+ tspec.it_interval.tv_nsec = (1000000000L / devc->samplerate);
+ tspec.it_value = tspec.it_interval;
+
+ if (timerfd_settime(devc->timer_fd, 0, &tspec, NULL)) {
+ sr_err("Failed to set timer");
+ close(devc->timer_fd);
return SR_ERR;
}
- devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
+ devc->channel = g_io_channel_unix_new(devc->timer_fd);
g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
g_io_channel_set_encoding(devc->channel, NULL, NULL);
g_io_channel_set_buffered(devc->channel, FALSE);
sr_session_source_add_channel(sdi->session, devc->channel,
- G_IO_IN | G_IO_ERR, 1, bl_acme_receive_data, (void *)sdi);
+ G_IO_IN | G_IO_ERR, 1000, bl_acme_receive_data, (void *)sdi);
/* Send header packet to the session bus. */
std_session_send_df_header(sdi, LOG_PREFIX);
g_io_channel_shutdown(devc->channel, FALSE, NULL);
g_io_channel_unref(devc->channel);
devc->channel = NULL;
+ close(devc->timer_fd);
/* Send last packet. */
packet.type = SR_DF_END;
sr_session_send(sdi, &packet);
+ if (devc->samples_missed > 0)
+ sr_warn("%d samples missed", devc->samples_missed);
+
return SR_OK;
}
SR_PRIV int bl_acme_receive_data(int fd, int revents, void *cb_data)
{
- uint32_t cur_time, elapsed_time, diff_time;
- int64_t time_to_sleep;
+ uint32_t cur_time, elapsed_time;
+ uint64_t nrexpiration;
struct sr_datafeed_packet packet, framep;
struct sr_datafeed_analog analog;
struct sr_dev_inst *sdi;
memset(&analog, 0, sizeof(struct sr_datafeed_analog));
analog.data = &valf;
+ if (read(devc->timer_fd, &nrexpiration, sizeof(nrexpiration)) < 0) {
+ sr_warn("Failed to read timer information");
+ return TRUE;
+ }
+
/*
- * Reading from sysfs takes some time - try to keep up with samplerate.
+ * We were not able to process the previous timer expiration, we are
+ * overloaded.
*/
- if (devc->samples_read) {
- cur_time = g_get_monotonic_time();
- diff_time = cur_time - devc->last_sample_fin;
- time_to_sleep = G_USEC_PER_SEC / devc->samplerate - diff_time;
- if (time_to_sleep > 0)
- g_usleep(time_to_sleep);
- }
+ if (nrexpiration > 1)
+ devc->samples_missed += nrexpiration - 1;
framep.type = SR_DF_FRAME_BEGIN;
sr_session_send(cb_data, &framep);