213 lines
6.1 KiB
C++
213 lines
6.1 KiB
C++
/*
|
|
* 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<TLinFrame, 8> _rx_queue;
|
|
|
|
CircularBuffer<uint16_t, 16> _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_ */
|