// Basic FIR filter using timer interrupts for precise sampling time
// -----------------------------------------
// This implements a low-pass filter with cutoff frequency fc=150Hz @ fs=1kHz
// The impulse response is at coeffs.h.
//
// (c) 2024 Jorge Iván Marín ([email protected])
#include <SPI.h>
#define ADC_IN 36
#define DAC_OUT 25
#define CS_DAC 5
// Driver for DAC TLC5616
// ----------------------
class TLC5616 {
int CS_pin;
public:
TLC5616(int _CS_pin) {
CS_pin = _CS_pin;
}
void begin(void) {
SPI.begin();
pinMode(CS_pin, OUTPUT);
digitalWrite(CS_pin, HIGH);
}
void write(uint16_t value) {
value = (value & 0x3ff) << 2;
digitalWrite(CS_pin, LOW);
SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));
SPI.transfer16(value);
SPI.endTransaction();
digitalWrite(CS_pin, HIGH);
}
};
// Digital Filtering
// ------------------------------------------------
#include "coeffs.h"
float x[Nh];
float filter(float x_ADC) {
int k;
float y;
x[0] = x_ADC;
//Compute convolution
y = 0;
for(k=0; k<Nh; k++) {
y += h[k]*x[k];
}
//Delay elements in the array x
for(k=Nh-1; k>0; k--) {
x[k] = x[k-1];
}
return y;
}
// Entry point
// ----------------
TLC5616 dac(CS_DAC);
hw_timer_t* timer = NULL; //Hardware timer
void ARDUINO_ISR_ATTR isrTimer() {
//ADC read (Note: ADC is 12-bit resolution)
int x = analogRead(ADC_IN);
//Perform filtering
int y = filter(x);
//Control output saturation
if (y>4095) y=4095;
if (y<0) y=0;
//DAC Write (Note: DAC is 10-bit resolution, so we need to scale down)
dac.write(y >> 2);
//For internal DAC replaces the above line by
// dacWrite(DAC1, y>>4);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
//DAC Initialization
dac.begin();
// For internal DAC initialization replaces the above line by
// (Note: Not supported in Wowki):
// analogReadResolution(12);
// pinMode(DAC_OUT, OUTPUT);
//Timer configuration to set the sampling frequency at 1kHz
timer = timerBegin(1000000); // Set timer frequency to 1Mhz
timerAttachInterrupt(timer, &isrTimer); // Attach ISR to timer
// Set alarm to call isrTimer function every Ts (value in microseconds).
// Repeat the alarm (third parameter) with unlimited count = 0 (fourth parameter).
timerAlarm(timer, 1000, true, 0);
}
void loop() {
}