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