/******************************************************************************
 * file    Core/Src/recording_wave.c 
 * author  YuLiang
 * version 1.0.0
 * date    03-Aug-2022
 * brief   This file provides all the recording wave related operation functions.
 ******************************************************************************
 * Attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2022 LandPower</center></h2>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of WTOE nor the names of its contributors may be used to 
 *      endorse or promote products derived from this software without specific
 *      prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "stdio.h"
#include "string.h"

#include "spi.h"
#include "tim.h"

#include "common.h"
#include "dev_config.h"
#include "flash_if.h"
#include "ADC_collect.h"
#include "recording_wave.h"

/* Private define ------------------------------------------------------------*/
#define FPGA_ADC_NUMBER0            (0x00)
#define FPGA_ADC_NUMBER1            (0x01)

#define FPGA_ADC_SPI_READ           (0x01)
#define FPGA_ADC_SPI_WRITE          (0x00)

#define IO32BASE_ADR                (0x40)  
#define IO32MOUDLE0_ADR             (IO32BASE_ADR+0x00)  
#define IO32MOUDLE1_ADR             (IO32BASE_ADR+0x01)  
#define IO32MOUDLE2_ADR             (IO32BASE_ADR+0x02)  
#define IO32MOUDLE3_ADR             (IO32BASE_ADR+0x03)  
#define IO32MOUDLE4_ADR             (IO32BASE_ADR+0x04)  
#define IO32MOUDLE5_ADR             (IO32BASE_ADR+0x05)  
#define IO32MOUDLE6_ADR             (IO32BASE_ADR+0x06)  
#define IO32MOUDLE7_ADR             (IO32BASE_ADR+0x07)  

////  FPGA_ADC_SPI 位定义 -------------------------------------------------------------------------------------------------
#define ADC_SPI1_EN                 (BIT31)      // ADC的配置SPI接口： ADC1
#define ADC_SPI2_EN                 (BIT30)      // ADC的配置SPI接口： ADC2

#define ADC_SPI_CS_EN               (BIT00)      // ADC的配置SPI接口： 片选允许输出
#define ADC_SPI_CS_OUT              (BIT01)      // ADC的配置SPI接口： 片选输出的数据
#define ADC_SPI_CLK_EN              (BIT02)      // ADC的配置SPI接口： 时钟允许输出
#define ADC_SPI_CLK_OUT             (BIT03)      // ADC的配置SPI接口： 时钟输出的数据
#define ADC_SPI_SDO_EN              (BIT04)      // ADC的配置SPI接口： 数据管脚允许输出
#define ADC_SPI_SDO_OUT             (BIT05)      // ADC的配置SPI接口： 数据管脚输出的数据
#define ADC_SPI_SDI_IN              (BIT00)      // ADC的配置SPI接口： 数据管脚输入的数据位 
#define ADC2_SPI_SDI_IN             (BIT01)      // ADC的配置SPI接口： 数据管脚输入的数据位

/* Private typedef -----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
const osThreadAttr_t WAVE_attributes =
{
    .name = "WAVE",
    .stack_size = 160 * 4,
    .priority = (osPriority_t) osPriorityLow,
};

wave_ctrl_t wave_ctrl;

/* Private function prototypes -----------------------------------------------*/
/* Internal functions --------------------------------------------------------*/
static void _wave_transmit_Receive(uint8_t cmd, uint8_t addr, uint32_t len, uint8_t *buf_wr, uint8_t *buf_rd) 
{
    uint8_t data = cmd | addr;

    HAL_GPIO_WritePin(DAU_CS_GPIO_Port, DAU_CS_Pin, GPIO_PIN_RESET);
    if (HAL_SPI_Transmit(wave_ctrl.spi, &data, 1, 3000) != HAL_OK)
    {
        vty_print("@21\r\n");
        return;
    }

    if (HAL_SPI_Transmit(wave_ctrl.spi, buf_wr, 1, 3000) != HAL_OK)
    {
        vty_print("@22\r\n");
        return;
    }

    if (HAL_SPI_TransmitReceive(wave_ctrl.spi, buf_wr + 1, buf_rd, len, 3000) != HAL_OK)
    {
        vty_print("@23\r\n");
        return;
    }    
    HAL_GPIO_WritePin(DAU_CS_GPIO_Port, DAU_CS_Pin, GPIO_PIN_SET);

    DBG(DBG_M_WAVE, "Send(cmd: %x):\r\n", data);
    if (dbg_stat_get(DBG_M_WAVE))
    {
        buf_print((uint8_t*)buf_wr, len + 1);
    }
    DBG(DBG_M_WAVE, "Rcev:\r\n");
    if (dbg_stat_get(DBG_M_WAVE))
    {
        buf_print((uint8_t*)buf_rd, len);
        vty_print("\r\n");
    }
}

