#include <avr/io.h>
#include <util/delay.h>
#include <string.h>

#include "spi.h"
#include "bme280.h"
#include "bme280_interface.h"


void user_delay_ms(uint32_t period);
int8_t user_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len);
int8_t user_spi_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len);


struct bme280_dev deviceStructure;
uint32_t req_delay;


int8_t Initialize_BME280(void)
{
	int8_t rslt = BME280_OK;
	uint8_t settings_sel;


	Set_BME280_Pins();

	/* Sensor_0 interface over SPI with native chip select line */
	deviceStructure.dev_id = 0;
	deviceStructure.intf = BME280_SPI_INTF;
	deviceStructure.read = user_spi_read;
	deviceStructure.write = user_spi_write;
	deviceStructure.delay_ms = user_delay_ms;

	rslt = bme280_init(&deviceStructure);

	/* Settings for mode of operation: weather monitorint */
	deviceStructure.settings.osr_h = BME280_OVERSAMPLING_1X;
	deviceStructure.settings.osr_p = BME280_OVERSAMPLING_1X;
	deviceStructure.settings.osr_t = BME280_OVERSAMPLING_1X;
	deviceStructure.settings.filter = BME280_FILTER_COEFF_OFF;

	settings_sel = BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL;

	rslt = bme280_set_sensor_settings(settings_sel, &deviceStructure);

	/* calculate minimum delay required between consecutive measurments */
	req_delay = bme280_cal_meas_delay(&deviceStructure.settings);

	return rslt;
}

void Set_BME280_Pins(void)
{
	/* Setup the SPI interface */
	BME_CSN_DDR |= (1 << BME_CSN_PIN);
	BME_CSN_PORT |= (1 << BME_CSN_PIN);
}

/* Get one measurement in forced mode */
void BME280_Get_Measurement(struct bme280_data * data)
{
	memset(data, 0, sizeof(struct bme280_data));
	bme280_set_sensor_mode(BME280_FORCED_MODE, &deviceStructure);
	deviceStructure.delay_ms(req_delay);
	bme280_get_sensor_data(BME280_ALL, data, &deviceStructure);
}

/* Implementation of the interface function needed by the BME280 library */
void user_delay_ms(uint32_t period)
{
	while (period--)
	{
		_delay_ms(1);
	}
}

int8_t user_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
	int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */

	/* unused parameters */
	(void)dev_id;

	SPI_Start_Transmission(&BME_CSN_PORT, BME_CSN_PIN);
	SPI_Transfer_Byte(reg_addr);

	for (uint16_t i = 0; i < len; i ++)
	{
		reg_data[i] = SPI_Transfer_Byte(0x0); /* Value to send doesn't matter */
	}
	SPI_Stop_Transmission(&BME_CSN_PORT, BME_CSN_PIN);

	return rslt;
}

int8_t user_spi_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
	int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */

	/* unused parameters */
	(void)dev_id;

	/* SPI routine */
	SPI_Start_Transmission(&BME_CSN_PORT, BME_CSN_PIN);
	SPI_Transfer_Byte(reg_addr);

	for (uint16_t i = 0; i < len; i ++)
	{
		SPI_Transfer_Byte(reg_data[i]);
	}
	SPI_Stop_Transmission(&BME_CSN_PORT, BME_CSN_PIN);

	return rslt;
}
