/*
 * Copyright (c) 2016, 2018, Sascha Schade
 * Copyright (c) 2017, Niklas Hauser
 *
 * This file is part of the modm project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
// ----------------------------------------------------------------------------

#include <inttypes.h>
#include <modm/board.hpp>
#include <modm/debug/logger.hpp>

#include "thread_bme280.hpp"

// ----------------------------------------------------------------------------
// Set the log level
#undef	MODM_LOG_LEVEL
#define	MODM_LOG_LEVEL modm::log::INFO

// ----------------------------------------------------------------------------
Bme280Thread::Bme280Thread() :
	Fiber([this] { this->update(); }),
	barometerA(dataA, 0x76),
	barometerB(dataB, 0x76),
	start_measurement(false),
	new_data(false)
{
}

bool
Bme280Thread::startMeasurement()
{
	start_measurement = true;
	new_data = false;
	return true;
}

void
Bme280Thread::update()
{
	MODM_LOG_DEBUG << MODM_FILE_INFO;
	MODM_LOG_DEBUG << "Ping the BME280" << modm::endl;

	// ping the device until it responds
	while(true)
	{
		// we wait until the task started
		if (barometerA.ping())
			break;
		// otherwise, try again in 100ms
		modm::this_fiber::sleep_for(100ms);
	}

	while(true)
	{
		// we wait until the task started
		if (barometerB.ping())
			break;
		// otherwise, try again in 100ms
		modm::this_fiber::sleep_for(100ms);
	}

	// stream << "Barometer BME280 responded" << modm::endl;

	// Configure the device until it responds
	while(true)
	{
		// we wait until the task started
		if (barometerA.initialize())
			break;
		// otherwise, try again in 100ms
		modm::this_fiber::sleep_for(100ms);
	}

	while(true)
	{
		// we wait until the task started
		if (barometerB.initialize())
			break;
		// otherwise, try again in 100ms
		modm::this_fiber::sleep_for(100ms);
	}

	MODM_LOG_DEBUG << MODM_FILE_INFO;
	MODM_LOG_DEBUG << "BME280 configured" << modm::endl;

	{
		static modm::bme280::Calibration &cal = dataA.getCalibration();

		MODM_LOG_DEBUG << MODM_FILE_INFO;
		MODM_LOG_DEBUG << "BME280 A Calibration data is: " << modm::endl;
		MODM_LOG_DEBUG.printf(" T1 %d\n", cal.T1);
		MODM_LOG_DEBUG.printf(" T2 %d\n", cal.T2);
		MODM_LOG_DEBUG.printf(" T3 %d\n", cal.T3);
		MODM_LOG_DEBUG.printf(" P1 %d\n", cal.P1);
		MODM_LOG_DEBUG.printf(" P2 %d\n", cal.P2);
		MODM_LOG_DEBUG.printf(" P3 %d\n", cal.P3);
		MODM_LOG_DEBUG.printf(" P4 %d\n", cal.P4);
		MODM_LOG_DEBUG.printf(" P5 %d\n", cal.P5);
		MODM_LOG_DEBUG.printf(" P6 %d\n", cal.P6);
		MODM_LOG_DEBUG.printf(" P7 %d\n", cal.P7);
		MODM_LOG_DEBUG.printf(" P8 %d\n", cal.P8);
		MODM_LOG_DEBUG.printf(" P9 %d\n", cal.P9);
		MODM_LOG_DEBUG.printf(" H1 %d\n", cal.H1);
		MODM_LOG_DEBUG.printf(" H2 %d\n", cal.H2);
		MODM_LOG_DEBUG.printf(" H3 %d\n", cal.H3);
		MODM_LOG_DEBUG.printf(" H4 %d\n", cal.H4);
		MODM_LOG_DEBUG.printf(" H5 %d\n", cal.H5);
		MODM_LOG_DEBUG.printf(" H6 %d\n", cal.H6);
	}

	{
		static modm::bme280::Calibration &cal = dataB.getCalibration();

		MODM_LOG_DEBUG << MODM_FILE_INFO;
		MODM_LOG_DEBUG << "BME280 B Calibration data is: " << modm::endl;
		MODM_LOG_DEBUG.printf(" T1 %d\n", cal.T1);
		MODM_LOG_DEBUG.printf(" T2 %d\n", cal.T2);
		MODM_LOG_DEBUG.printf(" T3 %d\n", cal.T3);
		MODM_LOG_DEBUG.printf(" P1 %d\n", cal.P1);
		MODM_LOG_DEBUG.printf(" P2 %d\n", cal.P2);
		MODM_LOG_DEBUG.printf(" P3 %d\n", cal.P3);
		MODM_LOG_DEBUG.printf(" P4 %d\n", cal.P4);
		MODM_LOG_DEBUG.printf(" P5 %d\n", cal.P5);
		MODM_LOG_DEBUG.printf(" P6 %d\n", cal.P6);
		MODM_LOG_DEBUG.printf(" P7 %d\n", cal.P7);
		MODM_LOG_DEBUG.printf(" P8 %d\n", cal.P8);
		MODM_LOG_DEBUG.printf(" P9 %d\n", cal.P9);
		MODM_LOG_DEBUG.printf(" H1 %d\n", cal.H1);
		MODM_LOG_DEBUG.printf(" H2 %d\n", cal.H2);
		MODM_LOG_DEBUG.printf(" H3 %d\n", cal.H3);
		MODM_LOG_DEBUG.printf(" H4 %d\n", cal.H4);
		MODM_LOG_DEBUG.printf(" H5 %d\n", cal.H5);
		MODM_LOG_DEBUG.printf(" H6 %d\n", cal.H6);
	}

	while (true)
	{
		modm::this_fiber::poll([&]{ return start_measurement; });

		// Returns when new data was read from the sensor
		barometerA.readout();
		barometerB.readout();
		new_data = true;

		int32_t temp = dataA.getTemperature();
		int32_t press = dataA.getPressure();
		int32_t hum = dataA.getHumidity();
		MODM_LOG_DEBUG << MODM_FILE_INFO;
		MODM_LOG_DEBUG.printf("BME280: Calibrated temperature in 0.01 degree Celsius is: %" PRId32 "\n", temp  );
		MODM_LOG_DEBUG << MODM_FILE_INFO;
		MODM_LOG_DEBUG.printf("BME280: Calibrated pressure in mPa is                   : %" PRId32 "\n", press );
		MODM_LOG_DEBUG << MODM_FILE_INFO;
		MODM_LOG_DEBUG.printf("BME280: Calibrated humidity in 0.001 %% is               : %" PRId32 "\n", hum );


		start_measurement = false;
	}
}
