<commit_before>/**
 * \file
 * \brief SpiMasterHandle class header
 *
 * \author Copyright (C) 2018-2019 <NAME> http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 */

#ifndef INCLUDE_DISTORTOS_DEVICES_COMMUNICATION_SPIMASTERHANDLE_HPP_
#define INCLUDE_DISTORTOS_DEVICES_COMMUNICATION_SPIMASTERHANDLE_HPP_

#include "distortos/devices/communication/SpiMaster.hpp"
#include "distortos/devices/communication/SpiMasterBase.hpp"
#include "distortos/devices/communication/SpiMasterTransfersRange.hpp"
#include "distortos/devices/communication/SpiMode.hpp"

namespace distortos
{

class Semaphore;

namespace devices
{

/**
 * SpiMasterHandle is a [std::lock_guard](https://en.cppreference.com/w/cpp/thread/lock_guard)-like class for locking
 * SpiMaster and for accessing its core functionality.
 *
 * \note Locks are recursive.
 *
 * \ingroup devices
 */

class SpiMasterHandle : private SpiMasterBase
{
public:

	/**
	 * \brief SpiMasterHandle's constructor
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] spiMaster is a reference to SpiMaster associated with this handle
	 */

	explicit SpiMasterHandle(SpiMaster& spiMaster) :
			transfersRange_{},
			ret_{},
			semaphore_{},
			spiMaster_{spiMaster}
	{
		spiMaster_.mutex_.lock();
	}

	/**
	 * \brief SpiMasterHandle's destructor
	 *
	 * \warning This function must not be called from interrupt context!
	 */

	~SpiMasterHandle() override
	{
		spiMaster_.mutex_.unlock();
	}

	/**
	 * \brief Configures parameters of associated SPI master.
	 *
	 * \param [in] mode is the desired SPI mode
	 * \param [in] clockFrequency is the desired clock frequency, Hz
	 * \param [in] wordLength selects word length, bits, [1; 32]
	 * \param [in] lsbFirst selects whether MSB (false) or LSB (true) is transmitted first
	 * \param [in] dummyData is the dummy data that will be sent if write buffer of transfer is nullptr
	 *
	 * \return pair with return code (0 on success, error code otherwise) and real clock frequency; error codes:
	 * - EBADF - associated SPI master is not opened;
	 * - error codes returned by SpiMasterLowLevel::configure();
	 */

	std::pair<int, uint32_t> configure(SpiMode mode, uint32_t clockFrequency, uint8_t wordLength, bool lsbFirst,
			uint32_t dummyData) const;

	/**
	 * \brief Executes series of transfers as a single atomic transaction.
	 *
	 * The transaction is finished when all transfers are complete or when any error is detected.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] transfersRange is the range of transfers that will be executed
	 *
	 * \return pair with return code (0 on success, error code otherwise) and number of successfully completed transfers
	 * from \a transfersRange; error codes:
	 * - EBADF - associated SPI master is not opened;
	 * - EINVAL - \a transfersRange has no transfers;
	 * - EIO - failure detected by low-level SPI master driver;
	 * - error codes returned by SpiMasterLowLevel::startTransfer();
	 */

	std::pair<int, size_t> executeTransaction(SpiMasterTransfersRange transfersRange);

	SpiMasterHandle(const SpiMasterHandle&) = delete;
	SpiMasterHandle& operator=(const SpiMasterHandle&) = delete;

private:

