/*
 * hal_SPI.c
 *
 *  Created on: Nov 12, 2011
 *      Author: RomanM
 */

#include "stm32f10x.h"
#include "hal_SPI.h"

void hal_SPI_Init(SPI_TypeDef *SPIx) {
	hal_SPI_RCC_Config(SPIx);
	hal_SPI_GPIO_Config(SPIx);
	hal_SPI_Config(SPIx);
}

void hal_SPI_Config(SPI_TypeDef *SPIx) {
	SPI_InitTypeDef SPI_InitStructure;

	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
	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_4;
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
	SPI_Init(SPIx, &SPI_InitStructure);

	SPI_Cmd(SPIx, ENABLE);
}

void hal_SPI_GPIO_Config(SPI_TypeDef *SPIx) {
	GPIO_InitTypeDef GPIO_InitStructure;

	if (SPIx == SPI1) {
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_5;	// MOSI and SCK
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;			// Alternative function push-pull
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOA, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;				// MISO pin
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;			// Input pull-up
		GPIO_Init(GPIOA, &GPIO_InitStructure);
	}
	else if (SPIx == SPI2) {
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;	// MOSI and SCK
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;				// Alternative function push-pull
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOB, &GPIO_InitStructure);

		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;			// MISO pin
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;		// Input pull-up
		GPIO_Init(GPIOB, &GPIO_InitStructure);
	}
}

void hal_SPI_RCC_Config(SPI_TypeDef *SPIx) {
	if (SPIx == SPI1) {
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
	}
	else if (SPIx == SPI2) {
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
	}
}

uint8_t hal_SPI_RW(SPI_TypeDef *SPIx, uint8_t data) {
	while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
	SPI_I2S_SendData(SPIx, data);
	while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
	return (uint8_t)SPI_I2S_ReceiveData(SPIx);
}

void hal_SPI_WriteN(SPI_TypeDef *SPIx, uint8_t *outBuff, uint8_t n) {
	while (n--) hal_SPI_RW(SPIx, *(outBuff++));
}

void hal_SPI_ReadN(SPI_TypeDef *SPIx, uint8_t *inBuff, uint8_t n) {
	while (n--) *(inBuff++) = hal_SPI_RW(SPIx, 0);
}
