timer/gpio.c
2024-06-23 23:20:44 -05:00

87 lines
1.8 KiB
C

#include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <linux/gpio.h>
#include <sys/ioctl.h>
#include <time.h>
#include "gpio.h"
#include "timespec.h"
#include "ping_pong.h"
#define LAST_PONG_TIMEOUT (PING_INTERVAL * 3)
/*
17 red (11)
27 green (13)
22 blue (15)
*/
#define RED 0b001
#define GREEN 0b010
#define BLUE 0b100
int gpio_open(const char * path,
struct gpio_state * gpio_state)
{
gpio_state->chip_fd = open(path, O_RDWR);
if (gpio_state->chip_fd == -1) {
perror("open gpio");
return -1;
}
struct gpio_v2_line_request request = {
.offsets = { 17, 27, 22 },
.consumer = "timer",
.config = {
.flags = GPIO_V2_LINE_FLAG_OUTPUT,
},
.num_lines = 3,
};
int ret = ioctl(gpio_state->chip_fd, GPIO_V2_GET_LINE_IOCTL, &request);
assert(ret != -1);
gpio_state->req_fd = request.fd;
return 0;
}
void gpio_set_values(struct gpio_state * gpio_state, uint64_t bits)
{
struct gpio_v2_line_values values = {
.bits = bits,
.mask = 0b111,
};
int ret = ioctl(gpio_state->req_fd, GPIO_V2_LINE_SET_VALUES_IOCTL, &values);
assert(ret != -1);
}
void gpio_set_values_from_link_state(struct gpio_state * gpio_state,
struct link_state * link_state)
{
struct timespec now;
int ret = clock_gettime(CLOCK_MONOTONIC_RAW, &now);
assert(ret != -1);
struct timespec delta = timespec_sub(&now, &link_state->last_pong);
if (delta.tv_sec >= LAST_PONG_TIMEOUT) {
printf("pong timeout %ld\n", delta.tv_sec);
if (gpio_state->chip_fd != -1)
gpio_set_values(gpio_state, GREEN);
} else {
printf("pong ok %ld\n", delta.tv_sec);
if (gpio_state->chip_fd != -1)
gpio_set_values(gpio_state, RED);
}
}
/*
int main()
{
struct gpio_state gpio_state;
gpio_open("/dev/gpiochip0", &gpio_state);
set_gpio_values(&gpio_state, 0b000);
}
*/