	/**
	 * \brief Notifies waiting thread about completion of transaction.
	 *
	 * \param [in] ret is the last error code returned by transaction handling code, default - 0<commit_msg>Add SpiMasterHandle::open() and ...::close() wrappers<commit_after>/**
 * \file
 * \brief SpiMasterHandle class header
 *
 * \author Copyright (C) 2018-2019 <NAME> http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 */

#ifndef INCLUDE_DISTORTOS_DEVICES_COMMUNICATION_SPIMASTERHANDLE_HPP_
#define INCLUDE_DISTORTOS_DEVICES_COMMUNICATION_SPIMASTERHANDLE_HPP_

#include "distortos/devices/communication/SpiMaster.hpp"
#include "distortos/devices/communication/SpiMasterBase.hpp"
#include "distortos/devices/communication/SpiMasterTransfersRange.hpp"
#include "distortos/devices/communication/SpiMode.hpp"

namespace distortos
{

class Semaphore;

namespace devices
{

/**
 * SpiMasterHandle is a [std::lock_guard](https://en.cppreference.com/w/cpp/thread/lock_guard)-like class for locking
 * SpiMaster and for accessing its core functionality.
 *
 * \note Locks are recursive.
 *
 * \ingroup devices
 */

class SpiMasterHandle : private SpiMasterBase
{
public:

	/**
	 * \brief SpiMasterHandle's constructor
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] spiMaster is a reference to SpiMaster associated with this handle
	 */

	explicit SpiMasterHandle(SpiMaster& spiMaster) :
			transfersRange_{},
			ret_{},
			semaphore_{},
			spiMaster_{spiMaster}
	{
		spiMaster_.mutex_.lock();
	}

	/**
	 * \brief SpiMasterHandle's destructor
	 *
	 * \warning This function must not be called from interrupt context!
	 */

	~SpiMasterHandle() override
	{
		spiMaster_.mutex_.unlock();
	}

	/**
	 * \brief Closes associated SPI master.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by SpiMaster::close();
	 */

	int close() const
	{
		return spiMaster_.close();
	}

	/**
	 * \brief Configures parameters of associated SPI master.
	 *
	 * \param [in] mode is the desired SPI mode
	 * \param [in] clockFrequency is the desired clock frequency, Hz
	 * \param [in] wordLength selects word length, bits, [1; 32]
	 * \param [in] lsbFirst selects whether MSB (false) or LSB (true) is transmitted first
	 * \param [in] dummyData is the dummy data that will be sent if write buffer of transfer is nullptr
	 *
	 * \return pair with return code (0 on success, error code otherwise) and real clock frequency; error codes:
	 * - EBADF - associated SPI master is not opened;
	 * - error codes returned by SpiMasterLowLevel::configure();
	 */

	std::pair<int, uint32_t> configure(SpiMode mode, uint32_t clockFrequency, uint8_t wordLength, bool lsbFirst,
			uint32_t dummyData) const;

	/**
	 * \brief Executes series of transfers as a single atomic transaction.
	 *
	 * The transaction is finished when all transfers are complete or when any error is detected.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \param [in] transfersRange is the range of transfers that will be executed
	 *
	 * \return pair with return code (0 on success, error code otherwise) and number of successfully completed transfers
	 * from \a transfersRange; error codes:
	 * - EBADF - associated SPI master is not opened;
	 * - EINVAL - \a transfersRange has no transfers;
	 * - EIO - failure detected by low-level SPI master driver;
	 * - error codes returned by SpiMasterLowLevel::startTransfer();
	 */

	std::pair<int, size_t> executeTransaction(SpiMasterTransfersRange transfersRange);

	/**
	 * \brief Opens associated SPI master.
	 *
	 * \warning This function must not be called from interrupt context!
	 *
	 * \return 0 on success, error code otherwise:
	 * - error codes returned by SpiMaster::open();
	 */

	int open() const
	{
		return spiMaster_.open();
	}

	SpiMasterHandle(const SpiMasterHandle&) = delete;
	SpiMasterHandle& operator=(const SpiMasterHandle&) = delete;

private:

	/**
	 * \brief Notifies waiting thread about completion of transaction.
	 *
	 * \param [in] ret is the last error code returned by transaction handling code, default - 0
{'fraction_non_alphanumeric': 0.09423616424381535, 'fraction_numerical': 0.0066309614894159655, 'mean_word_length': 3.9576485461441213, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '254829', 'n_tokens_mistral': 2481, 'n_tokens_neox': 2240, 'n_words': 821}