#include "stm32l0xx_hal.h"
#include "lt8920_trs.h"
#include "stm32l0xx_nucleo.h"
#include <stdio.h>

SPI_HandleTypeDef SpiHandle;


//
void lt_init(void)
{
    lt_gpio_init();
    
    lt_spi_gpio_init();
    
    lt_spi_init();
}

//
void lt_spi_init(void)
{
    __HAL_RCC_SPI2_CLK_ENABLE();
    
    SpiHandle.Instance               = SPI2;
    SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
    SpiHandle.Init.Direction         = SPI_DIRECTION_2LINES;
    SpiHandle.Init.CLKPhase          = SPI_PHASE_1EDGE;
    SpiHandle.Init.CLKPolarity       = SPI_POLARITY_HIGH;
    SpiHandle.Init.CRCCalculation    = SPI_CRCCALCULATION_DISABLE;
    SpiHandle.Init.CRCPolynomial     = 7;
    SpiHandle.Init.DataSize          = SPI_DATASIZE_8BIT;
    SpiHandle.Init.FirstBit          = SPI_FIRSTBIT_MSB;
    SpiHandle.Init.NSS               = SPI_NSS_SOFT;
    SpiHandle.Init.TIMode            = SPI_TIMODE_DISABLE;
    SpiHandle.Init.Mode = SPI_MODE_MASTER;

    HAL_SPI_Init(&SpiHandle);
    
    __HAL_SPI_ENABLE(&SpiHandle);
      
}

//
void lt_gpio_init(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    
    __HAL_RCC_GPIOB_CLK_ENABLE();
        
    // LT8920 Reset pin PB2
    GPIO_InitStruct.Pin       = GPIO_PIN_2;
    GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull      = GPIO_PULLUP;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
    // LT8920 PKT pin PB12
    GPIO_InitStruct.Pin       = GPIO_PIN_12;
    GPIO_InitStruct.Mode      = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull      = GPIO_PULLUP;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

//
void lt_spi_gpio_init(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    
    __HAL_RCC_GPIOB_CLK_ENABLE();
    
    // SPI SCK PB_13
    GPIO_InitStruct.Pin       = GPIO_PIN_13;
    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull      = GPIO_PULLUP;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH  ;
    GPIO_InitStruct.Alternate = GPIO_AF0_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
    // SPI MISO PB14
    GPIO_InitStruct.Pin = GPIO_PIN_14;
    GPIO_InitStruct.Alternate = GPIO_AF0_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  
    // SPI MOSI PB15
    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Alternate = GPIO_AF0_SPI2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
    // SPI CS PB1
    GPIO_InitStruct.Pin       = GPIO_PIN_1;
    GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull      = GPIO_PULLUP;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH  ;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
 
//
uint16_t lt_spi_transfer_byte(uint8_t byte)
{
    while (__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_TXE) != SET) {}
    SpiHandle.Instance->DR = (uint16_t)byte;
  
    while (__HAL_SPI_GET_FLAG(&SpiHandle, SPI_FLAG_RXNE) != SET) {}
    return SpiHandle.Instance->DR;
}


// -------------------------------------------------------------------------- //

//
void lt_spi_test(void)
{
    uint8_t tx_buf[12] = "hello world";
    uint8_t rx_buf[12] = {0};
    
    if (HAL_SPI_TransmitReceive(&SpiHandle, tx_buf, rx_buf, 11, 1000) != HAL_OK) 
    {
        printf("[SPI] tx/rx error\r\n");
        BSP_LED_On(LED2);
    }
    else 
    {
        printf("[SPI] rx: %s\r\n", rx_buf);
        printf("[SPI] tx/rx OK\r\n");
        BSP_LED_Toggle(LED2);
    }
}