#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"

//MPL115A barometer

//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)
{
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);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
}


void read_pt(uint16_t *p, uint16_t *t)
{
uint8_t msg1[3] = {0x24,0,0};
spi_write(msg1,2);
//printf("msg1 %d %d %d\n",msg1[0],msg1[1],msg1[2]);
delay_ms(10);
uint8_t msg2[8] = {0x80,0,0x82,0,0x84,0,0x86,0};
spi_write(msg2,8);
//printf("msg2 %d %d %d %d\n",msg2[1],msg2[3],msg2[5],msg2[7]);
*p = msg2[1]<<2 | msg2[3]>>6;
*t = msg2[5]<<2 | msg2[7]>>6;
}


void read_coefs(float *a0, float *b1, float *b2, float *c12)
{
uint8_t msg2[16] = {0x88,0,0x8A,0,0x8C,0,0x8E,0,0x90,0,0x92,0,0x94,0,0x96,0};
spi_write(msg2,16);
int16_t raw = msg2[1]; raw<<=8; raw|=msg2[3]; 
*a0 = raw/8.;
raw = msg2[5]; raw<<=8; raw|=msg2[7];
*b1 = raw/8192.;
raw = msg2[9]; raw<<=8; raw|=msg2[11];
*b2 = raw/16384.;
raw = msg2[13]; raw<<=8; raw|=msg2[15];
*c12 = raw/16777216.;
}
                

float pressure(float a0, float b1, float b2, float c12, uint16_t nrep)
{
uint16_t i;
float pres=0.;
for(i=0; i<nrep; ++i)
	{
	uint16_t p,t;
	read_pt(&p,&t);
	//printf("p %d t %d\n",p,t);
        float pcomp = a0 + (b1 + c12*t)*p + b2*t;
        //printf("pcomp %g\n",pcomp);
        pres += pcomp;
	}
return pres/nrep*(115.-50.)/1023.+50.;
}


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


RCC_ClocksTypeDef RCC_ClocksStatus;

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

float a0,b1,b2,c12;
read_coefs(&a0,&b1,&b2,&c12);
printf("a0=%g, b1=%g, b2=%g, c12=%g\n",a0,b1,b2,c12);

while(1)
	{
	printf("pressure= %g kPa\n",pressure(a0,b1,b2,c12,256));
	delay_ms(1000);
	}

}


