346 lines
11 KiB
C
346 lines
11 KiB
C
#include "CanDataHandler.h"
|
|
#include "string.h"
|
|
|
|
#define MAX_DATA_STORAGE 100
|
|
#define MAX_EVENT_STORAGE 100
|
|
#define MAX_FILTER_SLOTS 100
|
|
|
|
// storage for upto MAX_DATA_STORAGE diffrent messages
|
|
static CanDataMessageSlot CanDataStore[MAX_DATA_STORAGE] = {0};
|
|
|
|
// storage for upto MAX_EVENT_STORAGE diffrent event handlers
|
|
static CanDataEventSlot CanEventStore[MAX_DATA_STORAGE] = {0};
|
|
|
|
// storage for upto MAX_FILTER_SLOTS diffrent can filters
|
|
static CanDataFilterSlot CanFilterSlots[MAX_FILTER_SLOTS] = {0};
|
|
|
|
// this will setup the canfilter accoridng to the settings
|
|
void setup_StmCanFilter(const CanDataFilterSlot* filterSetting ) {
|
|
size_t f_index = filterSetting - CanFilterSlots;// index of the filter in CanFilterSlots
|
|
|
|
CLS_BSP_CAN_UniversalFilter clsFilterConfig = {
|
|
.filterIndex = f_index,
|
|
.filterDestination = filterSetting->fifo,
|
|
.filterMode = CLS_BSP_CAN_FILTER_LIST,
|
|
.id0 = filterSetting->id[0],
|
|
.id1 = filterSetting->id[1],
|
|
};
|
|
|
|
CLS_BSP_CAN_SetUniversalFilter(&clsFilterConfig);
|
|
}
|
|
|
|
// this will setup the canfilter using a custom defined filter
|
|
void setup_StmCanFilterManual(const CanDataFilterSlot* filterSetting, CLS_BSP_CAN_UniversalFilter * filter ) {
|
|
size_t f_index = filterSetting - CanFilterSlots;// index of the filter in CanFilterSlots
|
|
filter->filterIndex = f_index;
|
|
CLS_BSP_CAN_SetUniversalFilter(filter);
|
|
}
|
|
|
|
|
|
void CanDataHandler_init(void) {
|
|
// Reset all data message slots
|
|
for (int i = 0; i < MAX_DATA_STORAGE; i++) {
|
|
CanDataStore[i].msg.canid = 0;
|
|
CanDataStore[i].msg.data_length = 0;
|
|
memset(CanDataStore[i].msg.data, 0, MAX_DATA_LENGTH);
|
|
CanDataStore[i].filter.ref = NULL;
|
|
CanDataStore[i].filter.index = 0;
|
|
}
|
|
|
|
// Reset all event message slots
|
|
for (int i = 0; i < MAX_EVENT_STORAGE; i++) {
|
|
CanEventStore[i].canid = 0;
|
|
CanEventStore[i].eventCall = NULL;
|
|
CanEventStore[i].filter.ref = NULL;
|
|
CanEventStore[i].filter.index = 0;
|
|
}
|
|
|
|
// Reset all filter slots
|
|
for (int i = 0; i < MAX_FILTER_SLOTS; i++) {
|
|
CanFilterSlots[i].free = CANDATA_ALLFREE;
|
|
CanFilterSlots[i].fifo = CANDATA_FIFOX_UNDEFIEND;
|
|
CanFilterSlots[i].id[0] = 0;
|
|
CanFilterSlots[i].id[1] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Finds and returns an unused filter slot. If no unused slot is found, returns NULL.
|
|
*/
|
|
CanDataFilterRef CanData_unusedFilterSlot(CanDataSlotFifo reqest_fifo) {
|
|
CanDataFilterRef filterRef = {NULL, 0};
|
|
|
|
for (size_t i = 0; i < MAX_FILTER_SLOTS; i++) {
|
|
// find a slot with free some id
|
|
if (CanFilterSlots[i].free < CANDATA_FULL) {
|
|
|
|
// either the fifo settig matches or is undefined
|
|
if(CanFilterSlots[i].fifo == reqest_fifo || CanFilterSlots[i].fifo == CANDATA_FIFOX_UNDEFIEND)
|
|
filterRef.ref = &CanFilterSlots[i];
|
|
if (CanFilterSlots[i].fifo == CANDATA_FIFOX_UNDEFIEND) {
|
|
CanFilterSlots[i].fifo = reqest_fifo;
|
|
}
|
|
|
|
// Determine the index based on the 'free' field
|
|
switch (CanFilterSlots[i].free) {
|
|
case CANDATA_ALLFREE:
|
|
filterRef.index = 0;
|
|
CanFilterSlots[i].free = CANDATA_FREE1;
|
|
break;
|
|
case CANDATA_FREE1:
|
|
filterRef.index = 1;
|
|
CanFilterSlots[i].free = CANDATA_FULL;
|
|
break;
|
|
case CANDATA_FREE0:
|
|
filterRef.index = 0;
|
|
CanFilterSlots[i].free = CANDATA_FULL;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
return filterRef;
|
|
}
|
|
|
|
void CanData_clearFilterSlot(CanDataFilterRef filter) {
|
|
|
|
// reset the filter can id
|
|
filter.ref->id[filter.index] = 0;
|
|
|
|
// set the slot as free
|
|
if(filter.index == 0) {
|
|
filter.ref->free = filter.ref->free & CANDATA_FREE0;
|
|
} else if( filter.index == 1) {
|
|
filter.ref->free = filter.ref->free & CANDATA_FREE1;
|
|
}
|
|
|
|
// if the filterslot is now fully free reset the fifo settings
|
|
if(filter.ref->free == CANDATA_ALLFREE) {
|
|
filter.ref->fifo = CANDATA_FIFOX_UNDEFIEND;
|
|
}
|
|
|
|
|
|
// finaly write new HW config
|
|
setup_StmCanFilter(filter.ref);
|
|
}
|
|
|
|
/**
|
|
* Finds and returns an unused data message slot. If no unused slot is found, returns NULL.
|
|
*/
|
|
CanDataMessageSlot * CanData_unusedDataSlot() {
|
|
for (size_t i = 0; i < MAX_DATA_STORAGE; i++) {
|
|
if (CanDataStore[i].msg.canid == 0) {
|
|
return &CanDataStore[i];
|
|
}
|
|
}
|
|
return NULL; // No unused slot found
|
|
}
|
|
|
|
/**
|
|
* Finds and returns an unused event slot. If no unused slot is found, returns NULL.
|
|
*/
|
|
CanDataEventSlot * CanData_unusedEventSlot() {
|
|
for (size_t i = 0; i < MAX_EVENT_STORAGE; i++) {
|
|
if (CanEventStore[i].canid == 0) {
|
|
return &CanEventStore[i];
|
|
}
|
|
}
|
|
return NULL; // No unused slot found
|
|
}
|
|
|
|
/**
|
|
* Registers a data message with given CanDataId. Returns true if registration is successful, false otherwise.
|
|
*/
|
|
bool CanData_regDataMsg(CanDataId canid) {
|
|
|
|
// check if we already have this canid to avoid duplicates
|
|
if(CanData_getDataMessage(canid) != NULL) {
|
|
return true; // but return true beause there is already a vaild entry for this canid
|
|
}
|
|
|
|
// Find an unused slot in the data store
|
|
CanDataMessageSlot *dataSlot = CanData_unusedDataSlot();
|
|
if (!dataSlot) {
|
|
return false; // No unused data slot available
|
|
}
|
|
|
|
// Find and configure an unused slot for the data message
|
|
CanDataFilterRef filter = CanData_unusedFilterSlot(CANDATA_FIFO0_DATA);
|
|
if (filter.ref == NULL) {
|
|
return false; // No unused filter slot available
|
|
}
|
|
|
|
// Configure the filter slot
|
|
filter.ref->id[filter.index] = canid;
|
|
|
|
// Set up the filter with the new settings
|
|
setup_StmCanFilter(filter.ref);
|
|
|
|
|
|
// Register the data message with the data slot
|
|
dataSlot->msg.canid = canid;
|
|
dataSlot->filter = filter; // Store the pointer to the filter slot
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// Function to register a Set of ID for Data Messages using a Manual filter
|
|
size_t CanData_regDataManualMsg(const CanDataId* canid, size_t id_count, CLS_BSP_CAN_UniversalFilter * filter) {
|
|
// first check all id to be new
|
|
for (size_t i = 0; i < id_count; i++) {
|
|
if(CanData_getDataMessage(canid[i]) != NULL) {
|
|
return 0; // invalid operation one id is already used
|
|
}
|
|
}
|
|
|
|
// Find and configure one unused slot for the manual filter
|
|
CanDataFilterRef filterRef = CanData_unusedFilterSlot(CANDATA_FIFOX_MANUAL);
|
|
if (filterRef.ref == NULL) {
|
|
return 0; // No unused filter slot available
|
|
}
|
|
|
|
// setup the manual filters
|
|
filterRef.ref->fifo = CANDATA_FIFOX_MANUAL;
|
|
filterRef.ref->free = CANDATA_MANUAL;
|
|
setup_StmCanFilterManual(filterRef.ref, filter);
|
|
|
|
|
|
for (size_t i = 0; i < id_count; i++) {
|
|
// Find an unused slot in the data store
|
|
CanDataMessageSlot *dataSlot = CanData_unusedDataSlot();
|
|
if (!dataSlot) {
|
|
return i; // No unused data slot available
|
|
}
|
|
|
|
dataSlot->filter = filterRef;
|
|
dataSlot->filter.index = -1; // this idecates is a manual filter
|
|
}
|
|
|
|
return id_count;
|
|
}
|
|
|
|
/**
|
|
* Registers a event message with given CanDataId. Returns true if registration is successful, false otherwise.
|
|
*/
|
|
bool CanData_regEventMsg(CanDataId canid, EventCallback event_callback) {
|
|
|
|
// Check for vaild callback
|
|
if(event_callback == NULL) {
|
|
return false;
|
|
}
|
|
|
|
// Check if the canid is already registered
|
|
for (int i = 0; i < MAX_EVENT_STORAGE; i++) {
|
|
if (CanEventStore[i].canid == canid) {
|
|
return false; // The canid is already registered
|
|
}
|
|
}
|
|
|
|
// Find an unused slot in the event store
|
|
CanDataEventSlot *eventSlot = CanData_unusedEventSlot();
|
|
if (eventSlot == NULL) {
|
|
return false; // No unused event slot available
|
|
}
|
|
|
|
// Find and configure an unused slot for the data message
|
|
CanDataFilterRef filter = CanData_unusedFilterSlot(CANDATA_FIFO0_DATA);
|
|
if (filter.ref == NULL) {
|
|
return false; // No unused filter slot available
|
|
}
|
|
|
|
// Configure the filter slot
|
|
filter.ref->id[filter.index] = canid;
|
|
|
|
// Set up the filter with the new settings
|
|
setup_StmCanFilter(filter.ref);
|
|
|
|
// Register the event message with the event slot
|
|
eventSlot->canid = canid;
|
|
eventSlot->eventCall = event_callback;
|
|
eventSlot->filter = filter; // Store the pointer to the filter slot
|
|
|
|
return true;
|
|
}
|
|
|
|
// Function to remove a CAN ID from Event Messages Register
|
|
bool CanData_removeEvent(CanDataId canid) {
|
|
// Search for the event slot with the given CanDataId
|
|
for (size_t i = 0; i < MAX_EVENT_STORAGE; i++) {
|
|
if (CanEventStore[i].canid == canid) {
|
|
CanDataEventSlot * eventSlot = &CanEventStore[i];
|
|
CanDataFilterRef filter = eventSlot->filter;
|
|
|
|
// reset the CanDataEventSlot
|
|
eventSlot->canid =0;
|
|
eventSlot->eventCall = NULL;
|
|
eventSlot->filter.index =0;
|
|
eventSlot->filter.ref = NULL;
|
|
|
|
|
|
// reset the filter
|
|
CanData_clearFilterSlot(filter);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
// Function to insert a Data Message into the array
|
|
void CanData_insertDataMessage(CanDataId canid, uint8_t* data, uint8_t data_length) {
|
|
if(data == NULL || data_length == 0 ) {
|
|
return;
|
|
}
|
|
|
|
// Search for the data slot with the given CanDataId
|
|
for (size_t i = 0; i < MAX_DATA_STORAGE; i++) {
|
|
if (CanDataStore[i].msg.canid == canid) {
|
|
// If found, update the data message in the slot
|
|
CanDataStore[i].msg.data_length = data_length;
|
|
memcpy(CanDataStore[i].msg.data, data, data_length);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Function to read stored Data Message based on CAN ID
|
|
// Returns a const pointer to the stored data or NULL if not found
|
|
const CanDataMessage* CanData_getDataMessage(CanDataId canid) {
|
|
// Search for the data message with the given CanDataId
|
|
for (size_t i = 0; i < MAX_DATA_STORAGE; i++) {
|
|
if (CanDataStore[i].msg.canid == canid) {
|
|
return &CanDataStore[i].msg; // Return a pointer to the found data message
|
|
}
|
|
}
|
|
return NULL; // No data message with the given CanDataId found
|
|
}
|
|
|
|
|
|
|
|
// Function to handle reception of Data Messages from FIFO0
|
|
void CanData_canFifo0RxCallback(CanDataId canid, uint8_t* data, uint8_t len) {
|
|
// Insert the data message into the data store
|
|
CanData_insertDataMessage(canid, data, len);
|
|
}
|
|
|
|
// Function to handle reception of Event Messages from FIFO1
|
|
void CanData_canFifo1RxCallback(CanDataId canid, uint8_t* data, uint8_t len) {
|
|
// Search for the event slot with the given CanDataId
|
|
for (size_t i = 0; i < MAX_EVENT_STORAGE; i++) {
|
|
if (CanEventStore[i].canid == canid) {
|
|
// If found, call the event callback with the received data
|
|
CanEventStore[i].eventCall(canid ,data, len);
|
|
return;
|
|
}
|
|
}
|
|
}
|