?
Diff: DesignerDrawer.cpp
- Revision:
- 0:cacfc9e25452
diff -r 000000000000 -r cacfc9e25452 DesignerDrawer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DesignerDrawer.cpp Tue Jun 04 21:58:08 2019 +0000 @@ -0,0 +1,134 @@ +//------------------------------------------------------------------------------ +// IIR フィルタを双一次 z 変換で設計し,その周波数特性を描画するためのクラス +// +// 2016/05/01, Copyright (c) 2016 MIKAMI, Naoki +//------------------------------------------------------------------------------ + +#include "DesignerDrawer.hpp" + +namespace Mikami +{ + // Constructor + DesignerDrawer::DesignerDrawer(uint16_t x0, uint16_t y0, + float db1, int fs, int order, + float fc, uint16_t fL, uint16_t fH, + BilinearDesign::Type lpHp) + : lcd_(GuiBase::GetLcdPtr()), ts_(GuiBase::GetTsPtr()), + X0_(x0), Y0_(y0), ORDER_(order), + CURSOR_Y0_(y0+1-db1*60), CURSOR_LENGTH_(db1*60-1), + LOWER_F_(fL), HIGHER_F_(fH), + CURSOR_COLOR_(0xFFE000D0), CURSOR_TOUCHED_COLOR_(0xFFFF80FF) + { + drawerObj_ = new FrqRespDrawer(x0, 100.0f, 20000.0f, 140, + y0, -60, 0, db1, 10, fs); + + // 双一次 z 変換による IIR フィルタの設計 + designObj_ = new BilinearDesign(order, fs); + coefs_ = new BilinearDesign::Coefs[order/2]; + ck_ = (Biquad::Coefs *)coefs_; + + fC_ = fc; // 最初に与える遮断周波数 + designObj_->Execute(fC_, lpHp, coefs_, g0_); + frqResp_ = new IIR_CascadeFrqResp(); + frqResp_->SetParams(ORDER_, g0_, ck_); + + // 周波数特性の描画 + lblFrq_ = new NumericLabel<int>(110, 38); + DrawResponse(); + tp_ = new TouchPanelDetectorX( + drawerObj_->X(LOWER_F_), drawerObj_->X(HIGHER_F_), + CURSOR_Y0_, y0); + lp_ = lpHp; + cursorRedraw_ = false; + } + + DesignerDrawer::~DesignerDrawer() + { + delete tp_; + delete lblFrq_; + delete coefs_; + delete designObj_; + delete drawerObj_; + } + + // フィルタの再設計と周波数特性の再描画 + bool DesignerDrawer::ReDesignAndDraw(Biquad::Coefs *ck, float &g0, + BilinearDesign::Type lpHp) + { + bool changed = (lpHp != lp_) ? true : false; + bool tch = tp_->IsTouched(cursorX_, cursorX_); + if (tch || changed) + { + int newFc = Frq10(drawerObj_->PosToFrq(cursorX_)); + newFc = (newFc > HIGHER_F_) ? HIGHER_F_ : newFc; + if ((abs(newFc - fC_) >= 10) || changed) + { + fC_ = newFc; + lblFrq_->Draw("Tan So Cat = %4d Hz", newFc); + designObj_->Execute(newFc, lpHp, coefs_, g0_); + GetCoefficients(ck, g0); + + frqResp_->SetParams(ORDER_, g0_, ck_); + drawerObj_->Erase(); + drawerObj_->DrawAxis(); // 目盛線の描画 + drawerObj_->DrawGraph(frqResp_); // 周波数特性のグラフのカーブを描画する + + if (tch) // カーソルの移動 + { + lcd_->SetTextColor(CURSOR_TOUCHED_COLOR_); + lcd_->DrawVLine(cursorX_, CURSOR_Y0_, CURSOR_LENGTH_); + } + cursorRedraw_ = true; + oldCursorX_ = cursorX_; + lp_ = lpHp; + return true; + } + } + + if (!tch && cursorRedraw_) // カーソルを元の色に戻す + { + lcd_->SetTextColor(CURSOR_COLOR_); + lcd_->DrawVLine(oldCursorX_, CURSOR_Y0_, CURSOR_LENGTH_); + cursorRedraw_ = false; + } + return false; + } + + // 周波数特性の描画 + void DesignerDrawer::DrawResponse() + { + lblFrq_->Draw("Tan So Cat = %4d Hz", fC_); + drawerObj_->DrawAxis(); // 目盛線の描画 + FrqRespDrawer::AxisX_Char numX[] = // 横軸の目盛値を描画する際に使う構造体の配列 + {{ 100, "0.1"}, { 200, "0.2"}, { 500, "0.5"}, { 1000, "1"}, + { 2000, "2"}, { 5000, "5"}, {10000, "10"}, {20000, "20"}}; + drawerObj_->DrawNumericX(numX, 8, 6, "Tan So [kHz]"); // 横軸の目盛 + drawerObj_->DrawNumericY(-24, -6, 20, "%3d"); // 縦軸の目盛は 20 dB 間隔 + drawerObj_->DrawGraph(frqResp_); // 周波数特性のカーブの描画 + + cursorX_ = drawerObj_->X(fC_); + lcd_->SetTextColor(CURSOR_COLOR_); + lcd_->DrawVLine(cursorX_, CURSOR_Y0_, CURSOR_LENGTH_); + } + + // フィルタ係数の取得 + void DesignerDrawer::GetCoefficients(Biquad::Coefs *c, float &g0) + { + for (int k=0; k<ORDER_/2; k++) c[k] = ck_[k]; + g0 = g0_; + } + + // 周波数を 10, 20, 50, 100 Hz の倍数にする + int DesignerDrawer::Frq10(float f) + { + if (f < 1000) + return ((int)(f/10.0f + 0.5f))*10; + if (f < 2000) + return ((int)(f/20.0f + 0.5f))*20; + if (f < 3000) + return ((int)(f/50.0f + 0.5f))*50; + else + return ((int)(f/100.0f + 0.5f))*100; + } +} +