Welcome! Log In Create A New Profile

Advanced

Understanding Marlin

Posted by Jrodenba 
Understanding Marlin
March 29, 2016 01:56AM
Recently, in an attempt to better understand the deeper aspects of 3D printing (and because I'm bored and want to test my own software engineering skills) I have been reverse engineering Marlin. I hope this is OK since I'm not planning on creating or selling anything with the techniques/algorithms, I just want to understand what's going on in my printer. I have looked for resources teaching the fundamental principles that turn a block of gcode on one end into physical motor movements on the other, but haven't found any (slowly working through the code myself gives me a better understanding anyway).
It has been slow going (although I'm not in any rush), but I haven't hit any obstacles that I couldn't figure out with a little time; until now. I am still relatively new to coding, but have taught myself Arduino, C, C++, and Java so I haven't had too many issues understanding the code, although my question will probably end up being a more of a general coding question, since it specifically revolves around Marlin I hope I can find some answers here.
So.....

My question revolves around pulling info off the SD, the section of code that I'm working on can be found in Marlin_main.cpp, in the void get_command() function, lines 522-571. *I have included the function name from line 415, but have left out the code between lines 415 and 522 since it doesn't have any effect (that I can find) on the following code:
void get_command(){
/*
.
.
omitted lines 416-521 
.
.
  #ifdef SDSUPPORT
  if(!card.sdprinting || serial_count != 0){
    return;
  }
  while( !card.eof()  && buflen < BUFSIZE) {
    int16_t n=card.get();
    serial_char = (char)n;
    if(serial_char == '\n' || 
       serial_char == '\r' || 
       (serial_char == ':' && comment_mode == false) || 
       serial_count >= (MAX_CMD_SIZE - 1)||n==-1) 
    {
      if(card.eof()){
        SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
        stoptime=millis();
        char time[30];
        unsigned long t=(stoptime-starttime)/1000;
        int hours, minutes;
        minutes=(t/60)%60;
        hours=t/60/60;
        sprintf_P(time, PSTR("%i hours %i minutes"),hours, minutes);
        SERIAL_ECHO_START;
        SERIAL_ECHOLN(time);
        lcd_setstatus(time);
        card.printingHasFinished();
        card.checkautostart(true);
        
      }
      if(!serial_count)
      {
        comment_mode = false; //for new command
        return; //if empty line
      }
      cmdbuffer[bufindw][serial_count] = 0; //terminate string
//      if(!comment_mode){
        fromsd[bufindw] = true;
        buflen += 1;
        bufindw = (bufindw + 1)%BUFSIZE;
//      }     
      comment_mode = false; //for new command
      serial_count = 0; //clear buffer
    }
    else
    {
      if(serial_char == ';') comment_mode = true;
      if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;
    }
  }
  
  #endif //SDSUPPORT


My question is about the variable serial_count, defined on line 187, "static int serial_count = 0;"

1) The first thing the variable encounters is line 523:
if(!card.sdprinting || serial_count != 0){
    return;
  }
if serial_count is not zero, the code kicks us out of "void get_command()" and back into "void loop()", so we know if we got past this point that serial_count is equal to 0.

2) if serial_count is zero (ignoring "!card.sdprinting" for the moment) we bypass this if statement and move on to a while statement, line 526:
 while( !card.eof()  && buflen < BUFSIZE) {
then another if statement, line 529:
if(serial_char == '\n' || 
       serial_char == '\r' || 
       (serial_char == ':' && comment_mode == false) || 
       serial_count >= (MAX_CMD_SIZE - 1)||n==-1) 
    {
if we don't pass this conditionals for this if statement we are sent down to lines 566-567
 if(serial_char == ';') comment_mode = true;
      if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;
where serial_count gets advanced by 1 (serial_count++) and then used in the cmdbuffer array.
then "void get_command()" ends and we are returned to "void loop()", but serial_count is now greater than 0, so the next time "void get_command()" is called it will automatically trigger the "return" on line 524

Let's assume we pass the if conditional on line 529; so we know that serial_count must be 0 (it hasn't been updated since we evaluated it at line 523)

then we skip over the momentarily unrelated "if(card.eof()){" statement

3) then there's this if statement, line 550:
if(!serial_count)
      {
        comment_mode = false; //for new command
        return; //if empty line
      }
so if serial_count equals 0, it will pass this conditional and hit the "return;" that will kick us back out to "void loop()"


I must be missing something, but as I'm understanding it, there is no way to get to the code between lines 555 and 563. If serial_count isn't 0, it triggers a return to loop() (line 524), if it is 0 it triggers a return to loop() (line 553)


I have not found any function calls to void get_command outside of the one time it is called in loop(), and I have found no updates to serial_count outside of the get_command() function.
As it is this code seems like it shouldn't work, but I use marlin on 2 of my printers, so I know it does work.

Anyone know what I'm missing? (I'm sure it's something little and silly as usual)

Thanks,
Josh
Re: Understanding Marlin
April 16, 2016 02:17PM
Quote
Jrodenba
where serial_count gets advanced by 1 (serial_count++) and then used in the cmdbuffer array.
then "void get_command()" ends and we are returned to "void loop()", but serial_count is now greater than 0, so the next time "void get_command()" is called it will automatically trigger the "return" on line 524

I'm a bit late but... after adding a character to the buffer, the function does not return, but loops on "while( !card.eof() && buflen < BUFSIZE) {"


What is Open Source?
What is Open Source Hardware?
Open Source in a nutshell: the Four Freedoms
CC BY-NC is not an Open Source license
Re: Understanding Marlin
April 17, 2016 09:11PM
Hey!
Thanks so much! I moved on to the next part the code, but I still hadn't figured that one out, thanks!
-J
Sorry, only registered users may post in this forum.

Click here to login