Last active
December 4, 2021 18:33
-
-
Save zavorka/91b107c196467381797152cce263c1be to your computer and use it in GitHub Desktop.
IJP 0612 controlled from SL1 board
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <fcntl.h> | |
#include <gpiod.h> | |
#include <signal.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <time.h> | |
#include <unistd.h> | |
#ifndef CONSUMER | |
#define CONSUMER "Pragotron" | |
#endif | |
static int gpio_state; | |
static struct gpiod_line_bulk lines; | |
static struct gpiod_chip *chip; | |
static struct gpiod_line *line_in1; | |
static struct gpiod_line *line_in2; | |
static struct gpiod_line *line_en1; | |
static struct gpiod_line *line_en2; | |
static int16_t clock_state; | |
static int reset_clock_state(void) | |
{ | |
time_t t; | |
struct tm *tmp; | |
t = time(NULL); | |
tmp = localtime(&t); | |
clock_state = tmp->tm_hour * 60 + tmp->tm_min; | |
return 0; | |
}; | |
static int read_clock_state(void) | |
{ | |
int fd = open("/etc/pragotron_state", O_RDONLY); | |
if (fd < 0) return reset_clock_state(); | |
ssize_t ret = read(fd, &clock_state, sizeof(clock_state)); | |
close(fd); | |
if (ret < sizeof(clock_state)) return reset_clock_state(); | |
return 0; | |
} | |
static int write_clock_state(void) | |
{ | |
int fd = open("/etc/pragotron_state", O_CREAT | O_WRONLY | O_TRUNC, 0644); | |
write(fd, &clock_state, sizeof(clock_state)); | |
fsync(fd); | |
close(fd); | |
return 0; | |
} | |
static int increment_clock_state(void) | |
{ | |
clock_state = (clock_state + 1) % 1440; | |
write_clock_state(); | |
usleep(500000); | |
} | |
static int clock_state_dev_from_local() | |
{ | |
int local; | |
time_t t; | |
struct tm *tmp; | |
t = time(NULL); | |
tmp = localtime(&t); | |
local = tmp->tm_hour * 60 + tmp->tm_min; | |
return (local - clock_state + 1440) % 1440; | |
} | |
static void timestamp(FILE *stream) | |
{ | |
static char buf[256]; | |
time_t t; | |
struct tm *tmp; | |
t = time(NULL); | |
tmp = localtime(&t); | |
if (tmp == NULL) { | |
perror("localtime"); | |
exit(EXIT_FAILURE); | |
} | |
if (strftime(buf, 256, "%a, %d %b %Y %T %z", tmp) == 0) { | |
fprintf(stderr, "strftime returned 0"); | |
exit(EXIT_FAILURE); | |
} | |
fprintf(stream, "%s|%4d: ", buf, clock_state_dev_from_local()); | |
} | |
static void flip_minute(void) | |
{ | |
int ret; | |
gpio_state = !gpio_state; | |
ret = gpiod_line_set_value(line_in1, gpio_state); | |
if (ret) { | |
perror("gpiod_line_set_value"); | |
exit(1); | |
} | |
ret = gpiod_line_set_value(line_in2, !gpio_state); | |
if (ret) { | |
perror("gpiod_line_set_value"); | |
exit(1); | |
} | |
increment_clock_state(); | |
timestamp(stderr); | |
fprintf(stderr, "[%d, %d]\n", gpio_state, !gpio_state); | |
} | |
static void handler(int sig) | |
{ | |
flip_minute(); | |
} | |
int main(int argc, char **argv) | |
{ | |
struct sigaction sa = { 0 }; | |
sa.sa_handler = handler; | |
sigaction(SIGALRM, &sa, NULL); | |
int ret; | |
chip = gpiod_chip_open_by_name("gpiochip2"); | |
if (!chip) { | |
perror("Open chip failed\n"); | |
exit(1); | |
} | |
line_in1 = gpiod_chip_get_line(chip, 136); | |
if (ret < 0) { | |
perror("gpiod_chip_get_line\n"); | |
exit(1); | |
} | |
line_in2 = gpiod_chip_get_line(chip, 137); | |
if (ret < 0) { | |
perror("gpiod_chip_get_line\n"); | |
exit(1); | |
} | |
line_en1 = gpiod_chip_get_line(chip, 138); | |
if (ret < 0) { | |
perror("gpiod_chip_get_line\n"); | |
exit(1); | |
} | |
line_en2 = gpiod_chip_get_line(chip, 139); | |
if (ret < 0) { | |
perror("gpiod_chip_get_line\n"); | |
exit(1); | |
} | |
read_clock_state(); | |
gpio_state = clock_state % 2; | |
ret = gpiod_line_request_output(line_in1, CONSUMER, gpio_state); | |
if (ret < 0) { | |
perror("Request line as output failed\n"); | |
exit(1); | |
} | |
ret = gpiod_line_request_output(line_in2, CONSUMER, !gpio_state); | |
if (ret < 0) { | |
perror("Request line as output failed\n"); | |
exit(1); | |
} | |
ret = gpiod_line_request_output(line_en1, CONSUMER, 1); | |
if (ret < 0) { | |
perror("Request line as output failed\n"); | |
exit(1); | |
} | |
ret = gpiod_line_request_output(line_en2, CONSUMER, 1); | |
if (ret < 0) { | |
perror("Request line as output failed\n"); | |
exit(1); | |
} | |
timestamp(stderr); | |
fprintf(stderr, "[%d, %d]\n", gpio_state, !gpio_state); | |
timer_t timer_id; | |
ret = timer_create(CLOCK_REALTIME_ALARM, NULL, &timer_id); | |
struct itimerspec its = { 0 }; | |
clock_gettime(CLOCK_REALTIME_ALARM, &its.it_value); | |
its.it_value.tv_sec = (((its.it_value.tv_sec + 2) / 60) + 1) * 60; | |
its.it_interval.tv_sec = 60; | |
timer_settime(&timer_id, TIMER_ABSTIME, &its, NULL); | |
while (1) { | |
if (clock_state_dev_from_local() == 0) { | |
pause(); | |
} else { | |
timestamp(stderr); | |
fprintf(stderr, "clock state diverges from localtime, let's fix it ...\n"); | |
signal(SIGALRM, SIG_IGN); | |
while (clock_state_dev_from_local() != 0) | |
flip_minute(); | |
timestamp(stderr); | |
fprintf(stderr, "done! Switching to normal operating mode.\n"); | |
sigaction(SIGALRM, &sa, NULL); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment