From RepRap
Revision as of 02:42, 10 January 2011 by Triffid hunter (talk | contribs) (Future-proof M-codes?: new section)
Jump to: navigation, search

Ah excellent, I've been waiting for this! I've been working from the gcode and mcode pages in the old wiki which have a few holes.

The line number and checksum stuff is new to me- I'll implement that into my firmware in the coming days. So are some of these M-codes for that matter.

Can we add some sort of reference for what the host expects in response from the firmware? So far, I'm sending back OK when the command is queued or executed and T: nnn every second when the heater is on, which as far as I can tell is all that's needed.

ps: why are G20/G21/G90/G91/G92 specified to block? ("The following commands are not buffered. When one is received it is stored, but it is not acknowledged to the host until the buffer is exhausted and then the command has been executed.") they simply alter the conversion factors for the next command received in my firmware, and so can respond OK immediately.

Only G4 (dwell) and M101 (start extruder when up to temperature, apparently superceded by the new M109) block in my firmware at the moment, and I'm seriously considering making even these queue-able so they block the queue instead of the command download stream.

-- Triffid Hunter

I agree. It's great for this to be documented.

I had one suggestion on the checksum -- it should perhaps use a stronger CRC checksum, and should also encorporate the length as well? Is the N and * part of an external standard, or a RepRap special sauce?

If they are RepRap specific, I'd suggest changing the N code to include line length as something like "N101.50" for line 101, consisting of 50 characters.

I use the following CRC algorithm, which I believe I stole from the CCITT standard:

static inline uint16_t GetCRC( uint16_t crc, char ser_data )
  crc  = (unsigned char)(crc >> 8) | (crc << 8);
  crc ^= ser_data;
  crc ^= (unsigned char)(crc & 0xff) >> 4;
  crc ^= (crc << 8) << 4;
  crc ^= ((crc & 0xff) << 4) << 1;
  return crc;

The logic to compute checksum would then become:

uint16_t cs = 0;
for(int i = 0; i < cmd.length(); i++)
  cs = GetCRC( cs, cmd.charAt(i) );

computedCrc = cs;

So, the full logic for accepting or testing a line, encoded with full N and CRC checksum would be something like:

// was line number and checksum provided?
bool value = true;
if( lineNumber != 0 )
  valid = lineNumber == expectedLineNumber
    && cmd.length() == providedLength
    && computedCrc == providedCrc;

// accept or reject the line based on valid flag

This does add a few bytes of overhead (3-4 for length, 2-3 for 16 bit crc), but may be worth it allows you to run a higher baud rate with reasonably low error rates -- the odds of a false positive are near enough to zero to make any statistician happy.

-- BeagleFury

Just wanted to chime in - Thanks Adrian! This answers many questions for me! -- Wade

what part of the line does cmd.length() refer to?

Just trying to implement the checksum logic, and realised that it makes no sense for the checksum to include itself or things get very recursive. What point is considered end-of-line? is it the asterisk? the space before the asterisk? the last non-whitespace before the asterisk?

My firmware doesn't buffer the line, rather processes it character by character so this has to become another special case.

-- Triffid Hunter

The checksum includes all characters in the string up to and including the character before the asterisk (i.e. up to but not including the asterisk). -- neilrqm

Future-proof M-codes?

Adding new M-codes for extra sensors/heaters seems a little non-future-proof to me. My firmware uses P parameter to know which sensor/heater is being referred to eg M104 S100 sets heater 0 to 100c, but M104 P2 S100 sets heater 2 to 100c. Same for all the temperature sensor readback stuff. Future proofing protocols is always a good idea :)