int32_t _wave_ADC9231_spi_rw(uint8_t rw, uint8_t adc_number, uint16_t spi_addr, uint8_t data)
{
    uint32_t *buf_wr = wave_ctrl.buf_wr;
    uint32_t *buf_rd = wave_ctrl.buf_rd;
    uint32_t i = 0;
    uint32_t j = 0;
    uint32_t k = 0; 
    
    /* 2. 初始化: 关掉所有的模块, 管脚都输出 1. */
    buf_wr[0] = 0;  // 关掉所有的模块 
    buf_wr[1] = ADC_SPI_CS_EN | ADC_SPI_CS_OUT | ADC_SPI_CLK_EN | ADC_SPI_CLK_OUT | ADC_SPI_SDO_EN | ADC_SPI_SDO_OUT;
    buf_wr[2] = 0;
    buf_wr[3] = 0;
    buf_wr[4] = 0;

    _wave_transmit_Receive(WAVE_WRITE, IO32MOUDLE2_ADR, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);      

    /* 3. 初始化: 打开对于的模块, 管脚都输出 1. */
    if (FPGA_ADC_NUMBER0 == adc_number)
    {
        buf_wr[0] = ADC_SPI1_EN;
    }
    else
    {
        buf_wr[0] = ADC_SPI2_EN;
    }
    
    /* Pin nCS=1  CLK=1  SDO=1 */
    _wave_transmit_Receive(WAVE_WRITE, IO32MOUDLE2_ADR, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);        

    /* Pin nCS=0  CLK=1  SDO=1 */
    buf_wr[1] = ADC_SPI_CS_EN  | ADC_SPI_CLK_EN | ADC_SPI_CLK_OUT | ADC_SPI_SDO_EN | ADC_SPI_SDO_OUT ;
    _wave_transmit_Receive(WAVE_WRITE, IO32MOUDLE2_ADR, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);        

    j = spi_addr;
    if (1 == rw)     
    { 
        j += 0;         // 如果是读数据, 则从后个地址从后面一个地址多读一个字节, 挤掉前一个无效数据  待测试!
        j |= 0x8000;    // AD9231  read:1  write:0  
    }   
    
    /* 6. out ADC adr */
    for(i=0;i<16;i++)   //  写一个bit
    {
        /* 6.1. Pin nCS=0  CLK=0  SDO=OutData */
        buf_wr[1] = ADC_SPI_CS_EN  | ADC_SPI_CLK_EN  | ADC_SPI_SDO_EN;
        if (j & 0x8000)
        {
            buf_wr[1] |= ADC_SPI_SDO_OUT;
        }
        _wave_transmit_Receive(WAVE_WRITE, IO32MOUDLE2_ADR, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);
        
        /* 6.1. Pin nCS=0  CLK=1  SDO=OutData */
        buf_wr[1] = ADC_SPI_CS_EN  | ADC_SPI_CLK_EN | ADC_SPI_CLK_OUT | ADC_SPI_SDO_EN  ;
        if (j & 0x8000)
        {
            buf_wr[1] |= ADC_SPI_SDO_OUT;
        }
        _wave_transmit_Receive(WAVE_WRITE, IO32MOUDLE2_ADR, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);
        
        j = j << 1;     // MSB16 is first
    }
    
    k = 0;
    if (0 == rw)        // RW: 1:read   0:Write
    {
        j = data << 8;
        
        for(i = 0; i < 8; i++)  // RW:  0:Write
        {
                /* 6.1. Pin nCS=0  CLK=0  SDO=OutData */
                buf_wr[1] = ADC_SPI_CS_EN  | ADC_SPI_CLK_EN  | ADC_SPI_SDO_EN  ;
                if (j & 0x8000)
                {
                    buf_wr[1] |= ADC_SPI_SDO_OUT;
                }
                _wave_transmit_Receive(WAVE_WRITE, IO32MOUDLE2_ADR, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);
                
                /* 6.2. Pin nCS=0  CLK=1  SDO=OutData */
                buf_wr[1] = ADC_SPI_CS_EN  | ADC_SPI_CLK_EN | ADC_SPI_CLK_OUT | ADC_SPI_SDO_EN  ;
                if (j & 0x8000)
                {
                    buf_wr[1] |= ADC_SPI_SDO_OUT;
                }
                _wave_transmit_Receive(WAVE_WRITE, IO32MOUDLE2_ADR, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);
                
                j = j<<1;       // MSB16 is first
        }
        
    }
    else
    {
        for(i = 0; i < 8; i++)  // RW: 1:read   
        {
            /* 6.3 Pin nCS=0  CLK=0  SDO=Z */
            buf_wr[1] = ADC_SPI_CS_EN  | ADC_SPI_CLK_EN  ;
            _wave_transmit_Receive(WAVE_WRITE, IO32MOUDLE2_ADR, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);
                      
            /* 6.4. Pin nCS=0  CLK=1  SDO=Z */
            buf_wr[1] = ADC_SPI_CS_EN  | ADC_SPI_CLK_EN | ADC_SPI_CLK_OUT ;
            _wave_transmit_Receive(WAVE_WRITE, IO32MOUDLE2_ADR, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);

            /* MSB is first 读字节在前, 写字节在后读完之后时钟再变高. */
            if (FPGA_ADC_NUMBER0 == adc_number)
            {
                if(buf_rd[1] & ADC_SPI_SDI_IN)
                {
                    k |= (0x01<<(7-i));
                }
            }  
            else
            {
                
                if(buf_rd[1] & ADC2_SPI_SDI_IN)
                {
                    k |= (0x01<<(7-i));
                }
            }
        }
    }
    
    /* 7.1. Pin nCS=1  CLK=1  SDO=Z(1) */
    buf_wr[1] = ADC_SPI_CS_EN | ADC_SPI_CS_OUT | ADC_SPI_CLK_EN | ADC_SPI_CLK_OUT | ADC_SPI_SDO_OUT ;
    _wave_transmit_Receive(WAVE_WRITE, IO32MOUDLE2_ADR, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);
    
    return k;
}

