#include <FastLED.h>

#define DATA_PIN 3
#define NUM_ROWS 8
#define NUM_COLS 1

#define BRIGHTNESS 255
#define NUM_LEDS NUM_ROWS * NUM_COLS

const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
const int maxScale = 8;
const int redZone = 6;
const int yellowZone = 3;

unsigned int sample;

CRGB leds[NUM_LEDS];

void setup() {
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
}

void loop() {
  unsigned long startMillis = millis(); // Start of sample window
  unsigned int peakToPeak = 0;          // Peak-to-peak level

  unsigned int signalMax = 0;
  unsigned int signalMin = 1024;

  while (millis() - startMillis < sampleWindow)
  {
    sample = analogRead(0);
    if (sample < 1024)  // Toss out spurious readings
    {
      if (sample > signalMax)
      {
        signalMax = sample;  // Save just the max levels
      }
      else if (sample < signalMin)
      {
        signalMin = sample;  // Save just the min levels
      }
    }
  }

  peakToPeak = signalMax - signalMin;

  // Map 1v p-p level to the max scale of the display
  int displayPeak = map(peakToPeak, 0, 1023, 0, maxScale);

  // Draw the new sample
  for (int i = maxScale - 1; i >= 0; i--)
  {
    if (i >= displayPeak) // Blank these pixels
    {
      leds[7 - i] = CRGB::Black;
    }
    else if (i >= redZone) // Draw in red
    {
      leds[7 - i] = CRGB::Red;
    }
    else if ((i >= yellowZone) && (i < redZone)) // Draw in yellow
    {
      leds[7 - i] = CRGB::Yellow;
    }
    else if (i < yellowZone) // Draw in green
    {
      leds[7 - i] = CRGB::Green;
    }
  }

  FastLED.show(); // Write the changes we just made to the display
}