#include "at32f403a_407.h"
#include "shift_reg.h"
#include "FreeRTOS.h"
#include "task.h"
#include "misc.h"
#include <stdio.h>
#include <stdbool.h>


#define SH_SPI  SPI2


// PD1 -  ART_nCS_LS_CH16/DAC2
// PC10 - ART_CLK_LS (SPI3_CK remap)
// PC11 - ART_MISO_CH16/CS_LS (SPI3_MISO remap)
// PC12 - ART_MOSI_LS (SPI3_MOSI remap)


// PD0 - ART_nCS_LS_CH712/DAC3
// PD2 - ART_MISO_CH712

void sh_init(void)
{
    spi_init_type spi_init_struct;
    gpio_init_type gpio_initstructure;
    
  
    crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
    
    // SCK
    gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;  
    gpio_initstructure.gpio_pull           = GPIO_PULL_DOWN;  
    gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;  
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_initstructure.gpio_pins           = GPIO_PINS_13;
    gpio_init(GPIOB, &gpio_initstructure);
  
    // MISO
    gpio_initstructure.gpio_pull           = GPIO_PULL_UP;  
    gpio_initstructure.gpio_mode           = GPIO_MODE_INPUT;  
    gpio_initstructure.gpio_pins           = GPIO_PINS_14;
    gpio_init(GPIOB, &gpio_initstructure);
    
    // MOSI
    gpio_initstructure.gpio_pull           = GPIO_PULL_UP;  
    gpio_initstructure.gpio_mode           = GPIO_MODE_MUX; 
    gpio_initstructure.gpio_pins           = GPIO_PINS_15;
    gpio_init(GPIOB, &gpio_initstructure);

    // CS
    // Эти два CS управляют двумя парами регистров
    gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;  
    gpio_initstructure.gpio_pull           = GPIO_PULL_NONE;  
    gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;  
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    
#if defined (MAI_12)        
    gpio_initstructure.gpio_pins           = GPIO_PINS_0 | GPIO_PINS_1;
    gpio_init(GPIOD, &gpio_initstructure); 
    
    // CS для сдвигового регистра U1010 -> MUX301, MUX401
    gpio_initstructure.gpio_pins           = GPIO_PINS_3;
    gpio_init(GPIOD, &gpio_initstructure); 
        
    gpio_bits_reset(GPIOD, GPIO_PINS_0 | GPIO_PINS_1 | GPIO_PINS_3);
#endif
    
#if defined (MAO_4)
    // CS для сдвиговых регистров U860, U861
    gpio_initstructure.gpio_pins           = GPIO_PINS_11;
    gpio_init(GPIOC, &gpio_initstructure); 
        
    gpio_bits_reset(GPIOC, GPIO_PINS_11);
    
#endif     
    
    crm_periph_clock_enable(CRM_SPI2_PERIPH_CLOCK, TRUE);
    
    spi_default_para_init(&spi_init_struct);
    spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
    spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
    spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_32;
    spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
    spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
    spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;//SPI_CLOCK_POLARITY_LOW;
    spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;
    spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
    
    spi_init(SH_SPI, &spi_init_struct);
 
    spi_hardware_cs_output_enable(SH_SPI, FALSE);
    
    spi_enable(SH_SPI, TRUE);
}

// Установка сигналов EN_CRNT_SNS_1..EN_CRNT_SNS_12 (режим измерения тока или напряжения)
// Получение сигналов ALRM_IN_1..ALRM_IN_12
uint16_t sh_ai_mode(uint16_t val)
{
    uint16_t ret = 0;

    // Данные отправлеяются во второй регистр U402
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_TDBE_FLAG) == RESET);
    SH_SPI->dt = (0x003F) & (val >> 8);

    // Данные из второго регистра U400
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_RDBF_FLAG) == RESET);
    ret = (SH_SPI->dt & 0x3F) << 6;

    // Данные отправлеяются во второй регистр U302
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_TDBE_FLAG) == RESET);
    SH_SPI->dt = (0x003F) & val;

    // Данные из первого регистра U300
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_RDBF_FLAG) == RESET);
    ret |= SH_SPI->dt & 0x3F;

    gpio_bits_set(GPIOD, GPIO_PINS_0);
    nop(5);
    gpio_bits_reset(GPIOD, GPIO_PINS_0);
    nop(5);
    
    vTaskDelay(1);
    
    // Данные отправлеяются во второй регистр U402
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_TDBE_FLAG) == RESET);
    SH_SPI->dt = (0x003F) & (val >> 8);
  
    // Данные из второго регистра U400
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_RDBF_FLAG) == RESET);
    ret = (SH_SPI->dt & 0x3F) << 6;
    
    // Данные отправлеяются во второй регистр U302
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_TDBE_FLAG) == RESET);
    SH_SPI->dt = (0x003F) & val;
  
    // Данные из первого регистра U300
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_RDBF_FLAG) == RESET);
    ret |= SH_SPI->dt & 0x3F;

    gpio_bits_set(GPIOD, GPIO_PINS_0);
    nop(5);
    gpio_bits_reset(GPIOD, GPIO_PINS_0);
    nop(5);
   
    //printf("SH return: %X\r\n", ret);
    
    return ret;    
}