static uint32_t Amp[5] = {2,2,2,2,2};
int32_t _wave_ADC9231_spi_init(void)
{
    uint8_t i;
    uint32_t id = 0; 
        
    /*  3. ADC9231的寄存器的读   . */
    id = _wave_ADC9231_spi_rw(FPGA_ADC_SPI_READ, FPGA_ADC_NUMBER0, 0x00, 0x00); // 从 ADC 的配置地址 0x00 读取一个字节 (0x18)
    id = _wave_ADC9231_spi_rw(FPGA_ADC_SPI_READ, FPGA_ADC_NUMBER0, 0x01, 0x00); // 从 ADC 的配置地址 0x01 读取一个字节 (AD9231 = 0x24)
    /* 3.1 判断器件是否挂在正确. */
    if (id != 0x24 && id != 0x36)
    {
        vty_print("@24: id = %x\r\n", id);
        return HAL_ERROR;
    }
    if (0x36 == id)
    {
        wave_ctrl.is_9231 = FALSE;
    }
    else
    {
        wave_ctrl.is_9231 = TRUE;
    }
    
    /* 4. ADC9231的寄存器的写 */
    if (0x24 == id)
    {
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER0, 0x19, 0xff); 
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER0, 0xFF, 0x01);     // 随意写一个寄存器则可以启动 ADC
        
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER0, 0x14, 0x81);     // 0x80: 1.8V CMOS    0x01: twos complement
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER0, 0xFF, 0x01);
        
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER0, 0x0d, 0x00);     // 0x00: 正常采集转换模式   难道写这个是启动？   
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER0, 0xFF, 0x01);

        /* 不知道干什么用的. */
        i = 0;
        if ((Amp[0] & 0x02) != 0)
        {
            i |=  0x80;
        }
        if( (Amp[0] & 0x01) != 0)
        {
            i |=  0x20;
        }
        i |= (Amp[1] & 0x07); 
        
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER0, 0x17, i);        //  0x17: DCO/Data OUTPUT_DELAY    
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER0, 0xFF, 0x01);
    }
    
    /*
    Adr 0x17:     
    bit7: 0x80 Enable DCO delay     
    bit5: 0x20 Enable data delay   
    DCO/Data delay[2:0]  
    0: 000 = 0.56 ns  
    1: 001 = 1.12 ns 
    2: 010 = 1.68 ns 
    3: 011 = 2.24 ns 
    4: 100 = 2.80 ns 
    5: 101 = 3.36 ns 
    6: 110 = 3.92 ns 
    7: 111 = 4.48 ns    
    */

    /* 10. 第ADC9231的寄存器的读 */
    id = _wave_ADC9231_spi_rw(FPGA_ADC_SPI_READ, FPGA_ADC_NUMBER1, 0x00, 0x00); // 从ADC的配置地址0x00 读取一个字节 （0x18）
    id = _wave_ADC9231_spi_rw(FPGA_ADC_SPI_READ, FPGA_ADC_NUMBER1, 0x01, 0x00); // 从ADC的配置地址0x01 读取一个字节 （AD9231 = 0x24）

    /* 3.1 判断器件是否挂在正确 */
    if (id != 0x24 && id != 0x36)
    {
        vty_print("@25: id = %x\r\n", id);
        return HAL_ERROR;
    }

    if (0x24 == id)
    {
        /* 4. ADC9231的寄存器的写 */
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER1, 0x19, 0xff); 
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER1, 0xFF, 0x01);    //  随意写一个寄存器则可以启动ADC
        
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER1, 0x14, 0x81);    //  0x80: 1.8V CMOS    0x01:twos complement
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER1, 0xFF, 0x01);  
        
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER1, 0x0d, 0x00);    //  0x00: 正常采集转换模式   难道写这个是启动？   
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER1, 0xFF, 0x01);     

        i = 0;
        if ((Amp[2] & 0x02) != 0)
        {
            i |=  0x80;
        }
        if ((Amp[2] & 0x01) != 0)
        {
            i |=  0x20;
        }
        i |= (Amp[3] & 0x07);
        
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER1, 0x17, i);        //  0x17: DCO/Data OUTPUT_DELAY    
        _wave_ADC9231_spi_rw(FPGA_ADC_SPI_WRITE, FPGA_ADC_NUMBER1, 0xFF, 0x01);
    }
    
    return HAL_OK;
}

