Files
gpio-reader/examples/gpio-interrupt.c
Maxim 79c711a486 wip
2026-06-09 13:44:52 +03:00

165 lines
4.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Чтение данных с параллельной 8-битной шины Raspberry Pi 4
и вывод в stdout
Сборка (внутри WiringPi/examples):
make really-all
Требования:
Используется модифицированный WiringPi с функцией digitalReadPins()
Режимы:
fill - заполняет паузы последним байтом (высокий CPU, непрерывный поток)
sleep - спит при отсутствии данных (низкий CPU, только реальные данные)
*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stddef.h>
#include <stdbool.h>
#include <time.h>
#include <sys/time.h>
#include <wiringPi.h>
/*
Подключение физические контакты на Raspberry pi4:
29 - D0
7 - D1
22 - D2
18 - D3
37 - D4
35 - D5
33 - D6
31 - D7
36 - Запись
14 - GND
*/
unsigned int wr_pin = 27; // Пин сигнала записи (WR)
unsigned int pins[] = { 21, 7, 6, 5, 25, 24, 23, 22 }; // 8-битная шина данных (wPi)
const size_t out_buffer_len = 32U; // Размер логируемого пакета
const size_t fifo_buffer_len = 4096U; // Размер ПППУ в байтах
struct fifo {
char *buffer;
size_t len;
size_t wri;
size_t rdi;
};
void fifo_reset(struct fifo* ff) {
ff->wri = 0;
ff->rdi = 0;
}
bool fifo_init(struct fifo* ff, size_t len) {
ff->buffer = malloc(len);
ff->len = len;
fifo_reset(ff);
return ff->buffer != NULL;
}
void fifo_uninit(struct fifo* ff) {
free(ff->buffer);
ff->buffer = NULL;
fifo_reset(ff);
}
size_t fifo_available(struct fifo *ff) {
if (ff->wri >= ff->rdi)
return ff->wri - ff->rdi;
else
return ff->wri + ff->len - ff->rdi;
}
bool fifo_can_write(struct fifo *ff, size_t len) {
return (ff->len - fifo_available(ff)) > len;
}
bool fifo_can_read(struct fifo *ff, size_t len) {
return fifo_available(ff) >= len;
}
bool fifo_try_read(struct fifo *ff, char* buffer, size_t len) {
if (!fifo_can_read(ff, len))
return false;
memcpy(buffer, &ff->buffer[ff->rdi], len);
ff->rdi = (ff->rdi + len) % ff->len;
return true;
}
bool fifo_try_write(struct fifo *ff, char* buffer, size_t len) {
if (!fifo_can_write(ff, len))
return false;
memcpy(&ff->buffer[ff->wri], buffer, len);
ff->wri = (ff->wri + len) % ff->len;
return true;
}
static struct fifo isr_ff;
// Антидребезг
static unsigned long long last_time_us = 0;
static const long debounce_us = 5000; // 5 мс
// Обработчик прерывания
void isr_handle(void) {
unsigned long long now_us;
struct timeval now;
gettimeofday(&now, NULL);
now_us = now.tv_sec * 1000000LL + now.tv_usec;
if (now_us - last_time_us < debounce_us) return;
last_time_us = now_us;
char byte_read = 0xff & digitalReadPins(pins, sizeof pins / sizeof pins[0]);
fifo_try_write(&isr_ff, &byte_read, 1);
}
int main(int argc, char *argv[]) {
// Обработка аргументов
if (!fifo_init(&isr_ff, fifo_buffer_len)) {
perror("fifo_init()");
exit(EXIT_FAILURE);
}
// WiringPi
if (wiringPiSetup() == -1) {
perror("wiringPiSetup()");
exit(EXIT_FAILURE);
}
pinMode(wr_pin, INPUT);
pullUpDnControl(wr_pin, PUD_UP);
// Настройка шины данных
for (unsigned int i = 0; i < (sizeof pins / sizeof pins[0]); i++) {
unsigned int pin = pins[i];
pullUpDnControl(pin, PUD_DOWN);
pinMode(pin, INPUT);
}
// Прерывание по фронту
if (wiringPiISR(wr_pin, INT_EDGE_RISING, &isr_handle) != 0) {
perror("wiringPiISR()");
exit(EXIT_FAILURE);
}
char byte_prev = 0;
while (true) {
char byte = 0;
if (fifo_try_read(&isr_ff, &byte, sizeof byte)) {
fwrite(&byte, 1, 1, stdout);
byte_prev = byte;
}
else {
fwrite(&byte_prev, 1, 1, stdout);
}
fflush(stdout);
}
fifo_uninit(&isr_ff);
return EXIT_SUCCESS;
}