<commit_before>/**
 * \file
 * \brief SerialPort class header
 *
 * \author Copyright (C) 2016 <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_SERIALPORT_HPP_
#define INCLUDE_DISTORTOS_DEVICES_COMMUNICATION_SERIALPORT_HPP_

#include "distortos/devices/communication/UartParity.hpp"

#include "distortos/internal/devices/UartBase.hpp"

#include "distortos/Mutex.hpp"

namespace distortos
{

class Semaphore;

namespace internal
{

class UartLowLevel;

}

namespace devices
{

/**
 * SerialPort class is a serial port with an interface similar to standard files
 *
 * \ingroup devices
 */

class SerialPort : private internal::UartBase
{
public:

	/// thread-safe, lock-free ring buffer for one-producer and one-consumer
	class RingBuffer
	{
	public:

		/**
		 * \brief RingBuffer's constructor
		 *
		 * \param [in] buffer is a buffer for data
		 * \param [in] size is the size of \a buffer, bytes, should be even, must be greater than or equal to 4
		 */

		constexpr RingBuffer(void* const buffer, const size_t size) :
				buffer_{static_cast<uint8_t*>(buffer)},
				size_{size},
				readPosition_{},
				writePosition_{}
		{

		}

		/**
		 * \brief Clears ring buffer
		 */

		void clear()
		{
			readPosition_ = 0;
			writePosition_ = 0;
		}

		/**
		 * \return First contiguous block (as a pair with pointer and size) available for reading
		 */

		std::pair<const uint8_t*, size_t> getReadBlock() const;

		/**
		 * \return total size of ring buffer, bytes
		 */

		size_t getSize() const
		{
			return size_;
		}

		/**
		 * \return First contiguous block (as a pair with pointer and size) available for writing
		 */

		std::pair<uint8_t*, size_t> getWriteBlock() const;

		/**
		 * \brief Increases read position by given value
		 *
		 * \param [in] value is the value which will be added to read position, must come from previous call to
		 * getReadBlock()
		 */

		void increaseReadPosition(const size_t value)
		{
			readPosition_ += value;
			readPosition_ %= size_;
		}

		/**
		 * \brief Increases write position by given value
		 *
		 * \param [in] value is the value which will be added to write position, must come from previous call to
		 * getWriteBlock()
		 */

		void increaseWritePosition(const size_t value)
		{
			writePosition_ += value;
			writePosition_ %= size_;
		}

		/**
		 * \return true if ring buffer is empty, false otherwise
		 */

		bool isEmpty() const
		{
			return writePosition_ == readPosition_;
		}

		/**
		 * \return true if ring buffer is full, false otherwise
		 */

		bool isFull() const
		{
			return readPosition_ == (writePosition_ + 2) % size_;
		}

	private:

		/// pointer to beginning of buffer
		uint8_t* buffer_;

		/// size of \a buffer_, bytes
		size_t size_;

		/// current read position
		volatile size_t readPosition_;

		/// current write position
		volatile size_t writePosition_;
	};

	/**
	 * \brief SerialPort's constructor
	 *
	 * \param [in] uart is a reference to low-level implementation of internal::UartLowLevel interface
	 * \param [in] readBuffer is a buffer for read operations
	 * \param [in] readBufferSize is the size of \a readBuffer, bytes, should be divisible by 4, must be greater than or
	 * equal to 4
	 * \param [in] writeBuffer is a buffer to write operations
	 * \param [in] writeBufferSize is the size of \a writeBuffer, bytes, should be even, must be greater than or equal
	 * to 4
	 */

	constexpr SerialPort(internal::UartLowLevel& uart, void* const readBuffer, const size_t readBufferSize,
			void* const writeBuffer, const size_t writeBufferSize) :
					readMutex_{Mutex::Type::normal, Mutex::Protocol::priorityInheritance},
					writeMutex_{Mutex::Type::normal, Mutex::Protocol::priorityInheritance},
					readBuffer_{readBuffer, (readBufferSize / 4) * 4},
					writeBuffer_{writeBuffer, (writeBufferSize / 2) * 2},
					readSemaphore_{},
					transmitSemaphore_{},
					writeSemaphore_{},
					uart_{uart},
					baudRate_{},<commit_msg>Size of SerialPort's buffers can be even<commit_after>/**
 * \file
 * \brief SerialPort class header
 *
 * \author Copyright (C) 2016 <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_SERIALPORT_HPP_
#define INCLUDE_DISTORTOS_DEVICES_COMMUNICATION_SERIALPORT_HPP_

#include "distortos/devices/communication/UartParity.hpp"

#include "distortos/internal/devices/UartBase.hpp"

#include "distortos/Mutex.hpp"

namespace distortos
{

class Semaphore;

namespace internal
{

class UartLowLevel;

}

namespace devices
{

/**
 * SerialPort class is a serial port with an interface similar to standard files
 *
 * \ingroup devices
 */

class SerialPort : private internal::UartBase
{
public:

