/* * SerialPortAdapter.hpp * * Created on: 17 ���. 2019 �. * Author: titov */ #ifndef SOURCE_DRIVER_SERIALPORTADAPTER_HPP_ #define SOURCE_DRIVER_SERIALPORTADAPTER_HPP_ #include "../systemic/IHoldingRegister.hpp" #include "SpiPortRoutineOperation.hpp" #include "../peripheral/ISerialPort.hh" #include "../systemic/Timer.hh" #include namespace driver { /** * @brief Àäàïòåð ïîñëåäîâàòåëüíîãî ïîðòà ñ äîïîëíèòåëüíîé ïðîâåðêîé êîððåêòíîñòè îòïðàâëåííûõ äàííûõ * è âûñòàâëåíèåì ñîîòâåòñòâóþùåãî ñòàòóñà. * * @tparam Frame Òèï êîíòåéíåðà äëÿ äàííûõ * @tparam Latency Çàäåðæêà * @tparam AutoSet îòïðàâëÿòü ëè äàííûå, åñëè îíè íå áûëè èçìåíåíû * False - áóäóò îòïðàâëÿòüñÿ òîëüêî èçìåíåííûå äàííûå. * True - äàííûå áóäóò îòïðàâëÿòüñÿ ïî òàéìåðó. íåçàâèñèìî îò òîãî, èçìåíèëèñü ëè îíè */ template class SerialPortAdapter : public systemic::IHoldingRegister { public: // Çàäåðæêà static Latency temp; /** * @param port Ïîñëåäîâàòåëüíûé èíòåðôåéñ äëÿ îáìåíà äàííûìè * @param frame_size Ðàçìåð êàäðà * @param period_time Ïåðèîä îòïðàâêè/÷òåíèÿ äàííûõ * @param request_frame Ôðåéì äëÿ ïåðåäà÷è çàãîëîâêà * @param default_set_frame Ôðåéì äëÿ ïåðåäà÷è äàííûõ * @param default_get_frame Ôðåéì äëÿ ïîëó÷åíèÿ äàííûõ * @param locked Çàáëîêèðîàòü âûïîëíåíèå îáðàáîòêè äàííûõ * @param lset Çàäåðæêà íà îòïðàâêó äàííûõ * @param lget Çàäåðæêà íà ÷òåíèå äàííûõ */ SerialPortAdapter( peripheral::ISerialPort & port, std::size_t frame_size, systemic::time_t period_time, Frame request_frame, Frame default_set_frame, Frame default_get_frame, bool locked = false, Latency & lset = temp, Latency & lget = temp ); /** * @brief Îòïðàâèòü ôðåéì â ïîñëåäîâàòåëüíûé ïîðò. * @param frame ôðåéì äàííûõ */ void set( Frame frame ) final; /** * @brief Ïðî÷èòàòü ïîñëåäíèé ïîëó÷åííûé îòâåò èç ïîñëåäîâàòåëüíîãî ïîðòà. * @result Ôðåéì äàííûõ */ Frame get() const final; /** * Çàáëîêèðîâàòü îïåðàöèè îòïðàâêè/ïðèåìà äàííûõ. */ void lock() final; /** * Ðàçáëîêèðîâàòü îïåðàöèè îòïðàâêè/ïðèåìà äàííûõ. */ void unlock() final; /** * Ïåðåçàãðóæàåò àäàïòåð. */ void reset(); /** * Çàïóñê ïðîöåññà ÷òåíèÿ/îòïðàâêè äàííûõ ïî ïîñëåäîâàòåëüíîìó ïîðòó. */ void process(); ~SerialPortAdapter() = default; private: enum { SET, GET, SWITCH, LOCKED } op, prev_op, stash_op; // Íàáîð îïåðàöèé äëÿ äðàéâåðà SPI. typedef SpiOperationPack Operation; // Íàáîð îïåðàöèé äëÿ îòïðàâêè äàííûõ ïî SPI Operation set_op; // Íàáîð îïåðàöèé äëÿ ÷òåíèÿ äàííûõ ïî SPI Operation get_op; // Ôðåéì äëÿ ïåðåäà÷è äàííûõ Frame new_set_value; // Ôðåéì äëÿ ïîëó÷åíèÿ äàííûõ Frame new_get_value; // Ïåðèîä ìåæäó îïåðàöèÿìè systemic::time_t period_time; // Îòâå÷àåò çà îáðàáîòêó îïåðàöèé, ñâÿçàííûõ ñ ïåðèîäîì systemic::Timer periodizator; }; } template Latency driver::SerialPortAdapter::temp = 0; template inline driver::SerialPortAdapter::SerialPortAdapter( peripheral::ISerialPort & port, std::size_t frame_size, systemic::time_t period_time, Frame request_frame, Frame default_set_frame, Frame default_get_frame, bool locked, Latency & _lset, Latency & _lget ) : set_op( port, frame_size, default_set_frame, _lset ), get_op( port, frame_size, request_frame, _lget ), new_set_value(default_set_frame), new_get_value(default_get_frame), period_time(period_time), op( locked ? LOCKED : GET ), prev_op(SWITCH), stash_op(GET) { periodizator.start( period_time ); } template inline void driver::SerialPortAdapter::set( Frame set_value ) { new_set_value = set_value; } template inline Frame driver::SerialPortAdapter::get() const { return new_get_value; } template inline void driver::SerialPortAdapter::lock() { stash_op = op; op = LOCKED; periodizator.stop(); } template inline void driver::SerialPortAdapter::unlock() { periodizator.start(period_time); op = stash_op; } template inline void driver::SerialPortAdapter::reset() { op = LOCKED; periodizator.stop(); prev_op = SWITCH; stash_op = GET; periodizator.start( period_time ); op = GET; } template inline void driver::SerialPortAdapter::process() { switch(op) { case SET: { if( set_op() ) { prev_op = op; op = SWITCH; } } break; case GET: { if( get_op() ) { prev_op = op; op = SWITCH; new_get_value = get_op.output; } } break; case SWITCH: { if( periodizator.delayElapsed() ) { periodizator.start(period_time); if( prev_op == GET && ( set_op.input != new_set_value || AutoSet ) ) { set_op.input = new_set_value; op = SET; } else { op = GET; } } } break; case LOCKED: { } break; } } #endif /* SOURCE_DRIVER_SERIALPORTADAPTER_HPP_ */