//---------------------------------------------------------------------
//  オシロスコープ (Nucleo-F446RE 用)
//      ● 入力  A0: チャンネル1，A1 チャンネル2
//
//  2023/01/17, Copyright (c) 2023 MIKAMI, Naoki
//---------------------------------------------------------------------

#include <string>
#include "DSP_AdcDualIntr.hpp"
#include "InputBuffer.hpp"
#include "XferWaveform.hpp"
using namespace Mikami;

#ifndef __STM32F446xx_H
#error "Use Nucleo-F446RE"
#endif

const int N_FRAME_ = 1000;  // １フレーム当たり標本化するデータ数

DspAdcDualIntr myAdc_(100, A0, A1);
InputBuffer buf_(N_FRAME_); // AD の結果を保存するバッファ

// ADC 変換終了割り込みに対する割り込みサービス･ルーチン
void AdcIsr()
{
    float sn1, sn2;
    myAdc_.Read(sn1, sn2);
    buf_.Store(sn1, sn2);       // バッファへ格納
    if (buf_.IsFullNext())      // バッファが満杯になったら ADC 割り込みを禁止する
        myAdc_.DisableIntr();
}

int main()
{
    SerialRxTxIntr rxTx;                // PC との通信用，最初は 9600 baud
    XferWaveform tx(rxTx, 2*N_FRAME_);  // PC に転送するためのオブジェクトの生成

    myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て
    myAdc_.DisableIntr();
    while (true)
    {
        // PC からのコマンドの解析
        if (rxTx.IsEol())       // 受信バッファのデータが有効になった場合の処理
        {
            string str = rxTx.GetBuffer();
            if (str == "Oscilloscope")
            {
                rxTx.TxString("ACK\n"); // PC からの "Oscilloscope" 受信に対して"ACK" を送信
                wait_ms(10);
                rxTx.Baud(460800);      // 以降は 460,800 baud
            }
            else if (str.substr(0, 2) == "GO")
            {
                // str の [2..5] の内容：標本化周波数
                int fs = atoi(str.substr(2, 4).c_str());    // 標本化周波数
                myAdc_.SetFs(fs);       // 標本化周波数再設定
                myAdc_.EnableIntr();    // ADC 割り込みを有効にする
            }
        }

        if (buf_.IsFull())
            tx.XferToPC(buf_.Get());    // データを PC へ転送
    }
}
