Skip to content

Instantly share code, notes, and snippets.

@zavorka
Last active December 4, 2021 18:33
Show Gist options
  • Save zavorka/91b107c196467381797152cce263c1be to your computer and use it in GitHub Desktop.
Save zavorka/91b107c196467381797152cce263c1be to your computer and use it in GitHub Desktop.
IJP 0612 controlled from SL1 board
#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