Open FFBoard
Open source force feedback firmware
Loading...
Searching...
No Matches
CanBridge.cpp
Go to the documentation of this file.
1/*
2 * CanBridge.cpp
3 *
4 * Created on: 20.11.2020
5 * Author: Yannick
6 */
7
8
9#include <CanBridge.h>
10#ifdef CANBRIDGE
11
12#include "ledEffects.h"
13#include "cdc_device.h"
14
16 .name = "CAN Bridge (GVRET)" ,
17 .id=CLSID_MAIN_CAN,
18 .visibility = ClassVisibility::visible //Set false to list
19 };
20
22 return info;
23}
24
26 this->port = &canport;
27
28 // Set up a filter to receive everything
29 CAN_filter filterConf;
30 filterConf.buffer = 0;
31 filterConf.filter_id = 0;
32 filterConf.filter_mask = 0;
33
34 this->filterId = this->port->addCanFilter(filterConf);
35 conf1.enabled = true;
36
37 //CommandHandler::registerCommands();
38 registerCommand("can", CanBridge_commands::can, "Send a frame or get last received frame",CMDFLAG_GET | CMDFLAG_SETADR);
39 registerCommand("rtr", CanBridge_commands::canrtr, "Send a RTR frame",CMDFLAG_GET | CMDFLAG_SET);
40 registerCommand("spd", CanBridge_commands::canspd, "Change or get CAN baud",CMDFLAG_GET | CMDFLAG_SET);
41
42 this->port->setSilentMode(false);
43 this->port->takePort();
44}
45
47 this->port->removeCanFilter(filterId);
48 this->port->freePort();
49}
50
51
52
54 if(port == this->port){
56 }
57}
58
59void CanBridge::sendMessage(uint32_t id, uint64_t msg,uint8_t len = 8,bool rtr = false){
60 memcpy(txBuf,&msg,8);
61 txHeader.id = id;
62 txHeader.length = len;
63 txHeader.rtr = rtr;
64 if(id & 0x80000000){
65 txHeader.extId = true;
66 txHeader.id &= 0x7FFFFFFF;
67 }else{
68 txHeader.extId = false;
69 }
70 if(!this->port->sendMessage(&txHeader, txBuf, &this->txMailbox)){
72 }
73}
74
75// Can only send and receive 32bit for now
77
78 if(msg.fifo == rxfifo){
79
80 lastmsg = msg;
82
83 replyPending = true;
84 }
85}
86
88 std::string buf;
89 buf = "CAN:";
90 buf += std::to_string(msg.header.id);
91 buf += ":";
92 buf += std::to_string(*(int64_t*)msg.data);
93 return buf;
94}
95
97 if(replyPending){
98 CAN_rx_msg msg = lastmsg;
99 if(gvretMode){
100 CAN_msg_header_rx rxHeader = msg.header;
101 uint32_t time = rxHeader.timestamp;
102 uint32_t id = rxHeader.id;
103 if(rxHeader.extId){
104 id |= 0x80000000;
105 }
106 std::vector<char> reply = {
107 0xF1,0,(char)(time & 0xff), (char)((time >> 8) & 0xff), (char)((time >> 16) & 0xff), (char)((time >> 24) & 0xff),
108 (char)(id & 0xff), (char)((id >> 8) & 0xff), (char)((id >> 16) & 0xff), (char)((id >> 24) & 0xff),
109 (char)((rxHeader.length & 0xf) | (1 >> 4))
110 };
111
112 for(uint8_t i = 0; i< rxHeader.length; i++){
113 reply.push_back(msg.data[i]);
114 }
115
116 reply.push_back(0);
117// for(char c : reply){
118// replystr.push_back(c);
119// }
120 tud_cdc_n_write(0,reply.data(), reply.size());
122 }else{
123 std::string replystr = messageToString(msg);
125
126// tud_cdc_n_write(0,replystr.c_str(), replystr.length());
127// tud_cdc_write_flush();
128 }
129
130 replyPending = false;
131 }
132}
133
134
135void CanBridge::cdcRcv(char* Buf, uint32_t *Len){
136
137 // Not a gvret binary command
138
139 if(*Buf == 0xE7){
140 gvretMode = true;
141 }
142
143 if(gvretMode == false || (*Buf != 0xE7 && *Buf != 0xF1)){ // Not gvret command
144 FFBoardMain::cdcRcv(Buf, Len);
145 return;
146 }
147
148
149 /*
150 * Data format in buf:
151 * 0xE1,0xE1,0xF1,cmd,data...
152 * data = buf+2
153 */
154
155 // Find start marker
156 uint8_t pos = 0;
157 for(uint8_t i = 0; i < *Len-pos; i++){
158 pos = i+1;
159 if((Buf[i]) == 0xF1){
160 break;
161 }
162 }
163
164 std::vector<char> reply;
165 while(pos < *Len){
166
167 uint8_t datalength = *Len;
168 uint8_t* data = (uint8_t*)(Buf+pos+1);
169 uint8_t cmd = *(Buf+pos);
170
171 // find next F1 or end
172 for(uint8_t i = 0; i < *Len-pos; i++){
173 datalength = i;
174 if((data[i]) == 0xF1){
175 break;
176 }
177 }
178 pos = pos+datalength+2; // Move offset for next loop
179
180
181 switch(cmd){
182
183 case(0):
184 { // send can
185 if(*Len < 8)
186 break;
187 uint32_t id = *data | (*(data+1) << 8) | (*(data+2) << 16) | (*(data+3) << 24); // = dat[2] | dat[3] >> 8 | dat[3] >> 16 | dat[4] >> 21
188 uint64_t msg = 0;
189 uint8_t bus = data[4];
190 uint8_t msgLen = data[5];
191 if(bus == 0){
192 memcpy(&msg,data+6,std::min<int>(msgLen, 8)); // Copy variable length buffer
193 sendMessage(id, msg,msgLen);
194 }
195
196 break;
197 }
198 case(1):
199 { // sync. Microseconds since start up LSB to MSB
200 uint32_t time = HAL_GetTick()*1000;//HAL_CAN_GetTxTimestamp(CanHandle, txMailbox); // or use systick and scale.
201 std::vector<char> t = {0xF1,cmd,(char)(time & 0xff), (char)((time >> 8) & 0xff), (char)((time >> 16) & 0xff), (char)((time >> 24) & 0xff)};
202 reply.insert(reply.end(),t.begin(),t.end());
203
204 break;
205 }
206 case(2): // get digital in
207
208 break;
209
210 case(3): // get analog in
211
212 break;
213
214 case(4): // set digital out
215
216 break;
217
218 case(5): // set can config
219 {
220 uint32_t speed = *data | (*(data+1) << 8) | (*(data+2) << 16) | (*(data+3) << 24);
221 speed = speed & 0x1fffffff;
222 uint8_t b3 = *(data+3); // config byte
223 if(b3 & 0x80){
224 conf1.enabled = (b3 & 0x40) != 0;
225 conf1.listenOnly = (b3 & 0x20) != 0;
226 }
227 this->port->setSpeed(speed);
228 break;
229 }
230 case(6): // get can config
231 {
232 std::vector<char> t =
233 { 0xF1,cmd,
234 (char)(conf1.enabled | conf1.listenOnly << 4),(char)(conf1.speed & 0xff), (char)((conf1.speed >> 8) & 0xff),(char)((conf1.speed >> 16) & 0xff),(char)((conf1.speed >> 24) & 0xff),
235 (char)(conf2.enabled | conf2.listenOnly << 4),(char)(conf2.speed & 0xff), (char)((conf2.speed >> 8) & 0xff),(char)((conf2.speed >> 16) & 0xff),(char)((conf2.speed >> 24) & 0xff),
236 };
237 reply.insert(reply.end(),t.begin(),t.end());
238 break;
239 }
240
241
242 case(7): // get device info
243 {
244 std::vector<char> t = {0xF1,cmd,1,1,1,0,0,0};
245 reply.insert(reply.end(),t.begin(),t.end());
246 break;
247 }
248
249
250 case(8): // set single wire mode
251
252 break;
253
254 case(9):{ // keep alive
255 reply.insert(reply.end(),keepalivemsg.begin(),keepalivemsg.end());
256 break;
257 }
258 case(10): // set system
259
260 break;
261
262 case(11): // echo can frame
263
264 break;
265
266 case(12): // Num buses
267 {
268 std::vector<char> t = {0xF1,cmd,numBuses};
269 reply.insert(reply.end(),t.begin(),t.end());
270 }
271 break;
272 case(13): // ext buses
273 break;
274 case(14): // set ext buses
275 break;
276 default:
277 // unknown command
278 break;
279 }
280
281 }
282 tud_cdc_n_write(0,reply.data(), reply.size());
284}
285
286
287
288CommandStatus CanBridge::command(const ParsedCommand& cmd,std::vector<CommandReply>& replies){
289
290 switch(static_cast<CanBridge_commands>(cmd.cmdId)){
292 if(cmd.type == CMDtype::get){
293 replies.emplace_back(*(int64_t*)lastmsg.data,lastmsg.header.id);
294 }else if(cmd.type == CMDtype::setat){
295 sendMessage(cmd.adr,cmd.val);
296 }else{
297 return CommandStatus::ERR;
298 }
299 break;
300
301
303 if(cmd.type == CMDtype::get){
304 replies.emplace_back(*(int64_t*)lastmsg.data,lastmsg.header.id);
305 }else if(cmd.type == CMDtype::set){
306 sendMessage(cmd.val,0,8,true); // msg with rtr bit
307 }else{
308 return CommandStatus::ERR;
309 }
310 break;
311
313 if(cmd.type == CMDtype::get){
314 replies.emplace_back(this->port->getSpeed());
315 }else if(cmd.type == CMDtype::set){
316 this->port->setSpeed(cmd.val);
317 }
318 break;
319
320 default:
322 }
323
324 return CommandStatus::OK; // Valid command found
325}
326
327#endif
CommandStatus
uint32_t tud_cdc_n_write(uint8_t itf, void const *buffer, uint32_t bufsize)
Definition cdc_device.c:171
static TU_ATTR_ALWAYS_INLINE uint32_t tud_cdc_write_flush(void)
Definition cdc_device.h:175
uint32_t timestamp
Definition CAN.h:77
uint32_t id
Definition CAN.h:72
uint32_t length
Definition CAN.h:73
Definition CAN.h:121
void update()
Definition CanBridge.cpp:96
const std::vector< char > keepalivemsg
Definition CanBridge.h:81
const ClassIdentifier getInfo() override
Definition CanBridge.cpp:21
static ClassIdentifier info
Definition CanBridge.h:15
virtual ~CanBridge()
Definition CanBridge.cpp:46
CAN_Config_t conf2
Definition CanBridge.h:79
void cdcRcv(char *Buf, uint32_t *Len) override
void sendMessage()
bool gvretMode
Definition CanBridge.h:80
std::string messageToString(CAN_rx_msg msg)
Definition CanBridge.cpp:87
volatile bool replyPending
Definition CanBridge.h:59
uint8_t txBuf[8]
Definition CanBridge.h:75
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
int32_t filterId
Definition CanBridge.h:69
CANPort * port
Definition CanBridge.h:66
CAN_Config_t conf1
Definition CanBridge.h:78
void canRxPendCallback(CANPort *port, CAN_rx_msg &msg) override
Definition CanBridge.cpp:76
CAN_rx_msg lastmsg
Definition CanBridge.h:68
uint32_t rxfifo
Definition CanBridge.h:77
CAN_msg_header_tx txHeader
Definition CanBridge.h:73
CanBridge_commands
Definition CanBridge.h:37
const uint8_t numBuses
Definition CanBridge.h:70
void canErrorCallback(CANPort *port, uint32_t error)
Definition CanBridge.cpp:53
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
static void logSerial(std::string string)
Send a log formatted sequence.
virtual void cdcRcv(char *Buf, uint32_t *Len)
CANPort & canport
static struct @024127060247016123033304002117326322243354210111 data
void pulseSysLed()
void pulseErrLed()
static void * memcpy(void *dst, const void *src, size_t n)
Definition ringbuffer.c:8
uint32_t buffer
Definition CAN.h:112
uint32_t filter_mask
Definition CAN.h:111
uint32_t filter_id
Definition CAN.h:110
uint8_t fifo
Definition CAN.h:102
uint8_t data[CAN_MSGBUFSIZE]
Definition CAN.h:99
CAN_msg_header_rx header
Definition CAN.h:101