This commit is contained in:
e2002
2022-07-15 13:44:08 +03:00
parent f065d1505d
commit 1d02826166
14 changed files with 196 additions and 20 deletions

View File

@@ -3,7 +3,9 @@
#include "WiFi.h"
#include "time.h"
#include "display.h"
#if ENABLE_VU_METER
#include "display_vu.h"
#endif
#include "player.h"
#include "netserver.h"
#include "network.h"
@@ -453,6 +455,9 @@ void Display::loop() {
}
dsp.loop();
if (dsp_on_loop) dsp_on_loop(&dsp);
#if ENABLE_VU_METER
drawVU(&dsp);
#endif
}
void Display::centerText(const char* text, byte y, uint16_t fg, uint16_t bg) {

80
yoRadio/display_vu.h Normal file
View File

@@ -0,0 +1,80 @@
#if ENABLE_VU_METER
#ifndef display_vu_h
#define display_vu_h
#include "player.h"
#ifdef VU_PARAMS
enum : uint16_t VU_PARAMS;
#else
/*****************************************************************************************************************************************************************************/
/* vu left | vu top | band width | band height | band space |num of bands |max samples | horisontal | Max Bands Color | Min Bands Color */
/*****************************************************************************************************************************************************************************/
#if DSP_MODEL==DSP_ST7735 && DTYPE==INITR_BLACKTAB /* ST7735 160x128 */
enum : uint16_t { VU_X = 4, VU_Y = 50, VU_BW = 10, VU_BH = 44, VU_BS = 2, VU_NB = 8, VU_BMS = 2, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = SILVER };
#elif DSP_MODEL==DSP_ST7735 && DTYPE==INITR_144GREENTAB /* ST7735 128x128 */
enum : uint16_t { VU_X = 4, VU_Y = 45, VU_BW = 60, VU_BH = 8, VU_BS = 0, VU_NB = 10, VU_BMS = 3, VU_HOR = 1, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY };
#elif DSP_MODEL==DSP_ILI9341 /* ILI9341 320x240 */
enum : uint16_t { VU_X = 4, VU_Y = 100, VU_BW = 20, VU_BH = 86, VU_BS = 4, VU_NB = 10, VU_BMS = 2, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY };
#elif DSP_MODEL==DSP_ST7789 /* ST7789 320x240 */
enum : uint16_t { VU_X = 4, VU_Y = 100, VU_BW = 20, VU_BH = 86, VU_BS = 4, VU_NB = 10, VU_BMS = 3, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = GRAY };
#else
#error YOUR DISPLAY DOES NOT SUPPORT ENABLE_VU_METER FEATURE YET
#endif
#endif //VU_PARAMS
/*****************************************************************************************************************************************************************************/
void drawVU(DspCore *dsp);
GFXcanvas16 gfxc(VU_BW*2+VU_BS,VU_BH);
void drawVU(DspCore *dsp){
if((display.mode!=PLAYER && display.mode!=VOL)) return;
player.getVUlevel();
static uint16_t samples_cnt, measL, measR;
samples_cnt++;
uint16_t dimension = VU_HOR?VU_BW:VU_BH;
uint8_t L = map((VS1053_CS!=255)?player.vuLeft:log(player.vuLeft)*38+45, 255, 0, 0, dimension);
uint8_t R = map((VS1053_CS!=255)?player.vuRight:log(player.vuRight)*38+45, 255, 0, 0, dimension);
if(player.isRunning()){
if(L>measL) measL=L;
if(R>measR) measR=R;
}else{
if(measL<255) measL+=2;
if(measR<255) measR+=2;
}
#if VS1053_CS==255
if(samples_cnt<VU_BMS) return;
#endif
samples_cnt=0;
uint8_t h=(dimension/VU_NB)-2;
for(int i=0; i<dimension; i++){
if(i%(dimension/VU_NB)==0){
if(VU_HOR){
uint16_t bandColor = (i>VU_BW-(VU_BW/VU_NB)*4)?VU_COLOR_MAX:VU_COLOR_MIN;
gfxc.fillRect(i, 0, h, VU_BH, bandColor);
gfxc.fillRect(i+VU_BW+VU_BS, 0, h, VU_BH, bandColor);
}else{
uint16_t bandColor = (i<(VU_BH/VU_NB)*3)?VU_COLOR_MAX:VU_COLOR_MIN;
gfxc.fillRect(0, i, VU_BW, h, bandColor);
gfxc.fillRect(VU_BW+VU_BS, i, VU_BW, h, bandColor);
}
}
}
if(VU_HOR){
gfxc.fillRect(VU_BW-measL, 0, measL, VU_BW, TFT_BG);
gfxc.fillRect(VU_BW*2+VU_BS-measR, 0, measR, VU_BW, TFT_BG);
dsp->drawRGBBitmap (VU_X, VU_Y, gfxc.getBuffer(), 120, VU_BH);
}else{
gfxc.fillRect(0, 0, VU_BW, measL, TFT_BG);
gfxc.fillRect(VU_BW+VU_BS, 0, VU_BW, measR, TFT_BG);
dsp->drawRGBBitmap (VU_X, VU_Y, gfxc.getBuffer(), VU_BW*2+VU_BS, VU_BH);
}
if(player.isRunning()){
measL=0;
measR=0;
}
}
#endif
#endif

View File

@@ -1,7 +1,7 @@
#ifndef options_h
#define options_h
#define VERSION "0.6.450"
#define VERSION "0.6.494"
/*******************************************************
DO NOT EDIT THIS FILE.
@@ -225,6 +225,17 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#ifndef SOFT_AP_REBOOT_DELAY
#define SOFT_AP_REBOOT_DELAY 0 // Delay in ms after which ESP is rebooting if it is in softAP mode (0 - disabled)
#endif
#ifndef ENABLE_VU_METER
#define ENABLE_VU_METER false // enable? vu meter for some displays
/*
* !!! Important !!!
* if you enable this feathure on the esp32 wroom, due to lack of memory, you must modify the file Arduino/libraries/AsyncTCP/src/AsyncTCP.cpp
* replace the line 221
* xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
* with
* xTaskCreateUniversal(_async_service_task, "async_tcp", 8192 / 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
*/
#endif
/*
*** ST7735 display submodel ***
INITR_BLACKTAB // 1.8' https://aliexpress.ru/item/1005002822797745.html

View File

@@ -4269,7 +4269,8 @@ int32_t Audio::Gain(int16_t s[2]) {
step = step * m_balance * 16;
r = (uint8_t)(step);
}
vuLeft = s[LEFTCHANNEL] >> 7;
vuRight = s[RIGHTCHANNEL] >> 7;
v[LEFTCHANNEL] = (s[LEFTCHANNEL] * (m_vol - l)) >> 8;
v[RIGHTCHANNEL]= (s[RIGHTCHANNEL] * (m_vol - r)) >> 8;

View File

@@ -186,7 +186,10 @@ public:
uint32_t getAudioCurrentTime();
uint32_t getTotalPlayingTime();
void setDefaults();
/* VU METER */
void setVUmeter() {};
void getVUlevel() {};
uint8_t vuLeft, vuRight;
SemaphoreHandle_t mutex_pl=NULL;
esp_err_t i2s_mclk_pin_select(const uint8_t pin);

View File

@@ -331,6 +331,8 @@ void Audio::begin(){
write_register(SCI_AUDATA, 44100 + 1); // 44.1kHz + stereo
// The next clocksetting allows SPI clocking at 5 MHz, 4 MHz is safe then.
write_register(SCI_CLOCKF, 6 << 12); // Normal clock settings multiplyer 3.0=12.2 MHz
//set vu meter
setVUmeter();
//SPI Clock to 4 MHz. Now you can set high speed SPI clock.
VS1053_SPI=SPISettings(6700000, MSBFIRST, SPI_MODE0); // SPIDIV 12 -> 80/12=6.66 MHz
write_register(SCI_MODE, _BV (SM_SDINEW) | _BV(SM_LINE1));
@@ -353,6 +355,16 @@ size_t Audio::bufferFree(){
return InBuff.freeSpace();
}
//---------------------------------------------------------------------------------------------------------------------
uint32_t Audio::inBufferFilled() {
// current audio input buffer fillsize in bytes
return InBuff.bufferFilled();
}
//---------------------------------------------------------------------------------------------------------------------
uint32_t Audio::inBufferFree() {
// current audio input buffer free space in bytes
return InBuff.freeSpace();
}
//---------------------------------------------------------------------------------------------------------------------
void Audio::setVolume(uint8_t vol){
// Set volume. Both left and right.
@@ -1542,6 +1554,45 @@ void Audio::setDefaults(){
m_f_tts = false; // text to speech
m_f_localfile = false;
}
//------------------------------------------------------------------------------
/**
* \brief enable VSdsp VU Meter
*
* \param[in] enable when set will enable the VU meter
*
* Writes the SS_VU_ENABLE bit of the SCI_STATUS register to enable VU meter on
* board to the VSdsp.
*
* See data patches data sheet VU meter for details.
* \warning This feature is only available with patches that support VU meter.
* \n The VU meter takes about 0.2MHz of processing power with 48 kHz samplerate.
*/
void Audio::setVUmeter() {
if(!ENABLE_VU_METER) return;
uint16_t MP3Status = read_register(SCI_STATUS);
write_register(SCI_STATUS, MP3Status | _BV(9));
}
//------------------------------------------------------------------------------
/**
* \brief get current measured VU Meter
*
* Returns the calculated peak sample values from both channels in 3 dB
* increaments through. Where the high byte represent the left channel,
* and the low bytes the right channel.
*
* Values from 0 to 31 are valid for both channels.
*
* \warning This feature is only available with patches that support VU meter.
*/
void Audio::getVUlevel() {
if(!ENABLE_VU_METER) return;
int16_t reg = read_register(SCI_AICTRL3);
uint8_t rl = map((uint8_t)reg, 81, 92, 0, 255);
uint8_t rr = map((uint8_t)(reg >> 8), 81, 92, 0, 255);
if(rl>30 || !isRunning()) vuLeft = rl;
if(rr>30 || !isRunning()) vuRight = rr;
}
//---------------------------------------------------------------------------------------------------------------------
bool Audio::connecttohost(String host){
return connecttohost(host.c_str());

View File

@@ -241,7 +241,6 @@ protected:
void loadUserCode();
public:
// Constructor. Only sets pin values. Doesn't touch the chip. Be sure to call begin()!
Audio ( uint8_t _cs_pin, uint8_t _dcs_pin, uint8_t _dreq_pin, uint8_t spi = VSPI, uint8_t mosi = 23, uint8_t miso = 19, uint8_t sclk = 18);
@@ -269,11 +268,17 @@ public:
SemaphoreHandle_t mutex_pl=NULL;
size_t bufferFilled();
size_t bufferFree();
uint32_t inBufferFilled(); // returns the number of stored bytes in the inputbuffer
uint32_t inBufferFree(); // returns the number of free bytes in the inputbuffer
bool isRunning() {/*Serial.printf("m_f_running=%d\n", m_f_running); */return m_f_running;}
void setBalance(int8_t bal = 0);
void setTone(int8_t gainLowPass, int8_t gainBandPass, int8_t gainHighPass);
void setDefaults();
void forceMono(bool m) {} // TODO
/* VU METER */
void setVUmeter();
void getVUlevel();
uint8_t vuLeft, vuRight;
// implement several function with respect to the index of string
bool startsWith (const char* base, const char* str) { return (strstr(base, str) - base) == 0;}
bool endsWith (const char* base, const char* str) {

View File

@@ -284,7 +284,6 @@ void DspCore::displayHeapForDebug() {
fillRect(TFT_FRAMEWDT, vTop, swidth - TFT_FRAMEWDT / 2, 7, TFT_BG);
sprintf(buf, "%d / %d", ESP.getFreeHeap(), ESP.getMaxAllocHeap());
print(buf);
#if VS1053_CS==255
// audio buffer;
fillRect(0, sheight - 2, swidth, 2, TFT_BG);
int astored = player.inBufferFilled();
@@ -292,7 +291,6 @@ void DspCore::displayHeapForDebug() {
int aprcnt = 100 * astored / (astored + afree);
byte sbw = map(aprcnt, 0, 100 , 0, swidth);
fillRect(0, sheight - 2, sbw, 2, SILVER);
#endif
}
void DspCore::printClock(const char* timestr) {

View File

@@ -121,6 +121,7 @@ void DspCore::initD(uint16_t &screenwidth, uint16_t &screenheight) {
setTextSize(1);
screenwidth = width();
screenheight = height();
Serial.printf("ILI9341 %dx%d\n", screenwidth, screenheight);
swidth = screenwidth;
sheight = screenheight;
}
@@ -208,7 +209,6 @@ void DspCore::displayHeapForDebug() {
print(ESP.getFreeHeap());
print(" / ");
print(ESP.getMaxAllocHeap());
#if VS1053_CS==255
// audio buffer;
fillRect(0, sheight - 2, swidth, 2, TFT_BG);
int astored = player.inBufferFilled();
@@ -216,7 +216,6 @@ void DspCore::displayHeapForDebug() {
int aprcnt = 100 * astored / (astored + afree);
byte sbw = map(aprcnt, 0, 100 , 0, swidth);
fillRect(0, sheight - 2, sbw, 2, SILVER);
#endif
}
void DspCore::printClock(const char* timestr) {

View File

@@ -220,7 +220,6 @@ void DspCore::displayHeapForDebug() {
print(ESP.getFreeHeap());
print(" / ");
print(ESP.getMaxAllocHeap());
#if VS1053_CS==255
// audio buffer;
fillRect(0, sheight - 2, swidth, 2, TFT_BG);
int astored = player.inBufferFilled();
@@ -228,7 +227,6 @@ void DspCore::displayHeapForDebug() {
int aprcnt = 100 * astored / (astored + afree);
byte sbw = map(aprcnt, 0, 100 , 0, swidth);
fillRect(0, sheight - 2, sbw, 2, DARK_GRAY);
#endif
}
void DspCore::setClockBounds(){

View File

@@ -16,6 +16,12 @@
#define DEF_SPI_FREQ 40000000UL /* set it to 0 for system default */
#endif
#if ENABLE_VU_METER && DTYPE==INITR_BLACKTAB
#define CLOCK_DELTA 12
#else
#define CLOCK_DELTA 0
#endif
#define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY)
#define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl)
@@ -220,7 +226,6 @@ void DspCore::displayHeapForDebug() {
print(ESP.getFreeHeap());
print(" / ");
print(ESP.getMaxAllocHeap());
#if VS1053_CS==255
// audio buffer;
fillRect(0, sheight - 2, swidth, 2, TFT_BG);
int astored = player.inBufferFilled();
@@ -229,7 +234,6 @@ void DspCore::displayHeapForDebug() {
byte sbw = map(aprcnt, 0, 100 , 0, swidth);
fillRect(0, sheight - 2, sbw, 2, SILVER);
#endif
#endif
}
void DspCore::setClockBounds(){
@@ -263,10 +267,10 @@ void DspCore::printClock(struct tm timeinfo, bool dots, bool redraw){
setFont(&DS_DIGI28pt7b);
if(strstr(oldTimeBuf, timeBuf)==NULL || redraw){
getTextBounds(oldTimeBuf, 0, 0, &x, &y, &wot, &hot);
setCursor((swidth - wot) / 2 - 4, clockY+28+6);
setCursor((swidth - wot) / 2 - 4 + CLOCK_DELTA, clockY+28+6);
setTextColor(TFT_BG);
print(oldTimeBuf);
dot = (swidth - wot) / 2 - 4;
dot = (swidth - wot) / 2 - 4 + CLOCK_DELTA;
/* dots */
strlcpy(tmpBuf, oldTimeBuf, 3);
getTextBounds(tmpBuf, 0, 0, &x, &y, &ncwidth, &ncheight);
@@ -279,8 +283,8 @@ void DspCore::printClock(struct tm timeinfo, bool dots, bool redraw){
setTextSize(1);
getTextBounds(timeBuf, 0, 0, &x, &y, &ncwidth, &ncheight);
setTextColor(TFT_LOGO);
setCursor((swidth - ncwidth) / 2 - 4, clockY+28+6);
dot = (swidth - ncwidth) / 2 - 4;
setCursor((swidth - ncwidth) / 2 - 4 + CLOCK_DELTA, clockY+28+6);
dot = (swidth - ncwidth) / 2 - 4 + CLOCK_DELTA;
setTextSize(1);
print(timeBuf);
/* dots */

View File

@@ -216,7 +216,6 @@ void DspCore::displayHeapForDebug() {
print(ESP.getFreeHeap());
print(" / ");
print(ESP.getMaxAllocHeap());
#if VS1053_CS==255
// audio buffer;
fillRect(0, sheight - 2, swidth, 2, TFT_BG);
int astored = player.inBufferFilled();
@@ -224,7 +223,6 @@ void DspCore::displayHeapForDebug() {
int aprcnt = 100 * astored / (astored + afree);
byte sbw = map(aprcnt, 0, 100 , 0, swidth);
fillRect(0, sheight - 2, sbw, 2, SILVER);
#endif
yield();
}