Add remote control function with LED blinking test

This commit is contained in:
miketsai 2026-06-17 17:30:10 +08:00
parent c22b81dfba
commit 41c0a781f2
3 changed files with 223 additions and 0 deletions

View 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 */

View File

@ -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);

View 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;
}