#include "omw_config.h"
#include "omw_dbg.h"
#include "omw_uart.h"
#include "periph_uart.h"
#include "periph_gpio.h"
#include "periph_spim.h"
#include "periph_gpadc.h"

#define SPI_BYTE_NUM 4


GPIO_InitTypeDef GPIO_InitStruct;
int main(void) {
    int i;
    uint8_t rbuf[SPI_BYTE_NUM], tbuf[SPI_BYTE_NUM];

    SPIM_InitTypeDef SPIM_InitStruct;

    //---------------------------------------
    // init
    //---------------------------------------
    omw_dbg_init();
    printf("SPI master 4-wire half-duplex test ...\n");
    for(i=0; i<SPI_BYTE_NUM; i++){
        rbuf[i] = 0;
        tbuf[i] = 0x11 + i;
    }

    //---------------------------------------
    // SPIM1 GPIO configuration, GPIO[5]: NCS, GPIO[4]: TXD, GPIO[6]: MOSI, GPIO[7]: MISO
    //---------------------------------------
    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_DriveStrength = GPIO_DRIVE_STRENGTH_3;
    GPIO_InitStruct.GPIO_Pin = GPIO_PIN_5;
    GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IN_FLOATING;
    GPIO_InitStruct.GPIO_AltFunc = OMW_GPIO5_GPIO;
    GPIO_Init(&GPIO_InitStruct);
    GPIO_OutputCMD(GPIO_PIN_5, ENABLE);
    GPIO_WriteBit(GPIO_PIN_5, HIGH); // NCS high
    GPIO_InitStruct.GPIO_Pin = GPIO_PIN_4;
    GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IN_FLOATING;
    GPIO_InitStruct.GPIO_AltFunc = OMW_GPIO4_SPIM1_SCK;
    GPIO_Init(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin = GPIO_PIN_6;
    GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IN_FLOATING;
    GPIO_InitStruct.GPIO_AltFunc = OMW_GPIO6_SPIM1_MOSI;
    GPIO_Init(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin = GPIO_PIN_7;
    GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IPD;
    GPIO_InitStruct.GPIO_AltFunc = OMW_GPIO7_SPIM1_MISO;
    GPIO_Init(&GPIO_InitStruct);
    
    //KEY
    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin = GPIO_PIN_3;
    GPIO_InitStruct.GPIO_Mode = GPIO_MODE_IPU;
    GPIO_InitStruct.GPIO_AltFunc = OMW_GPIO3_GPIO;
    GPIO_Init(&GPIO_InitStruct);

    //---------------------------------------
    // SPIM1 configuration
    //---------------------------------------
    // de-init
    SPIM_Cmd(SPIM1, DISABLE);
    SPIM_DeInit(SPIM1);
    // init
    SPIM_StructInit(&SPIM_InitStruct);
    SPIM_InitStruct.SPIM_Direction = SPIM_DIRECTION_TX_AND_RX;
    SPIM_InitStruct.SPIM_SCPOL = SPIM_SCPOL_LOW;
    SPIM_InitStruct.SPIM_SCPH = SPIM_SCPH_MIDDLE;
    SPIM_InitStruct.SPIM_BaudRatePrescaler = 0x08;
    SPIM_InitStruct.SPIM_RxFIFOThreshold = 0x08;
    SPIM_InitStruct.SPIM_TxFIFOThreshold = 0x08;
    SPIM_InitStruct.SPIM_Wires = SPIM_WIRES_4;
    SPIM_Init(SPIM1, &SPIM_InitStruct);
    SPIM_ITConfig(SPIM1, SPIM_IT_ALL, DISABLE);
    SPIM_Cmd(SPIM1, ENABLE);

    //---------------------------------------
    // SPI master send N bytes
    //---------------------------------------
    //spim switch tx only
    /**/
    SPIM_Cmd(SPIM1, DISABLE);
    /**/
    SPIM_Direction_Switch(SPIM1, SPIM_DIRECTION_TX_ONLY);
    /**/
    SPIM_Cmd(SPIM1, ENABLE);
    //wait key
    while(GPIO_ReadInputDataBit(GPIO_PIN_3)==SET);
    // ncs=0
    GPIO_WriteBit(GPIO_PIN_5, LOW);
    // loop
    for(i=0; i<SPI_BYTE_NUM; i++) {
        // wait fifo
        while((SPIM_GetUsrStatus(SPIM1, SPIM_FLAG_TRANSMIT_FIFO_NOT_FULL)) == RESET); // if tx fifo full, wait here
        // send data byte
        SPIM_SendData(SPIM1, tbuf[i]);
    }
    // wait send finish
    while(SPIM_GetUsrStatus(SPIM1, SPIM_FLAG_BUSY)==SET);
    // ncs=1
    GPIO_WriteBit(GPIO_PIN_5, HIGH);
    //wait spis direction switch finish
    DELAY_US(2000);
    //---------------------------------------
    // SPI master receive N bytes
    //---------------------------------------
    //spim switch rx only
    /**/
    SPIM_Cmd(SPIM1, DISABLE);
    /**/
    SPIM_Direction_Switch(SPIM1, SPIM_DIRECTION_RX_ONLY);
    /**/
    SPIM_RecviveLengthConfig(SPIM1,4);
    /**/
    SPIM_Cmd(SPIM1, ENABLE);
    // ncs=0
    GPIO_WriteBit(GPIO_PIN_5, LOW);
    //spim receive trigger
    SPIM_SendData(SPIM1, 0x11);
    // loop
    for(i=0; i<SPI_BYTE_NUM; i++) {  
        while((SPIM_GetUsrStatus(SPIM1, SPIM_FLAG_RECEIVE_FIFO_NOT_EMPTY)) == RESET); // if rx fifo empty, wait here
        // receive data byte
        rbuf[i] = SPIM_ReceiveData(SPIM1);
    }
    // ncs=1
    GPIO_WriteBit(GPIO_PIN_5, HIGH);


    //---------------------------------------
    // DELAY
    //---------------------------------------
    DELAY_US(2000);

    //---------------------------------------
    // Display
    //---------------------------------------
    // send data bytes
    printf("    Send Data: ");
    for(i=0; i<SPI_BYTE_NUM; i++) printf("0x%02x ", tbuf[i]);
    printf("\n");
    // recv data bytes
    printf("    Recv Data: ");
    for(i=0; i<SPI_BYTE_NUM; i++) printf("0x%02x ", rbuf[i]);
    printf("\n");
    // end of test
    while(1);
    return 0;
}

