Skip to content

Instantly share code, notes, and snippets.

@CelliesProjects
Created November 1, 2019 09:39
Show Gist options
  • Select an option

  • Save CelliesProjects/1edb773fbe7a41895139fd8e50526f0b to your computer and use it in GitHub Desktop.

Select an option

Save CelliesProjects/1edb773fbe7a41895139fd8e50526f0b to your computer and use it in GitHub Desktop.
FFT demo on M5Stack-Fire in Arduino IDE.
#include "arduinoFFT.h"
//#include <M5Stack.h>
#include <esp_wifi.h>
#include <TFT_eSPI.h>
//#include <M5Display.h> // This library is a lot faster! But also a lot larger.
#define microphone 34
#define speaker 25
#define backlight 32
#define bufferSize 256
#define imgWidth 140
#define imgHeight 100
#define SAMPLING_FREQUENCY 22000
double vReal[bufferSize];
double vImag[bufferSize];
static volatile uint16_t currentSample = 0;
static volatile bool bufferFilled = false;
static hw_timer_t * sampleTimer = NULL;
static portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
unsigned int sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
arduinoFFT FFT = arduinoFFT();
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite img = TFT_eSprite(&tft);
//this ISR should run on core 0
static void IRAM_ATTR _sampleISR() {
if ( bufferFilled ) return;
vReal[currentSample] = analogRead( microphone );
vImag[currentSample] = 0;
portENTER_CRITICAL_ISR(&timerMux);
currentSample++;
portEXIT_CRITICAL_ISR(&timerMux);
if (currentSample == bufferSize ) bufferFilled = true;
}
void setup() {
pinMode( microphone, INPUT );
dacWrite( speaker, 0);
ledcAttachPin( backlight, 0);
ledcSetup( 0, 1300, 16 );
ledcWrite( 0, 0xFFFF / 16 ); //dimming the backlight will produce more base noise
sampleTimer = timerBegin( 0, 80, true );
timerAttachInterrupt( sampleTimer, &_sampleISR, true );
timerAlarmWrite( sampleTimer, sampling_period_us, true );
timerAlarmEnable( sampleTimer );
esp_wifi_set_mode(WIFI_MODE_NULL);
xTaskCreatePinnedToCore(
updateTFT, /* Function to implement the task */
"updateTFT", /* Name of the task */
3000, /* Stack size in words */
NULL, /* Task input parameter */
5, /* Priority of the task */
NULL, /* Task handle. */
0);
}
void loop() {
vTaskDelete(NULL);
}
uint16_t fps;
time_t previous;
void updateTFT( void * pvParameters ) {
tft.init();
tft.setRotation( 1 );
tft.fillScreen( TFT_BLUE );
tft.setTextSize( 2 );
img.setColorDepth( 8 );
img.setTextColor( TFT_WHITE);
img.createSprite( imgWidth, imgHeight );
while ( true ) {
if ( bufferFilled ) {
img.fillScreen( TFT_BLACK );
// https://github.com/kosme/arduinoFFT
FFT.Windowing(vReal, bufferSize, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(vReal, vImag, bufferSize, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, bufferSize);
for (int i = 2; i < (bufferSize/2); i++){
if (i<=2 ) displayBand(0,(int)vReal[i]); // 125Hz
if (i >2 && i<=4 ) displayBand(1,(int)vReal[i]); // 250Hz
if (i >4 && i<=7 ) displayBand(2,(int)vReal[i]); // 500Hz
if (i >7 && i<=15 ) displayBand(3,(int)vReal[i]); // 1000Hz
if (i >15 && i<=40 ) displayBand(4,(int)vReal[i]); // 2000Hz
if (i >40 && i<=70 ) displayBand(5,(int)vReal[i]); // 4000Hz
if (i >70 && i<=288 ) displayBand(6,(int)vReal[i]); // 8000Hz
if (i >288 ) displayBand(7,(int)vReal[i]); // 16000Hz
}
portENTER_CRITICAL(&timerMux);
bufferFilled = false;
currentSample = 0;
portEXIT_CRITICAL(&timerMux);
img.pushSprite( 90, 10 );
}
if ( time(NULL) != previous ) {
tft.setCursor(105, 120);
tft.printf( "%5.i fps", fps);
previous = time(NULL);
fps = 0;
}
fps++;
delay(1);
}
}
static inline void displayBand( const int band, const int dsize ){
img.fillRect( band * 20 + 5, imgHeight - dsize / ( bufferSize * 3 ) + 10 , 10, imgHeight, TFT_GREEN );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment