FrqRespDrawer class to draw frequency response for digital filter. ディジタルフィルタの周波数特性を,周波数軸をログスケールで描画するための FrqRespDrawer クラス. このライブラリを登録した際のプログラム:「F746_FrequencyResponseDrawer_Demo」
Dependents: F746_SD_WavPlayer F746_SD_GraphicEqualizer_ren0620 F746_FrequencyResponseDrawer_Demo F746_SD_VarableFilter ... more
Diff: FrquencyResponseDrawer.cpp
- Revision:
- 0:0bc63b49e2a3
- Child:
- 1:19a32f6279e6
diff -r 000000000000 -r 0bc63b49e2a3 FrquencyResponseDrawer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FrquencyResponseDrawer.cpp Sun May 01 14:00:06 2016 +0000 @@ -0,0 +1,104 @@ +//------------------------------------------------------------------------ +// ディジタルフィルタの周波数特性を,周波数軸が対数スケールで描画するクラス +// FrqRespDrawer class +// +// 2016/05/01, Copyright (c) 2016 MIKAMI, Naoki +//------------------------------------------------------------------------ + +#include "FrquencyResponseDrawer.hpp" + +namespace Mikami +{ + // 目盛線の描画 + void FrqRespDrawer::DrawAxis() + { + uint16_t height = DB1_*(MAX_DB_ - MIN_DB_); + int logMin = (int)floorf(log10f(MIN_)); + int loop = (int)floorf(log10f(MAX_)) - logMin; + + lcd_->SetTextColor(AXIS_COLOR_); + uint16_t y0 = ORGY_ - height; + lcd_->DrawVLine(X(MIN_), y0, height); // 最小値に対応する線 + + float du = powf(10.0, logMin); // 座標値の増分 + float u1 = (floorf(MIN_/du) + 1.0f)*du; // 最小値に対応する線の次の座標値 + + for (int n=0; n<=loop; n++) + { + float uMax = (10.0f*du < MAX_) ? 10.0f*du : MAX_; + for (float u=u1; u<uMax*0.99f; u+=du) + lcd_->DrawVLine(X(u), y0, height); + + du = uMax; // 値の増分を 10 倍する + u1 = du; // 次の for ループ の最初の値 + } + + lcd_->DrawVLine(X(MAX_), y0, height); // 最大値に対応する線 + + uint16_t width = X(MAX_) - X(MIN_); + int count = Round((MAX_DB_ - MIN_DB_)/(Y_SPACE_/DB1_)); + for (int n=0; n<= count; n++) + lcd_->DrawHLine(X(MIN_), Round(ORGY_-Y_SPACE_*n), width); + } + + // 横軸の目盛値の表示 + void FrqRespDrawer::DrawNumericX(AxisX_Char xChar[], int nDisp, int offsetY, + string str, sFONT &fonts, uint32_t textColor) + { + for (int n=0; n<nDisp; n++) + Label frq(X(xChar[n].frq), ORGY_+offsetY, + xChar[n].str, Label::CENTER); + uint16_t x0 = ORGX_ + (uint16_t)(DEC_*log10f(MAX_/MIN_))/2; + Label l_frq(x0, ORGY_+20, str, Label::CENTER); + } + + // 縦軸の目盛値の表示 + void FrqRespDrawer::DrawNumericY(int offsetX, int offsetY, uint16_t d_dB, + const char fmt[], sFONT &fonts, + uint32_t textColor, string str) + { + uint16_t x0 = ORGX_ + offsetX; + uint16_t y0 = ORGY_ + offsetY; + int count = Round((MAX_DB_ - MIN_DB_)/d_dB); + + for (int n=0; n<=count; n++) + NumericLabel<int> num(x0, y0-n*d_dB*DB1_, + fmt, (int)(MIN_DB_+d_dB*n)); + Label l_dB(x0, y0-count*d_dB*DB1_-12, str); + } + + // 周波数特性のグラフの描画 + void FrqRespDrawer::DrawGraph(FrequencyResponse *frqResp, uint32_t color) + { + lcd_->SetTextColor(color); + uint16_t width = X(MAX_) - X(MIN_); + uint16_t x1 = 0; + uint16_t y1 = 0; + float pi2FsM = -6.283185f/FS_; // -2*PI*Ts + for (int n=0; n<=width; n++) + { + float frq = PosToFrq(n+ORGX_); + uint16_t x2 = X(frq); + float absHz = frqResp->AbsH_z(exp(Complex(0, pi2FsM*frq))); + float dB = (absHz > 0.001f) ? 20.0f*log10f(absHz) : MIN_DB_; + uint16_t y2 = ORGY_ - Round((dB - MIN_DB_)*DB1_); + if (y2 > ORGY_) y2 = ORGY_; + + if (n != 0) lcd_->DrawLine(x1, y1, x2, y2); + + x1 = x2; + y1 = y2; + } + lcd_->SetTextColor(AXIS_COLOR_); + lcd_->DrawHLine(X(MIN_), ORGY_, width+1); + } + + // 消去 + void FrqRespDrawer::Erase(float upDb) + { + lcd_->SetTextColor(BACK_COLOR_); + uint16_t height = DB1_*(MAX_DB_+upDb - MIN_DB_); + lcd_->FillRect(ORGX_, ORGY_- height, X(MAX_)-X(MIN_)+1, height+1); + } +} +