207 lines
5.7 KiB
C++
207 lines
5.7 KiB
C++
/*
|
||
* 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 <cstddef>
|
||
|
||
namespace driver {
|
||
/**
|
||
* @brief Адаптер последовательного порта с дополнительной проверкой корректности отправленных данных
|
||
* и выставлением соответствующего статуса.
|
||
*
|
||
* @tparam Frame Тип контейнера для данных
|
||
* @tparam Latency Задержка
|
||
* @tparam AutoSet отправлять ли данные, если они не были изменены
|
||
* False - будут отправляться только измененные данные.
|
||
* True - данные будут отправляться по таймеру. независимо от того, изменились ли они
|
||
*/
|
||
template<typename Frame, typename Latency = unsigned int, bool AutoSet = false>
|
||
class SerialPortAdapter : public systemic::IHoldingRegister<Frame> {
|
||
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<Frame, Latency> 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<typename Frame, typename Latency, bool AutoSet>
|
||
Latency driver::SerialPortAdapter<Frame, Latency, AutoSet>::temp = 0;
|
||
|
||
template<typename Frame, typename Latency, bool AutoSet>
|
||
inline driver::SerialPortAdapter<Frame, Latency, AutoSet>::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<typename Frame, typename Latency, bool AutoSet>
|
||
inline void driver::SerialPortAdapter<Frame, Latency, AutoSet>::set( Frame set_value ) {
|
||
|
||
new_set_value = set_value;
|
||
|
||
}
|
||
|
||
template<typename Frame, typename Latency, bool AutoSet>
|
||
inline Frame driver::SerialPortAdapter<Frame, Latency, AutoSet>::get() const {
|
||
|
||
return new_get_value;
|
||
|
||
}
|
||
|
||
template<typename Frame, typename Latency, bool AutoSet>
|
||
inline void driver::SerialPortAdapter<Frame, Latency, AutoSet>::lock() {
|
||
|
||
stash_op = op;
|
||
op = LOCKED;
|
||
periodizator.stop();
|
||
|
||
|
||
}
|
||
|
||
template<typename Frame, typename Latency, bool AutoSet>
|
||
inline void driver::SerialPortAdapter<Frame, Latency, AutoSet>::unlock() {
|
||
|
||
periodizator.start(period_time);
|
||
op = stash_op;
|
||
|
||
}
|
||
|
||
template<typename Frame, typename Latency, bool AutoSet>
|
||
inline void driver::SerialPortAdapter<Frame, Latency, AutoSet>::reset() {
|
||
|
||
op = LOCKED;
|
||
|
||
periodizator.stop();
|
||
|
||
prev_op = SWITCH;
|
||
stash_op = GET;
|
||
|
||
periodizator.start( period_time );
|
||
|
||
op = GET;
|
||
}
|
||
|
||
template<typename Frame, typename Latency, bool AutoSet>
|
||
inline void driver::SerialPortAdapter<Frame, Latency, AutoSet>::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_ */
|