static void _wave_restart(void)
{
    MX_SPI1_Init();
    MX_TIM7_Init();
    wave_ctrl.rt = 0;
    wave_ctrl.state.state = WAVE_STATE_START;
}

static void _wave_stop(uint8_t rt)
{
    wave_ctrl.rt = rt;
    HAL_GPIO_WritePin(POWER_EN_DAU_GPIO_Port, POWER_EN_DAU_Pin, GPIO_PIN_RESET);
    HAL_SPI_Abort(wave_ctrl.spi);
    HAL_SPI_DeInit(wave_ctrl.spi);
    HAL_TIM_Base_Stop(wave_ctrl.tim);
    HAL_TIM_Base_DeInit(wave_ctrl.tim);

    wave_ctrl.state.state = WAVE_STATE_COMPLETION;
    if (rt != WAVE_RT_END)
    {
        wave_ctrl.time_restart = HAL_GetTick() + 3600000;
    }
    else
    {
        wave_ctrl.time_restart = 0;
    }
}

/* 高频录波读取数据. */
static void _wave_read(void)
{
    uint32_t *buf_wr = wave_ctrl.buf_wr;
    uint32_t *buf_rd = wave_ctrl.buf_rd;
    uint32_t addr = WARE_ADDRESS;
    int16_t *buf = NULL;
    uint16_t j = 0;
    uint16_t i = 0;
    int16_t min = 0;
    int16_t max = 0;
    int16_t min_ch[4] = {0};
    int16_t max_ch[4] = {0};

    vty_print("@2: %d\r\n", HAL_GetTick());
    /* 5. 采集数据到 SDR: 512B*8000 = 1MB   1MSample * 2B/Ch*2CH=4MB. */
    for(i = 0; i < WAVE_PKT_SUM; i++)
    {
        _wave_transmit_Receive(WAVE_READ,  0x32, WAVE_DATA_LEN + 4, (uint8_t*)buf_wr, (uint8_t*)buf_rd);   // FIFO read delay 4  实际延4个字节

        buf = ((int16_t*)buf_rd) + 2;
        for(j = 0; j < 256; j += 2)
        {
            if (!wave_ctrl.is_9231)
            {
                buf[j] -= 32768;
            }
            
            if (buf[j] > max)
            {
                max = buf[j];
            }
            else if (buf[j] < min)
            {
                min = buf[j];
            }

            if (buf[j] > max_ch[0])
            {
                max_ch[0] = buf[j];
            }
            else if (buf[j] < min_ch[0])
            {
                min_ch[0] = buf[j];
            }

            buf[j] = (int32_t)buf[j] * 100 / dev_config.wave_adj;
        }

        for(j = 1; j < 256; j += 2)
        {
            if (!wave_ctrl.is_9231)
            {
                buf[j] -= 32768;
            }
            
            if (buf[j] > max)
            {
                max = buf[j];
            }
            else if (buf[j] < min)
            {
                min = buf[j];
            }

            if (buf[j] > max_ch[1])
            {
                max_ch[1] = buf[j];
            }
            else if (buf[j] < min_ch[1])
            {
                min_ch[1] = buf[j];
            }

            buf[j] = (int32_t)buf[j] * 100 / dev_config.wave_adj;
        }
        
        if (spi_flash_write(addr, (uint8_t*)(&buf_rd[1]), WAVE_DATA_LEN) != HAL_OK)
        {
            wave_ctrl.state.state = WAVE_STATE_TIMEOUT;
            return;
        }

#if 0
        vty_print("%x\r\n", addr);
        buf = ((int16_t*)buf_rd) + 2;
        for(j = 0; j < 50;)
        {
            vty_print("%-05d ", buf[2*j + 1]);
            j++;
            if(0 == j % 10)
            {
                vty_print("\r\n");
            }
        }
        if (j % 10 != 0)
        {
            vty_print("\r\n");
        }
        osDelay(1000);
#endif
        addr += WAVE_DATA_LEN;

        _wave_transmit_Receive(WAVE_READ,  0x34, WAVE_DATA_LEN + 4, (uint8_t*)buf_wr, (uint8_t*)buf_rd);  // FIFO read delay 4  实际延4个字节

        buf = ((int16_t*)buf_rd) + 2;
        for(j = 0; j < 256; j += 2)
        {
            if (!wave_ctrl.is_9231)
            {
                buf[j] -= 32768;
            }
            
            if (buf[j] > max)
            {
                max = buf[j];
            }
            else if (buf[j] < min)
            {
                min = buf[j];
            }

            if (buf[j] > max_ch[2])
            {
                max_ch[2] = buf[j];
            }
            else if (buf[j] < min_ch[2])
            {
                min_ch[2] = buf[j];
            }

            buf[j] = (int32_t)buf[j] * 100 / dev_config.wave_adj;
        }

        for(j = 1; j < 256; j += 2)
        {
            if (!wave_ctrl.is_9231)
            {
                buf[j] -= 32768;
            }
            
            if (buf[j] > max)
            {
                max = buf[j];
            }
            else if (buf[j] < min)
            {
                min = buf[j];
            }

            if (buf[j] > max_ch[3])
            {
                max_ch[3] = buf[j];
            }
            else if (buf[j] < min_ch[3])
            {
                min_ch[3] = buf[j];
            }

            buf[j] = (int32_t)buf[j] * 100 / dev_config.wave_adj;
        }
        
        if (spi_flash_write(addr, (uint8_t*)(&buf_rd[1]), WAVE_DATA_LEN) != HAL_OK)
        {
            wave_ctrl.state.state = WAVE_STATE_TIMEOUT;
            return;
        }
#if 0
        vty_print("%x\r\n", addr);
        buf = ((int16_t*)buf_rd) + 2;
        for(j = 0; j < 50;)
        {
            vty_print("%-05d ", buf[2*j + 1]);
            j++;
            if(0 == j % 10)
            {
                vty_print("\r\n");
            }
        }
        if (j % 10 != 0)
        {
            vty_print("\r\n");
        }
        osDelay(1000);
#endif
        addr += WAVE_DATA_LEN;
    }

    st_data.wave_max_save = max;
    st_data.wave_min_save = min;
    max = (int32_t)max * 100 / dev_config.wave_adj;
    min = (int32_t)min * 100 / dev_config.wave_adj;    
    if (!st_data.wave_force
        && max < dev_config.wave_threshold
        && abs_cal(0, min) < dev_config.wave_threshold)
    {
        st_data.wave_up_start = FALSE;
    }
    for(i = 0; i < WAVE_SUM; i++)
    {
        st_data.wave_max[i] = (max_ch[i] > abs_cal(0, min_ch[i])) ? max_ch[i] : min_ch[i];
        st_data.wave_max[i] = (int32_t)st_data.wave_max[i] * 100 / dev_config.wave_adj;
    }
    if (0 == st_data.wave_max[3])
    {
        st_data.wave_max[3] = 1;
    }
    st_data.wave_start = FALSE;
    
    st_write(&st_data);
    vty_print("@3: %d %d %d %d\r\n", HAL_GetTick(), min, max, dev_config.wave_threshold);
    /* 录波完成后需要修改运行状态标志. */
    wave_ctrl.state.state = WAVE_STATE_COMPLETION;
    _wave_stop(WAVE_RT_END);
}

