/***********************************************************************
* (c) 2016 Frank DD4WH 2016_11_06 - MIT license
* Teensy Bat & Ultrasound detector
*
*
* RECORD TEST 1
*
*
* Version 1.1 (recording alpha)
* https://forum.pjrc.com/threads/38988-Bat-detector
*
* made possible by the samplerate code by Frank Boesing, thanks Frank!
*
* tested on Teensy 3.5 + Teensy audio board
* + standard tiny electret MIC soldered to the MIC Input of the audio board
*
*
* User adjustments - with buttons
*
* MIC-GAIN 33 + 34 -
* FREQUENCY 35 + 36 -
* SAMPLE RATE 37 + 38 -
* WATERFALL/SPECTRUM 39
* REC 31
* STOP 30
* PLAY 29
*
* Audio sample rate code - function setI2SFreq
* Copyright (c) 2016, Frank Bösing, f.boesing@gmx.de
*
* 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, development funding 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 <SD.h>
#include <SPI.h>
#include <Bounce.h>
#include <Metro.h>
#include <ILI9341_t3.h>
#include "font_Arial.h"
#define VERSION " v0.3"
#define BACKLIGHT_PIN 0
#define TFT_DC 20
#define TFT_CS 21
#define TFT_RST 32 // 255 = unused. connect to 3.3V
#define TFT_MOSI 7
#define TFT_SCLK 14
#define TFT_MISO 12
// would be nice to use the fast DMA lib, but it does not work on my Teensy 3.5
//ILI9341_t3DMA tft = ILI9341_t3DMA(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);
#define BUTTON_MIC_GAIN_P 33
#define BUTTON_MIC_GAIN_M 34
#define BUTTON_FREQ_P 35
#define BUTTON_FREQ_M 36
#define BUTTON_SAMPLE_RATE_P 37
#define BUTTON_SAMPLE_RATE_M 38
#define BUTTON_TOGGLE_WATERFALL 39
#define BUTTON_RECORD 31
#define BUTTON_STOP 30
#define BUTTON_PLAY 29
Bounce mic_gain_P = Bounce(BUTTON_MIC_GAIN_P, 50);
Bounce mic_gain_M = Bounce(BUTTON_MIC_GAIN_M, 50);
Bounce freq_P = Bounce(BUTTON_FREQ_P, 50);
Bounce freq_M = Bounce(BUTTON_FREQ_M, 50);
Bounce sample_rate_P = Bounce(BUTTON_SAMPLE_RATE_P, 50);
Bounce sample_rate_M = Bounce(BUTTON_SAMPLE_RATE_M, 50);
Bounce toggle_waterfall = Bounce(BUTTON_TOGGLE_WATERFALL, 50);
Bounce button_Record = Bounce(BUTTON_RECORD, 50);
Bounce button_Stop = Bounce(BUTTON_STOP, 50);
Bounce button_Play = Bounce(BUTTON_PLAY, 50);
#define SAMPLE_RATE_MIN 0
#define SAMPLE_RATE_8K 0
#define SAMPLE_RATE_11K 1
#define SAMPLE_RATE_16K 2
#define SAMPLE_RATE_22K 3
#define SAMPLE_RATE_32K 4
#define SAMPLE_RATE_44K 5
#define SAMPLE_RATE_48K 6
#define SAMPLE_RATE_88K 7
#define SAMPLE_RATE_96K 8
#define SAMPLE_RATE_176K 9
#define SAMPLE_RATE_192K 10
#define SAMPLE_RATE_MAX 10
// this audio comes from the codec by I2S2
AudioInputI2S i2s_in; // MIC input
AudioRecordQueue recorder;
//AudioSynthWaveformSine sine1; // local oscillator
//AudioEffectMultiply mult1; // multiply = mix
//AudioAnalyzeFFT256 myFFT; // for spectrum display
//AudioAnalyzeFFT1024 fft1024_1; // for waterfall display
AudioPlaySdRaw player;
AudioMixer4 mix1;
AudioOutputI2S i2s_out; // headphone output
AudioConnection patch3 (i2s_in, 0, recorder, 0);
AudioConnection patch4 (i2s_in, 0, mix1, 0);
//AudioConnection path7 (i2s_in, 0, fft1024_1, 0);
//AudioConnection path7 (i2s_in, 0, myFFT, 0);
AudioConnection patch5 (player, 0, mix1, 1);
AudioConnection patch8 (mix1, 0, i2s_out, 0);
AudioConnection patch9 (mix1, 0, i2s_out, 1);
AudioControlSGTL5000 sgtl5000_1;
// Metro 1 second
Metro second = Metro(1000);
const int8_t MODE_STOP = 0;
const int8_t MODE_REC = 1;
const int8_t MODE_PLAY = 2;
int mode = MODE_STOP;
File frec; // audio is recorded to this file first
int file_number = 0;
int count_help = 0;
int8_t waterfall_flag = 0;
int idx_t = 0;
int idx = 0;
int64_t sum;
float32_t mean;
int8_t mic_gain = 40; // start detecting with this MIC_GAIN in dB
int freq_real = 22000; // start detecting at this frequency
int sample_rate = SAMPLE_RATE_96K;
int sample_rate_real = 96000;
String text="96k";
int freq_LO = 7000;
int16_t FFT_bin [128];
int barm[512];
typedef struct SR_Descriptor
{
const int SR_n;
const char* const f1;
const char* const f2;
const char* const f3;
const char* const f4;
const float32_t x_factor;
} SR_Desc;
// Text and position for the FFT spectrum display scale
const SR_Descriptor SR [SAMPLE_RATE_MAX + 1] =
{
// SR_n , f1, f2, f3, f4, x_factor = pixels per f1 kHz in spectrum display
{ SAMPLE_RATE_8K, " 1", " 2", " 3", " 4", 64.0}, // which means 64 pixels per 1 kHz
{ SAMPLE_RATE_11K, " 1", " 2", " 3", " 4", 43.1},
{ SAMPLE_RATE_16K, " 2", " 4", " 6", " 8", 64.0},
{ SAMPLE_RATE_22K, " 2", " 4", " 6", " 8", 43.1},
{ SAMPLE_RATE_32K, "5", "10", "15", "20", 80.0},
{ SAMPLE_RATE_44K, "5", "10", "15", "20", 58.05},
{ SAMPLE_RATE_48K, "5", "10", "15", "20", 53.33},
{ SAMPLE_RATE_88K, "10", "20", "30", "40", 58.05},
{ SAMPLE_RATE_96K, "10", "20", "30", "40", 53.33},
{ SAMPLE_RATE_176K, "20", "40", "60", "80", 58.05},
{ SAMPLE_RATE_192K, "20", "40", "60", "80", 53.33} // which means 53.33 pixels per 20kHz
};
//const int myInput = AUDIO_INPUT_LINEIN;
const int myInput = AUDIO_INPUT_MIC;
void setup() {
Serial.begin(115200);
delay(200);
if(!(SD.begin(BUILTIN_SDCARD)))
{
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
//setup pins with pullups
pinMode(BUTTON_MIC_GAIN_P,INPUT_PULLUP);
pinMode(BUTTON_MIC_GAIN_M,INPUT_PULLUP);
pinMode(BUTTON_FREQ_P,INPUT_PULLUP);
pinMode(BUTTON_FREQ_M,INPUT_PULLUP);
pinMode(BUTTON_SAMPLE_RATE_P,INPUT_PULLUP);
pinMode(BUTTON_SAMPLE_RATE_M,INPUT_PULLUP);
pinMode(BUTTON_TOGGLE_WATERFALL,INPUT_PULLUP);
pinMode(BUTTON_RECORD,INPUT_PULLUP);
pinMode(BUTTON_STOP,INPUT_PULLUP);
pinMode(BUTTON_PLAY,INPUT_PULLUP);
// Audio connections require memory.
AudioMemory(200);
/*
setSyncProvider(getTeensy3Time);
*/
// Enable the audio shield. select input. and enable output
sgtl5000_1.enable();
sgtl5000_1.inputSelect(myInput);
sgtl5000_1.volume(0.8);
sgtl5000_1.micGain (mic_gain);
sgtl5000_1.adcHighPassFilterDisable(); // does not help too much!
// Init SD card use
// SPI.setMOSI(7);
// SPI.setSCK(14);
// Init TFT display
pinMode( BACKLIGHT_PIN, OUTPUT );
analogWrite( BACKLIGHT_PIN, 1023 );
tft.begin();
tft.setRotation( 3 );
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(14, 7);
tft.setTextColor(ILI9341_ORANGE);
tft.setFont(Arial_12);
tft.print("Teensy Bat Detector "); tft.print(VERSION);
tft.setTextColor(ILI9341_WHITE);
display_settings();
// sorry, couldn´t resist ;-)
logo_head();
for (int v = 0; v < 6; v++) {
logo(true);
delay(200);
logo(false);
delay(200);
}
set_sample_rate (sample_rate);
mix1.gain(0,1);
mix1.gain(1,1);
} // END SETUP
void loop() {
controls();
// spectrum();
check_processor();
}
/* void spectrum() { // spectrum analyser code by rheslip - modified
if (myFFT.available()) {
// if (fft1024_1.available()) {
int scale;
scale = 5;
for (int16_t x = 2; x < 128; x++) {
// for (int16_t x = 8; x < 512; x+=4) {
FFT_bin[x] = abs(myFFT.output[x]);
// FFT_bin[x/4] = abs(fft1024_1.output[x]);
int bar = (FFT_bin[x] * scale);
if (bar >175) bar=175;
// this is a very simple first order IIR filter to smooth the reaction of the bars
bar = 0.05 * bar + 0.95 * barm[x];
// if (bar > peak[x]) peak[x]=bar;
// tft.drawFastVLine(x, 210-bar,bar, ILI9341_PURPLE);
// tft.drawFastVLine(x*2+10, 210-bar,bar, ILI9341_PINK);
tft.drawPixel(x*2+10, 210-barm[x], ILI9341_BLACK);
tft.drawPixel(x*2+10, 210-bar, ILI9341_WHITE);
// tft.drawFastVLine(x*2+10, 20, 210-bar-20, ILI9341_BLACK);
// tft.drawPixel(x*2+10,209-peak[x], ILI9341_YELLOW);
// if(peak[x]>0) peak[x]-=1;
barm[x] = bar;
}
// search_bats();
} //end if
} // end void spectrum
*/
void controls() {
// first, check buttons
mic_gain_P.update();
mic_gain_M.update();
freq_P.update();
freq_M.update();
sample_rate_P.update();
sample_rate_M.update();
toggle_waterfall.update();
button_Record.update();
button_Stop.update();
button_Play.update();
// Respond to button presses
if (button_Record.fallingEdge()) {
Serial.println("Record Button Press");
if (mode == MODE_PLAY) stopPlaying();
if (mode == MODE_STOP) startRecording();
}
if (button_Stop.fallingEdge()) {
Serial.println("Stop Button Press");
if (mode == MODE_REC) stopRecording();
if (mode == MODE_PLAY) stopPlaying();
}
if (button_Play.fallingEdge()) {
Serial.println("Play Button Press");
if (mode == MODE_REC) stopRecording();
if (mode == MODE_STOP) startPlaying();
}
// If we're playing or recording, carry on...
if (mode == MODE_REC) {
continueRecording();
}
if (mode == MODE_PLAY) {
continuePlaying();
}
// change MIC GAIN
if ( mic_gain_P.fallingEdge()) {
mic_gain = mic_gain + 2;
if (mic_gain > 63) {
mic_gain = 63;
}
set_mic_gain(mic_gain);
}
if ( mic_gain_M.fallingEdge()) {
mic_gain = mic_gain - 2;
if (mic_gain < 0) {
mic_gain = 0;
}
set_mic_gain(mic_gain);
}
// change sample rate
if ( sample_rate_P.fallingEdge()) {
sample_rate = sample_rate + 1;
if (sample_rate > SAMPLE_RATE_MAX) {
sample_rate = SAMPLE_RATE_MAX;
}
set_sample_rate (sample_rate);
}
if ( sample_rate_M.fallingEdge()) {
sample_rate = sample_rate - 1;
if (sample_rate < SAMPLE_RATE_MIN) {
sample_rate = SAMPLE_RATE_MIN;
}
set_sample_rate (sample_rate);
}
} // END function "controls"
void set_mic_gain(int8_t gain) {
AudioNoInterrupts();
sgtl5000_1.micGain (mic_gain);
AudioInterrupts();
display_settings();
} // end function set_mic_gain
void display_settings() {
tft.fillRect(14,32,200,17,ILI9341_BLACK);
tft.setCursor(14, 32);
tft.setFont(Arial_12);
tft.print("gain: "); tft.print (mic_gain);
tft.print(" ");
tft.print("freq: "); tft.print (freq_real);
tft.print(" ");
tft.fillRect(232,32,88,17,ILI9341_BLACK);
tft.setCursor(232, 32);
tft.print(" ");
tft.print (text);
Serial.println(text);
/* // only for debugging
tft.fillRect(0,122,200,17,ILI9341_BLACK);
tft.setCursor(0, 122);
tft.print("LO: "); tft.print (freq_LO);
tft.print(" ");
*/
}
void set_sample_rate (int sr) {
switch (sr) {
case SAMPLE_RATE_8K:
sample_rate_real = 8000;
text = " 8k";
break;
case SAMPLE_RATE_11K:
sample_rate_real = 11025;
text = "11k";
break;
case SAMPLE_RATE_16K:
sample_rate_real = 16000;
text = "16k";
break;
case SAMPLE_RATE_22K:
sample_rate_real = 22050;
text = "22k";
break;
case SAMPLE_RATE_32K:
sample_rate_real = 32000;
text = "32k";
break;
case SAMPLE_RATE_44K:
sample_rate_real = 44100;
text = "44.1k";
break;
case SAMPLE_RATE_48K:
sample_rate_real = 48000;
text = "48k";
break;
case SAMPLE_RATE_88K:
sample_rate_real = 88200;
text = "88.2k";
break;
case SAMPLE_RATE_96K:
sample_rate_real = 96000;
text = "96k";
break;
case SAMPLE_RATE_176K:
sample_rate_real = 176400;
text = "176k";
break;
case SAMPLE_RATE_192K:
sample_rate_real = 192000;
text = "192k";
break;
}
AudioNoInterrupts();
setI2SFreq (sample_rate_real);
delay(200); // this delay seems to be very essential !
AudioInterrupts();
delay(20);
display_settings();
// prepare_spectrum_display();
} // END function set_sample_rate
// set samplerate code by Frank Boesing
void setI2SFreq(int freq) {
typedef struct {
uint8_t mult;
uint16_t div;
} tmclk;
const int numfreqs = 14;
const int samplefreqs[numfreqs] = { 8000, 11025, 16000, 22050, 32000, 44100, (int)44117.64706 , 48000, 88200, (int)44117.64706 * 2, 96000, 176400, (int)44117.64706 * 4, 192000};
#if (F_PLL==16000000)
const tmclk clkArr[numfreqs] = {{16, 125}, {148, 839}, {32, 125}, {145, 411}, {64, 125}, {151, 214}, {12, 17}, {96, 125}, {151, 107}, {24, 17}, {192, 125}, {127, 45}, {48, 17}, {255, 83} };
#elif (F_PLL==72000000)
const tmclk clkArr[numfreqs] = {{32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {128, 1125}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375}, {249, 397}, {32, 51}, {185, 271} };
#elif (F_PLL==96000000)
const tmclk clkArr[numfreqs] = {{8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {32, 375}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125}, {151, 321}, {8, 17}, {64, 125} };
#elif (F_PLL==120000000)
const tmclk clkArr[numfreqs] = {{32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {128, 1875}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625}, {178, 473}, {32, 85}, {145, 354} };
#elif (F_PLL==144000000)
const tmclk clkArr[numfreqs] = {{16, 1125}, {49, 2500}, {32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {4, 51}, {32, 375}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375} };
#elif (F_PLL==168000000)
const tmclk clkArr[numfreqs] = {{32, 2625}, {21, 1250}, {64, 2625}, {21, 625}, {128, 2625}, {42, 625}, {8, 119}, {64, 875}, {84, 625}, {16, 119}, {128, 875}, {168, 625}, {32, 119}, {189, 646} };
#elif (F_PLL==180000000)
const tmclk clkArr[numfreqs] = {{46, 4043}, {49, 3125}, {73, 3208}, {98, 3125}, {183, 4021}, {196, 3125}, {16, 255}, {128, 1875}, {107, 853}, {32, 255}, {219, 1604}, {214, 853}, {64, 255}, {219, 802} };
#elif (F_PLL==192000000)
const tmclk clkArr[numfreqs] = {{4, 375}, {37, 2517}, {8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {1, 17}, {8, 125}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125} };
#elif (F_PLL==216000000)
const tmclk clkArr[numfreqs] = {{32, 3375}, {49, 3750}, {64, 3375}, {49, 1875}, {128, 3375}, {98, 1875}, {8, 153}, {64, 1125}, {196, 1875}, {16, 153}, {128, 1125}, {226, 1081}, {32, 153}, {147, 646} };
#elif (F_PLL==240000000)
const tmclk clkArr[numfreqs] = {{16, 1875}, {29, 2466}, {32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {4, 85}, {32, 625}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625} };
#endif
for (int f = 0; f < numfreqs; f++) {
if ( freq == samplefreqs[f] ) {
while (I2S0_MCR & I2S_MCR_DUF) ;
I2S0_MDR = I2S_MDR_FRACT((clkArr[f].mult - 1)) | I2S_MDR_DIVIDE((clkArr[f].div - 1));
return;
}
}
}
// bat logo taken from Shezzy:
// http://sisterzpsptreasures.freeforums.org/easy-animated-bat-t77.html
// copyright free graphics
// "The image you create by following this tutorial belongs to you and you may do whatever you want with it."
void logo(bool wing1) {
// Logo ;-)
int x = 265;
int y = 10;
// grey background and white line rectangle around it
tft.fillRect(x + 23, y - 2,16,14,ILI9341_DARKGREY);
tft.fillRect(x - 2, y - 2,16,14,ILI9341_DARKGREY);
// tft.fillRect(x - 2, y - 2, 41, 14,ILI9341_DARKGREY);
if (wing1) {
//Wing1
tft.drawFastHLine(x + 2, y + 0, 5, ILI9341_BLACK);
tft.drawFastHLine(x + 31, y + 0, 5, ILI9341_BLACK);
tft.drawPixel(x + 1, y + 1, ILI9341_BLACK);
tft.drawPixel(x + 35, y + 1, ILI9341_BLACK);
tft.drawPixel(x + 6, y + 1, ILI9341_BLACK);
tft.drawPixel(x + 30, y + 1, ILI9341_BLACK);
// tft.drawPixel(x + 6, y + 2, ILI9341_BLACK);
// tft.drawPixel(x + 30, y + 2, ILI9341_BLACK);
tft.drawFastVLine(x , y + 2, 7, ILI9341_BLACK);
tft.drawFastVLine(x + 36 , y + 2, 7, ILI9341_BLACK);
tft.drawFastHLine(x + 7, y + 2, 2, ILI9341_BLACK);
tft.drawFastHLine(x + 28, y + 2, 2, ILI9341_BLACK);
tft.drawPixel(x + 13, y + 2, ILI9341_BLACK);
tft.drawPixel(x + 23, y + 2, ILI9341_BLACK);
tft.drawFastHLine(x + 9, y + 3, 4, ILI9341_BLACK);
tft.drawFastHLine(x + 24, y + 3, 4, ILI9341_BLACK);
tft.drawFastHLine(x + 3, y + 5, 3, ILI9341_BLACK);
tft.drawFastHLine(x + 31, y + 5, 3, ILI9341_BLACK);
tft.drawFastHLine(x + 7, y + 5, 3, ILI9341_BLACK);
tft.drawFastHLine(x + 27, y + 5, 3, ILI9341_BLACK);
tft.drawFastHLine(x + 11, y + 5, 2, ILI9341_BLACK);
tft.drawFastHLine(x + 24, y + 5, 2, ILI9341_BLACK);
tft.drawPixel(x + 2, y + 6, ILI9341_BLACK);
tft.drawPixel(x + 6, y + 6, ILI9341_BLACK);
tft.drawPixel(x + 10, y + 6, ILI9341_BLACK);
tft.drawPixel(x + 13, y + 6, ILI9341_BLACK);
tft.drawPixel(x + 23, y + 6, ILI9341_BLACK);
tft.drawPixel(x + 26, y + 6, ILI9341_BLACK);
tft.drawPixel(x + 30, y + 6, ILI9341_BLACK);
tft.drawPixel(x + 34, y + 6, ILI9341_BLACK);
tft.drawPixel(x + 1, y + 7, ILI9341_BLACK);
tft.drawPixel(x + 6, y + 7, ILI9341_BLACK);
tft.drawPixel(x + 10, y + 7, ILI9341_BLACK);
tft.drawPixel(x + 26, y + 7, ILI9341_BLACK);
tft.drawPixel(x + 30, y + 7, ILI9341_BLACK);
tft.drawPixel(x + 35, y + 7, ILI9341_BLACK);
}
else {
//Wing2
tft.drawFastHLine(x + 2, y + 2, 5, ILI9341_BLACK);
tft.drawFastHLine(x + 31, y + 2, 5, ILI9341_BLACK);
tft.drawPixel(x + 1, y + 3, ILI9341_BLACK);
tft.drawPixel(x + 35, y + 3, ILI9341_BLACK);
tft.drawPixel(x + 6, y + 3, ILI9341_BLACK);
tft.drawPixel(x + 30, y + 3, ILI9341_BLACK);
// tft.drawPixel(x + 6, y + 4, ILI9341_BLACK);
// tft.drawPixel(x + 30, y + 4, ILI9341_BLACK);
tft.drawFastVLine(x , y + 4, 7, ILI9341_BLACK);
tft.drawFastVLine(x + 36 , y + 4, 7, ILI9341_BLACK);
tft.drawFastHLine(x + 7, y + 4, 2, ILI9341_BLACK);
tft.drawFastHLine(x + 28, y + 4, 2, ILI9341_BLACK);
// tft.drawPixel(x + 13, y + 4, ILI9341_BLACK);
// tft.drawPixel(x + 23, y + 4, ILI9341_BLACK);
tft.drawFastHLine(x + 9, y + 5, 5, ILI9341_BLACK);
tft.drawFastHLine(x + 24, y + 5, 5, ILI9341_BLACK);
tft.drawFastHLine(x + 3, y + 7, 3, ILI9341_BLACK);
tft.drawFastHLine(x + 31, y + 7, 3, ILI9341_BLACK);
tft.drawFastHLine(x + 7, y + 7, 3, ILI9341_BLACK);
tft.drawFastHLine(x + 27, y + 7, 3, ILI9341_BLACK);
tft.drawFastHLine(x + 11, y + 7, 3, ILI9341_BLACK);
tft.drawFastHLine(x + 24, y + 7, 3, ILI9341_BLACK);
tft.drawPixel(x + 2, y + 8, ILI9341_BLACK);
tft.drawPixel(x + 6, y + 8, ILI9341_BLACK);
tft.drawPixel(x + 10, y + 8, ILI9341_BLACK);
// tft.drawPixel(x + 13, y + 8, ILI9341_BLACK);
// tft.drawPixel(x + 23, y + 8, ILI9341_BLACK);
tft.drawPixel(x + 26, y + 8, ILI9341_BLACK);
tft.drawPixel(x + 30, y + 8, ILI9341_BLACK);
tft.drawPixel(x + 34, y + 8, ILI9341_BLACK);
tft.drawPixel(x + 1, y + 9, ILI9341_BLACK);
tft.drawPixel(x + 6, y + 9, ILI9341_BLACK);
tft.drawPixel(x + 10, y + 9, ILI9341_BLACK);
tft.drawPixel(x + 26, y + 9, ILI9341_BLACK);
tft.drawPixel(x + 30, y + 9, ILI9341_BLACK);
tft.drawPixel(x + 35, y + 9, ILI9341_BLACK);
}
}
void logo_head() {
int x = 265;
int y = 10;
tft.fillRect(x + 14, y - 2,9,14,ILI9341_DARKGREY);
// Head
tft.drawPixel(x + 15, y + 2, ILI9341_BLACK);
tft.drawPixel(x + 21, y + 2, ILI9341_BLACK);
tft.drawPixel(x + 14, y + 3, ILI9341_BLACK);
tft.drawPixel(x + 16, y + 3, ILI9341_BLACK);
tft.drawPixel(x + 20, y + 3, ILI9341_BLACK);
tft.drawPixel(x + 22, y + 3, ILI9341_BLACK);
tft.drawPixel(x + 14, y + 4, ILI9341_BLACK);
tft.drawPixel(x + 22, y + 4, ILI9341_BLACK);
tft.drawFastHLine(x + 17, y + 4, 3, ILI9341_BLACK);
tft.drawPixel(x + 14, y + 5, ILI9341_BLACK);
tft.drawPixel(x + 22, y + 5, ILI9341_BLACK);
tft.drawPixel(x + 16, y + 5, ILI9341_RED);
tft.drawPixel(x + 20, y + 5, ILI9341_RED);
tft.drawPixel(x + 17, y + 6, ILI9341_RED);
tft.drawPixel(x + 19, y + 6, ILI9341_RED);
tft.drawPixel(x + 14, y + 6, ILI9341_BLACK);
tft.drawPixel(x + 22, y + 6, ILI9341_BLACK);
tft.drawPixel(x + 15, y + 7, ILI9341_BLACK);
tft.drawPixel(x + 21, y + 7, ILI9341_BLACK);
tft.drawPixel(x + 16, y + 8, ILI9341_BLACK);
tft.drawPixel(x + 20, y + 8, ILI9341_BLACK);
tft.drawPixel(x + 17, y + 8, ILI9341_WHITE);
tft.drawPixel(x + 19, y + 8, ILI9341_WHITE);
tft.drawFastHLine(x + 17, y + 9, 3, ILI9341_BLACK);
}
void check_processor() {
if (second.check() == 1) {
Serial.print("Proc = ");
Serial.print(AudioProcessorUsage());
Serial.print(" (");
Serial.print(AudioProcessorUsageMax());
Serial.print("), Mem = ");
Serial.print(AudioMemoryUsage());
Serial.print(" (");
Serial.print(AudioMemoryUsageMax());
Serial.println(")");
/* tft.fillRect(100,120,200,80,ILI9341_BLACK);
tft.setCursor(10, 120);
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.setFont(Arial_14);
tft.print ("Proc = ");
tft.setCursor(100, 120);
tft.print (AudioProcessorUsage());
tft.setCursor(180, 120);
tft.print (AudioProcessorUsageMax());
tft.setCursor(10, 150);
tft.print ("Mem = ");
tft.setCursor(100, 150);
tft.print (AudioMemoryUsage());
tft.setCursor(180, 150);
tft.print (AudioMemoryUsageMax());
*/
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
}
} // END function check_processor
const char* filename (int pointer) {
String NAME = "REC"+String(pointer)+".RAW";
char str[15];
NAME.toCharArray(str, sizeof(NAME));
return str;
}
void startRecording() {
Serial.print("startRecording");
/* if (SD.exists("RECORD.RAW")) {
// The SD library writes new data to the end of the
// file, so to start a new recording, the old file
// must be deleted before new data is written.
SD.remove("RECORD.RAW");
} */
file_number++;
Serial.println(file_number);
String NAME = "REC"+String(file_number)+".RAW";
char fi[15];
NAME.toCharArray(fi, sizeof(NAME));
if (SD.exists(fi)) {
// The SD library writes new data to the end of the
// file, so to start a new recording, the old file
// must be deleted before new data is written.
SD.remove(fi);
}
frec = SD.open(fi, FILE_WRITE);
if (frec) {
recorder.begin();
mode = MODE_REC;
Serial.println("RECORDING!");
}
}
void continueRecording() {
if (recorder.available() >= 32) {
byte buffer[512];
// Fetch 2 blocks from the audio library and copy
// into a 512 byte buffer. The Arduino SD library
// is most efficient when full 512 byte sector size
// writes are used.
memcpy(buffer, recorder.readBuffer(), 256);
recorder.freeBuffer();
memcpy(buffer+256, recorder.readBuffer(), 256);
recorder.freeBuffer();
// write all 512 bytes to the SD card
// elapsedMicros usec = 0;
frec.write(buffer, 512);
// Uncomment these lines to see how long SD writes
// are taking. A pair of audio blocks arrives every
// 5802 microseconds, so hopefully most of the writes
// take well under 5802 us. Some will take more, as
// the SD library also must write to the FAT tables
// and the SD card controller manages media erase and
// wear leveling. The recorder object can buffer
// approximately 301700 us of audio, to allow time
// for occasional high SD card latency, as long as
// the average write time is under 5802 us.
// if (one_sec.check() == 1) {
// Serial.print("SD write, us=");
// }
// Serial.println(usec);
}
}
void stopRecording() {
Serial.print("stopRecording");
recorder.end();
if (mode == MODE_REC) {
while (recorder.available() > 0) {
frec.write((byte*)recorder.readBuffer(), 256);
recorder.freeBuffer();
}
frec.close();
// playfile = recfile;
}
mode = MODE_STOP;
// clearname();
Serial.println (" Recording stopped!");
}
void startPlaying() {
String NAME = "REC"+String(file_number)+".RAW";
char fi[15];
NAME.toCharArray(fi, sizeof(NAME));
mix1.gain(1,1);
mix1.gain(0,0);
Serial.println("startPlaying ");
// const char* fi = filename(playfile);
// const char* fi = "REC13.RAW";
// Serial.print ("File: ");Serial.print(playfile);
Serial.println ("Playfile: "); Serial.print (file_number);
Serial.println ("Name: "); Serial.print (filename(file_number));
delay(100);
// playSd.play(filename(playfile));
// playSd.play("REC13.RAW");
player.play(fi);
mode = MODE_PLAY;
/* tft.fillRect(0, 102, 160, 12, ST7735_GREEN); //ST7735_BLACK);
tft.setCursor(0, 105);
tft.setTextColor(ST7735_BLACK);
tft.print (" Playing !");
tft.setTextColor(ST7735_WHITE);
showtrack();
*/
}
void continuePlaying() {
if (!player.isPlaying()) {
player.stop();
mode = MODE_STOP;
mix1.gain(1,0);
mix1.gain(0,1);
Serial.println("End of recording");
}
}
void stopPlaying() {
mix1.gain(1,0);
mix1.gain(0,1);
Serial.print("stopPlaying");
if (mode == MODE_PLAY) player.stop();
mode = MODE_STOP;
Serial.println (" Playing stopped");
}