Add remote control function with LED blinking test
This commit is contained in:
parent
c22b81dfba
commit
41c0a781f2
21
include/host_stream/remote_ctrl.h
Normal file
21
include/host_stream/remote_ctrl.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef REMOTE_CTRL_H
|
||||
#define REMOTE_CTRL_H
|
||||
|
||||
/*
|
||||
* remote_ctrl.h — 433MHz SK-RC433A remote control input via GPIO sysfs
|
||||
*
|
||||
* gpio65: INPUT — SK-RC433A OUT (interlock mode: HIGH=START, LOW=STOP)
|
||||
* gpio66: OUTPUT — test LED (blink when START, off when STOP)
|
||||
*/
|
||||
|
||||
/* Initialize GPIOs and start poll/blink threads.
|
||||
* Returns 0 on success, -1 on error. */
|
||||
int remote_ctrl_init(void);
|
||||
|
||||
/* Stop threads and release GPIO resources. */
|
||||
void remote_ctrl_cleanup(void);
|
||||
|
||||
/* Get current remote state: 1=START, 0=STOP. Thread-safe. */
|
||||
int remote_ctrl_get_state(void);
|
||||
|
||||
#endif /* REMOTE_CTRL_H */
|
||||
@ -44,6 +44,7 @@
|
||||
#include "bt_uart.h"
|
||||
#include "can_bus.h"
|
||||
#include "buzzer.h"
|
||||
#include "remote_ctrl.h"
|
||||
#include "handshake.h"
|
||||
|
||||
//fifo queue buffer setting
|
||||
@ -327,6 +328,8 @@ int loadConfig(HOST_STREAM_INIT_OPT_T* pHostStreamInit)
|
||||
can_bus_init(can_spidev, can_speed, (uint32_t)can_id_raw);
|
||||
}
|
||||
buzzer_init();
|
||||
if (remote_ctrl_init() != 0)
|
||||
printf("[FW] WARNING: remote_ctrl_init failed, remote disabled\n");
|
||||
|
||||
iniparser_freedict(ini);
|
||||
return 0;
|
||||
@ -581,6 +584,7 @@ int main (int argc, char* argv[])
|
||||
|
||||
EXIT:
|
||||
printf("%s free\n", __func__);
|
||||
remote_ctrl_cleanup();
|
||||
|
||||
free_fec_def_str();
|
||||
free_stream_init(&HostStreamInit);
|
||||
|
||||
198
src/host_stream/remote_ctrl.c
Normal file
198
src/host_stream/remote_ctrl.c
Normal file
@ -0,0 +1,198 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include "remote_ctrl.h"
|
||||
|
||||
#define REMOTE_INPUT_GPIO 65
|
||||
#define REMOTE_LED_GPIO 66
|
||||
#define LED_BLINK_ON_MS 500
|
||||
#define LED_BLINK_OFF_MS 500
|
||||
|
||||
static volatile int s_running = 0;
|
||||
static volatile int s_remote_start = 0; /* 1=START, 0=STOP */
|
||||
|
||||
static int s_input_val_fd = -1; /* gpio65 value fd for poll */
|
||||
static int s_led_val_fd = -1; /* gpio66 value fd for write */
|
||||
|
||||
static pthread_t s_poll_tid;
|
||||
static pthread_t s_led_tid;
|
||||
|
||||
/* ── GPIO sysfs helpers ──────────────────────────────────────────── */
|
||||
|
||||
static int gpio_setup(int gpio, const char *direction, const char *edge)
|
||||
{
|
||||
char path[64], buf[8];
|
||||
int fd;
|
||||
|
||||
/* export */
|
||||
fd = open("/sys/class/gpio/export", O_WRONLY);
|
||||
if (fd >= 0) {
|
||||
snprintf(buf, sizeof(buf), "%d", gpio);
|
||||
write(fd, buf, strlen(buf));
|
||||
close(fd);
|
||||
/* EBUSY = already exported, not an error */
|
||||
}
|
||||
|
||||
/* direction */
|
||||
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", gpio);
|
||||
fd = open(path, O_WRONLY);
|
||||
if (fd < 0) { perror("[RC] direction open"); return -1; }
|
||||
write(fd, direction, strlen(direction));
|
||||
close(fd);
|
||||
|
||||
/* edge (only for input) */
|
||||
if (edge) {
|
||||
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", gpio);
|
||||
fd = open(path, O_WRONLY);
|
||||
if (fd < 0) { perror("[RC] edge open"); return -1; }
|
||||
write(fd, edge, strlen(edge));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* open value fd */
|
||||
snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", gpio);
|
||||
int flags = strcmp(direction, "in") == 0 ? (O_RDONLY | O_NONBLOCK) : O_RDWR;
|
||||
fd = open(path, flags);
|
||||
if (fd < 0) perror("[RC] value open");
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void gpio_write(int fd, int value)
|
||||
{
|
||||
if (fd < 0) return;
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, value ? "1" : "0", 1);
|
||||
}
|
||||
|
||||
static int gpio_read(int fd)
|
||||
{
|
||||
if (fd < 0) return 0;
|
||||
char buf[4] = {0};
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
read(fd, buf, 1);
|
||||
return buf[0] == '1' ? 1 : 0;
|
||||
}
|
||||
|
||||
/* ── LED blink thread ────────────────────────────────────────────── */
|
||||
|
||||
static void *led_blink_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
printf("[RC] LED blink thread started (gpio%d)\n", REMOTE_LED_GPIO);
|
||||
|
||||
while (s_running) {
|
||||
if (s_remote_start) {
|
||||
gpio_write(s_led_val_fd, 1);
|
||||
usleep(LED_BLINK_ON_MS * 1000);
|
||||
if (!s_remote_start) { gpio_write(s_led_val_fd, 0); continue; }
|
||||
gpio_write(s_led_val_fd, 0);
|
||||
usleep(LED_BLINK_OFF_MS * 1000);
|
||||
} else {
|
||||
gpio_write(s_led_val_fd, 0);
|
||||
usleep(100 * 1000); /* idle: check state every 100ms */
|
||||
}
|
||||
}
|
||||
|
||||
gpio_write(s_led_val_fd, 0); /* ensure LED off on exit */
|
||||
printf("[RC] LED blink thread exit\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ── Input poll thread ───────────────────────────────────────────── */
|
||||
|
||||
static void *remote_poll_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
struct pollfd pfd;
|
||||
char dummy[4];
|
||||
|
||||
pfd.fd = s_input_val_fd;
|
||||
pfd.events = POLLPRI | POLLERR;
|
||||
|
||||
/* consume initial level so first real edge is not missed */
|
||||
lseek(pfd.fd, 0, SEEK_SET);
|
||||
read(pfd.fd, dummy, sizeof(dummy));
|
||||
|
||||
s_remote_start = (dummy[0] == '1') ? 1 : 0;
|
||||
printf("[RC] poll thread started gpio%d initial_state=%s\n",
|
||||
REMOTE_INPUT_GPIO, s_remote_start ? "START" : "STOP");
|
||||
|
||||
while (s_running) {
|
||||
int ret = poll(&pfd, 1, 1000);
|
||||
if (!s_running) break;
|
||||
if (!(pfd.revents & POLLPRI)) continue;
|
||||
|
||||
lseek(pfd.fd, 0, SEEK_SET);
|
||||
read(pfd.fd, dummy, sizeof(dummy));
|
||||
|
||||
int new_state = (dummy[0] == '1') ? 1 : 0;
|
||||
if (new_state != s_remote_start) {
|
||||
s_remote_start = new_state;
|
||||
printf("[RC] remote state changed: %s\n",
|
||||
new_state ? "START" : "STOP");
|
||||
}
|
||||
}
|
||||
|
||||
printf("[RC] poll thread exit\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ── Public API ──────────────────────────────────────────────────── */
|
||||
|
||||
int remote_ctrl_init(void)
|
||||
{
|
||||
/* setup input gpio65: direction=in, edge=both */
|
||||
s_input_val_fd = gpio_setup(REMOTE_INPUT_GPIO, "in", "both");
|
||||
if (s_input_val_fd < 0) {
|
||||
printf("[RC] ERROR: failed to init input gpio%d\n", REMOTE_INPUT_GPIO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* setup output gpio66: direction=out, no edge */
|
||||
s_led_val_fd = gpio_setup(REMOTE_LED_GPIO, "out", NULL);
|
||||
if (s_led_val_fd < 0) {
|
||||
printf("[RC] ERROR: failed to init LED gpio%d\n", REMOTE_LED_GPIO);
|
||||
close(s_input_val_fd);
|
||||
s_input_val_fd = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
s_running = 1;
|
||||
|
||||
if (pthread_create(&s_poll_tid, NULL, remote_poll_thread, NULL) != 0) {
|
||||
printf("[RC] ERROR: pthread_create poll thread failed\n");
|
||||
s_running = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pthread_create(&s_led_tid, NULL, led_blink_thread, NULL) != 0) {
|
||||
printf("[RC] ERROR: pthread_create LED thread failed\n");
|
||||
s_running = 0;
|
||||
pthread_join(s_poll_tid, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("[RC] remote_ctrl_init OK: input=gpio%d LED=gpio%d\n",
|
||||
REMOTE_INPUT_GPIO, REMOTE_LED_GPIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void remote_ctrl_cleanup(void)
|
||||
{
|
||||
s_running = 0;
|
||||
pthread_join(s_poll_tid, NULL);
|
||||
pthread_join(s_led_tid, NULL);
|
||||
|
||||
if (s_input_val_fd >= 0) { close(s_input_val_fd); s_input_val_fd = -1; }
|
||||
if (s_led_val_fd >= 0) { close(s_led_val_fd); s_led_val_fd = -1; }
|
||||
printf("[RC] remote_ctrl_cleanup done\n");
|
||||
}
|
||||
|
||||
int remote_ctrl_get_state(void)
|
||||
{
|
||||
return s_remote_start;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user