MotorControlModuleSDFM_TMS3.../Projects/EFC_Application/UMLibrary/driver/SpiBus.cpp

207 lines
5.5 KiB
C++
Raw Normal View History

#include "../memories/memories.hh"
/*
* SpiBus.cpp
*
* Created on: 6 <EFBFBD><EFBFBD><EFBFBD>. 2019 <EFBFBD>.
* Author: krugliy
*/
#include "SpiBus.hh"
#include <climits>
#include <stdint.h>
peripheral::ISerialPort* driver::SpiBus::SpiBusMaster::transfer_request(
SpiAbonent* spi_abonent) {
if( active_abonent && serial_port.isDataReady() ) {
active_abonent->transmite_complete_handler( serial_port );
cancel_request( active_abonent );
}
// ITransferHandler * volatile prev_handler = active_handler;
SpiAbonent * volatile prev_abonenet = active_abonent;
if( !prev_abonenet && !collision.isTiedTo( spi_abonent ) ) {
while( collision.popLink( static_cast<SpiAbonent *>( spi_abonent ) ) );
// spi.reset();
// interrupt_ctrl.enable();
if( active_abon_setting != spi_abonent->getSetting() ) {
serial_configurator.applySetting(
spi_abonent->getSetting().baud_rate,
spi_abonent->getSetting().clk_scheme,
spi_abonent->getSetting().transfer_delay,
spi_abonent->getSetting().loop_back_enable
);
active_abon_setting = spi_abonent->getSetting();
}
active_abonent = spi_abonent;
return & serial_port;
} else if( static_cast<SpiAbonent *>( prev_abonenet ) != spi_abonent && prev_abonenet ) {
collision.putLink( static_cast<SpiAbonent *>( spi_abonent ), prev_abonenet );
}
return nullptr;
}
void driver::SpiBus::SpiBusMaster::cancel_request(SpiAbonent* spi_abonent) {
while( collision.popLink( spi_abonent ) );
if( active_abonent == spi_abonent ) {
// interrupt_ctrl.disable();
// spi.reset();
active_abonent = nullptr;
}
}
driver::SpiBus::SpiBusMaster::SpiBusMaster(
peripheral::ISerialPort& _serial_port,
peripheral::ISerialPortConfigurator& _serial_configurator) :
serial_port(_serial_port), active_abonent( nullptr ),
serial_configurator(_serial_configurator),
active_abon_setting(), collision() {}
peripheral::ISerialPort * driver::SpiBus::createAbonent(
peripheral::IGpio& chip_select,
const SpiBusAbonentConfig& abon_config,
std::pmr::memory_resource* allocator ) {
if( num_spi_abonent < max_spi_bus_abonents ) {
num_spi_abonent++;
//todo: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return memories::instance_object<SpiAbonent>( *allocator, spiBusMaster, chip_select, abon_config );
}
return nullptr;
}
driver::SpiBus::SpiBus(peripheral::ISerialPort& _serial_port,
peripheral::ISerialPortConfigurator& _serial_configurator,
std::size_t _max_spi_abonents ) :
max_spi_bus_abonents( _max_spi_abonents ),
num_spi_abonent( 0 ),
spiBusMaster( _serial_port, _serial_configurator ) {}
bool driver::SpiBus::SpiAbonent::transmite(const void* bit_stream,
int bit_count) {
if( peripheral::ISerialPort * port = serial_bus.transfer_request( this ) ) {
num_words = bit_count / CHAR_BIT;
if( bit_count % CHAR_BIT ) num_words += 1;
chip_select.on();
if( not abon_config.getAbonentSetting().tx_inv ) {
if( not port->transmite( bit_stream, bit_count ) ) {
chip_select.off();
} else return true;
} else {
char tx_buff[fifo_buff_size];
for( int i = 0; i < num_words; i++ ) {
tx_buff[i] = ~*static_cast<const char*>(bit_stream);
bit_stream = static_cast<const char*>(bit_stream) + 1;
}
if( not port->transmite( tx_buff, bit_count ) ) {
chip_select.off();
} else return true;
}
}
return false;
}
bool driver::SpiBus::SpiAbonent::receive(void* data) {
if( isDataReady() ) {
if( abon_config.getAbonentSetting().rx_inv ) {
for( int i = 0; i < num_words; i++ )
static_cast<unsigned char *>(data)[i] = ~rx_buff[i];
} else {
for( int i = 0; i < num_words; i++ )
static_cast<unsigned char *>(data)[i] = rx_buff[i];
}
serial_bus.cancel_request( this );
data_ready = false;
return true;
}
return false;
}
driver::SpiBus::SpiAbonent::SpiAbonent(SpiBusMaster& _bus_master,
peripheral::IGpio& _chip_select,
const SpiBusAbonentConfig& _abon_config) :
serial_bus(_bus_master),
abon_config(_abon_config),
chip_select(_chip_select, _abon_config.getCsActiveLevel()),
rx_buff(), num_words(0) {}
bool driver::SpiBus::SpiAbonent::isDataReady() {
return serial_bus.is_response_ready( this ) || data_ready;
}
driver::SpiBus::SpiAbonent::~SpiAbonent() {
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
void driver::SpiBus::SpiAbonent::transmite_complete_handler(
peripheral::ISerialPort& serial_port) {
chip_select.off();
data_ready = ( sizeof( rx_buff ) >= num_words )
&& serial_port.receive( rx_buff );
}
bool driver::SpiBus::SpiBusMaster::is_response_ready( SpiAbonent* spi_abonent ) {
if( active_abonent && active_abonent == spi_abonent ) {
return serial_port.isDataReady() ? spi_abonent->transmite_complete_handler( serial_port ), true : false;
}
return false;
}