/* 高频录波等待采集完成. */
static void _wave_wait(void)
{
    uint32_t *buf_wr = wave_ctrl.buf_wr;
    uint32_t *buf_rd = wave_ctrl.buf_rd;

    /* 采集超时. */
    if (wave_ctrl.state.timeout < HAL_GetTick())
    {
        wave_ctrl.state.state = WAVE_STATE_TIMEOUT;
        return;
    }
    
    buf_wr[0] = 0x00000000;
    buf_wr[1] = 0x00000003;
    buf_wr[2] = 0x00000000;
    buf_wr[3] = 0x00000000;
    buf_wr[4] = 0x00000000;
    
    /* 1. 查询是否有数据. */
    _wave_transmit_Receive(WAVE_READ, 0x40, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);
    //vty_print("@28: %x %d\r\n", buf_rd[3], HAL_GetTick());
    if (0x00000002 == (buf_rd[3] & 0x00000002)) // 当没有上电的时候，读出的是1
    {
        /* LoadRD1(SPI) SDR 起始地址加载. */
        buf_wr[0] = 0x00000000; // reg    0:LoadWR1  1:LoadWR2  2:LoadRD1  3:LoadRD2    15:nRstFpgaSDR
        buf_wr[1] = 0x00000000; // WR1_ADDR
        buf_wr[2] = 0x00100000; // WR1_MAX_ADDR
        buf_wr[3] = 0x00000000; // RD1_ADDR
        buf_wr[4] = 0x00100000; // RD1_MAX_ADDR
        
        buf_wr[0] = BIT15 | BIT03 | BIT02;  // reg    0:LoadWR1(SPI)  1:LoadWR2(CPU)  2:LoadRD1(SPI)  3:LoadRD2(CPU)    15:nRstFpgaSDR
        _wave_transmit_Receive(WAVE_WRITE, 0x41, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);
        HAL_Delay(1);
        _wave_transmit_Receive(WAVE_READ,  0x41, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);

        buf_wr[0] = BIT15;  // reg    0:LoadWR1(SPI)  1:LoadWR2(CPU)  2:LoadRD1(SPI)  3:LoadRD2(CPU)    15:nRstFpgaSDR
        _wave_transmit_Receive(WAVE_WRITE, 0x41, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);
        HAL_Delay(1);
        _wave_transmit_Receive(WAVE_READ,  0x41, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);

        wave_ctrl.state.state = WAVE_STATE_READ;
    }
    else
    {
        osDelay(100);
    }
}