//
// Установка сигналов EN_CRNT_SNS_1..EN_CRNT_SNS_12 (режим измерения тока или напряжения)
// Получение сигналов ALRM_IN_1..ALRM_IN_12
uint16_t sh_ai_mode_two(uint16_t val, uint8_t ch_1, uint8_t ch_2)
{
    uint16_t ret = 0;

    // Данные отправлеяются во второй регистр U402
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_TDBE_FLAG) == RESET);
    SH_SPI->dt = ((0x003F) & (val >> 8)) | (ch_2 << 6);

    // Данные из второго регистра U400
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_RDBF_FLAG) == RESET);
    ret = (SH_SPI->dt & 0x3F) << 6;

    // Данные отправлеяются во второй регистр U302
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_TDBE_FLAG) == RESET);
    SH_SPI->dt = ((0x003F) & val) | (ch_1 << 6);

    // Данные из первого регистра U300
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_RDBF_FLAG) == RESET);
    ret |= SH_SPI->dt & 0x3F;

    gpio_bits_set(GPIOD, GPIO_PINS_0);
    nop(5);
    gpio_bits_reset(GPIOD, GPIO_PINS_0);
    nop(5);
    
    vTaskDelay(1);
    
    // Данные отправлеяются во второй регистр U402
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_TDBE_FLAG) == RESET);
    SH_SPI->dt = ((0x003F) & (val >> 8)) | (ch_2 << 6);
  
    // Данные из второго регистра U400
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_RDBF_FLAG) == RESET);
    ret = (SH_SPI->dt & 0x3F) << 6;
    
    // Данные отправлеяются во второй регистр U302
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_TDBE_FLAG) == RESET);
    SH_SPI->dt = ((0x003F) & val) | (ch_1 << 6);
  
    // Данные из первого регистра U300
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_RDBF_FLAG) == RESET);
    ret |= SH_SPI->dt & 0x3F;

    gpio_bits_set(GPIOD, GPIO_PINS_0);
    nop(5);
    gpio_bits_reset(GPIOD, GPIO_PINS_0);
    nop(5);
   
    //printf("SH return: %X\r\n", ret);
    
    return ret;    
}


//
uint16_t sh_ao_mode(uint16_t val)
{
    uint16_t ret = 0;
    
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_TDBE_FLAG) == RESET);
    SH_SPI->dt = val;
    
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_RDBF_FLAG) == RESET);
    ret = (uint16_t)SH_SPI->dt & 0x0F;
      
    
    gpio_bits_set(GPIOC, GPIO_PINS_11);
    nop(5);
    gpio_bits_reset(GPIOC, GPIO_PINS_11);
    nop(5);
    
    return ret;
}


// Подключает выбранный канал к АЦП
void sh_ai_connect(uint16_t val)
{
    uint16_t ret;
    
    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_TDBE_FLAG) == RESET);
    SH_SPI->dt = val;

    while (spi_i2s_flag_get(SH_SPI, SPI_I2S_RDBF_FLAG) == RESET);
    ret = SH_SPI->dt;
    
    gpio_bits_set(GPIOD, GPIO_PINS_3);
    nop(5);
    gpio_bits_reset(GPIOD, GPIO_PINS_3);
}

//
void sh_delay(void)
{
    for (unsigned int i = 0; i < 1; i++) {}
}