	/// thread-safe, lock-free ring buffer for one-producer and one-consumer
	class RingBuffer
	{
	public:

		/**
		 * \brief RingBuffer's constructor
		 *
		 * \param [in] buffer is a buffer for data
		 * \param [in] size is the size of \a buffer, bytes, should be even, must be greater than or equal to 4
		 */

		constexpr RingBuffer(void* const buffer, const size_t size) :
				buffer_{static_cast<uint8_t*>(buffer)},
				size_{size},
				readPosition_{},
				writePosition_{}
		{

		}

		/**
		 * \brief Clears ring buffer
		 */

		void clear()
		{
			readPosition_ = 0;
			writePosition_ = 0;
		}

		/**
		 * \return First contiguous block (as a pair with pointer and size) available for reading
		 */

		std::pair<const uint8_t*, size_t> getReadBlock() const;

		/**
		 * \return total size of ring buffer, bytes
		 */

		size_t getSize() const
		{
			return size_;
		}

		/**
		 * \return First contiguous block (as a pair with pointer and size) available for writing
		 */

		std::pair<uint8_t*, size_t> getWriteBlock() const;

		/**
		 * \brief Increases read position by given value
		 *
		 * \param [in] value is the value which will be added to read position, must come from previous call to
		 * getReadBlock()
		 */

		void increaseReadPosition(const size_t value)
		{
			readPosition_ += value;
			readPosition_ %= size_;
		}

		/**
		 * \brief Increases write position by given value
		 *
		 * \param [in] value is the value which will be added to write position, must come from previous call to
		 * getWriteBlock()
		 */

		void increaseWritePosition(const size_t value)
		{
			writePosition_ += value;
			writePosition_ %= size_;
		}

		/**
		 * \return true if ring buffer is empty, false otherwise
		 */

		bool isEmpty() const
		{
			return writePosition_ == readPosition_;
		}

		/**
		 * \return true if ring buffer is full, false otherwise
		 */

		bool isFull() const
		{
			return readPosition_ == (writePosition_ + 2) % size_;
		}

	private:

		/// pointer to beginning of buffer
		uint8_t* buffer_;

		/// size of \a buffer_, bytes
		size_t size_;

		/// current read position
		volatile size_t readPosition_;

		/// current write position
		volatile size_t writePosition_;
	};

	/**
	 * \brief SerialPort's constructor
	 *
	 * \param [in] uart is a reference to low-level implementation of internal::UartLowLevel interface
	 * \param [in] readBuffer is a buffer for read operations
	 * \param [in] readBufferSize is the size of \a readBuffer, bytes, should be even, must be greater than or equal to
	 * 4
	 * \param [in] writeBuffer is a buffer to write operations
	 * \param [in] writeBufferSize is the size of \a writeBuffer, bytes, should be even, must be greater than or equal
	 * to 4
	 */

	constexpr SerialPort(internal::UartLowLevel& uart, void* const readBuffer, const size_t readBufferSize,
			void* const writeBuffer, const size_t writeBufferSize) :
					readMutex_{Mutex::Type::normal, Mutex::Protocol::priorityInheritance},
					writeMutex_{Mutex::Type::normal, Mutex::Protocol::priorityInheritance},
					readBuffer_{readBuffer, (readBufferSize / 2) * 2},
					writeBuffer_{writeBuffer, (writeBufferSize / 2) * 2},
					readSemaphore_{},
					transmitSemaphore_{},
					writeSemaphore_{},
					uart_{uart},
					baudRate_{},
{'fraction_non_alphanumeric': 0.10043771442091565, 'fraction_numerical': 0.0053235537678930555, 'mean_word_length': 3.311065782763896, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, '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': '3517663', 'n_tokens_mistral': 2990, 'n_tokens_neox': 2523, 'n_words': 883}