Doug,
Interestingly enough I had already settled on a circuit similar to that second one. This particular amplifier originally had a single analog moving needle meter for a pair of channels, with 2 meters total for 4 channels. Being that it's capable of being bridged, the output of one of the channels is 180* out of phase with the other. This means all I have to do is clip the negative going waves from each channel with a diode, sum them, then feed that signal into A0 at the appropriate voltage with a divider, and the meter should respond to the peaks of both channels simultaneously.
Another interesting feature is since it's McIntosh, it has the powerguard circuit. This limits the output voltage, so that no matter how much input signal I feed it or how high I turn the gains, I'll only see around 18VAC at the output terminals because it detects distortion and limits output accordingly. In other words, it has a compressing sort of effect on the audio signals. This makes it very easy to spec out a divider, since I know what the maximum signal voltage will be.
This is the code.
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_MOSI 9
#define OLED_CLK 10
#define OLED_DC 11
#define OLED_CS 12
#define OLED_RESET 13
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
int analogInput = A0;
int hMeter = 65;
int vMeter = 85;
int rMeter = 80;
const int sampleWindow = 50;
unsigned int sample;
static const unsigned char PROGMEM VUMeter[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0x03, 0x03, 0x00, 0x00, 0x60, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00,
0x1f, 0x8f, 0x87, 0xc0, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00,
0x3f, 0xbf, 0xff, 0xf0, 0x01, 0xfc, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00,
0x0f, 0xff, 0xff, 0xf0, 0x01, 0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00,
0x07, 0xff, 0xff, 0xc0, 0x00, 0xf8, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00,
0x07, 0xc7, 0xc7, 0xc0, 0x00, 0xf8, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00,
0x07, 0x83, 0xc3, 0xc0, 0x80, 0xf8, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00,
0x07, 0x83, 0xc3, 0xc1, 0xc0, 0xf8, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00,
0x07, 0x83, 0xc3, 0xc7, 0xf8, 0xf8, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00,
0x07, 0x83, 0xc3, 0xcf, 0xfc, 0xf8, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00,
0x07, 0x83, 0xc3, 0xcf, 0xc0, 0xf8, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00,
0x07, 0x83, 0xc3, 0xc7, 0x80, 0xf8, 0x10, 0x40, 0x1f, 0x00, 0x10, 0x00, 0x20, 0x07, 0xc0, 0x00,
0x07, 0x83, 0xc3, 0xc7, 0x80, 0xf8, 0x79, 0xf0, 0x1f, 0x00, 0xf8, 0x00, 0x70, 0x07, 0xc1, 0x80,
0x07, 0x83, 0xc3, 0xc7, 0x80, 0xf8, 0xff, 0xfc, 0x1f, 0x1f, 0xfe, 0x00, 0xff, 0xc7, 0xc7, 0xe0,
0x07, 0x83, 0xc3, 0xc7, 0x80, 0xf8, 0xff, 0xff, 0x1f, 0x1f, 0xff, 0xc7, 0xff, 0xc7, 0xff, 0xf8,
0x07, 0x83, 0xc3, 0xc7, 0x80, 0xf8, 0x7e, 0xfe, 0x1f, 0x1f, 0xff, 0xc7, 0xff, 0x87, 0xff, 0xf8,
0x07, 0x83, 0xc3, 0xc7, 0x80, 0xf8, 0x7c, 0x3c, 0x1f, 0x0f, 0x9f, 0xc7, 0xfe, 0x07, 0xf7, 0xe0,
0x07, 0x83, 0xc3, 0xc7, 0x80, 0xf8, 0x7c, 0x3c, 0x1f, 0x0f, 0x87, 0x87, 0xc0, 0x07, 0xc3, 0xe0,
0x07, 0x83, 0xc3, 0xc7, 0x80, 0xf8, 0x3c, 0x3c, 0x1f, 0x0f, 0x87, 0x87, 0xc0, 0x07, 0xc3, 0xe0,
0x07, 0x83, 0xc3, 0xc7, 0xc0, 0xf8, 0x3c, 0x3c, 0x1f, 0x0f, 0x87, 0x87, 0xc7, 0x07, 0xc3, 0xe0,
0x07, 0x83, 0xc3, 0xcf, 0xfc, 0xf8, 0x3c, 0x3c, 0x1f, 0x0f, 0x87, 0x8f, 0xff, 0x87, 0xc3, 0xe0,
0x07, 0x83, 0xc3, 0xc7, 0xfc, 0xf8, 0x3c, 0x3c, 0x1f, 0x0f, 0x87, 0x87, 0xff, 0xc7, 0xc3, 0xe0,
0x07, 0x83, 0xc3, 0xc3, 0xe0, 0xf8, 0x3c, 0x3c, 0x1f, 0x0f, 0x87, 0x83, 0xf7, 0xc7, 0xc3, 0xe0,
0x07, 0x83, 0xc3, 0xc0, 0xc0, 0xf8, 0x3c, 0x3c, 0x1f, 0x0f, 0x87, 0x81, 0xc7, 0xc7, 0xc3, 0xe0,
0x07, 0x83, 0xc3, 0xc0, 0x00, 0xf8, 0x3c, 0x3c, 0x1f, 0x0f, 0x87, 0x80, 0x07, 0xc7, 0xc3, 0xe0,
0x07, 0x83, 0xc3, 0xc0, 0x00, 0xf8, 0x3c, 0x3c, 0x1f, 0x0f, 0x87, 0x80, 0x07, 0xc7, 0xc3, 0xe0,
0x07, 0xc7, 0xc3, 0xc0, 0x00, 0xf8, 0x3c, 0x3c, 0x1f, 0x0f, 0xe7, 0x87, 0xff, 0xc7, 0xc3, 0xe0,
0x0f, 0xc7, 0xe7, 0xe0, 0x01, 0xf8, 0x7c, 0x7e, 0x1f, 0x8f, 0xff, 0xcf, 0xff, 0xc7, 0xe3, 0xf0,
0x0f, 0xef, 0xe7, 0xf0, 0x01, 0xfc, 0xfe, 0x7f, 0x3f, 0x9f, 0xff, 0xcf, 0xff, 0xef, 0xe7, 0xf0,
0x07, 0x83, 0xc3, 0xc0, 0x00, 0xf0, 0x38, 0x3c, 0x0e, 0x01, 0xfe, 0x01, 0xfc, 0x03, 0xc1, 0xc0,
0x03, 0x01, 0x81, 0x80, 0x00, 0x20, 0x30, 0x18, 0x0e, 0x00, 0x78, 0x00, 0x78, 0x01, 0x80, 0x80,
0x01, 0x01, 0x00, 0x80, 0x00, 0x20, 0x10, 0x08, 0x04, 0x00, 0x10, 0x00, 0x20, 0x01, 0x00, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x73, 0xc6, 0x7b, 0x27, 0x0c, 0x76, 0xc7, 0xbd, 0xde, 0x31, 0xd8, 0xcc, 0xc8, 0xde, 0x00,
0x00, 0x21, 0x09, 0x21, 0x24, 0x8c, 0x52, 0x82, 0x91, 0x48, 0x49, 0x48, 0x8c, 0x49, 0x28, 0x00,
0x00, 0x21, 0x90, 0x31, 0xa4, 0x52, 0x79, 0x02, 0x99, 0xee, 0x85, 0xed, 0x92, 0x69, 0x0c, 0x00,
0x00, 0x21, 0x13, 0xa1, 0x64, 0x5e, 0x49, 0x03, 0x91, 0x28, 0x85, 0x2a, 0x9e, 0x59, 0x08, 0x00,
0x00, 0x25, 0x09, 0x21, 0x24, 0x92, 0x49, 0x02, 0x11, 0x28, 0x49, 0x2a, 0x92, 0x49, 0x28, 0x00,
0x00, 0x7d, 0xc7, 0x39, 0x37, 0x33, 0x4b, 0x87, 0x1d, 0x28, 0x31, 0x28, 0xb3, 0x4c, 0xce, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
void setup(){
pinMode(analogInput, INPUT);
Serial.begin(115200);
if(!display.begin(SSD1306_SWITCHCAPVCC)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
}
void loop(){
unsigned long startMillis = millis();
unsigned int PeaktoPeak = 0;
unsigned int SignalMax = 0;
unsigned int SignalMin = 1024;
while ( millis() - startMillis < sampleWindow ){
sample = analogRead(analogInput);
if (sample < 1024) {
if (sample > SignalMax){
SignalMax = sample;
}
else if (sample < SignalMin){
SignalMin = sample;
}
}
}
PeaktoPeak = SignalMax - SignalMin;
float MeterValue = PeaktoPeak * 330 / 1024;
MeterValue = MeterValue - 34;
display.clearDisplay();
display.drawBitmap(0, 0, VUMeter, 128, 64, WHITE);
int a1 = (hMeter + (sin(MeterValue / 57.296) * rMeter));
int a2 = (vMeter - (cos(MeterValue / 57.296) * rMeter));
display.drawLine(a1, a2, hMeter, vMeter, WHITE);
display.display();