#include <LiquidCrystal_I2C.h>
#include "fix_fft.h"
#define LCHAN 1
const int yres = 8;
const int gain = 3;
int i = 0, val;
int lmax[2]; // level max memory
int dly[2]; // delay & speed for peak return
char im[64], data[64];
char data_avgs[32];
// VU METER CHARACTERS
byte v1[8] = {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F};
byte sp[8] = {0x03, 0x05, 0x19, 0x11, 0x11, 0x19, 0x05, 0x03};
LiquidCrystal_I2C lcd(0x27, 16, 2); //saves 5 pwm pins for servos, leds, etc
void setup()
{
lcd.init();
lcd.backlight();
lcd.createChar(0, sp);
lcd.createChar(1, v1);
lcd.setCursor(2, 0);
lcd.print("FM 99.9 MHz");
}
// the loop routine runs over and over again forever;
void loop()
{
bars();
}
void vu()
{
for (i = 0; i < 64; i++)
{
val = ((analogRead(LCHAN)) - 96); // chose how to interpret the data from analog in
data[i] = val;
im[i] = 0;
}
fix_fft(data, im, 6, 0); // Send the data through fft
// get the absolute value of the values in the array, so we're only dealing with positive numbers
for (i = 0; i < 32 ; i++)
{
data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
}
// todo: average as many or as little dynamically based on yres
for (i = 0; i < 32; i++)
{
data_avgs[i] = (data[i]); // add 3 samples to be averaged, use 4 when yres < 16
data_avgs[i] = constrain(data_avgs[i], 0, 9 - gain); //data samples * range (0-9) = 9
data_avgs[i] = map(data_avgs[i], 0, 9 - gain, 0, yres); // remap averaged values
}
} // end loop
void bars()
{
vu();
int anL = map((data_avgs[18]), 0, 11, 0, 80); // sqrt to have non linear scale (better was log)
bar(1, anL);
}
void bar(int rows, int levs)
{
#define T_REFRESH 100 // msec bar refresh rate
#define T_PEAKHOLD 5 * T_REFRESH // msec peak hold time before return
lcd.setCursor(0, rows);
lcd.write(0);
lcd.setCursor(2, rows);
for (int i = 1 ; i < 16 ; i++)
{
int f = constrain(levs - i * 5, 0, 5);
int p = constrain(lmax[rows] - i * 5, 0, 6);
if (f)
lcd.write(1);
else
lcd.write(' ');
}
if (levs > lmax[rows])
{
lmax[rows] = levs;
dly[rows] = -(T_PEAKHOLD) / T_REFRESH; // Starting delay value. Negative=peak don't move
}
else
{
if (dly[rows] > 0)
lmax[rows] -= dly[rows];
if (lmax[rows] < 0)
lmax[rows] = 0;
else
dly[rows]++;
}
}