This repository has been archived on 2026-02-22. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
can/Src/mmr_can_send.c
T
Stefano Calabretti 906dfcd3db Update header (#9)
* Add ack message type

* Rename dictionaryEntry to messageId

* Refactor

* Map message ids
2022-01-29 13:27:37 +01:00

143 lines
3.4 KiB
C

#include <stdbool.h>
#include "mmr_can.h"
#include "mmr_can_util.h"
typedef struct {
CanHandle *handle;
MmrCanPacket *packet;
struct {
CanTxHeader tx;
MmrCanHeader mmr;
} headers;
} TransmissionParams;
static HalStatus send(TransmissionParams *tp);
static HalStatus sendNormal(TransmissionParams *tp);
static HalStatus sendMulti(TransmissionParams *tp);
static HalStatus sendSingleMultiFrame(TransmissionParams *tp);
static uint8_t computeFramesToSend(MmrCanPacket *packet);
static uint8_t computeNextMessageLength(MmrCanPacket *packet);
static void setMessageType(TransmissionParams *header, MmrCanMessageType type);
static void syncHeaders(TransmissionParams *tp);
HalStatus MMR_CAN_Send(CanHandle *hcan, MmrCanPacket packet) {
TransmissionParams tp = {
.handle = hcan,
.packet = &packet,
.headers.tx = {
.IDE = CAN_ID_EXT,
.RTR = CAN_RTR_DATA,
.DLC = packet.length,
.TransmitGlobalTime = DISABLE,
},
};
syncHeaders(&tp);
return packet.length <= MMR_CAN_MAX_DATA_LENGTH
? sendNormal(&tp)
: sendMulti(&tp);
}
static HalStatus sendNormal(TransmissionParams *tp) {
setMessageType(tp, MMR_CAN_MESSAGE_TYPE_NORMAL);
return send(tp);
}
static HalStatus sendMulti(TransmissionParams *tp) {
HalStatus status = HAL_OK;
uint8_t framesToSend = computeFramesToSend(tp->packet);
setMessageType(tp, MMR_CAN_MESSAGE_TYPE_MULTI_FRAME);
do {
bool isLastFrame = framesToSend <= 1;
if (isLastFrame) {
setMessageType(tp, MMR_CAN_MESSAGE_TYPE_MULTI_FRAME_END);
}
status |= sendSingleMultiFrame(tp);
}
while (framesToSend-- > 1 && status == HAL_OK);
return status;
}
static HalStatus sendSingleMultiFrame(TransmissionParams *tp) {
uint8_t length =
computeNextMessageLength(tp->packet);
tp->packet->length -= length;
tp->packet->data += length;
tp->headers.tx.DLC = length;
return send(tp);
}
static HalStatus send(TransmissionParams *tp) {
syncHeaders(tp);
return HAL_CAN_AddTxMessage(
tp->handle,
&tp->headers.tx,
tp->packet->data,
tp->packet->mailbox
);
}
static void syncHeaders(TransmissionParams *tp) {
tp->headers.tx.ExtId = *MMR_CAN_HeaderToBits(&tp->headers.mmr);
}
/**
* @brief
* Computes the frames that will need to be sent for a packet.
*
* For example, if a packet has 15 bytes, the function will return
* 2, as one packet is needed for the first 8 bytes and another is
* needed for the remaining 7.
*
* @example
* The computation is pretty simple
* Given
* length = 17 (bytes)
* We'll have
* framesToSend = 17 / 8 = 2 (frames)
* remainder = 17 % 8 = 1 (bytes)
* maybeOneForRemainder = 1 > 0 = 1 (frame)
* -------------------------------------------
* result = 2 + 1 = 3 (frames)
*/
static uint8_t computeFramesToSend(MmrCanPacket *packet) {
uint8_t length = packet->length;
uint8_t framesToSend = length / MMR_CAN_MAX_DATA_LENGTH;
uint8_t remainder = length % MMR_CAN_MAX_DATA_LENGTH;
uint8_t maybeOneForRemainder = remainder > 0;
return framesToSend + maybeOneForRemainder;
}
/**
* @brief
* Returns the length for the next message, either
* 8 bytes or a lower value.
*/
static uint8_t computeNextMessageLength(MmrCanPacket *packet) {
return min(
packet->length, MMR_CAN_MAX_DATA_LENGTH
);
}
static always_inline void setMessageType(TransmissionParams *tp, MmrCanMessageType type) {
tp->headers.mmr.messageType = type;
}