From 2941444a4c417406a4523a389c1c916906dae4cb Mon Sep 17 00:00:00 2001 From: Niellune Date: Sat, 28 Feb 2026 11:03:41 +0200 Subject: [PATCH] SPI Examples --- examples/emulator.cpp | 5 +- examples/spi.cpp | 167 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 examples/spi.cpp diff --git a/examples/emulator.cpp b/examples/emulator.cpp index 78dd7a0..34716d2 100644 --- a/examples/emulator.cpp +++ b/examples/emulator.cpp @@ -14,10 +14,11 @@ void signal_handler(int signum) { int main() { const int PIN_HOLD = 17; // stays ON const int PIN_BLINK = 27; // toggles - const double ON_INTERVAL = 0.2; // seconds - const double OFF_INTERVAL = 0.8; // seconds + const double ON_INTERVAL = 0.5; // seconds + const double OFF_INTERVAL = 0.5; // seconds signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); // Open the GPIO chip (0 = /dev/gpiochip0 on every Pi) int h = lgGpiochipOpen(0); diff --git a/examples/spi.cpp b/examples/spi.cpp new file mode 100644 index 0000000..f493ced --- /dev/null +++ b/examples/spi.cpp @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace chrono; + +#define SPI_DEVICE "/dev/spidev0.0" +#define SPI_SPEED_HZ 4000000 +#define ADC_RATE 16000 +#define BLOCK_SIZE 4096 +#define ALPHA 1 +#define CORR_POWER 0.1 + +volatile bool active = true; +int spi_fd = -1; +pa_simple *pa_handle = nullptr; + +double filtered = 0.0; +double correction = 0.0; + +uint8_t tx[2] = {0, 0}, rx[2] = {0, 0}; + +struct spi_ioc_transfer tr = { + .tx_buf = (unsigned long)tx, + .rx_buf = (unsigned long)rx, + .len = 2, + .speed_hz = SPI_SPEED_HZ, + .bits_per_word = 8}; + +void handler(int sig) +{ + active = false; +} + +void init_pulse() +{ + pa_sample_spec ss = { + .format = PA_SAMPLE_S16LE, + .rate = ADC_RATE, + .channels = 1}; + + pa_buffer_attr ba = { + .maxlength = BLOCK_SIZE * sizeof(int16_t) * 4, + .tlength = BLOCK_SIZE * sizeof(int16_t), + .prebuf = BLOCK_SIZE * sizeof(int16_t) * 2, + .minreq = BLOCK_SIZE * sizeof(int16_t)}; + + int error; + pa_handle = pa_simple_new(nullptr, "ADS8320", PA_STREAM_PLAYBACK, nullptr, "ADC", &ss, nullptr, &ba, &error); + if (!pa_handle) + { + std::cerr << "PulseAudio error: " << pa_strerror(error) << std::endl; + exit(1); + } +} + +void spi_init() +{ + spi_fd = open(SPI_DEVICE, O_RDWR); + if (spi_fd < 0) + { + std::cerr << "SPI error: " << strerror(errno) << std::endl; + exit(1); + } + + uint8_t mode = SPI_MODE_0; + uint8_t bits = 8; + uint32_t speed = SPI_SPEED_HZ; + if (ioctl(spi_fd, SPI_IOC_WR_MODE, &mode) < 0) + { + std::cerr << "SPI mode error: " << strerror(errno) << std::endl; + exit(1); + } + if (ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0) + { + std::cerr << "SPI bits error: " << strerror(errno) << std::endl; + exit(1); + } + if (ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) + { + std::cerr << "SPI speed error: " << strerror(errno) << std::endl; + exit(1); + } +} + +int16_t spi_read() +{ + ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr); + + uint32_t raw = (rx[0] << 11) | ((rx[1]) << 1); + return static_cast(raw+INT16_MIN); +} + +int main() +{ + signal(SIGINT, handler); + signal(SIGTERM, handler); + + spi_init(); + init_pulse(); + + steady_clock::time_point next = steady_clock::now(); + const duration step(1.0 / ADC_RATE); + const steady_clock::duration step_duration = duration_cast(step); + + int16_t buffer[BLOCK_SIZE]; + while (active) + { + int min_val = INT16_MAX; + int max_val = INT16_MIN; + double sum = 0.0; + + auto block_start = steady_clock::now(); + for (int i = 0; i < BLOCK_SIZE && active; i++) + { + steady_clock::time_point now = steady_clock::now(); + if (now < next) + std::this_thread::sleep_until(next); + + int16_t sample = spi_read(); + //filtered = ALPHA * sample + (1 - ALPHA) * filtered; + buffer[i] = sample; + + if(samplemax_val) + max_val=sample; + + sum += sample; + next += step_duration; + } + + int error; + if (pa_simple_write(pa_handle, buffer, BLOCK_SIZE * sizeof(int16_t), &error) < 0) { + std::cerr << "Pulse write error: " << pa_strerror(error) << std::endl; + } + + double block_time = duration_cast>(steady_clock::now() - block_start).count(); + + double avg = sum / BLOCK_SIZE; + correction = correction + avg * CORR_POWER; + + double voltage = avg / 32768.0 * 5; + + printf("Block: %.4fs (expected: %.4fs) | min=%6d max=%6d corr=%8.1f avg=%8.1f → %.3fV \n", + block_time, BLOCK_SIZE * 1.0 / ADC_RATE, min_val, max_val, correction, avg, voltage); + } + + if (pa_handle) + { + pa_simple_drain(pa_handle, nullptr); + pa_simple_free(pa_handle); + } + + if (spi_fd >= 0) + close(spi_fd); +} +