/* 高频录波开始准备工作. */
static void _wave_start(void)
{
    uint32_t *buf_wr = wave_ctrl.buf_wr;
    uint32_t *buf_rd = wave_ctrl.buf_rd;
    uint32_t addr = WARE_ADDRESS;

    vty_print("@1: %d\r\n", HAL_GetTick());
    
    /* 先擦除 FLASH. */
    while(addr != WARE_ADDRESS_END)
    {
        if (spi_flash_erase(addr, SPI_CMD_BLOCK64_ERASE) != HAL_OK)
        {
            wave_ctrl.state.state = WAVE_STATE_ADC_ERROR;
            return;
        }
        addr += SPI_FLASH_BLOCK64_SIZE;
    }
    
    /* 开启电源, 复位 DAU 板. */
    HAL_TIM_Base_Start_IT(wave_ctrl.tim);
    HAL_GPIO_WritePin(POWER_EN_DAU_GPIO_Port, POWER_EN_DAU_Pin, GPIO_PIN_SET);
    osDelay(100);
    HAL_GPIO_WritePin(DAU_RST_GPIO_Port, DAU_RST_Pin, GPIO_PIN_RESET);
    osDelay(500);
    HAL_GPIO_WritePin(DAU_RST_GPIO_Port, DAU_RST_Pin, GPIO_PIN_SET);
    osDelay(100);

    /* 复位 SPIM. */
    buf_wr[0] = 0x12345678;
    buf_wr[1] = 0x00000000;
    buf_wr[2] = 0xffffffff;  

    /* 1. 复位 FPGA SPI-M 外设. */
    _wave_transmit_Receive(WAVE_WRITE, 0x40, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);  // 0x40: 32bit IO   ExModule0
    HAL_Delay(1);

    /* 2. 正常 FPGA SPI-M 外设. */
    /*  AdcFifoTrig
            bit1:  1:启动转换, 0:停止转换
            bit2:  1:启动转换,     0:停止转换
        EnRunFlag <= regSpiM_gRst(1); */
    buf_wr[1] = 0x00000001;  
    _wave_transmit_Receive(WAVE_WRITE, 0x40, 21, (uint8_t*)buf_wr, (uint8_t*)buf_rd);  // 0x40: 32bit IO 
    wave_ctrl.DAU_version = buf_rd[4];
    HAL_Delay(1);

    /* SDRAM 初始化   . */
    buf_wr[0] = 0x00000000;  // reg    0:LoadWR1  1:LoadWR2  2:LoadRD1  3:LoadRD2    15:nRstFpgaSDR
    buf_wr[1] = 0x00000000;  // WR1_ADDR
    buf_wr[2] = 0x00100000;  // WR1_MAX_ADDR
    buf_wr[3] = 0x00000000;  // RD1_ADDR
    buf_wr[4] = 0x00100000;  // RD1_MAX_ADDR

    _wave_transmit_Receive(WAVE_WRITE, 0x41, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);
    HAL_Delay(1);
    _wave_transmit_Receive(WAVE_READ, 0x41, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);

    buf_wr[0] = BIT15 | BIT03 | BIT02 | BIT01 | BIT00;
    _wave_transmit_Receive(WAVE_WRITE, 0x41, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);

    /* 初始化 ADC 芯片. */
    if (_wave_ADC9231_spi_init() != HAL_OK)
    {
        wave_ctrl.state.state = WAVE_STATE_ADC_ERROR;
        return;
    }

    /* DDR 延迟 1s. */
    osDelay(1000);
    
    /* SDRAM 初始化  . */
    buf_wr[0] = 0x00000000; // reg    0:LoadWR1  1:LoadWR2  2:LoadRD1  3:LoadRD2    15:nRstFpgaSDR
    buf_wr[1] = 0x00000000; // WR1_ADDR
    buf_wr[2] = 0x00100000; // WR1_MAX_ADDR
    buf_wr[3] = 0x00000000; // RD1_ADDR
    buf_wr[4] = 0x00100000; // RD1_MAX_ADDR
            
    /* SDRAM 初始化2 */
    buf_wr[0] = BIT15 | BIT03 | BIT02 | BIT01 | BIT00;  // reg    0:LoadWR1  1:LoadWR2  2:LoadRD1  3:LoadRD2    15:nRstFpgaSDR
    _wave_transmit_Receive(WAVE_WRITE, 0x41, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);   // 0x41: 32bit IO   ExModule1 
    HAL_Delay(1);
    
    buf_wr[0] = BIT15 | BIT03 | BIT02;  // reg    0:LoadWR1(SPI)  1:LoadWR2(CPU)  2:LoadRD1(SPI)  3:LoadRD2(CPU)    15:nRstFpgaSDR
    _wave_transmit_Receive(WAVE_WRITE, 0x41, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);   // 0x41: 32bit IO   ExModule1  
    HAL_Delay(1);
        
    buf_wr[0] = BIT15 | 0x0;    // reg    0:LoadWR1  1:LoadWR2  2:LoadRD1  3:LoadRD2    15:nRstFpgaSDR
    _wave_transmit_Receive(WAVE_WRITE, 0x41, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);   // 0x41: 32bit IO   ExModule1  
    HAL_Delay(1);
    osDelay(2000);

    /* 50Hz 触发允许1: 完成上次的 */
    buf_wr[0] = 0x00000000;
    buf_wr[1] = 0x00000001;
    buf_wr[2] = 0x00000000;
    buf_wr[3] = 0x00000000;
    buf_wr[4] = 0x00000000;
    _wave_transmit_Receive(WAVE_WRITE, 0x40, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);   // 0x41: 32bit IO   ExModule1  
    HAL_Delay(1);
    
    /* 50Hz 触发允许2: 开始本次的 */
    buf_wr[0] = 0x00000000;
    buf_wr[1] = 0x00000003;
    buf_wr[2] = 0x00000000;
    buf_wr[3] = 0x00000000;
    buf_wr[4] = 0x00000000;
    _wave_transmit_Receive(WAVE_WRITE, 0x40, 25, (uint8_t*)buf_wr, (uint8_t*)buf_rd);   // 0x41: 32bit IO   ExModule1  
    HAL_Delay(1);

    wave_ctrl.state.state = WAVE_STATE_WAIT;
    wave_ctrl.state.timeout = HAL_GetTick() + 5000;
}

