174 lines
5.1 KiB
C++
174 lines
5.1 KiB
C++
/*
|
|
* SpiBus.h
|
|
*
|
|
* Created on: 6 èþí. 2019 ã.
|
|
* Author: krugliy
|
|
*/
|
|
|
|
#ifndef SOURCE_DRIVER_SPIBUS_H_
|
|
#define SOURCE_DRIVER_SPIBUS_H_
|
|
|
|
|
|
#include <cstddef>
|
|
|
|
#include "../common/Link.hpp"
|
|
|
|
#include "DiscreteOutput_OnePin.hh"
|
|
|
|
#include "../peripheral/ISerialPort.hh"
|
|
#include "../peripheral/ISerialPortConfigurator.hh"
|
|
|
|
|
|
namespace driver {
|
|
//serial port buffered driver
|
|
class ISerialPortBuff {
|
|
public:
|
|
virtual bool buff_transmite( const void * bit_stream, int bit_count ) = 0;
|
|
virtual bool receive( void * data ) = 0;
|
|
|
|
virtual ~ISerialPortBuff() = default;
|
|
};
|
|
|
|
//
|
|
class SpiBusAbonentConfig {
|
|
public:
|
|
struct Setting {
|
|
unsigned short clk_scheme;
|
|
unsigned short cs_polarity;
|
|
unsigned short transfer_delay;
|
|
unsigned long baud_rate;
|
|
bool rx_inv; //ïðèçíàê íåîáõîäèìîñòè èíâåðòèðîâàòü ïðèíèìàåìûå äàííûå
|
|
bool tx_inv; //ïðèçíàê íåîáõîäèìîñòè èíâåðòèðîâàòü äàííûå íà îòïðàâêó
|
|
bool loop_back_enable;
|
|
|
|
bool isValid() {
|
|
return true; //todo: baud_rate äîëæåí áûòü îãðàíè÷åí,
|
|
//ïðè÷åì ìàêñèìàëüíàÿ ÷àñòîòà êëîöèðîâàíèÿ äîëæíà áûòü ïðîïèñàíà â íàñòðîéêàõ ïåðèôåðèè
|
|
}
|
|
|
|
bool operator==( const Setting & other ) {
|
|
|
|
return ( clk_scheme == other.clk_scheme )
|
|
&& ( baud_rate == other.baud_rate )
|
|
&& ( loop_back_enable == other.loop_back_enable );
|
|
|
|
}
|
|
|
|
bool operator!=( const Setting & other ) { return not (*this == other ); }
|
|
|
|
};
|
|
|
|
bool configure( Setting & set ) {
|
|
|
|
if( not set.isValid() ) return false;
|
|
|
|
abonent_setting = set;
|
|
|
|
return true;
|
|
}
|
|
|
|
const Setting & getAbonentSetting() const { return abonent_setting; }
|
|
|
|
bool getCsActiveLevel() const { return abonent_setting.cs_polarity ==
|
|
1; }
|
|
|
|
private:
|
|
Setting abonent_setting;
|
|
|
|
};
|
|
|
|
|
|
class SpiBus {
|
|
public:
|
|
class SpiAbonent;
|
|
|
|
static const unsigned short max_links = 32; //äîëæíî áûòü ðàâíî max_spi_bus_abonents
|
|
|
|
static const unsigned short fifo_buff_size = 16; //ðàçìåð âíóòðåííåãî áóôåðà â 16-òè áèòíûõ ñëîâàõ
|
|
static const unsigned short fifo_buff_word_bit_len = 16;
|
|
static const unsigned short max_delay_cycle_count = 255;
|
|
|
|
peripheral::ISerialPort * createAbonent( peripheral::IGpio & chip_select,
|
|
const SpiBusAbonentConfig & abon_config,
|
|
std::pmr::memory_resource* allocator );
|
|
|
|
SpiBus( peripheral::ISerialPort & _serial_port,
|
|
peripheral::ISerialPortConfigurator & _serial_configurator,
|
|
std::size_t _max_spi_abonents );
|
|
|
|
virtual ~SpiBus() = default;
|
|
|
|
private:
|
|
const std::size_t max_spi_bus_abonents;
|
|
short num_spi_abonent;
|
|
|
|
class SpiBusMaster {
|
|
private:
|
|
peripheral::ISerialPort & serial_port;
|
|
peripheral::ISerialPortConfigurator & serial_configurator;
|
|
|
|
SpiAbonent * active_abonent;
|
|
SpiBusAbonentConfig::Setting active_abon_setting;
|
|
Link<SpiAbonent, max_links> collision;
|
|
|
|
public:
|
|
//çàïðîñ íà ïåðåäà÷ó
|
|
//åñëè ïîðò ñâîáîäåí, âîçâðàùàåòñÿ óêàçàòåëü íà èíòåðôåéñ
|
|
//â ïðîòèâíîì ñëó÷àå 0, à àáîíåíò êîòîðûé çàáëîêèðîâàë äîñòóï ê ïîðòó
|
|
//ïîâòîðíî íå ïîëó÷èò ïîðò ïîêà èì íå âîñïîëüçóåòñÿ àáîíåíò, ïîëó÷èâøèé 0 íà âûçîâ ôóíêöèè
|
|
peripheral::ISerialPort * transfer_request( SpiAbonent * spi_abonent );
|
|
|
|
//ïðîâåðêà ãîòîâíîñòè îòâåòà
|
|
bool is_response_ready( SpiAbonent * spi_abonent );
|
|
|
|
//îòìåíà çàïðîñà íà ïåðåäà÷ó
|
|
void cancel_request( SpiAbonent * spi_abonent );
|
|
|
|
SpiBusMaster( peripheral::ISerialPort & _serial_port, peripheral::ISerialPortConfigurator & _serial_configurator );
|
|
|
|
} spiBusMaster;
|
|
|
|
};
|
|
|
|
class SpiBus::SpiAbonent : public peripheral::ISerialPort {
|
|
private:
|
|
SpiBus::SpiBusMaster & serial_bus;
|
|
|
|
const SpiBusAbonentConfig abon_config;
|
|
driver::detail::DiscreteOutput_OnePin chip_select;
|
|
|
|
unsigned char rx_buff[fifo_buff_size]; //áóôôåðèçàöèÿ ôðåéìà, íå äàííûõ
|
|
bool data_ready = false; //áóôåð rx_buff - íå ïðî÷èòàí
|
|
|
|
short num_words;
|
|
|
|
public:
|
|
//ìàñòåð èñïîëüçóåò ýòè ôóíêöèè àáîíåíòà:
|
|
const SpiBusAbonentConfig::Setting & getSetting() const { return abon_config.getAbonentSetting(); }
|
|
|
|
// bool transmite_handler( peripheral::ISerialPort & serial_port ); //òóò äîëæíî âîçìîæíûì áûòü òîëüêî ÷òåíèå ïîðòà
|
|
// //ëèáî ðàññìàòðèâàòü ýòó ôóíêöèþ êàê çàâåðøåíèå ÷àñòè÷íîé ïåðåäà÷è äàííûõ,
|
|
// //òîãäà åå ìîæíî èñïîëüçîâàòü äëÿ äî ïåðåäà÷è èç âíóòðåííåãî fifo áóôåðà
|
|
//
|
|
//
|
|
void transmite_complete_handler( peripheral::ISerialPort & serial_port );
|
|
// bool transmite_complete_handler( CircularBuffer<spi_rx_buff_size, uint16_t> & master_rx_buff )
|
|
|
|
bool transmite( const void * bit_stream, int bit_count ) override;
|
|
|
|
bool receive( void * data ) override;
|
|
|
|
bool isDataReady();
|
|
|
|
SpiAbonent( SpiBusMaster & _bus_master, peripheral::IGpio & _chip_select,
|
|
const SpiBusAbonentConfig & _abon_config );
|
|
|
|
virtual ~SpiAbonent();
|
|
|
|
};
|
|
|
|
|
|
} /* namespace driver */
|
|
|
|
#endif /* SOURCE_DRIVER_SPIBUS_H_ */
|