/* * LinBus.h * * Created on: 17 дек. 2015 г. * Author: esaulenko */ #ifndef DRIVERS_LINBUS_H_ #define DRIVERS_LINBUS_H_ #ifndef CAN_FIRMWARE #include "KLineDrv.h" #include "ImoDrv.h" #include "Buffer.h" #include "SysTimer.h" #include "scmRTOS/scmRTOS.h" extern CLin LinBus1; extern CLin LinBus2; extern CLin LinBus3; union TLinInit; #endif // CAN_FIRMWARE #include "LinFrame.h" class CLin { public: enum TLinMode { Mode_RawNoParity, // без стандарта, принимает-передаёт любые пакеты (без чётности) Mode_Master, // LIN-мастер Mode_Slave, // LIN-слейв Mode_RawEvenParity, // без стандарта, байты с проверкой на чётность Mode_RawOddParity, // без стандарта, байты с проверкой на нечётность Mode_Raw9bit, // без стандарта, в байте 9 бит данных без чётности Mode_RawIgnoreError, // без стандарта, принимаются байты без чётности, стоп-бита и т.д. Mode_RawStop2bit, // без стандарта, 2 стоп-бита Mode_ImoImi, // протокол Toyota (старый), 48.8 бит/сек, 16 бит данных Mode_ImoRenault, // протокол Renault, 81,4 бит/с Mode_ImoImi2, // протокол Toyota (новый), 195.3 бит/сек, 32 бита данных Mode_FordDstTx, // протокол Ford DST80 (ШИМ, 1 бит = 1 мс / 0,5 мс) Mode_FordUartRx, // протокол Ford (UART 15625 бит/с, 384 мкс между байтами) Mode_Haval, // протокол с импульсами подтверждения (фильтрация/генерация) Mode_FordDstInversion, // протокол Ford DST80 (ШИМ, 1 бит = 1 мс / 0,5 мс, ИНВЕРСНЫЙ сигнал) }; #ifndef CAN_FIRMWARE CLin(const KLineHw & cfg) : _drv(cfg, this), _imoDrv(this, cfg) {} uint32_t Init(const TLinInit & init); // Для режима Haval void InitEXTI(void); void DeinitEXTI(void); void EdgeRcv(const bool newVal); void CheckTimeout(void); int32_t GetFrame(TLinFrame & aFrame); uint32_t SendFrame(const TLinFrame & aFrame); void Sleep(const bool sleepEnable); // вызывается из обработчиков прерываний: // приём/передача UART void IrqUart(void) { _drv.IrqProcess(); } // передача UART по таймеру uint32_t IrqTimerSend(void) { return _drv.IrqTimerSend(); } // фронт в режиме IMO/IMI void IrqImoEdge(const bool val) { Sleep(false); if (_mode == Mode_Haval) EdgeRcv(val); else _imoDrv.rx.EdgeRcv(val); } // таймер передачи в режиме IMO/IMI (только для LIN1) void IrqImoSend(void) { _imoDrv.tx.IrqSetNextBit(); } // управление выходом напрямую, как GPIO void SetOutput(const bool setZero); private: CKLineDrv _drv; CImoDrv _imoDrv; // вызывается из прерывания по приёму void DataRcvd(uint16_t data); void BreakRcvd(void); void ErrorRcvd(void); // вызывается из прерываний IMO/IMI void DataImiRcvd(const uint8_t * data, uint32_t data_len); // вызывается из прерывания по передаче bool IsTxData(void) { return _tx_buf.Avail() > 0; } uint16_t GetTxData(void) { return _tx_buf.Get(); } void TxComplete(void); friend CKLineDrv; friend CImoDrv; TLinMode _mode; union { bool _mode9bit = false; bool _InverseSignal; // инверсия входного сигнала }; // не-UART протоколы на таймере bool isCustomMode(void) const { return _mode == Mode_ImoImi || _mode == Mode_ImoImi2 || _mode == Mode_ImoRenault || _mode == Mode_FordDstTx || _mode == Mode_FordDstInversion; } enum { State_NoInit, State_BusOff, State_Idle, State_WaitSync, State_WaitId, State_WaitData, State_SlaveTxData, } _state = State_NoInit; TLinFrame _rx_frame; TimerMs _rx_tmr; uint32_t _rx_timeout; TimerMs _sleep_tmr; uint32_t _sleep_timeout; uint8_t _bytecnt; // счетчик байт для Mode_Haval uint8_t _bytes_noack; // кол-во байт без подтверждения для Mode_Haval uint8_t _bytes_ack; // кол-во байт c подтверждением для Mode_Haval // TimerUs _ack_tmr; // таймер для генерации импульов Mode_Haval uint8_t _bit_length_us; uint16_t _ack_pause_us; bool FrameToRxQueue(void); CircularBuffer _rx_queue; CircularBuffer _tx_buf; // буфер на передачу TLinFrame _tx_fr_buf[16]; // кадры для передачи slave'ом TLinFrame*_tx_fr_cur = _tx_fr_buf; // текущий передающийся кадр bool StartSlaveTx(uint8_t id); // функция отправки этого кадра TLinFrame * getTxFrame(void) // забрать фрейм из буфера (для imo_drv) { for (auto & it: _tx_fr_buf) if (it.data_len > 0) return ⁢ return nullptr; } // возвращает номер канала inline TLinChannel Instance(void) const { #ifdef MOBICAR_3 if (this == &LinBus3) return LINch3; #endif if (this == &LinBus2) return LINch2; return LINch1; } #endif // not CAN_FIRMWARE }; union TLinInit { struct TLin { uint16_t baudrate; CLin::TLinMode mode; uint32_t rxTimeout; uint32_t sleepTimeout; }Lin; struct THaval { uint16_t baudrate; CLin::TLinMode mode; uint16_t rxTimeout; uint32_t sleepTimeout; uint8_t bytes_noack; // кол-во байт без подтверждения uint8_t bytes_ack; // кол-во байт c подтверждением uint16_t ack_pause_us; // пауза в us перед ack в режиме генерации (0-режим фильтрации) }Haval; }; #endif /* DRIVERS_LINBUS_H_ */