/* * Sends the stored DMX state to its associated DMX port. If fewer than * frame_period microseconds have elapsed since the start of the last frame, * then this function will delay until that time, unless status->period_mode is * nonzero, in which case calls to send_state will be ignored until the * specified frame period has elapsed. This function should be called at least * once per second. Returns zero on success, nonzero on error. */ int send_state(dmx_state *status) { struct timespec this_time; if(status == NULL) { fprintf(stderr, "NULL status parameter"); return -1; } // Mark before break + rate control fsync(status->fd); // fsync on a tty probably doesn't do anything... if(status->period_mode) { // Skip frame rate control mode clock_gettime(CLOCK_MONOTONIC, &this_time); if(compare_timespec(&this_time, status->next_time) < 0) { return 0; } } else { // Sleep rate control mode while(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, status->next_time, NULL) == -1 && errno==EINTR) { // Repeatedly do nothing as long as clock_nanosleep() gets // interrupted (this space intentionally left blank) } } clock_gettime(CLOCK_MONOTONIC, status->next_time); status->next_time->tv_nsec += status->frame_period * 1000; if(status->next_time->tv_nsec >= 1000000000) { status->next_time->tv_nsec -= 1000000000; status->next_time->tv_sec += 1; } // Break if(ioctl(status->fd, TIOCSBRK, 0)) { perror("Error setting break"); return -1; } usleep(status->break_time); if(ioctl(status->fd, TIOCCBRK, 0)) { perror("Error clearing break"); return -1; } // Mark after break usleep(status->mark_time); // Data if(write(status->fd, &status->start_code, 1) < 0) { perror("Error sending start code"); return -1; } if(write(status->fd, status->dmx_values, status->channels_to_send) < 0) { perror("Error sending dmx data"); return -1; } return 0; }
int clock_abstime2ticks(clockid_t clockid, FAR const struct timespec *abstime, FAR int *ticks) { struct timespec currtime; struct timespec reltime; int ret; /* Convert the timespec to clock ticks. NOTE: Here we use internal knowledge * that CLOCK_REALTIME is defined to be zero! */ ret = clock_gettime(clockid, &currtime); if (ret != OK) { return EINVAL; } if (compare_timespec(abstime, &currtime) < 0) { /* Every caller of clock_abstime2ticks check 'ticks < 0' to see if * absolute time is in the past. So lets just return negative tick * here. */ *ticks = -1; return OK; } /* The relative time to wait is the absolute time minus the current time. */ reltime.tv_nsec = (abstime->tv_nsec - currtime.tv_nsec); reltime.tv_sec = (abstime->tv_sec - currtime.tv_sec); /* Check if we were supposed to borrow from the seconds to borrow from the * seconds */ if (reltime.tv_nsec < 0) { reltime.tv_nsec += NSEC_PER_SEC; reltime.tv_sec -= 1; } /* Convert this relative time into clock ticks. */ return clock_time2ticks(&reltime, ticks); }
static char* writes_and_reads_log() { const char* file_name = "histogram.log"; hdr_timespec timestamp; hdr_timespec interval; hdr_gettime(×tamp); interval.tv_sec = 5; interval.tv_nsec = 2000000; struct hdr_log_writer writer; struct hdr_log_reader reader; hdr_log_writer_init(&writer); hdr_log_reader_init(&reader); int rc = 0; FILE* log_file = fopen(file_name, "w+"); rc = hdr_log_write_header(&writer, log_file, "Test log", ×tamp); mu_assert("Failed header write", validate_return_code(rc)); hdr_log_write(&writer, log_file, ×tamp, &interval, cor_histogram); mu_assert("Failed corrected write", validate_return_code(rc)); hdr_log_write(&writer, log_file, ×tamp, &interval, raw_histogram); mu_assert("Failed raw write", validate_return_code(rc)); fprintf(log_file, "\n"); fflush(log_file); fclose(log_file); log_file = fopen(file_name, "r"); struct hdr_histogram* read_cor_histogram = NULL; struct hdr_histogram* read_raw_histogram = NULL; rc = hdr_log_read_header(&reader, log_file); mu_assert("Failed header read", validate_return_code(rc)); mu_assert("Incorrect major version", compare_int(reader.major_version, 1)); mu_assert("Incorrect minor version", compare_int(reader.minor_version, 2)); mu_assert( "Incorrect start timestamp", compare_timespec(&reader.start_timestamp, ×tamp)); hdr_timespec actual_timestamp; hdr_timespec actual_interval; rc = hdr_log_read( &reader, log_file, &read_cor_histogram, &actual_timestamp, &actual_interval); mu_assert("Failed corrected read", validate_return_code(rc)); mu_assert( "Incorrect first timestamp", compare_timespec(&actual_timestamp, ×tamp)); mu_assert( "Incorrect first interval", compare_timespec(&actual_interval, &interval)); rc = hdr_log_read(&reader, log_file, &read_raw_histogram, NULL, NULL); mu_assert("Failed raw read", validate_return_code(rc)); mu_assert( "Histograms do not match", compare_histogram(cor_histogram, read_cor_histogram)); mu_assert( "Histograms do not match", compare_histogram(raw_histogram, read_raw_histogram)); rc = hdr_log_read(&reader, log_file, &read_cor_histogram, NULL, NULL); mu_assert("No EOF at end of file", rc == EOF); fclose(log_file); remove(file_name); return 0; }