#include "stm32f4_discovery.h"
#include "stm32f4xx_conf.h" // again, added because ST didn't put it here ?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include "stm32f4xx_spi.h"
#include "usart.h"
#include "delay.h"

//MAX3100 spi uart

//PI2 AF5 - piny  SCK=PB10, miso=pc2, mosi=pc3, cs=pb12
void initSpi(void) {
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
    GPIO_Init(GPIOC, &GPIO_InitStruct);
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_SPI2);
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_SPI2);
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_SPI2);


    SPI_InitTypeDef SPI_InitStructure;
    SPI_I2S_DeInit(SPI2);
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; //set speed here
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_Init(SPI2, &SPI_InitStructure);

    SPI_Cmd(SPI2, ENABLE);
//	SPI_SSOutputCmd(SPI2,ENABLE);
}

u8 spi2_GetByte() {
    u32 LIS302DLTimeout = 0x1000;
    /* Wait to receive a Byte */
    while (SPI_I2S_GetFlagStatus(SPI2,  SPI_FLAG_RXNE) == RESET) {
        if((LIS302DLTimeout--) == 0) return 0x00;
    }

    /* Return the Byte read from the SPI bus */
    uint8_t r= (u8)SPI_I2S_ReceiveData(SPI2);
return r;
}


void spi2_SendByte(u8 byte) {
    u32 LIS302DLTimeout = 0x1000;

    while (SPI_I2S_GetFlagStatus(SPI2, SPI_FLAG_TXE) == RESET) {
        if((LIS302DLTimeout--) == 0) return;
    }

    /* Send a Byte through the SPI peripheral */
    SPI_I2S_SendData(SPI2, byte);
}

void spi_write(uint8_t *msg, uint8_t len, uint8_t release)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
while (SPI_I2S_GetFlagStatus(SPI2,  SPI_I2S_FLAG_RXNE) == SET) SPI_I2S_ReceiveData(SPI2); //flush rx fifo
while(len--)
        {
        spi2_SendByte(*msg);
        *msg++ = spi2_GetByte();
        }
FlagStatus s;
do {
        s= SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_BSY);
        }while(s==SET);
delay_us(3);
if(release) GPIO_SetBits(GPIOB, GPIO_Pin_12);
}


void initmax3100(void)
{
uint8_t msg[2]={0b11000000,0b00000001};

spi_write(msg,2,1);
printf("spi read %02x %02x\n",msg[0],msg[1]); //returns 0x40 0x00
}

void max3100putchar(const char c)
{
uint8_t msg;
do
	{
	msg=0b10000010;
	spi_write(&msg,1,0);
	if(msg&0x38) {printf("frame error\n"); break;}
	}
while((msg&0x40)==0);	
msg=c;
spi_write(&msg,1,1);
printf("spi read %02x\n",msg);
}


int max3100getchar(void)
{
uint8_t msg[2];
msg[0]=msg[1]=0;
spi_write(msg,2,1);
return msg[0]&0x80 ?msg[1]: -1;
}


void max3100print(const char *s)
{
while(*s) max3100putchar(*s++);
}


//@@@ switch on fifo

int main(void)
{
usart2_init(115200);
inuart2line=inuart2len=0;


print(USART2, "\nspi testik\n"); 
initSpi();
print(USART2, "spi init done\n"); 
initmax3100();
print(USART2, "max3100 init done\n"); 

while(1)
	{
	max3100print("\nPress any key: ");
	int c;
	//while((c=max3100getchar()) <0); max3100putchar(c);
	print(USART2,"done\n");
	delay_ms(1000);
	}

}


