diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 0b4d661..4ed07af 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -92,7 +92,7 @@ byte DCCEXParser::stashTarget=0; // Non-DCC things like turnouts, pins and sensors are handled in additional JMRI interface classes. -int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte *cmd) +int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte *cmd, bool usehex) { byte state = 1; byte parameterCount = 0; @@ -130,10 +130,15 @@ int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte case 3: // building a parameter if (hot >= '0' && hot <= '9') { - runningValue = 10 * runningValue + (hot - '0'); + runningValue = (usehex?16:10) * runningValue + (hot - '0'); break; } if (hot >= 'a' && hot <= 'z') hot=hot-'a'+'A'; // uppercase a..z + if (usehex && hot>='A' && hot<='F') { + // treat A..F as hex not keyword + runningValue = 16 * runningValue + (hot - 'A' + 10); + break; + } if (hot >= 'A' && hot <= 'Z') { // Since JMRI got modified to send keywords in some rare cases, we need this @@ -151,66 +156,6 @@ int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte return parameterCount; } -int16_t DCCEXParser::splitHexValues(int16_t result[MAX_COMMAND_PARAMS], const byte *cmd) -{ - byte state = 1; - byte parameterCount = 0; - int16_t runningValue = 0; - const byte *remainingCmd = cmd + 1; // skips the opcode - - // clear all parameters in case not enough found - for (int16_t i = 0; i < MAX_COMMAND_PARAMS; i++) - result[i] = 0; - - while (parameterCount < MAX_COMMAND_PARAMS) - { - byte hot = *remainingCmd; - - switch (state) - { - - case 1: // skipping spaces before a param - if (hot == ' ') - break; - if (hot == '\0' || hot == '>') - return parameterCount; - state = 2; - continue; - - case 2: // checking first hex digit - runningValue = 0; - state = 3; - continue; - - case 3: // building a parameter - if (hot >= '0' && hot <= '9') - { - runningValue = 16 * runningValue + (hot - '0'); - break; - } - if (hot >= 'A' && hot <= 'F') - { - runningValue = 16 * runningValue + 10 + (hot - 'A'); - break; - } - if (hot >= 'a' && hot <= 'f') - { - runningValue = 16 * runningValue + 10 + (hot - 'a'); - break; - } - if (hot==' ' || hot=='>' || hot=='\0') { - result[parameterCount] = runningValue; - parameterCount++; - state = 1; - continue; - } - return -1; // invalid hex digit - } - remainingCmd++; - } - return parameterCount; -} - FILTER_CALLBACK DCCEXParser::filterCallback = 0; FILTER_CALLBACK DCCEXParser::filterRMFTCallback = 0; AT_COMMAND_CALLBACK DCCEXParser::atCommandCallback = 0; @@ -248,9 +193,9 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream) int16_t p[MAX_COMMAND_PARAMS]; while (com[0] == '<' || com[0] == ' ') com++; // strip off any number of < or spaces - byte params = splitValues(p, com); byte opcode = com[0]; - + byte params = splitValues(p, com, opcode=='M' || opcode=='P'); + if (filterCallback) filterCallback(stream, opcode, params, p); if (filterRMFTCallback && opcode!='\0') @@ -364,8 +309,8 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream) case 'M': // WRITE TRANSPARENT DCC PACKET MAIN case 'P': // WRITE TRANSPARENT DCC PACKET PROG

- // Re-parse the command using a hex-only splitter - params=splitHexValues(p,com)-1; // drop REG + // NOTE: this command was parsed in HEX instead of decimal + params--; // drop REG if (params<1) break; { byte packet[params]; diff --git a/DCCEXParser.h b/DCCEXParser.h index 3bc94d4..3d376b2 100644 --- a/DCCEXParser.h +++ b/DCCEXParser.h @@ -38,8 +38,7 @@ struct DCCEXParser private: static const int16_t MAX_BUFFER=50; // longest command sent in - static int16_t splitValues( int16_t result[MAX_COMMAND_PARAMS], const byte * command); - static int16_t splitHexValues( int16_t result[MAX_COMMAND_PARAMS], const byte * command); + static int16_t splitValues( int16_t result[MAX_COMMAND_PARAMS], const byte * command, bool usehex); static bool parseT(Print * stream, int16_t params, int16_t p[]); static bool parseZ(Print * stream, int16_t params, int16_t p[]);