/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2023. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */
/******************************************************************************
 * @version: V1.0.0 demo
 ******************************************************************************/

/*!
* @file spi.c
*
* @brief This file contains the user spi function..
*
*/

/* ===========================================  Includes  =========================================== */
#include "gpio.h"
#include "spi.h"
#include "ac780x_spi.h"
#include "ac780x_spi_reg.h"

/* ============================================  Define  ============================================ */
#define SPI_DATA_LEN    8u /* In the full-duplex mode of SPI, the data length of TX and RX must be the same */

/* ===========================================  Typedef  ============================================ */

/* ==========================================  Variables  =========================================== */
uint32_t g_spiMasterRequest = 0;            /* Master request communication flag */
uint32_t g_spiSlaveAck = 0;                 /* Slave response communication flag */

uint8_t rxBuff[SPI_DATA_LEN] = {0};    /* SPI1 receive array */
uint8_t txBuff[SPI_DATA_LEN] = {0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55};  /* SPI1 send array */

/* ====================================  Functions declaration  ===================================== */

/* ======================================  Functions define  ======================================== */

/*!
* @brief  spi call back fun
*
* @param[in] none
* @return none
*/
void SPI1_Callback(void *device, uint32_t wpara, uint32_t lpara)
{
    if (wpara & SPI_STATUS_TXUF_Msk)
    {
        /* Software Reset SPI */
        SPI_SoftwareReset(SPI1);
    }
    if (wpara & SPI_STATUS_RXOF_Msk)
    {
        /* Software Reset SPI */
        SPI_SoftwareReset(SPI1);
    }
}

/*!
* @brief  SPI master and slave test
*
* @param[in] none
* @return none
*/
void Spi1_SlaveTest(void)
{
    ERROR_Type ret = ERROR;

    if(g_spiMasterRequest == 1)
    {
        txBuff[0]++;
        ret = SPI_TransmitReceiveInt(SPI1, rxBuff, txBuff, 8);
        if(SUCCESS == ret)
        {
            /* Pull high slave ready to receive pin*/
            GPIO_SetPinLevel(GPIOC , GPIO_PIN10, GPIO_LEVEL_HIGH);
            
            /* Wait SPI receive(interrupt mode) finish */
            ret = SPI_WaitReceiveFinish(SPI1);
            
            /* Pull down slave ready to receive pin*/
            GPIO_SetPinLevel(GPIOC , GPIO_PIN10, GPIO_LEVEL_LOW);
            if(ERROR == ret)
            {
                printf("Rx ERROR\r\n ");
            }
            else
            {
                printf("SPI rx data = 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X ",
                    rxBuff[0], rxBuff[1], rxBuff[2], rxBuff[3], rxBuff[4], rxBuff[5], rxBuff[6], rxBuff[7]);
            }
        }
        else
        {
            printf("ERROR\r\n ");
        }
        g_spiMasterRequest = 0;
    }
}



void GPIOC_11_Callback(void *device, uint32_t wpara, uint32_t lpara)
{
    /* Check whether the interrupt is caused by the host requesting the communication pin */
    if(GPIO_GetPinLevel(GPIOC, GPIO_PIN11) == GPIO_LEVEL_HIGH)
     {
        if(g_spiMasterRequest == 0)
        {
            g_spiMasterRequest = 1;
        }
    }
}
 
 /*!
* @brief  Init spi1 pin
*
* @param[in] none
* @return none
*/
void Spi1_Gpio_Init(void)
{
    GPIO_SetFunc(GPIOC, GPIO_PIN10, GPIO_FUN0);     /* Slave communication feedback pin */
    GPIO_SetDir(GPIOC, GPIO_PIN10, GPIO_OUT);
    GPIO_SetPinLevel(GPIOC , GPIO_PIN10, GPIO_LEVEL_LOW);
    
    GPIO_SetFunc(GPIOC, GPIO_PIN11, GPIO_FUN0);      /* Master initiates communication pin */
    GPIO_SetDir(GPIOC, GPIO_PIN11, GPIO_IN);
    GPIO_SetPulldown(GPIOC, GPIO_PIN11, ENABLE);
    GPIO_EnableExtInterrupt(GPIOC, GPIO_PIN11, EXTI_TRIGGER_RISING);
    GPIO_SetCallback(GPIO_PIN11, GPIOC_11_Callback);
    
    GPIO_SetFunc(GPIOB, GPIO_PIN12, GPIO_FUN3);     /* SCK */
    GPIO_SetFunc(GPIOB, GPIO_PIN11, GPIO_FUN3);     /* MOSI */
    GPIO_SetFunc(GPIOC, GPIO_PIN1, GPIO_FUN3);      /* CS */
    GPIO_SetFunc(GPIOC, GPIO_PIN0, GPIO_FUN3);      /* MISO */  
}


/*!
* @brief  Init spi
*
* @param[in] none
* @return none
*/
void Spi1_Init(void)
{
    SPI_ConfigType spi_config_t;
    
    memset(&spi_config_t, 0x00, sizeof(spi_config_t));
    
    /* The baud rate of SPI is 1Mhz */
    spi_config_t.csSetup = 20;   /* Chip Select Setup Time  = (CS_SETUP + 1) * CLK_PERIOD. */
    spi_config_t.csHold  = 20;   /* Chip Select Hold Time = (CS_HOLD + 1) * CLK_PERIOD. */
    spi_config_t.sckHigh = 15;   /* SCK clock high time= (SCK_HIGH + 1) * CLK_PERIOD. */
    spi_config_t.sckLow  = 15;   /* SCK clock low time = (SCK_LOW + 1) * CLK_PERIOD. */
    spi_config_t.csIdle  = 20;   /* CS free time = (CS_IDLE + 1) * CLK_PERIOD. */
    spi_config_t.mode      = SPI_SLAVE;        /* set master */
    spi_config_t.cpha      = SPI_CPHA_1EDGE;    /* second edge sampling */
    spi_config_t.cpol      = SPI_CPOL_LOW;     /* SCK active high */
    spi_config_t.frmSize   = SPI_FRAME_SIZE_8BITS;  /* transfer byte width 8bits */
    spi_config_t.rxMsbFirstEn      = ENABLE;    /* RX MSB */
    spi_config_t.txMsbFirstEn      = ENABLE;    /* TX MSB */
    spi_config_t.csOutputEn        = ENABLE;    /* CS is hardware control */
    spi_config_t.continuousCSEn    = ENABLE;    /* CS is continuous mode */
    spi_config_t.dmaRxEn       = DISABLE;   /* RX DMA disable */
    spi_config_t.dmaTxEn       = DISABLE;   /* TX DMA disable */
    spi_config_t.modeFaultEn   = DISABLE;   /* Fault detection mode disable*/
    spi_config_t.wakeUpEn      = DISABLE;   /* wake up disable */
    spi_config_t.spiEn         = ENABLE;    /* Spi enable */
    spi_config_t.callBack      = SPI1_Callback;      /* call back fun */
    spi_config_t.interruptEn   = ENABLE;   /* interrupt enable */
    spi_config_t.txUFInterruptEn       = ENABLE;   /* TX buffer underflow interrupt enable */
    spi_config_t.rxOFInterruptEn       = ENABLE;   /* RX buffer overflow interrupt enable */
    spi_config_t.modeFaultInterruptEn = DISABLE;    /* Mode Fault Interrupt disable */
    
    SPI_Init(SPI1, &spi_config_t);  /* spi initialization */
    Spi1_Gpio_Init();               /* spi Pin initialization */
}





/* =============================================  EOF  ============================================== */
