/* * DataImageStorage.hpp * * Created on: 16 февр. 2021 г. * Author: titov */ #ifndef UMLIBRARY_DRIVER_DATAIMAGESTORAGE_HPP_ #define UMLIBRARY_DRIVER_DATAIMAGESTORAGE_HPP_ #include "../systemic/IParameterProvider.hh" #include "../systemic/IProcess.hh" #include "../peripheral/IMemoryAccess.hh" #include "IParamStorage.hh" #include #include namespace driver { template class DataImageStorage : public systemic::IProcess, public driver::IParamStorage { public: typedef DataImage Image; DataImageStorage( peripheral::IMemoryAccess & persistent, peripheral::protected_char * buff, std::size_t buff_size ); void process(); systemic::SharedData createParameterBuff( Id parameter_id, std::size_t size ); systemic::SharedData getParameterBuff( Id parameter_id ) const; //!Данная реализация не поддерживает возможность сохранения отдельных параметров. bool flushParameterBuff( Id parameter_id ) { return false; } void flush(); void load(); void clear(); bool isDataSync() const; bool isCrcError() const; virtual ~DataImageStorage() = default; static const std::size_t align = alignof(long double); protected: peripheral::IMemoryAccess & memory; //!<Указатель на интерфейс работы с памятью peripheral::protected_char * const buff; //!<Буфер для работы с данными хранимыми в памяти. const std::size_t buff_size; //!<Размер буфера. Image image; //!<Образ данных. struct State { enum Id { Idle, UpdateCrc, StartWrite, WaitWrite, StartReadHead, WaitReadHead, StartReadEnd, WaitReadEnd, DataImageReset, }; }; typename State::Id state; bool crc_error; //!<Ошибка контрольной суммы данных, невозможно восстановить. bool data_ready; //!<Структура данных в ОЗУ загружена из ПЗУ. bool data_stored; //!<Структура данных в ПЗУ загружена из ОЗУ. bool isMemoryProcessing() const; }; } template inline driver::DataImageStorage::DataImageStorage( peripheral::IMemoryAccess & persistent, char * buff, std::size_t buff_size ) : memory(persistent), buff(buff), buff_size(buff_size), state(State::StartReadHead), crc_error(false), data_ready(false), data_stored(true) {} template inline void driver::DataImageStorage::process() { switch(state) { case State::UpdateCrc: { if( peripheral::write_lock( buff, buff_size ) ) { image.update_crc(); peripheral::write_unlock( buff, buff_size ); state = State::StartWrite; } } break; case State::StartWrite: { if( memory.write( buff, 0, image.get_image_size() ) ) state = State::WaitWrite; } break; case State::WaitWrite: { if( memory.isWriteComplete() ) state = State::StartReadEnd; } break; case State::StartReadHead: { if( memory.read( buff, 0, sizeof(typename Image::Head) ) ) state = State::WaitReadHead; } break; case State::WaitReadHead: { if( memory.isReadComplete() ) { if( image.build_from_buff(buff, buff_size, align) ) { state = State::StartReadEnd; } else { state = State::DataImageReset; } } } break; case State::StartReadEnd: { if( memory.read( buff + sizeof(typename Image::Head), sizeof(typename Image::Head), image.get_image_size() - sizeof(typename Image::Head) ) ) state = State::WaitReadEnd; } break; case State::WaitReadEnd: { if( memory.isReadComplete() ) { bool crc_equal = image.check_crc(); if( crc_equal ) { data_stored = data_ready = true; crc_error = false; state = State::Idle; } else { state = State::DataImageReset; } } } break; case State::DataImageReset: { if( peripheral::write_lock( buff, buff_size ) ) { image.reset(); peripheral::write_unlock( buff, buff_size ); data_stored = data_ready = false; crc_error = true; state = State::Idle; } } break; case State::Idle: {} break; }; } template systemic::SharedData driver::DataImageStorage::createParameterBuff( Id parameter_id, std::size_t size) { if( isMemoryProcessing() ) return { nullptr, 0 }; std::pair setting = image.show_setting( parameter_id ); if( not setting.first or setting.second != size ) { while( not peripheral::write_lock( buff, buff_size ) ); { data_ready = not image.change_setting_info( parameter_id, size ); peripheral::write_unlock( buff, buff_size ); return image.show_setting(parameter_id); } } return setting; } template systemic::SharedData driver::DataImageStorage::getParameterBuff( Id parameter_id ) const { if( isMemoryProcessing() ) return { nullptr, 0 }; return image.show_setting(parameter_id); } template void driver::DataImageStorage::flush() { if( not isMemoryProcessing() ) { data_stored = crc_error = false; state = State::UpdateCrc; } } template void driver::DataImageStorage::load() { if( not isMemoryProcessing() and data_stored ) { data_ready = false; state = State::StartReadHead; } } template void driver::DataImageStorage::clear() { while( not peripheral::write_lock( buff, buff_size ) ); image.reset(); data_stored = data_ready = false; state = State::Idle; } template bool driver::DataImageStorage::isDataSync() const { return data_ready and data_stored; } template bool driver::DataImageStorage::isCrcError() const { return crc_error; } template bool driver::DataImageStorage::isMemoryProcessing() const { return state != State::Idle; } #endif /* UMLIBRARY_DRIVER_DATAIMAGESTORAGE_HPP_ */