Skip to content

Commit 78077c0

Browse files
committed
Merge branch 'main' into Charger
2 parents 99200e0 + b7f76df commit 78077c0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2045
-7560
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ build/
2323
# Doxygen autogenerated files
2424
Doxygen
2525

26+
# mbed-os
27+
**/mbed-os/
28+
**/mbed-os-build/
29+
**/mbed-os-build
30+
2631
# Python virtual environment (for using mbed-cli)
2732
.venv/
2833

@@ -33,6 +38,8 @@ Doxygen
3338
# cmake build cache
3439
**/cmake_build
3540

41+
**/.idea
42+
3643

3744
*.iml
3845
mbed-os-build/

CANDecoder/CANInterface.hpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#ifndef CAN_INTERFACE_HPP
2+
#define CAN_INTERFACE_HPP
3+
4+
#include "mbed.h"
5+
6+
/**
7+
* @brief Abstract interface for CAN communication
8+
* This enables dependency injection and mocking for testing
9+
*/
10+
class ICAN {
11+
public:
12+
virtual ~ICAN() = default;
13+
14+
/**
15+
* @brief Read a CAN message if available
16+
* @param msg Reference to store the received message
17+
* @return true if message was read, false if no message available
18+
*/
19+
virtual bool read(CANMessage& msg) = 0;
20+
21+
/**
22+
* @brief Send a CAN message
23+
* @param msg Message to send
24+
* @return true if message was sent successfully
25+
*/
26+
virtual bool write(const CANMessage& msg) = 0;
27+
28+
/**
29+
* @brief Check if CAN interface is ready
30+
* @return true if ready for communication
31+
*/
32+
virtual bool isReady() const = 0;
33+
};
34+
35+
/**
36+
* @brief Real CAN implementation using mbed CAN
37+
*/
38+
class MbedCAN : public ICAN {
39+
private:
40+
CAN& _can;
41+
42+
public:
43+
explicit MbedCAN(CAN& can) : _can(can) {}
44+
45+
bool read(CANMessage& msg) override {
46+
return _can.read(msg);
47+
}
48+
49+
bool write(const CANMessage& msg) override {
50+
return _can.write(msg);
51+
}
52+
53+
bool isReady() const override {
54+
return true; // mbed CAN is always ready after construction
55+
}
56+
};
57+
58+
/**
59+
* @brief Mock CAN implementation for testing on STM32
60+
*/
61+
class MockCAN : public ICAN {
62+
private:
63+
static constexpr size_t MAX_MESSAGES = 32;
64+
CANMessage _incomingMessages[MAX_MESSAGES];
65+
CANMessage _sentMessages[MAX_MESSAGES];
66+
size_t _incomingCount = 0;
67+
size_t _sentCount = 0;
68+
size_t _messageIndex = 0;
69+
bool _isReady = true;
70+
71+
public:
72+
// Test setup methods
73+
void injectMessage(const CANMessage& msg) {
74+
if (_incomingCount < MAX_MESSAGES) {
75+
_incomingMessages[_incomingCount++] = msg;
76+
}
77+
}
78+
79+
void setReady(bool ready) { _isReady = ready; }
80+
81+
// Verification methods
82+
size_t getSentMessageCount() const { return _sentCount; }
83+
const CANMessage& getSentMessage(size_t index) const { return _sentMessages[index]; }
84+
85+
void clearSentMessages() { _sentCount = 0; }
86+
void clearIncomingMessages() {
87+
_incomingCount = 0;
88+
_messageIndex = 0;
89+
}
90+
91+
// ICAN implementation
92+
bool read(CANMessage& msg) override {
93+
if (_messageIndex >= _incomingCount) {
94+
return false;
95+
}
96+
msg = _incomingMessages[_messageIndex++];
97+
return true;
98+
}
99+
100+
bool write(const CANMessage& msg) override {
101+
if (!_isReady || _sentCount >= MAX_MESSAGES) return false;
102+
_sentMessages[_sentCount++] = msg;
103+
return true;
104+
}
105+
106+
bool isReady() const override {
107+
return _isReady;
108+
}
109+
};
110+
111+
#endif // CAN_INTERFACE_HPP

