/*
 * Copyright 2020-2022 Yuntu Microelectronics Co., Ltd.
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef SWSPI_DRIVER_H
#define SWSPI_DRIVER_H

#include <stddef.h>
#include <stdbool.h>
#include "status.h"
#include "device_registers.h"

/*!
 * @addtogroup swspi_driver SWSPI Driver
 * @ingroup swspi
 * @brief Software Serial Peripheral Interface Peripheral Driver
 * @{
 */


/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*!
 * @brief SWSPI pin structure
 *
 * This structure is used to provide configuration parameters for pins used for swspi driver.
 * Implements : swspi_pin_t_Class
 */
typedef struct
{
    uint16_t pinNumber;
    GPIO_Type *port;
} swspi_pin_t;

/*! @brief SWSPI Signal (PCS and Host Request) Polarity configuration.
 * Implements : swspi_signal_polarity_t_Class
 */
typedef enum
{
    SWSPI_ACTIVE_HIGH = 1U, /*!< Signal is Active High (idles low). */
    SWSPI_ACTIVE_LOW = 0U  /*!< Signal is Active Low (idles high). */
} swspi_signal_polarity_t;

/*! @brief SWSPI clock phase configuration.
 * Implements : swspi_clock_phase_t_Class
 */
typedef enum
{
    SWSPI_CLOCK_PHASE_1ST_EDGE = 0U, /*!< Data captured on SCK 1st edge, changed on 2nd. */
    SWSPI_CLOCK_PHASE_2ND_EDGE = 1U  /*!< Data changed on SCK 1st edge, captured on 2nd. */
} swspi_clock_phase_t;

/*! @brief SWSPI Clock Signal (SCK) Polarity configuration.
 * Implements : swspi_sck_polarity_t_Class
 */
typedef enum
{
    SWSPI_SCK_ACTIVE_HIGH = 0U, /*!< Signal is Active High (idles low). */
    SWSPI_SCK_ACTIVE_LOW = 1U  /*!< Signal is Active Low (idles high). */
} swspi_sck_polarity_t;

/*!
 * @brief Data structure containing information about a device on the SPI bus.
 *
 * The user must populate these members to set up the SWSPI master and
 * properly communicate with the SPI device.
 * Implements : spi_master_config_t_Class
 */
typedef struct
{
    uint32_t bitsDelay;                         /*!< Bits delay Cycles*/
    swspi_signal_polarity_t pcsPolarity;        /*!< PCS polarity */
    bool isPcsContinuous;                       /*!< Keeps PCS asserted until transfer complete */
    uint16_t bitcount;                          /*!< Number of bits/frame, minimum is 8-bits */
    swspi_clock_phase_t clkPhase;               /*!< Selects which phase of clock to capture data */
    swspi_sck_polarity_t clkPolarity;           /*!< Selects clock polarity */
    bool lsbFirst;                              /*!< Option to transmit LSB first */
    swspi_pin_t *sdiPin;
    swspi_pin_t *sdoPin;
    swspi_pin_t *sckPin;
    swspi_pin_t *pcsPin;
} swspi_master_config_t;

/*!
 * @brief Runtime state structure for the SWSPI master driver.
 *
 * This structure holds data that is used by the SPI peripheral driver to
 * communicate between the transfer function and the interrupt handler. The
 * interrupt handler also uses this information to keep track of its progress.
 * The user must pass  the memory for this run-time state structure. The
 * SPI master driver populates the members.
 * Implements : swspi_state_t_Class
 */
typedef struct
{
/*! @cond DRIVER_INTERNAL_USE_ONLY */
    uint32_t bitsDelay;                     /*!< Bits delay Cycles*/
    swspi_signal_polarity_t pcsPolarity;    /*!< PCS polarity */
    bool isPcsContinuous;                   /*!< Keeps PCS asserted until transfer complete */
    uint16_t bitcount;                      /*!< Number of bits/frame, minimum is 8-bits */
    swspi_clock_phase_t clkPhase;           /*!< Selects which phase of clock to capture data */
    swspi_sck_polarity_t clkPolarity;       /*!< Selects clock polarity */
    bool lsbFirst;                          /*!< Option to transmit LSB first */
    swspi_pin_t *sdiPin;
    swspi_pin_t *sdoPin;
    swspi_pin_t *sckPin;
    swspi_pin_t *pcsPin;
    volatile status_t status;                   /* Status of last driver operation */
} spi_state_t;

/*******************************************************************************
 * API
 ******************************************************************************/

#if defined(__cplusplus)
extern "C" {
#endif


/*!
 * @name Blocking transfers
 * @{
 */

/*!
 * @brief Performs an interrupt driven blocking SWSPI master mode transfer.
 *
 * This function simultaneously sends and receives data on the SPI bus, as SPI is naturally
 * a full-duplex bus. The function does not return until the transfer is complete.
 * This function allows the user to optionally pass in a SPI configuration structure which
 * allows the user to change the SPI bus attributes in conjunction with initiating a SPI transfer.
 * The difference between passing in the SPI configuration structure here as opposed to the
 * configure bus function is that the configure bus function returns the calculated baud rate where
 * this function does not. The user can also call the configure bus function prior to the transfer
 * in which case the user would simply pass in a NULL to the transfer function's device structure
 * parameter.
 * Depending on frame size sendBuffer and receiveBuffer must be aligned like this:
 * -1 byte if frame size <= 8 bits 
 * -2 bytes if 8 bits < frame size <= 16 bits 
 * -4 bytes if 16 bits < frame size   
 *
 * @param spiConfig The data structure containing information about a device on the SWSPI bus
 * @param sendBuffer The pointer to the data buffer of the data to send. You may pass NULL for this
 *  parameter and  bytes with a value of 0 (zero) is sent.
 * @param receiveBuffer Pointer to the buffer where the received bytes are stored. If you pass NULL
 *  for this parameter, the received bytes are ignored.
 * @param transferByteCount The number of bytes to send and receive which is equal to size of send or receive buffers
 * @return STATUS_SUCCESS The transfer was successful, or
 *         STATUS_ERROR Cannot perform transfer
 */
status_t SWSPI_DRV_MasterTransferBlocking(const swspi_master_config_t *spiConfig,
                                          const uint8_t *sendBuffer,
                                          uint8_t *receiveBuffer,
                                          uint16_t transferByteCount);

/*@}*/


#if defined(__cplusplus)
}
#endif

/*! @}*/


#endif /* __SWSPI_MASTER_DRIVER_H__*/
/*******************************************************************************
 * EOF
 ******************************************************************************/