/* 高频录波初始化. */
static void _wave_init(void)
{
    wave_ctrl.spi = &hspi1;
    wave_ctrl.tim = &htim7;
    wave_ctrl.state.state = WAVE_STATE_START;
}

/* 高频录波主任务循环. */
static void _wave_task(void *argument)
{
    /* 等待完成 1 次 ADC 采样, 因为需要根据电流电压采样结果决定是否进行录波. */
    while(1)
    {
        if (IS_MONITOR_BIT_SET(system_init_flag, SYS_INIT_ADC))
        {
            break;
        }

        osDelay(3000);
    }

    /* 初始化. */
    _wave_init();

    /* 主循环. */
    for (;;)
    {
        /* 非正常模式不录波. */
        if (ADC_ctrl.energy_mode != ADC_ENERGY_NORMAL
            || 0 == dev_config.is_wave_col
            || (ADC_ctrl.ADCi_vbat < 3600 && dev_info.type_s != DEV_TYPE_ACDC))
        {
            _wave_stop(WAVE_RT_END);
            osDelay(3000);
            continue;
        }

        /* 等待录波开始. */
        if (!st_data.wave_start)
        {
            osDelay(3000);
            continue;
        }

        /* 完成后再次采样. */
        if (wave_ctrl.time_restart < HAL_GetTick()
            && WAVE_STATE_COMPLETION == wave_ctrl.state.state)
        {
            _wave_restart();
            continue;
        }

        /* 采样过程. */
        switch(wave_ctrl.state.state)
        {
        case WAVE_STATE_START:
            _wave_start();
            break;
        case WAVE_STATE_WAIT:
            _wave_wait();
            break;
        case WAVE_STATE_READ:
            _wave_read();
            break;
        case WAVE_STATE_ADC_ERROR:
            _wave_stop(WAVE_RT_E_ADC);
            break;
        case WAVE_STATE_TIMEOUT:
            _wave_stop(WAVE_RT_E_TO);
            break;
        case WAVE_STATE_COMPLETION:
            osDelay(3000);
            break;
        default:
            _wave_stop(WAVE_RT_E_ERR);
            break;
        }
    }
}

/* Interface functions -------------------------------------------------------*/
/* 高频录波任务初始化. */
void wave_init_os(void)
{
    /* 故障定位模式不进行高频录波 */
    if (DEV_TYPE_CT_P != dev_info.type_s)
    {
        wave_ctrl.handle = osThreadNew(_wave_task, NULL, &WAVE_attributes);
    }
}

void wave_show(void)
{
    vty_print("ST  RT IN FO WS US IDX  MAXS  MINS  TIME\r\n");
    vty_print("%-03d %-02d %-02d %-02d %-02d %-02d %-04d %-05d %-05d %d\r\n\n", wave_ctrl.state.state, wave_ctrl.rt,
        dev_config.wave_interval, st_data.wave_force, st_data.wave_start, st_data.wave_up_start, st_data.wave_index,
        st_data.wave_max_save, st_data.wave_min_save, st_data.wave_time);

    vty_print("MAX1  MAX2 MAX3 MAX4\r\n");
    vty_print("%-04d %-04d %-04d %-04d\r\n\n", st_data.wave_max[0], st_data.wave_max[1], st_data.wave_max[2],
        st_data.wave_max[3]);
}
/******************* (C) COPYRIGHT LandPower ***** END OF FILE ****************/
