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

FrquencyResponseDrawer.cpp

Committer:
MikamiUitOpen
Date:
2016-07-24
Revision:
2:8bccc97de938
Parent:
1:19a32f6279e6
Child:
4:47c6cbdd8d77

File content as of revision 2:8bccc97de938:

//------------------------------------------------------------------------
//  ディジタルフィルタの周波数特性を,周波数軸が対数スケールで描画するクラス
//  FrqRespDrawer class
//
//  2016/07/24, 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-2, 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);
    }
}