/* Чтение данных с параллельной 8-битной шины Raspberry Pi 4 и вывод в stdout Сборка (внутри WiringPi/examples): make really-all Требования: Используется модифицированный WiringPi с функцией digitalReadPins() Режимы: fill - заполняет паузы последним байтом (высокий CPU, непрерывный поток) sleep - спит при отсутствии данных (низкий CPU, только реальные данные) */ #include #include #include #include #include #include #include #include #include /* Подключение физические контакты на 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; }