CANDecoder/CANProtocol.hpp

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
// CANProtocol.hpp
2+
// Types for extracting CAN messages from the CAN bus
3+
// (Refer to ../CANbus.dbc for the protocol)
4+
// Written by: Njeri Gachoka
5+
6+
#ifndef CANPROTOCOL_HPP
7+
#define CANPROTOCOL_HPP
8+
9+
#include "mbed.h"
10+
#include <cstdint>
11+
12+
namespace CAN_ID {
13+
// ACC
14+
constexpr uint32_t ACC_STATUS = 0x188;
15+
constexpr uint32_t ACC_SEG0_VOLTS = 0x191;
16+
constexpr uint32_t ACC_SEG1_VOLTS = 0x192;
17+
constexpr uint32_t ACC_SEG2_VOLTS = 0x193;
18+
constexpr uint32_t ACC_SEG3_VOLTS = 0x194;
19+
constexpr uint32_t ACC_SEG4_VOLTS = 0x195;
20+
constexpr uint32_t ACC_POWER = 0x288;
21+
constexpr uint32_t ACC_SEG0_TEMPS = 0x291;
22+
constexpr uint32_t ACC_SEG1_TEMPS = 0x292;
23+
constexpr uint32_t ACC_SEG2_TEMPS = 0x293;
24+
constexpr uint32_t ACC_SEG3_TEMPS = 0x294;
25+
constexpr uint32_t ACC_SEG4_TEMPS = 0x295;
26+
// ETC
27+
constexpr uint32_t ETC_STATUS = 0x189;
28+
// PDB
29+
constexpr uint32_t PDB_POWER_A = 0x19A;
30+
constexpr uint32_t PDB_POWER_B = 0x29B;
31+
// SME
32+
constexpr uint32_t SME_THROTTLE_DEMAND = 0x186;
33+
constexpr uint32_t SME_MAX_CURRENTS = 0x286;
34+
constexpr uint32_t SME_TRQSPD = 0x482;
35+
constexpr uint32_t SME_TEMP = 0x682;
36+
// TMAIN
37+
constexpr uint32_t TMAIN_DATA = 0x1A0;
38+
// TPERIPH
39+
constexpr uint32_t TPERIPH_BL_DATA = 0x1A4;
40+
constexpr uint32_t TPERIPH_BL_TIRETEMP = 0x2A3;
41+
constexpr uint32_t TPERIPH_BR_DATA = 0x1A5;
42+
constexpr uint32_t TPERIPH_BR_TIRETEMP = 0x2A4;
43+
constexpr uint32_t TPERIPH_FL_DATA = 0x1A2;
44+
constexpr uint32_t TPERIPH_FL_TIRETEMP = 0x2A1;
45+
constexpr uint32_t TPERIPH_FR_DATA = 0x1A3;
46+
constexpr uint32_t TPERIPH_FR_TIRETEMP = 0x2A2;
47+
// VDM
48+
constexpr uint32_t VDM_GPS_LAT_LONG = 0x000A0000;
49+
constexpr uint32_t VDM_GPS_DATA = 0x000A0001;
50+
constexpr uint32_t VDM_DATE_TIME = 0x000A0002;
51+
constexpr uint32_t VDM_ACCELERATION = 0x000A0003;
52+
constexpr uint32_t VDM_YAW_RATE = 0x000A0004;
53+
}
54+
55+
struct ACC_STATUS_t {
56+
uint8_t BMS_FAULT : 1; // bit 0
57+
uint8_t IMD_FAULT : 1; // bit 1
58+
uint8_t SHUTDOWN_STATE : 1; // bit 2
59+
uint8_t PRECHARGE_DONE : 1; // bit 3
60+
uint8_t PRECHARGING : 1; // bit 4
61+
uint8_t CHARGING : 1; // bit 5
62+
uint8_t padding_6_7 : 2; // bits 6-7 (padding for gaps)
63+
uint8_t CELL_TOO_LOW : 1; // bit 8
64+
uint8_t CELL_TOO_HIGH : 1; // bit 9
65+
uint8_t TEMP_TOO_LOW : 1; // bit 10
66+
uint8_t TEMP_TOO_HIGH : 1; // bit 11
67+
uint8_t TEMP_TOO_HIGH_CRG : 1; // bit 12
68+
uint8_t padding_13_15 : 3; // bits 13-15 (padding to complete byte)
69+
uint16_t GLV_VOLTAGE; // bits 16-31
70+
uint32_t CELL_FAULT_INDEX; // bits 32-63
71+
};
72+
73+
struct ACC_SEG_VOLTS_t {
74+
uint8_t VOLTS_CELL0; // bits 0-7
75+
uint8_t VOLTS_CELL1; // bits 8-15
76+
uint8_t VOLTS_CELL2; // bits 16-23
77+
uint8_t VOLTS_CELL3; // bits 24-31
78+
uint8_t VOLTS_CELL4; // byte 32-39
79+
uint8_t VOLTS_CELL5; // byte 40-47
80+
};
81+
82+
struct ACC_POWER_t {
83+
uint16_t PACK_VOLTAGE; // bits 0-15
84+
uint8_t SOC; // bits 16-23
85+
uint16_t CURRENT; // bits 24-39
86+
};
87+
88+
struct ACC_SEG_TEMPS_t {
89+
uint8_t TEMPS_CELL0; // bits 0-7
90+
uint8_t TEMPS_CELL1; // bits 8-15
91+
uint8_t TEMPS_CELL2; // bits 16-23
92+
uint8_t TEMPS_CELL3; // bits 24-31
93+
uint8_t TEMPS_CELL4; // bits 32-39
94+
uint8_t TEMPS_CELL5; // bits 40-47
95+
};
96+
97+
struct ETC_STATUS_t {
98+
uint16_t HE1; // bits 0-15
99+
uint16_t HE2; // bits 16-31
100+
uint16_t BRAKE_SENSE_VOLTAGE; // bits 32-47
101+
uint8_t PEDAL_TRAVEL; // bits 48-55
102+
uint8_t RTD_BUTTON : 1; // bit 56
103+
uint8_t RTDS : 1; // bit 57
104+
uint8_t REVERSE : 1; // bit 58
105+
uint8_t BRAKELIGHT : 1; // bit 59
106+
uint8_t RTD : 1; // bit 60
107+
uint8_t IMPLAUSIBILITY : 1; // bit 61
108+
uint8_t TS_ACTIVE : 1; // bit 62
109+
};
110+
111+
struct PDB_POWER_A_t {
112+
uint16_t GLV_VOLTAGE; // bits 0-15
113+
uint8_t CURRENT_SHUTDOWN; // bits 16-23
114+
uint8_t CURRENT_ACC; // bits 24-31
115+
uint8_t CURRENT_ETC; // bits 32-39
116+
uint8_t CURRENT_BPS; // bits 40-47
117+
uint8_t CURRENT_TRACTIVE; // bits 48-55
118+
uint8_t CURRENT_BSPD; // bits 56-63
119+
};
120+
121+
struct PDB_POWER_B_t {
122+
uint8_t CURRENT_TELEMETRY; // bits 0-7
123+
uint8_t CURRENT_PDB; // bits 8-15
124+
uint8_t CURRENT_DASH; // bits 16-23
125+
uint8_t CURRENT_RTML; // bits 24-31
126+
uint8_t CURRENT_EXTRA_1; // bits 32-39
127+
uint8_t CURRENT_EXTRA_2; // bits 40-47
128+
};
129+
130+
struct SME_THROTTLE_DEMAND_t {
131+
uint16_t TORQUE_DEMAND; // bits 0-15
132+
uint16_t MAX_SPEED; // bits 16-31
133+
uint8_t FORWARD : 1; // bit 32
134+
uint8_t REVERSE : 1; // bit 33
135+
uint8_t padding_34 : 1; // bit 34 (used for alignment)
136+
uint8_t POWER_READY : 1; // bit 35
137+
uint8_t padding2 : 4; // bits 36-39
138+
uint8_t MBB_ALIVE: 1; // bit 40
139+
};
140+
141+
struct SME_TRQSPD_t {
142+
uint16_t SPEED; // bits 0-15
143+
uint16_t TORQUE; // bits 16-31
144+
uint8_t SOC_LOW_TRACTION : 1; // bit 32
145+
uint8_t SOC_LOW_HYDRAULIC : 1; // bit 33
146+
uint8_t REVERSE : 1; // bit 34
147+
uint8_t FORWARD : 1; // bit 35
148+
uint8_t PARK_BRAKE : 1; // bit 36
149+
uint8_t PEDAL_BRAKE : 1; // bit 37
150+
uint8_t CONTROLLER_OVERTEMP : 1; // bit 38
151+
uint8_t KEY_SWITCH_OVERVOLT : 1; // bit 39
152+
uint8_t KEY_SWITCH_UNDERVOLT: 1; // bit 40
153+
uint8_t RUNNING : 1; // bit 41
154+
uint8_t TRACTION : 1; // bit 42
155+
uint8_t HYDRAULIC : 1; // bit 43
156+
uint8_t POWERING_ENABLED : 1; // bit 44
157+
uint8_t POWERING_READY : 1; // bit 45
158+
uint8_t PRECHARGING : 1; // bit 46
159+
uint8_t CONTACTOR_CLOSED : 1; // bit 47
160+
uint16_t MOTOR_FLAGS; // bits 48-63
161+
};
162+
163+
struct SME_TEMP_t {
164+
uint8_t MOTOR_TEMP; // bits 0-7
165+
uint8_t CONTROLLER_TEMP; // bits 8-15
166+
uint16_t DC_BUS_V; // bits 16-31
167+
uint8_t FAULT_CODE; // bits 32-39
168+
uint8_t FAULT_LEVEL; // bits 40-47
169+
uint16_t BUS_CURRENT; // bits 48-63
170+
};
171+
172+
struct SME_MAX_CURRENTS_t {
173+
uint16_t CHARGE_CURRENT; // bits 0-15
174+
uint16_t DISCHARGE_CURRENT; // bits 16-31
175+
};
176+
177+
struct TMAIN_DATA_t {
178+
uint16_t BRAKES_F; // bits 0-15
179+
uint16_t BRAKES_R; // bits 16-31
180+
};
181+
182+
struct TPERIPH_DATA_t {
183+
uint16_t WHEELSPEED; // bits 0-15
184+
uint16_t SUSTRAVEL; // bits 16-31
185+
uint16_t STRAIN; // bits 32-47
186+
uint8_t SIDE_TIRE_TEMP; // bits 48-55
187+
};
188+
189+
struct TPERIPH_TIRETEMP_t {
190+
uint8_t TIRETEMP_1; // bits 0-7
191+
uint8_t TIRETEMP_2; // bits 8-15
192+
uint8_t TIRETEMP_3; // bits 16-23
193+
uint8_t TIRETEMP_4; // bits 24-31
194+
uint8_t TIRETEMP_5; // bits 32-39
195+
uint8_t TIRETEMP_6; // bits 40-47
196+
uint8_t TIRETEMP_7; // bits 48-55
197+
uint8_t TIRETEMP_8; // bits 56-63
198+
199+
};
200+
201+
struct VDM_GPS_LAT_LONG_t {
202+
int32_t LATITUDE; // bits 7-38
203+
int32_t LONGITUDE; // bits 39-50
204+
};
205+
206+
struct VDM_GPS_DATA_t {
207+
int16_t SPEED; // bits 7-22
208+
int16_t ALTITUDE; // bits 23-38
209+
int16_t TRUE_COURSE; // bits 39-54
210+
int8_t SATELLITES_IN_USE; // bits 55-62
211+
int8_t VALID1; // bits 63-70
212+
};
213+
214+
struct VDM_DATE_TIME_t {
215+
int8_t VALID2; // bits 7-14
216+
int8_t UTC_DATE_YEAR; // bits 15-22
217+
int8_t UTC_DATE_MONTH; // bits 23-30
218+
int8_t UTC_DATE_DAY; // bits 31-38
219+
int8_t UTC_TIME_HOURS; // bits 47-54
220+
int8_t UTC_TIME_MINUTES; // bits 55-62
221+
int8_t UTC_TIME_SECONDS; // bits 63-70
222+
};
223+
224+
struct VDM_ACCELERATION_t {
225+
int16_t X; // bits 7-22
226+
int16_t Y; // bits 23-38
227+
int16_t Z; // bits 39-54
228+
};
229+
230+
struct VDM_YAW_RATE_t {
231+
int16_t X; // bits 7-22
232+
int16_t Y; // bits 23-38
233+
int16_t Z; // bits 39-54
234+
};
235+
236+
#endif // CANPROTOCOL_HPP

0 commit comments

Comments
 (0)