-
-
Notifications
You must be signed in to change notification settings - Fork 136
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'upstream/master' into cpp_and_qt_support
- Loading branch information
Showing
22 changed files
with
1,481 additions
and
632 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,3 +14,11 @@ ex* | |
*.html | ||
*.xhtml | ||
*.exe | ||
|
||
Debug/ | ||
*.sln | ||
*.vcxproj* | ||
dbcc.VC.db | ||
*.opendb | ||
|
||
Release/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,314 @@ | ||
/* @brief Convert the Abstract Syntax Tree generated by mpc for the DBC file | ||
* into an equivalent XML file. | ||
* @copyright Richard James Howe (2018) | ||
* @license MIT * | ||
*/ | ||
#include "2bsm.h" | ||
#include "util.h" | ||
#include <assert.h> | ||
#include <time.h> | ||
|
||
/* | ||
Add: | ||
<?xml-stylesheet type="text/xsl" href="yourxsl.xsl"?> | ||
*/ | ||
|
||
#define BSM_PREFIX "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ | ||
<beSTORM Version=\"1.2\">\n\ | ||
<GeneratorOptSettings >\n\ | ||
<BT FactoryDefined=\"1\" MaxBytesToGenerate=\"8\" FactoryType=\"Binary\" />\n\ | ||
</GeneratorOptSettings>\n\ | ||
<ModuleSettings>\n\ | ||
<M Name=\"CAN\">\n\ | ||
<P Name=\"CAN Protocol\">\n\ | ||
<SC Name=\"CAN Sequence\">\n\ | ||
<SP Name=\"CAN Open\" Library=\"CAN Interface.dll\" Procedure=\"OpenDevice\">\n\ | ||
<S Name=\"IPAddress\">\n\ | ||
<EV Name=\"IPAddress\" Description=\"CAN IP Address\" ASCIIValue=\"<CAN Device>\" Required=\"1\" />\n\ | ||
</S>\n\ | ||
<S Name=\"Port\">\n\ | ||
<EV Name=\"Port\" Description=\"CAN Port\" ASCIIValue=\"0\" Required=\"1\" Comment=\"Should be either 0, 1, 2, or 3\"/>\n\ | ||
</S>\n\ | ||
</SP>\n\ | ||
<SP Name=\"CAN SetGlobals\" Library=\"CAN Interface.dll\" Procedure=\"SetGlobals\">\n\ | ||
<S Name=\"HANDLE\">\n\ | ||
<PC Name=\"CAN\" ConditionedName=\"CAN Open\" Parameter=\"HANDLE\" />\n\ | ||
</S>\n\ | ||
<S Name=\"Baudrate\">\n\ | ||
<EV Name=\"Baudrate\" Description=\"Baudrate\" ASCIIValue=\"250000\" Required=\"1\" Comment=\"Should be either '10000', '20000', '50000', '62500', '100000', '125000', '250000', '500000', '800000', or '1000000'\"/>\n\ | ||
</S>\n\ | ||
</SP>\n\ | ||
\n\ | ||
<SE Name=\"Messages\">\n\ | ||
" | ||
|
||
#define BSM_MESSAGE_PREFIX "\n\ | ||
<SP Name=\"CAN Send (%s - %d)\" Library=\"CAN Interface.dll\" Procedure=\"Write\">\n\ | ||
<S Name=\"HANDLE\">\n\ | ||
<PC Name=\"HANDLE\" ConditionedName=\"CAN Open\" Parameter=\"HANDLE\" />\n\ | ||
</S>\n\ | ||
<S Name=\"Identifier\">\n\ | ||
<C Name=\"Identifier\">%d</C>\n\ | ||
</S>\n\ | ||
<S ParamName=\"Data\" Name=\"Message\">\n\ | ||
<BC Name=\"Message Bits\" PaddingSize=\"%d\" PaddingBit=\"0\">\n\ | ||
" | ||
|
||
#define BSM_MESSAGE_SUFFIX " </BC>\n\ | ||
</S>\n\ | ||
</SP>\n\ | ||
" | ||
|
||
#define BSM_SUFFIX "\n\ | ||
</SE>\n\ | ||
\n\ | ||
<SP Name=\"CAN Close\" Library=\"CAN Interface.dll\" Procedure=\"CloseDevice\">\n\ | ||
<S Name=\"HANDLE\">\n\ | ||
<PC Name=\"CAN\" ConditionedName=\"CAN Open\" Parameter=\"HANDLE\" />\n\ | ||
</S>\n\ | ||
</SP>\n\ | ||
</SC>\n\ | ||
</P>\n\ | ||
</M>\n\ | ||
</ModuleSettings>\n\ | ||
</beSTORM>\n\ | ||
" | ||
|
||
/*static int print_escaped(FILE * o, const char *string) | ||
{ | ||
assert(o); | ||
assert(string); | ||
char c; | ||
int r = 0; | ||
while ((c = *(string)++)) { | ||
switch (c) { | ||
case '"': | ||
r = fputs(""", o); | ||
break; | ||
case '\'': | ||
r = fputs("'", o); | ||
break; | ||
case '<': | ||
r = fputs("<", o); | ||
break; | ||
case '>': | ||
r = fputs(">", o); | ||
break; | ||
case '&': | ||
r = fputs("&", o); | ||
break; | ||
default: | ||
r = fputc(c, o); | ||
} | ||
if (r < 0) | ||
return -1; | ||
} | ||
return 0; | ||
}*/ | ||
|
||
static int indent(FILE * o, unsigned depth) | ||
{ | ||
assert(o); | ||
while (depth--) | ||
if (fputc('\t', o) != '\t') | ||
return -1; | ||
return 0; | ||
} | ||
|
||
/*static int pnode(FILE * o, unsigned depth, const char *node, const char *fmt, ...) | ||
{ | ||
assert(o); | ||
assert(node); | ||
assert(fmt); | ||
va_list args; | ||
assert(o && node && fmt); | ||
errno = 0; | ||
if (indent(o, depth) < 0) | ||
goto warn; | ||
if (fprintf(o, "<%s>", node) < 0) | ||
goto warn; | ||
assert(fmt); | ||
va_start(args, fmt); | ||
int r = vfprintf(o, fmt, args); | ||
va_end(args); | ||
if (r < 0) | ||
goto warn; | ||
if (fprintf(o, "</%s>\n", node) < 0) | ||
goto warn; | ||
return 0; | ||
warn: | ||
warning("XML node generation, problem writing to FILE* <%p>: %s", o, | ||
emsg()); | ||
return -1; | ||
}*/ | ||
|
||
static int comment(FILE * o, unsigned depth, const char *fmt, ...) | ||
{ | ||
assert(o); | ||
assert(fmt); | ||
va_list args; | ||
assert(o && fmt); | ||
errno = 0; | ||
if (indent(o, depth) < 0) | ||
goto warn; | ||
if (fputs("<!-- ", o) < 0) | ||
goto warn; | ||
assert(fmt); | ||
va_start(args, fmt); | ||
int r = vfprintf(o, fmt, args); | ||
va_end(args); | ||
if (r < 0) | ||
goto warn; | ||
if (fputs(" -->\n", o) < 0) | ||
goto warn; | ||
return 0; | ||
warn: | ||
warning("XML comment generation, problem writing to FILE* <%p>: %s", o, | ||
emsg()); | ||
return -1; | ||
} | ||
|
||
static int signal2bsm(signal_t * sig, FILE * o, unsigned depth) | ||
{ | ||
assert(sig); | ||
assert(o); | ||
|
||
if (sig->bit_length > 16) { | ||
// We need to split it into two, because we assume a <BB> is a 16 bit element (0xXX 0x00) | ||
fprintf(o, " <BB Name=\"%s (LSB)\" Bits=\"0\" Size=\"%d\" />\n", sig->name, 16); | ||
fprintf(o, " <BB Name=\"%s (MSB)\" Bits=\"0\" Size=\"%d\" />\n", sig->name, sig->bit_length - 16); | ||
} else { | ||
fprintf(o, " <BB Name=\"%s\" Bits=\"0\" Size=\"%d\" />\n", sig->name, sig->bit_length); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int msg2bsm(can_msg_t * msg, FILE * o, unsigned depth) | ||
{ | ||
assert(msg); | ||
assert(o); | ||
indent(o, depth); | ||
|
||
unsigned last_bit = 0; // Detect gaps between signals | ||
|
||
unsigned int padding_size = 0; // Find how much we need to pad the data to, 8, 16, 24, or 32 | ||
for (size_t i = 0; i < msg->signal_count; i++) { | ||
signal_t *sig = msg->signal_s[i]; | ||
|
||
if (last_bit < sig->start_bit) { | ||
// We have a void, create a fake signal of UNKNOWN in the middle | ||
padding_size += sig->start_bit - last_bit; | ||
|
||
last_bit = sig->start_bit; | ||
} | ||
|
||
padding_size += sig->bit_length; | ||
last_bit = sig->start_bit + sig->bit_length; | ||
} | ||
|
||
if (padding_size <= 8) { | ||
padding_size = 8; | ||
} else if (padding_size <= 16) { | ||
padding_size = 16; | ||
} else if (padding_size <= 24) { | ||
padding_size = 24; | ||
} else if (padding_size <= 32) { | ||
padding_size = 32; | ||
} | ||
|
||
fprintf(o, BSM_MESSAGE_PREFIX, msg->name, msg->id, msg->id, padding_size); | ||
|
||
last_bit = 0; | ||
signal_t *multiplexor = NULL; | ||
for (size_t i = 0; i < msg->signal_count; i++) { | ||
signal_t *sig = msg->signal_s[i]; | ||
if (sig->is_multiplexor) { | ||
if (multiplexor) { | ||
error ("multiple multiplexor values detected (only one per CAN msg is allowed) for %s", msg->name); | ||
return -1; | ||
} | ||
multiplexor = sig; | ||
continue; | ||
} | ||
if (sig->is_multiplexed) | ||
continue; | ||
|
||
if (last_bit < sig->start_bit) { | ||
// We have a void, create a fake signal of UNKNOWN in the middle | ||
char szUNKNOWN[] = "UNKNOWN"; | ||
char szUNITS[] = ""; | ||
signal_t unknownsig = { 0 }; | ||
unknownsig.name = szUNKNOWN; | ||
unknownsig.units = szUNITS; | ||
unknownsig.start_bit = last_bit; | ||
unknownsig.bit_length = sig->start_bit - last_bit; | ||
|
||
if (signal2bsm(&unknownsig, o, depth + 1) < 0) | ||
return -1; | ||
|
||
last_bit = sig->start_bit; | ||
} | ||
// Generate a Signal element | ||
if (signal2bsm(sig, o, depth + 1) < 0) | ||
return -1; | ||
|
||
last_bit = sig->start_bit + sig->bit_length; | ||
} | ||
|
||
/*// We don't support multiplexor for now | ||
if (0 && multiplexor) { | ||
indent(o, depth + 1); | ||
fprintf(o, "<multiplexor-group>\n"); | ||
indent(o, depth + 2); | ||
fprintf(o, "<multiplexor>\n"); | ||
if (signal2xml(multiplexor, o, depth + 2) < 0) | ||
return -1; | ||
indent(o, depth + 2); | ||
fprintf(o, "</multiplexor>\n"); | ||
for (size_t i = 0; i < msg->signal_count; i++) { | ||
signal_t *sig = msg->signals[i]; | ||
if (!(sig->is_multiplexed)) | ||
continue; | ||
indent(o, depth + 2); | ||
fprintf(o, "<multiplexed>\n"); | ||
pnode(o, depth + 3, "multiplexed-on", "%u", sig->switchval); | ||
if (signal2bsm(sig, o, depth + 3) < 0) | ||
return -1; | ||
indent(o, depth + 2); | ||
fprintf(o, "</multiplexed>\n"); | ||
} | ||
indent(o, depth + 2); | ||
fprintf(o, "</multiplexor-group>\n"); | ||
} */ | ||
|
||
if (fprintf(o, BSM_MESSAGE_SUFFIX) < 0) | ||
return -1; | ||
return 0; | ||
} | ||
|
||
int dbc2bsm(dbc_t * dbc, FILE * output, bool use_time_stamps) | ||
{ | ||
assert(dbc); | ||
assert(output); | ||
/**@todo print out ECU node information, and the standard XML header */ | ||
time_t rawtime = time(NULL); | ||
struct tm *timeinfo = localtime(&rawtime); | ||
|
||
comment(output, 0, "Generated by dbcc (see https://github.com/howerj/dbcc)"); | ||
fprintf(output, BSM_PREFIX); | ||
|
||
if (use_time_stamps) | ||
comment(output, 0, "Generated on: %s", asctime(timeinfo)); | ||
|
||
for (int i = 0; i < dbc->message_count; i++) { | ||
if (msg2bsm(dbc->messages[i], output, 1) < 0) { | ||
return -1; | ||
} | ||
} | ||
|
||
fprintf(output, BSM_SUFFIX); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#ifndef _2BSM_H | ||
#define _2BSM_H | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#include "can.h" | ||
|
||
int dbc2bsm(dbc_t *dbc, FILE *output, bool use_time_stamps); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif |
Oops, something went wrong.