Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,13 @@ Interfaces for receiving packets:
7. [```int GetNQueued()```](#getnqueued)
8. [```int GetMaxQueued()```](#getmaxqueued)
9. [```void SetDropPolicy(int startAt, bool (*isEssential)(const TVanPacketRxDesc&) = 0)```](#setdroppolicy)
10. [```void ActiveACK(const uint8_t len, const uint16_t array[]={})```](#activeack)

Interfaces for transmitting packets:

10. [```bool SyncSendPacket(uint16_t iden, uint8_t cmdFlags, const uint8_t* data, size_t dataLen, unsigned int timeOutMs = 10)```](#syncsendpacket)
11. [```bool SendPacket(uint16_t iden, uint8_t cmdFlags, const uint8_t* data, size_t dataLen, unsigned int timeOutMs = 10)```](#sendpacket)
12. [```uint32_t GetTxCount()```](#gettxcount)
11. [```bool SyncSendPacket(uint16_t iden, uint8_t cmdFlags, const uint8_t* data, size_t dataLen, unsigned int timeOutMs = 10)```](#syncsendpacket)
12. [```bool SendPacket(uint16_t iden, uint8_t cmdFlags, const uint8_t* data, size_t dataLen, unsigned int timeOutMs = 10)```](#sendpacket)
13. [```uint32_t GetTxCount()```](#gettxcount)

---

Expand Down Expand Up @@ -322,15 +323,39 @@ VanBusRx.SetDropPolicy(VAN_PACKET_QUEUE_SIZE * 8 / 10, &IsImportantPacket);
The above example will drop incoming packets if the receive queue contains 48 or more packets, unless they
are recognized by ```IsImportantPacket```.

#### 10. ```bool SyncSendPacket(uint16_t iden, uint8_t cmdFlags, const uint8_t* data, size_t dataLen, unsigned int timeOutMs = 10)``` <a id="syncsendpacket"></a>
#### 10. ```void ActiveACK(const uint8_t len, const uint16_t array[]={})``` <a id="activeack"></a>

Acknowleges the frames coming from adresses listed in the array. Sends an ACK by pulling down the bus line into dominant state for 1 timeslot.
IMPORTANT : you have to indicate the **lenght** of the array of adresses you are passing.

Example:

```cpp

void setup() {
TVanBus::Setup(RX_PIN, TX_PIN);
uint16_t KnownIdens[] = {0x8EC, 0x8C4};
VanBusRx.ActiveACK(2, KnownIdens);
}
```

To disable :

```cpp
void loop() {
VanBusRx.ActiveACK(0);
}
```

#### 11. ```bool SyncSendPacket(uint16_t iden, uint8_t cmdFlags, const uint8_t* data, size_t dataLen, unsigned int timeOutMs = 10)``` <a id="syncsendpacket"></a>

Sends a packet for transmission. Returns ```true``` if the packet was successfully transmitted.

#### 11. ```bool SendPacket(uint16_t iden, uint8_t cmdFlags, const uint8_t* data, size_t dataLen, unsigned int timeOutMs = 10)``` <a id="sendpacket"></a>
#### 12. ```bool SendPacket(uint16_t iden, uint8_t cmdFlags, const uint8_t* data, size_t dataLen, unsigned int timeOutMs = 10)``` <a id="sendpacket"></a>

Queues a packet for transmission. Returns ```true``` if the packet was successfully queued.

#### 12. ```uint32_t GetTxCount()``` <a id="gettxcount"></a>
#### 13. ```uint32_t GetTxCount()``` <a id="gettxcount"></a>

Returns the number of VAN packets, offered for transmitting, since power-on. Counter may roll over.

Expand Down Expand Up @@ -484,6 +509,8 @@ Only available when ```#define VAN_RX_IFS_DEBUGGING``` is uncommented (see
Currently the library supports only 125 kbit/s VAN bus. Need to add support for different rate, like 62.5 kbit/s,
which can be passed as an optional parameter to ```VanBusRx.Setup(...)```.

Some equipments on a VAN bus use a special frame called Remote Transmission Request (RTR). A device interrogates another by sending a "blank" frame, without any data payload. The target device completes the message in real time by inserting its data plus a checksum directly into this request frame, creating one complete message on the bus. The library doesn't support answering to RTR frames yet.

## 📖 License<a name = "license"></a>

This library is open-source and licensed under the [MIT license](http://opensource.org/licenses/MIT).
Expand Down
101 changes: 78 additions & 23 deletions src/VanBusRx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,35 @@ void TVanPacketRxDesc::DumpRaw(Stream& s, char last) const
s.print(last);
} // TVanPacketRxDesc::DumpRaw

void TVanPacketRxQueue::ActiveACK(const uint8_t len, const uint16_t array[]={}) //optionnal array for when len==0
{
if (len==0)
{
ActiveAckStatus = false;
idenAckLen = 0;
return;
}
else { //check if the array given by the user has the correct length? : if(array[len-1] != NULL)
ActiveAckStatus = true;
idenAckLen = len;
for(uint i = 0; i < len; i++){
idenAck[i]=array[i];
}
}
}

bool TVanPacketRxDesc::decisionActiveACK()
{
if(TVanPacketRxQueue::ActiveAckStatus == false || TVanPacketRxQueue::idenAckLen == 0){return 0;}
if((CommandFlags() ^ 0b0100) & 0b0101){return 0;} // (if != 0) do not acknowledge if Request Acknowledge is 0 or if we are receiving an RTR frame.
for(int i=0 ; i < TVanPacketRxQueue::idenAckLen ; i++){
if(Iden() == TVanPacketRxQueue::idenAck[i]){
return 1;
}
}
return 0;
} // TVanPacketRxDesc::decisionActiveACK

// Normal bit time (8 microseconds), expressed as number of CPU cycles
#define VAN_NORMAL_BIT_TIME_CPU_CYCLES (CPU_CYCLES(667))

Expand Down Expand Up @@ -1226,35 +1255,50 @@ void IRAM_ATTR RxPinChangeIsr()
// Experiment for 3 last "0"-bits: too short means it is not EOD
&& (nBits != 3 || nCycles > CPU_CYCLES(1963)))
{
const unsigned long eodMicrosActiveAck = micros() - 6; //record the time when eod detected, 6us offset on ESP32S3 +-2.5us

rxDesc->state = VAN_RX_WAITING_ACK;
DEBUG_IFS(toState, VAN_RX_WAITING_ACK);

rxDesc->ack = VAN_NO_ACK;

TRIGGER_ANALYSER_WAIT_ACK_ISR;

// Set a timeout for the ACK bit

#ifdef ARDUINO_ARCH_ESP32

#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
timerWrite(timer, 0);
timerAlarm(timer, 40 * RX_TIMER_TICKS_PER_MICROSECOND, false, 0); // 5 time slots = 5 * 8 us = 40 microseconds
#else // ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
timerWrite(timer, 0);
timerAlarmEnable(timer);
#endif // ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)

#else // ! ARDUINO_ARCH_ESP32

timer1_disable();
timer1_attachInterrupt(WaitAckIsr);

// Clock to timer (prescaler) is always 80 MHz, even if F_CPU is 160 MHz
timer1_enable(TIMER_DIVIDER, TIM_EDGE, TIM_SINGLE);
timer1_write(40 * TIMER_TICKS_PER_MICROSECOND); // 5 time slots = 5 * 8 us = 40 us = 200 ticks (0.2 microsecond/tick)

#endif // ARDUINO_ARCH_ESP32

if (VanBusRx.ActiveAckStatus && rxDesc->decisionActiveACK()){
rxDesc->ack = VAN_ACTIVE_ACK;
unsigned long elapsedMicros = micros() - eodMicrosActiveAck;
while(elapsedMicros < 18){
if(elapsedMicros > 7){ //target : 7-18us duration 11us actual(ESP32-S3): 9.0/7.7/6.5-17.7/16.6us duration 8.7/10us
digitalWrite(globalTxPin,VAN_BIT_DOMINANT);
}
elapsedMicros = micros() - eodMicrosActiveAck;
}
digitalWrite(globalTxPin,VAN_BIT_RECESSIVE);
}
else{
// Set a timeout for the ACK bit

#ifdef ARDUINO_ARCH_ESP32

#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
timerWrite(timer, 0);
timerAlarm(timer, 40 * RX_TIMER_TICKS_PER_MICROSECOND, false, 0); // 5 time slots = 5 * 8 us = 40 microseconds
#else // ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
timerWrite(timer, 0);
timerAlarmEnable(timer);
#endif // ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)

#else // ! ARDUINO_ARCH_ESP32

timer1_disable();
timer1_attachInterrupt(WaitAckIsr);

// Clock to timer (prescaler) is always 80 MHz, even if F_CPU is 160 MHz
timer1_enable(TIMER_DIVIDER, TIM_EDGE, TIM_SINGLE);
timer1_write(40 * TIMER_TICKS_PER_MICROSECOND); // 5 time slots = 5 * 8 us = 40 us = 200 ticks (0.2 microsecond/tick)

#endif // ARDUINO_ARCH_ESP32
}

}
else if (rxDesc->size >= VAN_MAX_PACKET_SIZE)
Expand All @@ -1269,10 +1313,15 @@ void IRAM_ATTR RxPinChangeIsr()
RETURN;
} // RxPinChangeIsr

bool TVanPacketRxQueue::ActiveAckStatus = false;
uint8_t TVanPacketRxQueue::idenAckLen = 0;
uint16_t TVanPacketRxQueue::idenAck[] = {};

// Initializes the VAN packet receiver
bool TVanPacketRxQueue::Setup(uint8_t rxPin, int queueSize)
{
if (pin != VAN_NO_PIN_ASSIGNED) return false; // Already setup
ActiveAckStatus = false;

#if defined ANALYSE_WAIT_ACK_ISR || defined ANALYSE_RX_PIN_CHANGE_ISR
pinMode(ANALYSER_PIN, OUTPUT);
Expand Down Expand Up @@ -1335,6 +1384,12 @@ void TVanPacketRxQueue::SetTxPinRecessive(uint8_t txPin)
digitalWrite(txPin, VAN_BIT_RECESSIVE); // Set bus state to 'recessive' (CANH and CANL: not driven)
} // TVanPacketRxQueue::SetTxPinRecessive

void TVanPacketRxQueue::SetTxPinDominant(uint8_t txPin)
{
pinMode(txPin, OUTPUT);
digitalWrite(txPin, VAN_BIT_DOMINANT); // Set bus state to 'dominant' (CANH active high and CANL active low)
} // TVanPacketRxQueue::SetTxPinDominant

// Copy a VAN packet out of the receive queue, if available. Otherwise, returns false.
// If a valid pointer is passed to 'isQueueOverrun', will report then clear any queue overrun condition.
bool TVanPacketRxQueue::Receive(TVanPacketRxDesc& pkt, bool* isQueueOverrun)
Expand Down
13 changes: 11 additions & 2 deletions src/VanBusRx.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@

// Forward declarations

extern uint8_t globalTxPin;
void WaitAckIsr();
void RxPinChangeIsr();

Expand Down Expand Up @@ -166,7 +167,7 @@ class TIfsDebugPacket

enum PacketReadState_t { VAN_RX_VACANT = 2, VAN_RX_SEARCHING, VAN_RX_LOADING, VAN_RX_WAITING_ACK, VAN_RX_DONE };
enum PacketReadResult_t { VAN_RX_PACKET_OK, VAN_RX_ERROR_NBITS, VAN_RX_ERROR_MANCHESTER, VAN_RX_ERROR_MAX_PACKET };
enum PacketAck_t { VAN_ACK, VAN_NO_ACK };
enum PacketAck_t { VAN_ACK, VAN_NO_ACK, VAN_ACTIVE_ACK };

// VAN packet Rx descriptor
class TVanPacketRxDesc
Expand Down Expand Up @@ -212,7 +213,7 @@ class TVanPacketRxDesc
return result;
} // CommandFlagsStr

const char* AckStr() const { return ack == VAN_ACK ? "ACK" : ack == VAN_NO_ACK ? "NO_ACK": "ACK_??"; }
const char* AckStr() const { return ack == VAN_ACK ? "ACK" : ack == VAN_NO_ACK ? "NO_ACK": ack == VAN_ACTIVE_ACK ? "ACTIVE_ACK" : "ACK_??"; }

const char* ResultStr() const
{
Expand Down Expand Up @@ -302,6 +303,8 @@ class TVanPacketRxDesc

bool CheckCrcFix(bool mustCount, uint32_t* pCounter1, uint32_t* pCounter2 = nullptr);

bool decisionActiveACK();

friend void WaitAckIsr();
friend void RxPinChangeIsr();
friend class TVanPacketRxQueue;
Expand Down Expand Up @@ -382,8 +385,10 @@ class TVanPacketRxQueue

bool Setup(uint8_t rxPin, int queueSize = VAN_DEFAULT_RX_QUEUE_SIZE);
void SetTxPinRecessive(uint8_t txPin);
void SetTxPinDominant(uint8_t txPin);
bool Available() const { ISR_SAFE_GET(bool, tail->state == VAN_RX_DONE); }
bool Receive(TVanPacketRxDesc& pkt, bool* isQueueOverrun = NULL);
void ActiveACK(const uint8_t len, const uint16_t array[]);

// Disabling the VAN bus receiver is necessary for timer-intensive tasks, like e.g. operations on the SPI Flash
// File System (SPIFFS), which otherwise cause system crash. Unfortunately, after disabling then enabling the
Expand Down Expand Up @@ -455,6 +460,10 @@ class TVanPacketRxQueue
if (++tail == end) tail = pool; // Roll over if needed
ISR_SAFE_SET(nQueued, nQueued - 1);
} // AdvanceTail

static bool ActiveAckStatus;
static uint8_t idenAckLen;
static uint16_t idenAck[];

friend void FinishPacketTransmission(TVanPacketTxDesc* txDesc);
friend void SendBitIsr();
Expand Down
3 changes: 3 additions & 0 deletions src/VanBusTx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

#endif // ARDUINO_ARCH_ESP32

uint8_t globalTxPin = VAN_NO_PIN_ASSIGNED;

// Finish packet transmission
void IRAM_ATTR FinishPacketTransmission(TVanPacketTxDesc* txDesc)
{
Expand Down Expand Up @@ -169,6 +171,7 @@ void IRAM_ATTR SendBitIsr()
void TVanPacketTxQueue::Setup(uint8_t theRxPin, uint8_t theTxPin)
{
txPin = theTxPin;
globalTxPin = txPin;

pinMode(theTxPin, OUTPUT);
digitalWrite(theTxPin, VAN_BIT_RECESSIVE); // Set bus state to 'recessive' (CANH and CANL: not driven)
Expand Down
Loading