Vehicle Control Unit 0.01
This is the c library for controlling the car.
Loading...
Searching...
No Matches
Can.c
Go to the documentation of this file.
1#ifndef TEST_MODE
2#include "stm32f7xx_it.h"
3#endif
4
5#include "../../../../Inc/Systems/Comms/Can/Can.h"
6#include "../../../../Inc/Systems/Comms/Can/DBCParser.h"
7#include "../../../../Inc/Utils/Common.h"
8#include "../../../../Inc/Utils/MessageFormat.h"
9
10#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13#include <inttypes.h>
14
15// CAN message list
17
19 // Initialize the CAN message list
20 can_messages[bus].bus = bus;
22
23 return 0;
24}
25
26int load_dbc_file(CANBus bus, const unsigned char* filename)
27{
28 // Load the DBC file
29 #ifdef TEST_MODE
30 // unsigned char* dbc_contents = fopen(filename, "w");
31 #else
32 unsigned char* dbc_contents = filename;
33 #endif
34// //printf("Loading DBC file: %c\r\r\n", filename[0]);
35
36 #ifndef TEST_MODE
37 // Parse the DBC file
38 parseDbcFile(&can_messages[bus], dbc_contents);
39 #endif
40
41 #ifdef TEST_MODE
42 // fclose(dbc_contents);
43 #endif
44
46 return 0;
47}
48
50 // Add the message to the list
53 return 0;
54}
55
56int add_message_lop(CANBus bus, int id, int dlc, int ide, int rtr, const char* name, const char* sender, int signal_count, CAN_Signal_Template* signals)
57{
58 // Create a CAN message template
60 message.id = id;
61 message.dlc = dlc;
62 message.ide = ide;
63 message.rtr = rtr;
64 strcpy(message.name, name);
65 strcpy(message.sender, sender);
66 message.signal_count = signal_count;
67 message.payload_length = 0;
68
69 // Copy the signals
70 for (int i = 0; i < signal_count; i++) {
71 message.signals[i] = signals[i];
72 message.payload_length += signals[i].length;
73 }
74
75 // Add the message to the list
76 return add_message(bus, message);
77}
78
79// Send a CAN message
80int send_CAN_message(CANBus bus, CANProtocol protocol, uint32_t id, uint8_t* data, uint8_t len) {
81 CAN_TxHeaderTypeDef TxHeader;
82 if (protocol == CAN_2A) {
83 TxHeader.StdId = id;
84 TxHeader.IDE = CAN_ID_STD;
85 } else if (protocol == CAN_2B) {
86 TxHeader.ExtId = id;
87 TxHeader.IDE = CAN_ID_EXT;
88 } else {
89 //printf("Invalid CAN protocol\r\n");
90 return -1;
91 }
92
93 TxHeader.RTR = CAN_RTR_DATA;
94 TxHeader.DLC = len;
95
96 // Print the message
97 printf(ANSI_COLOR_YELLOW "Sending CAN Message" ANSI_COLOR_RESET ": ID: %d, DLC: %d, Data: ", id, len);
98 for (int i = 0; i < len; i++) {
99 printf("%02X ", data[i]);
100 }
101 printf("\r\n");
102
103 #ifndef TEST_MODE
104 // Send the CAN message
105 if (send_CAN_message_helper(bus, &TxHeader, data) != 0) {
106 return -2;
107 }
108 #endif
109 return 0;
110}
111
112// Receive a CAN message from the Callback
113void receive_CAN_message(CAN_RxHeaderTypeDef* RxHeader, uint8_t* RxData, CANBus bus) {
114 CAN_Message* can_message = malloc(sizeof(CAN_Message) + sizeof(CAN_Signal) * 8);
115 can_message->header = *RxHeader;
116 memcpy(can_message->data, RxData, 8);
117
118 // Send telemetry message for received CAN data
119 char data_hex[17]; // 8 bytes * 2 hex chars + null terminator
120 for (int i = 0; i < RxHeader->DLC && i < 8; i++) {
121 sprintf(&data_hex[i*2], "%02X", RxData[i]);
122 }
123 data_hex[RxHeader->DLC * 2] = '\0';
124
125 // Send properly formatted CAN RX message
126 sendMessage("CAN", MSG_CAN_RX, "ID:0x%lX;DLC:%lu;Data:%s",
127 RxHeader->StdId, RxHeader->DLC, data_hex);
128
129 // Parse the message
130 parseMessage(&can_messages[bus], can_message);
131
132 // Print out the contents of the message
133 //printf(ANSI_COLOR_YELLOW "Received CAN Message" ANSI_COLOR_RESET ": %s (ID: %d, DLC: %d, Sender: %s)\r\n", can_message->template->name, can_message->header.StdId, can_message->header.DLC, can_message->template->sender);
134
135 // Print the signals
136 for (int i = 0; i < can_message->template->signal_count; i++) {
137 CAN_Signal* signal = &can_message->signals[i];
138 //printf("\t" ANSI_COLOR_MAGENTA "Signal" ANSI_COLOR_RESET ": %s (Value: %u, Unit: %s)\r\n", signal->template->name, signal->value, signal->template->unit);
139 }
140 //printf("\r\n");
141
142 // Free the message
143 free(can_message);
144}
145
146// Parse a CAN message
147void parseMessage(CAN_MessageList* messages, CAN_Message* can_message) {
148 // Find the message in the list
149 // TODO: Implement a hash table or map for faster lookup
150 for (int i = 0; i < messages->num_messages; i++) {
151 CAN_Message_Template* msg = &messages->messages[i];
152 if (msg->id == can_message->header.StdId || msg->id == can_message->header.ExtId) {
153 // Parse the signals of the message
154 can_message->template = msg;
155 parseSignals(msg, can_message);
156 return;
157 }
158 }
159}
160
161// Parse the signals of a CAN message
162void parseSignals(CAN_Message_Template* message, CAN_Message* can_message) {
163 // Find the signals in the message
164 for (int i = 0; i < message->signal_count; i++) {
165 CAN_Signal_Template* signal = &message->signals[i];
166 // Parse the signal
167 parseSignal(signal, &can_message->signals[i], can_message);
168 }
169}
170
171// Parse a CAN signal
172void parseSignal(CAN_Signal_Template* signal, CAN_Signal* can_signal, CAN_Message* can_message) {
173 can_signal->template = signal;
174
175 // Extract the raw data from the message
176 uint64_t raw_data = 0;
177 for (int i = signal->start_bit; i < signal->start_bit + signal->length; i++) {
178 raw_data |= ((can_message->data[i / 8] >> (i % 8)) & 1) << (i - signal->start_bit);
179 }
180
181 // Check if the signal is big endian
182 if (signal->endian == 1) {
183 // Reverse the bits
184 uint64_t reversed_data = 0;
185 for (int i = 0; i < signal->length; i++) {
186 reversed_data |= ((raw_data >> i) & 1) << (signal->length - i - 1);
187 }
188 raw_data = reversed_data;
189 }
190
191 // Check if the signal is signed
192 if (signal->isSigned) {
193 // Sign extend the data
194 raw_data = (raw_data << (64 - signal->length)) >> (64 - signal->length);
195 }
196
197 // Scale and offset the data
198 can_signal->value = (raw_data * signal->scale) + signal->offset;
199
200}
201
203 for (int i = 0; i < MAX_BUS; i++) {
204 //printf("Printing CAN Message List for bus %d with %d messages\r\n", i, can_messages[i].num_messages);
205 for (int j = 0; j < can_messages[i].num_messages; j++) {
206 const CAN_Message_Template* msg = &can_messages[i].messages[j];
207 //printf(ANSI_COLOR_GREEN "Message" ANSI_COLOR_RESET ": %s (ID: %d, DLC: %d, Sender: %s, SIGs: %d)\r\n", msg->name, msg->id, msg->dlc, msg->sender, msg->signal_count);
208 for (int k = 0; k < msg->signal_count; k++) {
209 const CAN_Signal_Template* sig = &msg->signals[k];
210 //printf("\t" ANSI_COLOR_BLUE "Signal" ANSI_COLOR_RESET ": %s (Start bit: %d, Length: %d, Endain: %d, Signed: %c,\r\n\t\tScale: %f, Offset: %f, Min: %f, Max: %f, \r\n\t\tUnit: %s, Reciever: %s)\r\n", sig->name, sig->start_bit, sig->length, sig->endian, sig->isSigned, sig->scale, sig->offset, sig->min, sig->max, sig->unit, sig->reciever);
211 }
212 //printf("\r\n");
213 }
214 if (can_messages[i].num_messages == 0) {
215 //printf("No messages on bus %d\r\n", i);
216 }
217 }
218}
int init_CANBus(CANBus bus)
Initializes the CANBus struct.
Definition: Can.c:18
CAN_MessageList can_messages[MAX_BUS]
Definition: Can.c:16
void parseSignals(CAN_Message_Template *message, CAN_Message *can_message)
Parses signals in a CAN message.
Definition: Can.c:162
void parseSignal(CAN_Signal_Template *signal, CAN_Signal *can_signal, CAN_Message *can_message)
Parses a CAN signal.
Definition: Can.c:172
void parseMessage(CAN_MessageList *messages, CAN_Message *can_message)
Parses a CAN message.
Definition: Can.c:147
int add_message(CANBus bus, CAN_Message_Template message)
Adds a message to the CAN message list.
Definition: Can.c:49
int add_message_lop(CANBus bus, int id, int dlc, int ide, int rtr, const char *name, const char *sender, int signal_count, CAN_Signal_Template *signals)
Adds a message to the CAN message list by passing in the individual message parameters hence "LOP" (L...
Definition: Can.c:56
int send_CAN_message(CANBus bus, CANProtocol protocol, uint32_t id, uint8_t *data, uint8_t len)
Sends a CAN message.
Definition: Can.c:80
void receive_CAN_message(CAN_RxHeaderTypeDef *RxHeader, uint8_t *RxData, CANBus bus)
Receives a CAN message.
Definition: Can.c:113
int load_dbc_file(CANBus bus, const unsigned char *filename)
Loads a DBC file into the CAN database. Makes the messages and signals and stores them in the list.
Definition: Can.c:26
void print_CAN_Messages_Lists()
Prints the CAN message list.
Definition: Can.c:202
CANBus
Definition: Can.h:98
#define MAX_BUS
Definition: Can.h:94
CANProtocol
Definition: Can.h:104
@ CAN_2A
Definition: Can.h:105
@ CAN_2B
Definition: Can.h:106
#define ANSI_COLOR_YELLOW
Definition: Common.h:11
#define ANSI_COLOR_RESET
Definition: Common.h:15
int parseDbcFile(CAN_MessageList *messages, const unsigned char *dbc_contents)
Parses a DBC (CAN database) file and populates the DBC structure.
Definition: DBCParser.c:31
void print_CAN_MessageList(const CAN_MessageList *messages)
Prints the contents of a CAN message list (aka DBC file).
Definition: DBCParser.c:44
@ MSG_CAN_RX
Definition: MessageFormat.h:16
void sendMessage(const char *sender, MessageType type, const char *format,...)
Definition: MessageFormat.c:5
static TelemetrySignal signals[MAX_TELEMETRY_SIGNALS]
Definition: Telemetry.c:8
This file contains the headers of the interrupt handlers.
int send_CAN_message_helper(CANBus bus, CAN_TxHeaderTypeDef *TxHeader, uint8_t *data)
Definition: stm32f7xx_it.c:382
CANBus bus
Definition: Can.h:122
CAN_Message_Template messages[MAX_MESSAGES]
Definition: Can.h:123
int num_messages
Definition: Can.h:124
char sender[MAX_NODE_NAME_LENGTH]
Definition: Can.h:78
int signal_count
Definition: Can.h:80
int payload_length
Definition: Can.h:81
CAN_Signal_Template signals[MAX_SIGNALS]
Definition: Can.h:79
char name[MAX_MESSAGE_NAME_LENGTH]
Definition: Can.h:77
uint8_t data[8]
Definition: Can.h:86
CAN_Signal signals[]
Definition: Can.h:88
CAN_Message_Template * template
Definition: Can.h:87
CAN_RxHeaderTypeDef header
Definition: Can.h:85
float offset
Definition: Can.h:26
float scale
Definition: Can.h:25
Definition: Can.h:33
int value
Definition: Can.h:34
CAN_Signal_Template * template
Definition: Can.h:35