116 lines
2.6 KiB
C
116 lines
2.6 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)
|
|
*/
|
|
|
|
/*
|
|
19 switch (35)
|
|
26 switch (37)
|
|
*/
|
|
|
|
#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_leds = {
|
|
.offsets = { 17, 27, 22 },
|
|
.consumer = "timer-leds",
|
|
.config = {
|
|
.flags = GPIO_V2_LINE_FLAG_OUTPUT,
|
|
},
|
|
.num_lines = 3,
|
|
};
|
|
int ret1 = ioctl(gpio_state->chip_fd, GPIO_V2_GET_LINE_IOCTL, &request_leds);
|
|
assert(ret1 != -1);
|
|
gpio_state->led_request_fd = request_leds.fd;
|
|
|
|
struct gpio_v2_line_request request_switch = {
|
|
.offsets = { 19, 26 },
|
|
.consumer = "timer-switch",
|
|
.config = {
|
|
.flags = GPIO_V2_LINE_FLAG_INPUT | GPIO_V2_LINE_FLAG_BIAS_PULL_UP,
|
|
},
|
|
.num_lines = 2,
|
|
};
|
|
int ret2 = ioctl(gpio_state->chip_fd, GPIO_V2_GET_LINE_IOCTL, &request_switch);
|
|
assert(ret2 != -1);
|
|
gpio_state->switch_request_fd = request_switch.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->led_request_fd, GPIO_V2_LINE_SET_VALUES_IOCTL, &values);
|
|
assert(ret != -1);
|
|
}
|
|
|
|
uint64_t gpio_get_values(struct gpio_state * gpio_state)
|
|
{
|
|
struct gpio_v2_line_values values = {
|
|
.mask = 0b11,
|
|
};
|
|
|
|
int ret = ioctl(gpio_state->switch_request_fd, GPIO_V2_LINE_GET_VALUES_IOCTL, &values);
|
|
assert(ret != -1);
|
|
|
|
return (~values.bits) & 0b11;
|
|
}
|
|
|
|
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("gpio pong timeout %ld\n", delta.tv_sec);
|
|
if (gpio_state->chip_fd != -1)
|
|
gpio_set_values(gpio_state, RED);
|
|
} else {
|
|
printf("gpio pong ok %ld\n", delta.tv_sec);
|
|
if (gpio_state->chip_fd != -1)
|
|
gpio_set_values(gpio_state, GREEN);
|
|
}
|
|
}
|
|
|
|
/*
|
|
int main()
|
|
{
|
|
struct gpio_state gpio_state;
|
|
gpio_open("/dev/gpiochip0", &gpio_state);
|
|
set_gpio_values(&gpio_state, 0b000);
|
|
}
|
|
*/
|