MotorControlModuleSDFM_TMS3.../Projects/EFC_Application/UMLibrary/driver/SerialPortAdapter.hpp

207 lines
5.7 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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_ */