#pragma once
#include "BKMPIDevice.h"

#include <thread>
#include <mutex>
#include <queue>
#include <condition_variable>


class CIRPS : public CBKMPIDevice
{
	protected:
		uint16_t            RX_CSR; //адрес регистра состояния приёмника (РСПР) доступ - чтение/запись
		uint16_t            RX_DAT; //адрес буферного регистра приёмника (БРПР) доступ - чтение, запись - игнорируется, но ошибки не вызывает
		uint16_t            TX_CSR; //адрес регистра состояния передатчика (РСПЕР) доступ - чтение/запись
		uint16_t            TX_DAT; //адрес буферного регистра передатчика (БРПЕР) доступ - чтение/запись.
		uint16_t            RX_VEC; //вектор прерывания приёмника
		uint16_t            TX_VEC; //вектор прерывания передатчика

		//RX
		uint8_t             m_chRXData; //принятые данные
		bool                m_bRX_Ready;  // terminal receiver ready, бит 7 RX_CSR
		bool                m_bRX_InterruptEnable, m_bRX_InterruptEnable_prev; // terminal receiver interrupt enable, бит 6 RX_CSR
		bool                m_bRX_Break;       //бит 0 RX_CSR
		bool                m_bRX_Overflow;    //бит 12 RX_CSR
		bool                m_bRX_ParityError; //бит 15 RX_CSR

		bool                m_bRX_ParityCheck; //true - проверять чётность, false - нет
		bool                m_bRX_PEV;         //true - контроль чётных битов, false - контроль нечётных.

		void                _int_ReceiveData(uint8_t data);

		//TX
		uint8_t             m_chTXData;
		bool                m_bTX_Ready;  // terminal transmitter ready, бит 7 TX_CSR
		bool                m_bTX_InterruptEnable, m_bTX_InterruptEnable_prev;       // terminal transmitter interrupt enable
		bool                m_bTX_Break;       //бит 0 TX_CSR
		bool                m_bTX_Loop;        //бит 2 TX_CSR


		OVERLAPPED          m_ovr;
		void                RXFunc();           //функция приёма символа
		void                TXFunc();           //функция передачи символа

		std::queue<uint8_t> m_RXQueue;          //очередь полученных данных

		//потоки ввода-вывода
		std::mutex          m_mutQRXThreadWork; //событие, означающее, что поток работает
		bool                m_bStopQRXThread;   //событие, что пора завершить работу потока
		std::thread         m_QRXthr;           //поток выдачи данных из очереди
		void                QRXThreadFunc();    //собственно функция
		std::condition_variable m_QRXcv;        //условная переменная, запуск потока
		std::mutex          m_QRXmutex;         //мутекс условной переменной

		std::mutex          m_mutCONThreadWork; //событие, означающее, что поток работает
		bool                m_bStopCONThread;   //событие, что пора завершить работу потока
		bool                m_bCONTrigger;      //флаг запуска потока
		std::thread         m_CONthr;           //поток выдачи данных из очереди
		void                CONThreadFunc();    //собственно функция
		std::condition_variable m_CONcv;        //условная переменная, запуск потока
		std::mutex          m_CONmutex;         //мутекс условной переменной


		std::mutex          m_mutEVTThreadWork; //событие, означающее, что поток работает
		bool                m_bStopEVTThread;   //событие, что пора завершить работу потока
		std::thread         m_EVTthr;           //поток обработки событий
		void                EVTThreadFunc();    //собственно функция

		bool                StartThreads();
		void                StopThreads();

		HANDLE              m_hPort;     //хэндл открытого порта, куда отображается ВП1-65
		HANDLE              OpenPort(CString &strCOM);  //откытие порта
		void                ClosePort(HANDLE &Port); //закрытие порта

		LARGE_INTEGER       m_liDelayMKS;
		void                CalcDelay();
		void                MakeDelay();
		HANDLE              m_hWaitableTimer;
		bool                CreateTimer();
		void                DeleteTimer();

	public:
		CIRPS();
		virtual ~CIRPS() override;
		virtual BK_BOARD_MODEL  GetBoardModel() override;
		void Configure(IRPS_MODE nMode);
		void Reconfigure();
		// Virtual method called after reset command
		virtual void        OnReset() override;

		// Methods for Set/Get byte/word
		virtual bool        GetByteT(uint16_t addr, uint8_t *pValue, int &nTC) override;
		virtual bool        GetWordT(uint16_t addr, uint16_t *pValue, int &nTC) override;
		virtual bool        SetByteT(uint16_t addr, uint8_t value, int &nTC) override;
		virtual bool        SetWordT(uint16_t addr, uint16_t value, int &nTC) override;

		virtual bool        GetByteIndirect(uint16_t addr, uint8_t *pValue) override;
		virtual bool        GetWordIndirect(uint16_t addr, uint16_t *pValue) override;

		void                ReceiveData(uint8_t data);

};

