|
|
@@ -0,0 +1,128 @@ |
|
|
|
/* Waterfall Audio Spectrum Analyzer, adapted from Nathaniel Quillin's |
|
|
|
award winning (most over the top) Hackaday SuperCon 2015 Badge Hack. |
|
|
|
|
|
|
|
https://hackaday.io/project/8575-audio-spectrum-analyzer-a-supercon-badge |
|
|
|
https://github.com/nqbit/superconbadge |
|
|
|
|
|
|
|
ILI9341 Color TFT Display is used to display spectral data. |
|
|
|
Two pots on analog A2 and A3 are required to adjust sensitivity. |
|
|
|
|
|
|
|
Copyright (c) 2015 Nathaniel Quillin |
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining |
|
|
|
a copy of this software and associated documentation files |
|
|
|
(the "Software"), to deal in the Software without restriction, |
|
|
|
including without limitation the rights to use, copy, modify, merge, |
|
|
|
publish, distribute, sublicense, and/or sell copies of the Software, |
|
|
|
and to permit persons to whom the Software is furnished to do so, |
|
|
|
subject to the following conditions: |
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be |
|
|
|
included in all copies or substantial portions of the Software. |
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
|
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
|
|
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
|
|
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
|
|
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
|
|
*/ |
|
|
|
|
|
|
|
#include <Audio.h> |
|
|
|
#include <ILI9341_t3.h> |
|
|
|
#include <SD.h> |
|
|
|
#include <SerialFlash.h> |
|
|
|
#include <SPI.h> |
|
|
|
#include <Wire.h> |
|
|
|
|
|
|
|
// ILI9341 Color TFT Display connections |
|
|
|
#define TFT_DC 20 |
|
|
|
#define TFT_CS 21 |
|
|
|
#define TFT_RST 255 // 255 = unused, connect to 3.3V |
|
|
|
#define TFT_MOSI 7 |
|
|
|
#define TFT_SCLK 14 |
|
|
|
#define TFT_MISO 12 |
|
|
|
|
|
|
|
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO); |
|
|
|
|
|
|
|
AudioInputI2S i2s1; |
|
|
|
AudioOutputI2S i2s2; |
|
|
|
AudioAnalyzeFFT1024 fft1024_1; |
|
|
|
AudioConnection patchCord5(i2s1, 0, i2s2, 0); |
|
|
|
AudioConnection patchCord6(i2s1, 0, i2s2, 1); |
|
|
|
AudioConnection patchCord7(i2s1, fft1024_1); |
|
|
|
AudioControlSGTL5000 sgtl5000_1; |
|
|
|
|
|
|
|
static int count = 0; |
|
|
|
static uint16_t line_buffer[320]; |
|
|
|
static float scale = 10.0; |
|
|
|
static int knob = 0; |
|
|
|
static int vol = 0; |
|
|
|
|
|
|
|
void setup(void) { |
|
|
|
// Initialize the peripherals. |
|
|
|
tft.begin(); |
|
|
|
tft.fillScreen(ILI9341_BLACK); |
|
|
|
tft.setTextColor(ILI9341_YELLOW); |
|
|
|
tft.setTextSize(2); |
|
|
|
|
|
|
|
AudioMemory(20); |
|
|
|
sgtl5000_1.enable(); |
|
|
|
sgtl5000_1.volume(0.5); |
|
|
|
sgtl5000_1.inputSelect(AUDIO_INPUT_MIC); |
|
|
|
sgtl5000_1.micGain(36); |
|
|
|
|
|
|
|
// Uncomment one these to try other window functions |
|
|
|
// fft1024_1.windowFunction(NULL); |
|
|
|
// fft1024_1.windowFunction(AudioWindowBartlett1024); |
|
|
|
// fft1024_1.windowFunction(AudioWindowFlattop1024); |
|
|
|
|
|
|
|
tft.println("Waterfall Spectrum"); |
|
|
|
tft.println("adapted from"); |
|
|
|
tft.println("Nathaniel Quillin"); |
|
|
|
tft.println("SuperCon Badge Hack"); |
|
|
|
for (int i = 0; i < 100; i++) { |
|
|
|
tft.setScroll(count++); |
|
|
|
count = count % 320; |
|
|
|
delay(12); |
|
|
|
} |
|
|
|
tft.setRotation(0); |
|
|
|
} |
|
|
|
|
|
|
|
void loop() { |
|
|
|
knob = analogRead(A2); |
|
|
|
vol = analogRead(A3); |
|
|
|
|
|
|
|
scale = 1024 - knob; |
|
|
|
sgtl5000_1.micGain((1024 - vol) / 4); |
|
|
|
|
|
|
|
if (fft1024_1.available()) { |
|
|
|
for (int i = 0; i < 240; i++) { |
|
|
|
line_buffer[240 - i - 1] = colorMap(fft1024_1.output[i]); |
|
|
|
} |
|
|
|
tft.writeRect(0, count, 240, 1, (uint16_t*) &line_buffer); |
|
|
|
tft.setScroll(count++); |
|
|
|
count = count % 320; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
uint16_t colorMap(uint16_t val) { |
|
|
|
float red; |
|
|
|
float green; |
|
|
|
float blue; |
|
|
|
float temp = val / 65536.0 * scale; |
|
|
|
|
|
|
|
if (temp < 0.5) { |
|
|
|
red = 0.0; |
|
|
|
green = temp * 2; |
|
|
|
blue = 2 * (0.5 - temp); |
|
|
|
} else { |
|
|
|
red = temp; |
|
|
|
green = (1.0 - temp); |
|
|
|
blue = 0.0; |
|
|
|
} |
|
|
|
return tft.color565(red * 256, green * 256, blue * 256); |
|
|
|
} |
|
|
|
|
|
|
|
|