163 lines
4.0 KiB
C
163 lines
4.0 KiB
C
/*
|
||
Чтение данных с параллельной 8-битной шины Raspberry Pi 4
|
||
и вывод в stdout
|
||
|
||
Сборка (внутри WiringPi/examples):
|
||
make really-all
|
||
Требования:
|
||
Используется модифицированный WiringPi с функцией digitalReadPins()
|
||
*/
|
||
|
||
#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; // Размер ПППУ в байтах
|
||
|
||
// ================= FIFO =================
|
||
|
||
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[]) {
|
||
// Инициализация FIFO
|
||
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;
|
||
while (true) {
|
||
if (fifo_try_read(&isr_ff, &byte, 1)) {
|
||
fwrite(&byte, 1, 1, stdout);
|
||
fflush(stdout);
|
||
} else {
|
||
usleep(1000); // 1 мс пауза при отсутствии данных
|
||
}
|
||
}
|
||
|
||
fifo_uninit(&isr_ff);
|
||
return EXIT_SUCCESS;
|
||
} |