#pragma once

#include "BKSoundDevice.h"


class Counter8253
{
		int         m_phase{0};            // see phase definition tables in simulate2(), below
		uint16_t    m_nValue{0};           // текущее значение счётчика ("CE" in Intel docs)
		uint16_t    m_nCounter{0};         // новое значение счётчика ("CR" in Intel docs)
		uint8_t     m_nMode{0};            // режим работы счётчика
		uint8_t     m_nRL{0};              // режим чтения/записи
		uint8_t     m_lowcount{0};         // младший байт нового значения счётчика для 16-битной записи
		bool        m_bwmsb{false};            // true = следующая запись будет старший байт 16-битного значения
		bool        m_bBCD{false};             // тип счёта: true - двоично-десятичный, false - двоичный
		bool        m_gate{false};             // разрешение выхода (0 = low, 1 = high)
		bool        m_nOutput{true};          // значение на выходе

		// загрузка нового значения счётчика
		void        load_count(uint16_t newcount);
		// установка выходного значения счётчика
		void        set_output(const bool v);
		//
		void        load_counter_value();
		int         adjusted_count() const;
		void        decrease_counter_value(int32_t cycles);

	public:
		Counter8253() = default;
		~Counter8253() = default;
		void        reset();
		void        simulate_0();
		void        simulate_1();
		void        SetControl(const uint8_t ctrl);
		void        SetCount(const uint8_t cnt);
		void        SetGate(const bool state);
		bool        GetOutput() const;
};

class CMenestrel : public CBKSoundDevice
{
		struct MenesChan
		{
			std::vector <SAMPLE_INT> v;
			SAMPLE_INT *y{ nullptr };
			int ny{ 0 };
		};
		MenesChan   LS, RS;
		std::array<Counter8253, 3> LChn;
		std::array<Counter8253, 3> RChn;

		/* m_nRate converter*/
		double      m_dRealStep{ 0.0 };
		double      m_dPSGTime{ 0.0 };
		double      m_dPSGStep{ 0.0 };

		double      m_nClock{ 0.0 }, m_nRate{ 0.0 };
		uint16_t    m_nData{ 0 };
		bool        m_bGatePrev{ false };
		bool        m_bWrPrev{ true };

	public:
		CMenestrel();
		virtual ~CMenestrel() override;

		void            init(const int c, const int r);
		virtual void    ReInit() override;
		virtual void    Reset() override;

		// запись данных. мл.байт - данные, ст.байт - адрес и управление
		virtual void    SetData(const uint16_t inVal) override;
		// получение текущего сэмпла
		virtual void    GetSample(sOneSample *pSm) override;

};

/*
Биты управления:
15 - разрешение счёта, т.е. по сути Mute
12 - nWR - запись данных
11 - nCS - выбор микросхемы правого канала
10 - nCS - выбор микросхемы левого канала
09 - A1 - адресные входы, для выбора номера
08 - A0   счётчика в микросхеме


*/
