Exemplo n.º 1
0
//Window constants (DEF_TITLE, etc) are defined in Gamelan_Window.h
Gamelan_Window::Gamelan_Window()
	:Window( DEF_LOCATION, DEF_WIDTH, DEF_HEIGHT, DEF_TITLE ),
	strings( 7, NULL ),
	index(0), game(false),

	//start screen objects
	in_name( Point( 200, 200 ), 200, 30, "Name: "),
	but_amazing( Point((x_max()-400),(y_max()-200)),200,20,"Amazing Grace", cb_amazing),
	but_sweet( Point((x_max()-400),(y_max()-150)),200,20,"Swing Low, Sweet Chariot", cb_sweet),
	but_west( Point((x_max()-400),(y_max()-100)),200,20,"Westminster", cb_west),
	instr( Point( 100, 110 ), "Click the circles to get through the song as fast as you can!" ),

	//Final Screen objects
	top_scores( Point( 245, 110 ), "Top Scores" ),
	your_score( Point( 100, 700 ), "" ),
	score1( Point(100,275), "" ),
	score2( Point(100,300), "" ),
	score3( Point(100,325), "" ),
	score4( Point(100,350), "" ),
	score5( Point(100,375), "" )
{
	for( int i = 0; i < 7; i++ )
		strings[i] = new Gam_String( Point( 200 + 25*i, 50 ), -105 + 35*i, 700, NUM_DIVISIONS, COLORS[i] );
	init();
}
Exemplo n.º 2
0
		My_window(Point xy, int w, int h, const string& title)
			: Window(xy, w, h, title),
			button_pressed(false),
			next_button(Point(x_max() - 150, 0), 70, 20, "next", cb_next),
			quit_button(Point(x_max() - 70, 0), 70, 20, "quit", cb_quit)
		{ 
			attach(next_button);
			attach(quit_button);
		}
Imagebutton_window::Imagebutton_window(Point xy, int w, int h, const string& title)
    :Window(xy,w,h,title),
    quit_button(Point(x_max()-70,0),70,20,"Quit",cb_quit),
    image_button(Point(rint(0,x_max()-100),rint(0,y_max()-100)),100,100,"",cb_ibpushed),
    button_image(image_button.loc,"pics_and_txt/snow_cpp.gif")
{
    attach(quit_button);
    attach(image_button);
    button_image.set_mask(Point(110,70),100,100);
    attach(button_image);
}
Calc_window::Calc_window(Point xy, int w, int h, const string& title)
    :Quit_window(xy,w,h,title),
    help_button(Point(x_max()-210,0),70,20,"Help",cb_help_button),
    calc_button(Point(x_max()-140,0),70,20,"Calculate",cb_calc_button),
    input(Point(53,30),x_max()-68,20,"Input:"),
    output(Point(53,60),x_max()-68,20,"Output:")
{
    attach(help_button);
    attach(calc_button);
    attach(input);
    attach(output);
}
Exemplo n.º 5
0
		Checker_window(Point xy, int w, int h, const string& title)
			: My_window(xy, w, h, title), outbox(Point(0, 0), x_max() - 160, 20, "(x, y)")
		{
			attach(outbox);
			
			const int column = 4;	// 列数
			const int row = 4;		// 行数

			for(int i = 0; i < column * row; ++i){
				checker.push_back(new Button(Point(x_max() / column * (i % column), (y_max() - 20) / row * (i / row) + 20),
					x_max() / column, (y_max() - 20) / row, to_string(i), cb_checker));
				attach(checker[i]);
			}
		}
Exemplo n.º 6
0
	Lines_window::Lines_window(Point xy, int w, int h, const string& title)
		: Window(xy, w, h, title),
		next_button(Point(x_max() - 150, 0), 70, 20, "Next point", cb_next),
		quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit),
		next_x(Point(x_max() - 310, 0), 50, 20, "next x:"),
		next_y(Point(x_max() - 210, 0), 50, 20, "next y:"),
		xy_out(Point(100, 0), 100, 20, "(x,y):")
	{
		attach(next_button);
		attach(quit_button);
		attach(next_x);
		attach(next_y);
		attach(xy_out);
		attach(lines);
	}
Exemplo n.º 7
0
Pseudo_window::Pseudo_window(Point xy, int w, int h, const string& title) :
Window(xy,w,h,title),
next_button(Point(x_max()-100,0), 100, 50, "NEXT", cb_next),
button_pushed(false)
{
    attach(next_button);
}
Simple_window::Simple_window(Point xy, int w, int h, const string& title) :
    Window(xy,w,h,title),
    next_button(Point(x_max()-70,0), 70, 20, "Next", cb_next),
    button_pushed(false)
{
    attach(next_button);
}
void Imagebutton_window::move()
{
    int dx = rint(0,x_max()-100) - image_button.loc.x;
    int dy = rint(0,y_max()-100) - image_button.loc.y;
    image_button.move(dx,dy);
    button_image.move(dx,dy);
}
Exemplo n.º 10
0
void GL_widget_2::save_view(bool) {
	QString bounding_box = tr("%1 %2 %3 %4").arg(x_min()).arg(x_max()).arg(y_min()).arg(y_max());

	QSettings settings;
	QString file_name = QFileDialog::getSaveFileName(
		this,
		"Choose a filename to save view",
		settings.value("last-view-directory",QString()).toString(),
		"View files (*.2view)");
	if (file_name=="") return;
	if (!file_name.endsWith(".2view")) file_name += ".2view";
	QString save_directory = file_name;
	save_directory.truncate(file_name.lastIndexOf('/'));
	settings.setValue("last-view-directory",save_directory);

	QFile f(file_name);
	if ( !f.open( QIODevice::WriteOnly ) ) {
		std::cout << LOG_ERROR << tr("File `%1' could not be open for writing!").arg(file_name).toStdString() << std::endl;
		return;
	}
	QTextStream fs( &f );
	fs << bounding_box;
	f.close();

	std::cout << "Camera view stored in " << file_name.toStdString()  << std::endl;

}
Exemplo n.º 11
0
Button_window::Button_window(Point xy, int w, int h, const string& title)
    :My_window(xy,w,h,title),
    menu1(Point(0,0),100,100,Menu::vertical,"menu1"),
    menu2(Point(100,0),100,100,Menu::vertical,"menu2"),
    menu3(Point(200,0),100,100,Menu::vertical,"menu3"),
    menu4(Point(300,0),100,100,Menu::vertical,"menu4"),
    xy_out(Point(x_max()-70,60),70,20,"(x,y)")
{
    menu1.attach(new Button(Point(0,0),0,0,"1-1",cb_action11));
    menu1.attach(new Button(Point(0,0),0,0,"1-2",cb_action12));
    menu1.attach(new Button(Point(0,0),0,0,"1-3",cb_action13));
    menu1.attach(new Button(Point(0,0),0,0,"1-4",cb_action14));
    attach(menu1);
    menu2.attach(new Button(Point(0,0),0,0,"2-1",cb_action21));
    menu2.attach(new Button(Point(0,0),0,0,"2-2",cb_action22));
    menu2.attach(new Button(Point(0,0),0,0,"2-3",cb_action23));
    menu2.attach(new Button(Point(0,0),0,0,"2-4",cb_action24));
    attach(menu2);
    menu3.attach(new Button(Point(0,0),0,0,"3-1",cb_action31));
    menu3.attach(new Button(Point(0,0),0,0,"3-2",cb_action32));
    menu3.attach(new Button(Point(0,0),0,0,"3-3",cb_action33));
    menu3.attach(new Button(Point(0,0),0,0,"3-4",cb_action34));
    attach(menu3);
    menu4.attach(new Button(Point(0,0),0,0,"4-1",cb_action41));
    menu4.attach(new Button(Point(0,0),0,0,"4-2",cb_action42));
    menu4.attach(new Button(Point(0,0),0,0,"4-3",cb_action43));
    menu4.attach(new Button(Point(0,0),0,0,"4-4",cb_action44));
    attach(menu4);
    attach(xy_out);
    xy_out.put("no point");
}
Exemplo n.º 12
0
Arquivo: 01.cpp Projeto: fanqo/PPPCpp
Lines_window::Lines_window(Point xy, int w, int h, const string& title)
  : Graph_lib::Window{xy, w, h, title},
  next_button{Point{x_max() - 150, 0}, 70, 20, "Next point",
    [](Address, Address pw) {reference_to<Lines_window>(pw).next();}},
  quit_button{Point{x_max()-70, 0}, 70, 20, "Quit",
    [](Address, Address pw){reference_to<Lines_window>(pw).quit();}},
  next_x{Point{x_max()-310, 0}, 50, 20, "next x:"},
  next_y{Point{x_max()-210, 0}, 50, 20, "next y:"},
  xy_out{Point{100, 0}, 100, 20, "current (x, y):"}
{
  attach(next_button);
  attach(quit_button);
  attach(next_x);
  attach(next_y);
  attach(xy_out);
  attach(lines);
}
Exemplo n.º 13
0
/// find X_MAX endstop
void home_x_positive() {
	queue_wait();

	#if defined X_MAX_PIN
		uint8_t	denoise_count = 0;

		// home X
		x_enable();
		// hit home hard
		x_direction(1);
		while (denoise_count < 8) {
			// denoise
			if (x_max())
				denoise_count++;
			else
				denoise_count = 0;
			// step
			x_step();
			delay(5);
			unstep();
			// wait until next step time
			delay((uint32_t) (60.0 * 1000000.0 / STEPS_PER_M_X * 1000.0 / ((float) MAXIMUM_FEEDRATE_X)));
		}
		denoise_count = 0;

		// back off slowly
		x_direction(0);
		while (x_max() != 0) {
			// step
			x_step();
			delay(5);
			unstep();
			// wait until next step time
			delay((uint32_t) (60.0 * 1000000.0 / STEPS_PER_M_X * 1000.0 / ((float) SEARCH_FEEDRATE_X)));
		}

		// set X home
		TARGET t = {0, 0, 0, 0, 0};
		// set position to MAX
		startpoint.X = current_position.X = (int32_t)(X_MAX * 1000.0);
		// go to zero
		t.F = MAXIMUM_FEEDRATE_X;
		enqueue(&t);
	#endif
}
Exemplo n.º 14
0
Shmenu_window::Shmenu_window(Point xy, int w, int h, const string& title)
    :Window(xy,w,h,title),
    quit_button(Point(x_max()-70,0),70,20,"Quit",cb_qpushed),
    shapes_menu(Point(x_max()-70,30),70,20,Menu::vertical,"shapes"),
    x_in(Point(x_max()-70,120),70,20,"x:"),
    y_in(Point(x_max()-70,140),70,20,"y:"),
    x(0),
    y(0)
{
    attach(quit_button);
    shapes_menu.attach(new Button(Point(),0,0,"Circle",cb_circle));
    shapes_menu.attach(new Button(Point(),0,0,"Square",cb_square));
    shapes_menu.attach(new Button(Point(),0,0,"Triangle",cb_triangle));
    shapes_menu.attach(new Button(Point(),0,0,"Hexagon",cb_hexagon));
    attach(shapes_menu);
    attach(x_in);
    attach(y_in);
}
Exemplo n.º 15
0
void volume::inset(double x_inset, double y_inset, double z_inset)
{
	double x_min = this->x_min();
	double y_min = this->y_min();
	double z_min = this->z_min();
	x_inset = area::inset(x_min, size.dx, x_inset);
	y_inset = area::inset(y_min, size.dy, y_inset);
	z_inset = area::inset(z_min, size.dz, z_inset);
	assign(x_min + x_inset, y_min + y_inset, z_min + z_inset, x_max() - x_inset, y_max() - y_inset, z_max() - z_inset);
}
Exemplo n.º 16
0
 Random_window(Point xy, int w, int h, const string& title)
     : My_window(xy, w, h, title),
       x(rint(0, x_max() - 100)),
       y(rint(20, y_max() - 100)),
       image_button(Point(x, y), 100, 100, "", cb_image),
       image(Point(x, y), "../image1.jpg")
 {
     attach(image_button);
     attach(image);
 }
Exemplo n.º 17
0
    void push() {
        int tmp_x = rint(0, x_max()- 100);
        int tmp_y = rint(20, y_max() - 100);

        image_button.move(tmp_x - x, tmp_y - y);
        image.move(tmp_x - x, tmp_y - y);

        x = tmp_x;
        y = tmp_y;
    }
Exemplo n.º 18
0
bool hit_home_stop_x (unsigned dir)
{
  if (config.home_direction_x < 0)
  {
    return !x_min();
  }
  else
  {
    return !x_max();
  }
}
Exemplo n.º 19
0
Fgraph_window::Fgraph_window(Point xy, int w, int h, const string& title)
    :Quit_window(xy,w,h,title),
    draw_button(Point(x_max()-140,0),70,20,"Draw",cb_draw_button),
    message_box(Point(15,15),x_max()-170,20,""),
    fct_menu(Point(x_max()-85,210),70,20,Menu::vertical,"Function"),
    fct_menu_button(Point(x_max()-85,210),70,20,"Function",cb_fct_mbutton),
    input_r1(Point(x_max()-85,35),70,20,"r1:"),
    input_r2(Point(x_max()-85,70),70,20,"r2:"),
    input_count(Point(x_max()-85,105),70,20,"Count:"),
    input_xscale(Point(x_max()-85,140),70,20,"xscale:"),
    input_yscale(Point(x_max()-85,175),70,20,"yscale:"),
    x_axis(Axis::x,Point(15,(y_max()-65)/2+50),x_max()-120,10,""),
    y_axis(Axis::y,Point(15,y_max()-15),y_max()-65,10,""),
    fl_funct(sin,0,10*pi,Point(15,(y_max()-65)/2+50)),
    fct_pointer(sin)
{
    attach(draw_button);
    attach(message_box);
    fct_menu.attach(new Button(Point(),0,0,"sin",cb_sin_button));
    fct_menu.attach(new Button(Point(),0,0,"cos",cb_cos_button));
    fct_menu.attach(new Button(Point(),0,0,"log",cb_log_button));
    fct_menu.attach(new Button(Point(),0,0,"exp",cb_exp_button));
    attach(fct_menu);
    fct_menu.hide();
    attach(fct_menu_button);
    attach(input_r1);
    attach(input_r2);
    attach(input_count);
    attach(input_xscale);
    attach(input_yscale);
    x_axis.label.set_color(Color::red);
    x_axis.label.move(-180,0);
    attach(x_axis);
    y_axis.label.set_color(Color::red);
    y_axis.label.move(30,20);
    attach(y_axis);
    fl_funct.set_color(Color::invisible);   // we don't want to see anything yet
    attach(fl_funct);
}
Exemplo n.º 20
0
void reset_label(int max, double scale, Axis& a, Axis::Orientation a_or)
{
    double notch = 0;
    int x = x_max();
    switch (a_or) {
    case Axis::x:
        notch = (max-115)/10.0/scale;
        break;
    case Axis::y:
        notch = (max-65)/10.0/scale;
        break;
    }
    ostringstream oss;
    oss << "1 notch = " << fixed << setprecision(2) << notch;
    a.label.set_label(oss.str());
}
Exemplo n.º 21
0
		void eval_radial_function(const TGrid &grid_2d, Value_type<TGrid> x, Value_type<TGrid> y, TVector &V)
		{	
			using X = Value_type<TGrid>;

			X r_max = x_max();
			X fr_max = (*this)(r_max);
			for(auto ix = 0; ix < grid_2d.nx; ix++)
			{
				for(auto iy = 0; iy < grid_2d.ny; iy++)
				{
					X r = grid_2d.R2(ix, iy, x, y);
					int ixy = grid_2d.ind_col(ix, iy);
					V[ixy] = (r < r_max)?(*this)(r):fr_max;
				}
			}
		}
Exemplo n.º 22
0
Currency_window::Currency_window(Point xy, int w, int h, const string& title)
    :Quit_window(xy,w,h,title),
    calc_button(Point(x_max()-140,0),70,20,"Calculate",cb_calc),
    amount_in(Point(15,35),70,20,""),
    from_cur_text(Point(95,52),"CAD"),
    from_cur_menu(Point(95,60),70,20,Menu::vertical,"Change"),
    from_cur_mbutton(Point(95,60),70,20,"Change",cb_from_mbutton),
    equals(Point(175,52),"equals"),
    amount_out(Point(250,35),70,20,""),
    to_cur_text(Point(325,52),"CHF"),
    to_cur_menu(Point(325,60),70,20,Menu::vertical,"Change"),
    to_cur_mbutton(Point(325,60),70,20,"Change",cb_to_mbutton),
    from_cur(CAD),
    to_cur(CHF)
{
    // Build GUI
    attach(calc_button);
    attach(amount_in);
    attach(from_cur_text);
    from_cur_menu.attach(new Button(Point(0,0),0,0,"CAD",cb_from_cur0));
    from_cur_menu.attach(new Button(Point(0,0),0,0,"CHF",cb_from_cur1));
    from_cur_menu.attach(new Button(Point(0,0),0,0,"KYD",cb_from_cur2));
    attach(from_cur_menu);
    from_cur_menu.hide();
    attach(from_cur_mbutton);
    attach(equals);
    attach(amount_out);
    attach(to_cur_text);
    to_cur_menu.attach(new Button(Point(0,0),0,0,"CAD",cb_to_cur0));
    to_cur_menu.attach(new Button(Point(0,0),0,0,"CHF",cb_to_cur1));
    to_cur_menu.attach(new Button(Point(0,0),0,0,"KYD",cb_to_cur2));
    attach(to_cur_menu);
    to_cur_menu.hide();
    attach(to_cur_mbutton);

    // Add currency names
    cur_labels.push_back("CAD");
    cur_labels.push_back("CHF");
    cur_labels.push_back("KYD");

    // Read data from text file
    get_conversion_rates();
}
Exemplo n.º 23
0
void calendar_window::refresh(int m, int y)
{
	req_month.label = "Month: ";	// Clear the inbox text
	req_year.label = "Year: ";
	current_month = m;
	current_year = y;
	ostringstream ss;
	ss << m;	// Put the month - currently an int - into the buffer
	string month = ss.str();	// Pull the characters - the month - out of the buffer as a string
	
	ostringstream sss;
	sss << y;	// Put the month - currently an int - into the buffer
	string year = sss.str();	// Pull the characters - the month - out of the buffer as a string
	detach(*month_display);
	month_display = new Text(Point(x_max()/2, 30),  month + " " + year);
	month_display->set_font_size(30);
	attach(*month_display);
	
	wait_for_button();
}
Exemplo n.º 24
0
	Lines_window::Lines_window(Point xy, int w, int h, const string& title)
		: Window(xy, w, h, title),
		next_button(Point(x_max() - 150, 0), 70, 20, "Next point", cb_next),
		quit_button(Point(x_max() - 70, 0), 70, 20, "Quit", cb_quit),
		next_x(Point(x_max() - 310, 0), 50, 20, "next x:"),
		next_y(Point(x_max() - 210, 0), 50, 20, "next y:"),
		xy_out(Point(100, 0), 100, 20, "(x,y):"),
		color_menu(Point(x_max() - 70, 40), 70, 20, Menu::vertical, "color"),
		color_menu_button(Point(x_max() - 70, 40), 70, 20, "color", cb_color_menu),
		style_menu(Point(x_max() - 150, 40), 70, 20, Menu::vertical, "style"),
		style_menu_button(Point(x_max() - 150, 40), 70, 20, "style", cb_style_menu)
	{
		attach(next_button);
		attach(quit_button);
		attach(next_x);
		attach(next_y);
		attach(xy_out);
		xy_out.put("no print");

		color_menu.attach(new Button(Point(0, 0), 0, 0, "red", cb_red));
		color_menu.attach(new Button(Point(0, 0), 0, 0, "blue", cb_blue));
		color_menu.attach(new Button(Point(0, 0), 0, 0, "black", cb_black));
		attach(color_menu);
		style_menu.attach(new Button(Point(0, 0), 0, 0, "solid", cb_solid));
		style_menu.attach(new Button(Point(0, 0), 0, 0, "dash", cb_dash));
		style_menu.attach(new Button(Point(0, 0), 0, 0, "dashdot", cb_dashdot));
		style_menu.attach(new Button(Point(0, 0), 0, 0, "dashdotdot", cb_dashdotdot));
		style_menu.attach(new Button(Point(0, 0), 0, 0, "dot", cb_dot));
		attach(style_menu);

		color_menu.hide();
		style_menu.hide();

		attach(color_menu_button); 
		attach(style_menu_button);
		attach(lines);
	}
Exemplo n.º 25
0
	calendar_window::calendar_window(Point xy, int w, int h, const string& title)
	:Window(w,h,title),
	submit1(Point((this->x_max()-100),0),90,20, "Submit:",cb_submit),
	req_month(Point(60,0),90,20, "Month:"),
	req_year(Point(200,0),90,20, "Year:"),
	current_date(Point(100,70),100,20, " "),
	calendar_template(Point(50,50),"calendar_template.jpg"),
	button_pushed(false),
	text_box(Point(100,100), day_num, event_text)
{
	current_month = -5;
	current_year = -5;
	month_display = new Text(Point(x_max()/2, 30), "January 2000");
	month_display->set_font_size(30);
	attach(*month_display);
	//Image calendar_template(Point(50,50),"calendar_template.jpg");
	attach(calendar_template); 
	attach(req_month);
	attach(req_year);
	attach(submit1);
	attach(current_date);
	attach(text_box);
}
Exemplo n.º 26
0
		Shape_window(Point xy, int w, int h, const string& title)
			: My_window(xy, w, h, title),
			inbox_x(Point(20, 0), 70, 20, "X:"),
			inbox_y(Point(120, 0), 70, 20, "Y:"),
			menu(Point(x_max() - 230, 0), 70, 20, "kind", cb_menu),
			kind(Point(x_max() - 230, 0), 70, 20, Menu::vertical, "shape kind")		
		{
			attach(inbox_x);
			attach(inbox_y);
			attach(menu);

			kind.attach(new Button(Point(x_max() - 230, 0), 70, 20, "circle", cb_circle));
			kind.attach(new Button(Point(x_max() - 230, 20), 70, 20, "triangle", cb_triangle));
			kind.attach(new Button(Point(x_max() - 230, 40), 70, 20, "square", cb_square));
			kind.attach(new Button(Point(x_max() - 230, 60), 70, 20, "hexagon", cb_hexagon));
			attach(kind);
			kind.hide();
		}
Exemplo n.º 27
0
void Fgraph_window::draw_pressed()
try {
    // set range
    fl_funct.reset_range(get_double(input_r1),get_double(input_r2));

    // reset count
    fl_funct.reset_count(get_int(input_count));

    // reset xscale
    double xscale = get_double(input_xscale);
    fl_funct.reset_xscale(xscale);

    // reset axis label
    reset_label(x_max(),xscale,x_axis,Axis::x);

    // reset yscale
    double yscale = get_double(input_yscale);
    fl_funct.reset_yscale(yscale);

    // reset axis label
    reset_label(y_max(),yscale,y_axis,Axis::y);

    // set function
    fl_funct.reset_fct(fct_pointer);

    // clear message window
    message_box.put("");

    // finally, make function visible in case this was the first time
    fl_funct.set_color(Color::visible);
    fl_funct.set_color(Color::blue);
    redraw();
}
catch (exception& e) {
    message_box.put(e.what());
}
Exemplo n.º 28
0
 My_window(Point xy, int w, int h, const string& title)
     : Simple_window(xy, w, h, title),
       quit_button(Point(x_max() - 70, 20), 70, 20, "Quit", cb_quit)
 {
     attach(quit_button);
 }
Exemplo n.º 29
0
void process_gcode_command() {
	uint32_t	backup_f;

	// convert relative to absolute
	if (next_target.option_all_relative) {
    next_target.target.axis[X] += startpoint.axis[X];
    next_target.target.axis[Y] += startpoint.axis[Y];
    next_target.target.axis[Z] += startpoint.axis[Z];
	}

	// E relative movement.
	// Matches Sprinter's behaviour as of March 2012.
	if (next_target.option_e_relative)
		next_target.target.e_relative = 1;
	else
		next_target.target.e_relative = 0;

	if (next_target.option_all_relative && !next_target.option_e_relative)
		next_target.target.axis[E] += startpoint.axis[E];

	// implement axis limits
	#ifdef	X_MIN
    if (next_target.target.axis[X] < (int32_t)(X_MIN * 1000.))
      next_target.target.axis[X] = (int32_t)(X_MIN * 1000.);
	#endif
	#ifdef	X_MAX
    if (next_target.target.axis[X] > (int32_t)(X_MAX * 1000.))
      next_target.target.axis[X] = (int32_t)(X_MAX * 1000.);
	#endif
	#ifdef	Y_MIN
    if (next_target.target.axis[Y] < (int32_t)(Y_MIN * 1000.))
      next_target.target.axis[Y] = (int32_t)(Y_MIN * 1000.);
	#endif
	#ifdef	Y_MAX
    if (next_target.target.axis[Y] > (int32_t)(Y_MAX * 1000.))
      next_target.target.axis[Y] = (int32_t)(Y_MAX * 1000.);
	#endif
	#ifdef	Z_MIN
    if (next_target.target.axis[Z] < (int32_t)(Z_MIN * 1000.))
      next_target.target.axis[Z] = (int32_t)(Z_MIN * 1000.);
	#endif
	#ifdef	Z_MAX
    if (next_target.target.axis[Z] > (int32_t)(Z_MAX * 1000.))
      next_target.target.axis[Z] = (int32_t)(Z_MAX * 1000.);
	#endif

	// The GCode documentation was taken from http://reprap.org/wiki/Gcode .

	if (next_target.seen_T) {
	    //? --- T: Select Tool ---
	    //?
	    //? Example: T1
	    //?
	    //? Select extruder number 1 to build with.  Extruder numbering starts at 0.

	    next_tool = next_target.T;
	}

	if (next_target.seen_G) {
		uint8_t axisSelected = 0;

		switch (next_target.G) {
			case 0:
				//? G0: Rapid Linear Motion
				//?
				//? Example: G0 X12
				//?
				//? In this case move rapidly to X = 12 mm.  In fact, the RepRap firmware uses exactly the same code for rapid as it uses for controlled moves (see G1 below), as - for the RepRap machine - this is just as efficient as not doing so.  (The distinction comes from some old machine tools that used to move faster if the axes were not driven in a straight line.  For them G0 allowed any movement in space to get to the destination as fast as possible.)
				//?
        temp_wait();
				backup_f = next_target.target.F;
				next_target.target.F = MAXIMUM_FEEDRATE_X * 2L;
				enqueue(&next_target.target);
				next_target.target.F = backup_f;
				break;

			case 1:
				//? --- G1: Linear Motion at Feed Rate ---
				//?
				//? Example: G1 X90.6 Y13.8 E22.4
				//?
				//? Go in a straight line from the current (X, Y) point to the point (90.6, 13.8), extruding material as the move happens from the current extruded length to a length of 22.4 mm.
				//?
        temp_wait();
				enqueue(&next_target.target);
				break;

				//	G2 - Arc Clockwise
				// unimplemented

				//	G3 - Arc Counter-clockwise
				// unimplemented

			case 4:
				//? --- G4: Dwell ---
				//?
				//? Example: G4 P200
				//?
				//? In this case sit still doing nothing for 200 milliseconds.  During delays the state of the machine (for example the temperatures of its extruders) will still be preserved and controlled.
				//?
				queue_wait();
				// delay
				if (next_target.seen_P) {
					for (;next_target.P > 0;next_target.P--) {
						clock();
						delay_ms(1);
					}
				}
				break;

			case 20:
				//? --- G20: Set Units to Inches ---
				//?
				//? Example: G20
				//?
				//? Units from now on are in inches.
				//?
				next_target.option_inches = 1;
				break;

			case 21:
				//? --- G21: Set Units to Millimeters ---
				//?
				//? Example: G21
				//?
				//? Units from now on are in millimeters.  (This is the RepRap default.)
				//?
				next_target.option_inches = 0;
				break;

			case 28:
				//? --- G28: Home ---
				//?
				//? Example: G28
				//?
        //? This causes the RepRap machine to search for its X, Y and Z
        //? endstops. It does so at high speed, so as to get there fast. When
        //? it arrives it backs off slowly until the endstop is released again.
        //? Backing off slowly ensures more accurate positioning.
				//?
        //? If you add axis characters, then just the axes specified will be
        //? seached. Thus
				//?
        //?   G28 X Y72.3
				//?
        //? will zero the X and Y axes, but not Z. Coordinate values are
        //? ignored.
				//?

				queue_wait();

				if (next_target.seen_X) {
					#if defined	X_MIN_PIN
						home_x_negative();
					#elif defined X_MAX_PIN
						home_x_positive();
					#endif
					axisSelected = 1;
				}
				if (next_target.seen_Y) {
					#if defined	Y_MIN_PIN
						home_y_negative();
					#elif defined Y_MAX_PIN
						home_y_positive();
					#endif
					axisSelected = 1;
				}
				if (next_target.seen_Z) {
          #if defined Z_MIN_PIN
            home_z_negative();
          #elif defined Z_MAX_PIN
            home_z_positive();
					#endif
					axisSelected = 1;
				}
				// there's no point in moving E, as E has no endstops

				if (!axisSelected) {
					home();
				}
				break;

			case 90:
				//? --- G90: Set to Absolute Positioning ---
				//?
				//? Example: G90
				//?
				//? All coordinates from now on are absolute relative to the origin
				//? of the machine. This is the RepRap default.
				//?
				//? If you ever want to switch back and forth between relative and
				//? absolute movement keep in mind, X, Y and Z follow the machine's
				//? coordinate system while E doesn't change it's position in the
				//? coordinate system on relative movements.
				//?

				// No wait_queue() needed.
				next_target.option_all_relative = 0;
				break;

			case 91:
				//? --- G91: Set to Relative Positioning ---
				//?
				//? Example: G91
				//?
				//? All coordinates from now on are relative to the last position.
				//?

				// No wait_queue() needed.
				next_target.option_all_relative = 1;
				break;

			case 92:
				//? --- G92: Set Position ---
				//?
				//? Example: G92 X10 E90
				//?
				//? Allows programming of absolute zero point, by reseting the current position to the values specified.  This would set the machine's X coordinate to 10, and the extrude coordinate to 90. No physical motion will occur.
				//?

				queue_wait();

				if (next_target.seen_X) {
          startpoint.axis[X] = next_target.target.axis[X];
					axisSelected = 1;
				}
				if (next_target.seen_Y) {
          startpoint.axis[Y] = next_target.target.axis[Y];
					axisSelected = 1;
				}
				if (next_target.seen_Z) {
          startpoint.axis[Z] = next_target.target.axis[Z];
					axisSelected = 1;
				}
				if (next_target.seen_E) {
          startpoint.axis[E] = next_target.target.axis[E];
					axisSelected = 1;
				}

				if (axisSelected == 0) {
          startpoint.axis[X] = next_target.target.axis[X] =
          startpoint.axis[Y] = next_target.target.axis[Y] =
          startpoint.axis[Z] = next_target.target.axis[Z] =
          startpoint.axis[E] = next_target.target.axis[E] = 0;
				}

				dda_new_startpoint();
				break;

			case 161:
				//? --- G161: Home negative ---
				//?
				//? Find the minimum limit of the specified axes by searching for the limit switch.
				//?
        #if defined X_MIN_PIN
          if (next_target.seen_X)
            home_x_negative();
        #endif
        #if defined Y_MIN_PIN
          if (next_target.seen_Y)
            home_y_negative();
        #endif
        #if defined Z_MIN_PIN
          if (next_target.seen_Z)
            home_z_negative();
        #endif
				break;

			case 162:
				//? --- G162: Home positive ---
				//?
				//? Find the maximum limit of the specified axes by searching for the limit switch.
				//?
        #if defined X_MAX_PIN
          if (next_target.seen_X)
            home_x_positive();
        #endif
        #if defined Y_MAX_PIN
          if (next_target.seen_Y)
            home_y_positive();
        #endif
        #if defined Z_MAX_PIN
          if (next_target.seen_Z)
            home_z_positive();
        #endif
				break;

				// unknown gcode: spit an error
			default:
				sersendf_P(PSTR("E: Bad G-code %d\n"), next_target.G);
				return;
		}
	}
	else if (next_target.seen_M) {
		uint8_t i;

		switch (next_target.M) {
			case 0:
				//? --- M0: machine stop ---
				//?
				//? Example: M0
				//?
				//? http://linuxcnc.org/handbook/RS274NGC_3/RS274NGC_33a.html#1002379
				//? Unimplemented, especially the restart after the stop. Fall trough to M2.
				//?

			case 2:
      case 84: // For compatibility with slic3rs default end G-code.
				//? --- M2: program end ---
				//?
				//? Example: M2
				//?
				//? http://linuxcnc.org/handbook/RS274NGC_3/RS274NGC_33a.html#1002379
				//?
				queue_wait();
				for (i = 0; i < NUM_HEATERS; i++)
					temp_set(i, 0);
				power_off();
        serial_writestr_P(PSTR("\nstop\n"));
				break;

			case 6:
				//? --- M6: tool change ---
				//?
				//? Undocumented.
				tool = next_tool;
				break;

      #ifdef SD
      case 20:
        //? --- M20: list SD card. ---
        sd_list("/");
        break;

      case 21:
        //? --- M21: initialise SD card. ---
        //?
        //? Has to be done before doing any other operation, including M20.
        sd_mount();
        break;

      case 22:
        //? --- M22: release SD card. ---
        //?
        //? Not mandatory. Just removing the card is fine, but results in
        //? odd behaviour when trying to read from the card anyways. M22
        //? makes also sure SD card printing is disabled, even with the card
        //? inserted.
        sd_unmount();
        break;

      case 23:
        //? --- M23: select file. ---
        //?
        //? This opens a file for reading. This file is valid up to M22 or up
        //? to the next M23.
        sd_open(gcode_str_buf);
        break;

      case 24:
        //? --- M24: start/resume SD print. ---
        //?
        //? This makes the SD card available as a G-code source. File is the
        //? one selected with M23.
        gcode_sources |= GCODE_SOURCE_SD;
        break;

      case 25:
        //? --- M25: pause SD print. ---
        //?
        //? This removes the SD card from the bitfield of available G-code
        //? sources. The file is kept open. The position inside the file
        //? is kept as well, to allow resuming.
        gcode_sources &= ! GCODE_SOURCE_SD;
        break;
      #endif /* SD */

			case 82:
				//? --- M82 - Set E codes absolute ---
				//?
				//? This is the default and overrides G90/G91.
				//? M82/M83 is not documented in the RepRap wiki, behaviour
				//? was taken from Sprinter as of March 2012.
				//?
				//? While E does relative movements, it doesn't change its
				//? position in the coordinate system. See also comment on G90.
				//?

				// No wait_queue() needed.
				next_target.option_e_relative = 0;
				break;

			case 83:
				//? --- M83 - Set E codes relative ---
				//?
				//? Counterpart to M82.
				//?

				// No wait_queue() needed.
				next_target.option_e_relative = 1;
				break;

			// M3/M101- extruder on
			case 3:
			case 101:
				//? --- M101: extruder on ---
				//?
				//? Undocumented.
        temp_wait();
				#ifdef DC_EXTRUDER
					heater_set(DC_EXTRUDER, DC_EXTRUDER_PWM);
				#endif
				break;

			// M5/M103- extruder off
			case 5:
			case 103:
				//? --- M103: extruder off ---
				//?
				//? Undocumented.
				#ifdef DC_EXTRUDER
					heater_set(DC_EXTRUDER, 0);
				#endif
				break;

			case 104:
				//? --- M104: Set Extruder Temperature (Fast) ---
				//?
				//? Example: M104 S190
				//?
        //? Set the temperature of the current extruder to 190<sup>o</sup>C
        //? and return control to the host immediately (''i.e.'' before that
        //? temperature has been reached by the extruder). For waiting, see M116.
        //?
        //? Teacup supports an optional P parameter as a zero-based temperature
        //? sensor index to address (e.g. M104 P1 S100 will set the temperature
        //? of the heater connected to the second temperature sensor rather
        //? than the extruder temperature).
        //?
				if ( ! next_target.seen_S)
					break;
        if ( ! next_target.seen_P)
          #ifdef HEATER_EXTRUDER
            next_target.P = HEATER_EXTRUDER;
          #else
            next_target.P = 0;
          #endif
				temp_set(next_target.P, next_target.S);
				break;

			case 105:
        //? --- M105: Get Temperature(s) ---
				//?
				//? Example: M105
				//?
        //? Request the temperature of the current extruder and the build base
        //? in degrees Celsius. For example, the line sent to the host in
        //? response to this command looks like
				//?
				//? <tt>ok T:201 B:117</tt>
				//?
        //? Teacup supports an optional P parameter as a zero-based temperature
        //? sensor index to address.
				//?
				#ifdef ENFORCE_ORDER
					queue_wait();
				#endif
				if ( ! next_target.seen_P)
					next_target.P = TEMP_SENSOR_none;
				temp_print(next_target.P);
				break;

			case 7:
			case 106:
				//? --- M106: Set Fan Speed / Set Device Power ---
				//?
				//? Example: M106 S120
				//?
				//? Control the cooling fan (if any).
				//?
        //? Teacup supports an optional P parameter as a zero-based heater
        //? index to address. The heater index can differ from the temperature
        //? sensor index, see config.h.

				#ifdef ENFORCE_ORDER
					// wait for all moves to complete
					queue_wait();
				#endif
        if ( ! next_target.seen_P)
          #ifdef HEATER_FAN
            next_target.P = HEATER_FAN;
          #else
            next_target.P = 0;
          #endif
				if ( ! next_target.seen_S)
					break;
        heater_set(next_target.P, next_target.S);
				break;

			case 110:
				//? --- M110: Set Current Line Number ---
				//?
				//? Example: N123 M110
				//?
				//? Set the current line number to 123.  Thus the expected next line after this command will be 124.
				//? This is a no-op in Teacup.
				//?
				break;

      #ifdef DEBUG
			case 111:
				//? --- M111: Set Debug Level ---
				//?
				//? Example: M111 S6
				//?
				//? Set the level of debugging information transmitted back to the host to level 6.  The level is the OR of three bits:
				//?
				//? <Pre>
				//? #define         DEBUG_PID       1
				//? #define         DEBUG_DDA       2
				//? #define         DEBUG_POSITION  4
				//? </pre>
				//?
				//? This command is only available in DEBUG builds of Teacup.

				if ( ! next_target.seen_S)
					break;
				debug_flags = next_target.S;
				break;
      #endif /* DEBUG */

      case 112:
        //? --- M112: Emergency Stop ---
        //?
        //? Example: M112
        //?
        //? Any moves in progress are immediately terminated, then the printer
        //? shuts down. All motors and heaters are turned off. Only way to
        //? restart is to press the reset button on the master microcontroller.
        //? See also M0.
        //?
        timer_stop();
        queue_flush();
        power_off();
        cli();
        for (;;)
          wd_reset();
        break;

			case 114:
				//? --- M114: Get Current Position ---
				//?
				//? Example: M114
				//?
				//? This causes the RepRap machine to report its current X, Y, Z and E coordinates to the host.
				//?
				//? For example, the machine returns a string such as:
				//?
				//? <tt>ok C: X:0.00 Y:0.00 Z:0.00 E:0.00</tt>
				//?
				#ifdef ENFORCE_ORDER
					// wait for all moves to complete
					queue_wait();
				#endif
				update_current_position();
				sersendf_P(PSTR("X:%lq,Y:%lq,Z:%lq,E:%lq,F:%lu\n"),
                        current_position.axis[X], current_position.axis[Y],
                        current_position.axis[Z], current_position.axis[E],
				                current_position.F);

        if (mb_tail_dda != NULL) {
          if (DEBUG_POSITION && (debug_flags & DEBUG_POSITION)) {
            sersendf_P(PSTR("Endpoint: X:%ld,Y:%ld,Z:%ld,E:%ld,F:%lu,c:%lu}\n"),
                       mb_tail_dda->endpoint.axis[X],
                       mb_tail_dda->endpoint.axis[Y],
                       mb_tail_dda->endpoint.axis[Z],
                       mb_tail_dda->endpoint.axis[E],
                       mb_tail_dda->endpoint.F,
                       #ifdef ACCELERATION_REPRAP
                         mb_tail_dda->end_c
                       #else
                         mb_tail_dda->c
                       #endif
            );
          }
          print_queue();
        }

				break;

			case 115:
				//? --- M115: Get Firmware Version and Capabilities ---
				//?
				//? Example: M115
				//?
				//? Request the Firmware Version and Capabilities of the current microcontroller
				//? The details are returned to the host computer as key:value pairs separated by spaces and terminated with a linefeed.
				//?
				//? sample data from firmware:
				//?  FIRMWARE_NAME:Teacup FIRMWARE_URL:http://github.com/traumflug/Teacup_Firmware/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1 TEMP_SENSOR_COUNT:1 HEATER_COUNT:1
				//?

				sersendf_P(PSTR("FIRMWARE_NAME:Teacup FIRMWARE_URL:http://github.com/traumflug/Teacup_Firmware/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:%d TEMP_SENSOR_COUNT:%d HEATER_COUNT:%d\n"), 1, NUM_TEMP_SENSORS, NUM_HEATERS);
				break;

			case 116:
				//? --- M116: Wait ---
				//?
				//? Example: M116
				//?
				//? Wait for temperatures and other slowly-changing variables to arrive at their set values.
        temp_set_wait();
				break;

      case 119:
        //? --- M119: report endstop status ---
        //? Report the current status of the endstops configured in the
        //? firmware to the host.
        power_on();
        endstops_on();
        delay_ms(10); // allow the signal to stabilize
        {
          #if ! (defined(X_MIN_PIN) || defined(X_MAX_PIN) || \
                 defined(Y_MIN_PIN) || defined(Y_MAX_PIN) || \
                 defined(Z_MIN_PIN) || defined(Z_MAX_PIN))
            serial_writestr_P(PSTR("No endstops defined."));
          #else
            const char* const open = PSTR("open ");
            const char* const triggered = PSTR("triggered ");
          #endif

          #if defined(X_MIN_PIN)
            serial_writestr_P(PSTR("x_min:"));
            x_min() ? serial_writestr_P(triggered) : serial_writestr_P(open);
          #endif
          #if defined(X_MAX_PIN)
            serial_writestr_P(PSTR("x_max:"));
            x_max() ? serial_writestr_P(triggered) : serial_writestr_P(open);
          #endif
          #if defined(Y_MIN_PIN)
            serial_writestr_P(PSTR("y_min:"));
            y_min() ? serial_writestr_P(triggered) : serial_writestr_P(open);
          #endif
          #if defined(Y_MAX_PIN)
            serial_writestr_P(PSTR("y_max:"));
            y_max() ? serial_writestr_P(triggered) : serial_writestr_P(open);
          #endif
          #if defined(Z_MIN_PIN)
            serial_writestr_P(PSTR("z_min:"));
            z_min() ? serial_writestr_P(triggered) : serial_writestr_P(open);
          #endif
          #if defined(Z_MAX_PIN)
            serial_writestr_P(PSTR("z_max:"));
            z_max() ? serial_writestr_P(triggered) : serial_writestr_P(open);
          #endif
        }
        endstops_off();
        serial_writechar('\n');
        break;

      #ifdef EECONFIG
			case 130:
				//? --- M130: heater P factor ---
				//? Undocumented.
			  	//  P factor in counts per degreeC of error
        if ( ! next_target.seen_P)
          #ifdef HEATER_EXTRUDER
            next_target.P = HEATER_EXTRUDER;
          #else
            next_target.P = 0;
          #endif
				if (next_target.seen_S)
					pid_set_p(next_target.P, next_target.S);
				break;

			case 131:
				//? --- M131: heater I factor ---
				//? Undocumented.
			  	// I factor in counts per C*s of integrated error
        if ( ! next_target.seen_P)
          #ifdef HEATER_EXTRUDER
            next_target.P = HEATER_EXTRUDER;
          #else
            next_target.P = 0;
          #endif
				if (next_target.seen_S)
					pid_set_i(next_target.P, next_target.S);
				break;

			case 132:
				//? --- M132: heater D factor ---
				//? Undocumented.
			  	// D factor in counts per degreesC/second
        if ( ! next_target.seen_P)
          #ifdef HEATER_EXTRUDER
            next_target.P = HEATER_EXTRUDER;
          #else
            next_target.P = 0;
          #endif
				if (next_target.seen_S)
					pid_set_d(next_target.P, next_target.S);
				break;

			case 133:
				//? --- M133: heater I limit ---
				//? Undocumented.
        if ( ! next_target.seen_P)
          #ifdef HEATER_EXTRUDER
            next_target.P = HEATER_EXTRUDER;
          #else
            next_target.P = 0;
          #endif
				if (next_target.seen_S)
					pid_set_i_limit(next_target.P, next_target.S);
				break;

			case 134:
				//? --- M134: save PID settings to eeprom ---
				//? Undocumented.
				heater_save_settings();
				break;
      #endif /* EECONFIG */

      #ifdef DEBUG
			case 136:
				//? --- M136: PRINT PID settings to host ---
				//? Undocumented.
				//? This comand is only available in DEBUG builds.
        if ( ! next_target.seen_P)
          #ifdef HEATER_EXTRUDER
            next_target.P = HEATER_EXTRUDER;
          #else
            next_target.P = 0;
          #endif
				heater_print(next_target.P);
				break;
      #endif /* DEBUG */

			case 140:
				//? --- M140: Set heated bed temperature ---
				//? Undocumented.
				#ifdef	HEATER_BED
					if ( ! next_target.seen_S)
						break;
					temp_set(HEATER_BED, next_target.S);
				#endif
				break;

      case 220:
        //? --- M220: Set speed factor override percentage ---
        if ( ! next_target.seen_S)
          break;
        // Scale 100% = 256
        next_target.target.f_multiplier = (next_target.S * 64 + 12) / 25;
        break;

      case 221:
        //? --- M221: Control the extruders flow ---
        if ( ! next_target.seen_S)
          break;
        // Scale 100% = 256
        next_target.target.e_multiplier = (next_target.S * 64 + 12) / 25;
        break;

      #ifdef DEBUG
			case 240:
				//? --- M240: echo off ---
				//? Disable echo.
				//? This command is only available in DEBUG builds.
				debug_flags &= ~DEBUG_ECHO;
				serial_writestr_P(PSTR("Echo off\n"));
				break;

			case 241:
				//? --- M241: echo on ---
				//? Enable echo.
				//? This command is only available in DEBUG builds.
				debug_flags |= DEBUG_ECHO;
				serial_writestr_P(PSTR("Echo on\n"));
				break;
      #endif /* DEBUG */

				// unknown mcode: spit an error
			default:
				sersendf_P(PSTR("E: Bad M-code %d\n"), next_target.M);
		} // switch (next_target.M)
	} // else if (next_target.seen_M)
} // process_gcode_command()
Exemplo n.º 30
0
void process_gcode_command() {
	uint32_t	backup_f;

	// convert relative to absolute
	if (next_target.option_all_relative) {
		next_target.target.X += startpoint.X;
		next_target.target.Y += startpoint.Y;
		next_target.target.Z += startpoint.Z;
	}

	// E relative movement.
	// Matches Sprinter's behaviour as of March 2012.
	if (next_target.option_all_relative || next_target.option_e_relative)
		next_target.target.e_relative = 1;
	else
		next_target.target.e_relative = 0;

	// implement axis limits
	#ifdef	X_MIN
		if (next_target.target.X < X_MIN * 1000.)
			next_target.target.X = X_MIN * 1000.;
	#endif
	#ifdef	X_MAX
		if (next_target.target.X > X_MAX * 1000.)
			next_target.target.X = X_MAX * 1000.;
	#endif
	#ifdef	Y_MIN
		if (next_target.target.Y < Y_MIN * 1000.)
			next_target.target.Y = Y_MIN * 1000.;
	#endif
	#ifdef	Y_MAX
		if (next_target.target.Y > Y_MAX * 1000.)
			next_target.target.Y = Y_MAX * 1000.;
	#endif
	#ifdef	Z_MIN
		if (next_target.target.Z < Z_MIN * 1000.)
			next_target.target.Z = Z_MIN * 1000.;
	#endif
	#ifdef	Z_MAX
		if (next_target.target.Z > Z_MAX * 1000.)
			next_target.target.Z = Z_MAX * 1000.;
	#endif


	// The GCode documentation was taken from http://reprap.org/wiki/Gcode .

	if (next_target.seen_T) {
	    //? --- T: Select Tool ---
	    //?
	    //? Example: T1
	    //?
	    //? Select extruder number 1 to build with.  Extruder numbering starts at 0.

	    next_tool = next_target.T;
	}

	if (next_target.seen_G) {
		uint8_t axisSelected = 0;
		switch (next_target.G) {
			case 0:
				//? G0: Rapid Linear Motion
				//?
				//? Example: G0 X12
				//?
				//? In this case move rapidly to X = 12 mm.  In fact, the RepRap firmware uses exactly the same code for rapid as it uses for controlled moves (see G1 below), as - for the RepRap machine - this is just as efficient as not doing so.  (The distinction comes from some old machine tools that used to move faster if the axes were not driven in a straight line.  For them G0 allowed any movement in space to get to the destination as fast as possible.)
				//?
				backup_f = next_target.target.F;
				next_target.target.F = MAXIMUM_FEEDRATE_X * 2L;
				enqueue(&next_target.target);
				next_target.target.F = backup_f;
				break;

			case 1:
				//? --- G1: Linear Motion at Feed Rate ---
				//?
				//? Example: G1 X90.6 Y13.8 E22.4
				//?
				//? Go in a straight line from the current (X, Y) point to the point (90.6, 13.8), extruding material as the move happens from the current extruded length to a length of 22.4 mm.
				//?
				enqueue(&next_target.target);
				break;

				//	G2 - Arc Clockwise
				// unimplemented

				//	G3 - Arc Counter-clockwise
				// unimplemented

			case 4:
				//? --- G4: Dwell ---
				//?
				//? Example: G4 P200
				//?
				//? In this case sit still doing nothing for 200 milliseconds.  During delays the state of the machine (for example the temperatures of its extruders) will still be preserved and controlled.
				//?
				queue_wait();
				// delay
				if (next_target.seen_P) {
					for (;next_target.P > 0;next_target.P--) {
						clock();
						delay_ms(1);
					}
				}
				break;

			case 20:
				//? --- G20: Set Units to Inches ---
				//?
				//? Example: G20
				//?
				//? Units from now on are in inches.
				//?
				next_target.option_inches = 1;
				break;

			case 21:
				//? --- G21: Set Units to Millimeters ---
				//?
				//? Example: G21
				//?
				//? Units from now on are in millimeters.  (This is the RepRap default.)
				//?
				next_target.option_inches = 0;
				break;

			case 30:
				//? --- G30: Go home via point ---
				//?
				//? Undocumented.
				enqueue(&next_target.target);
				// no break here, G30 is move and then go home

			case 28:
				//? --- G28: Home ---
				//?
				//? Example: G28
				//?
				//? This causes the RepRap machine to move back to its X, Y and Z zero endstops.  It does so accelerating, so as to get there fast.  But when it arrives it backs off by 1 mm in each direction slowly, then moves back slowly to the stop.  This ensures more accurate positioning.
				//?
				//? If you add coordinates, then just the axes with coordinates specified will be zeroed.  Thus
				//?
				//? G28 X0 Y72.3
				//?
				//? will zero the X and Y axes, but not Z.  The actual coordinate values are ignored.
				//?

				queue_wait();

				if (next_target.seen_X) {
					#if defined	X_MIN_PIN
						home_x_negative();
					#elif defined X_MAX_PIN
						home_x_positive();
					#endif
					axisSelected = 1;
				}
				if (next_target.seen_Y) {
					#if defined	Y_MIN_PIN
						home_y_negative();
					#elif defined Y_MAX_PIN
						home_y_positive();
					#endif
					axisSelected = 1;
				}
				if (next_target.seen_Z) {
					#if defined Z_MAX_PIN
						home_z_positive();
					#elif defined	Z_MIN_PIN
						home_z_negative();
					#endif
					axisSelected = 1;
				}
				// there's no point in moving E, as E has no endstops

				if (!axisSelected) {
					home();
				}
				break;

			case 90:
				//? --- G90: Set to Absolute Positioning ---
				//?
				//? Example: G90
				//?
				//? All coordinates from now on are absolute relative to the origin
				//? of the machine. This is the RepRap default.
				//?
				//? If you ever want to switch back and forth between relative and
				//? absolute movement keep in mind, X, Y and Z follow the machine's
				//? coordinate system while E doesn't change it's position in the
				//? coordinate system on relative movements.
				//?

				// No wait_queue() needed.
				next_target.option_all_relative = 0;
				break;

			case 91:
				//? --- G91: Set to Relative Positioning ---
				//?
				//? Example: G91
				//?
				//? All coordinates from now on are relative to the last position.
				//?

				// No wait_queue() needed.
				next_target.option_all_relative = 1;
				break;

			case 92:
				//? --- G92: Set Position ---
				//?
				//? Example: G92 X10 E90
				//?
				//? Allows programming of absolute zero point, by reseting the current position to the values specified.  This would set the machine's X coordinate to 10, and the extrude coordinate to 90. No physical motion will occur.
				//?

				queue_wait();

				if (next_target.seen_X) {
					startpoint.X = next_target.target.X;
					axisSelected = 1;
				}
				if (next_target.seen_Y) {
					startpoint.Y = next_target.target.Y;
					axisSelected = 1;
				}
				if (next_target.seen_Z) {
					startpoint.Z = next_target.target.Z;
					axisSelected = 1;
				}
				if (next_target.seen_E) {
					startpoint.E = next_target.target.E;
					axisSelected = 1;
				}

				if (axisSelected == 0) {
					startpoint.X = next_target.target.X =
					startpoint.Y = next_target.target.Y =
					startpoint.Z = next_target.target.Z =
					startpoint.E = next_target.target.E = 0;
				}

				dda_new_startpoint();
				break;

			case 161:
				//? --- G161: Home negative ---
				//?
				//? Find the minimum limit of the specified axes by searching for the limit switch.
				//?
				if (next_target.seen_X)
					home_x_negative();
				if (next_target.seen_Y)
					home_y_negative();
				if (next_target.seen_Z)
					home_z_negative();
				break;

			case 162:
				//? --- G162: Home positive ---
				//?
				//? Find the maximum limit of the specified axes by searching for the limit switch.
				//?
				if (next_target.seen_X)
					home_x_positive();
				if (next_target.seen_Y)
					home_y_positive();
				if (next_target.seen_Z)
					home_z_positive();
				break;

				// unknown gcode: spit an error
			default:
				sersendf_P(PSTR("E: Bad G-code %d"), next_target.G);
				// newline is sent from gcode_parse after we return
				return;
		}
	}
	else if (next_target.seen_M) {
		uint8_t i;

		switch (next_target.M) {
			case 0:
				//? --- M0: machine stop ---
				//?
				//? Example: M0
				//?
				//? http://linuxcnc.org/handbook/RS274NGC_3/RS274NGC_33a.html#1002379
				//? Unimplemented, especially the restart after the stop. Fall trough to M2.
				//?

			case 2:
      case 84: // For compatibility with slic3rs default end G-code.
				//? --- M2: program end ---
				//?
				//? Example: M2
				//?
				//? http://linuxcnc.org/handbook/RS274NGC_3/RS274NGC_33a.html#1002379
				//?
				queue_wait();
				for (i = 0; i < NUM_HEATERS; i++)
					temp_set(i, 0);
				power_off();
				break;

			case 112:
				//? --- M112: Emergency Stop ---
				//?
				//? Example: M112
				//?
				//? Any moves in progress are immediately terminated, then RepRap shuts down.  All motors and heaters are turned off.
				//? It can be started again by pressing the reset button on the master microcontroller.  See also M0.
				//?

				timer_stop();
				queue_flush();
				power_off();
				cli();
				for (;;)
					wd_reset();
				break;

			case 6:
				//? --- M6: tool change ---
				//?
				//? Undocumented.
				tool = next_tool;
				break;

			case 82:
				//? --- M82 - Set E codes absolute ---
				//?
				//? This is the default and overrides G90/G91.
				//? M82/M83 is not documented in the RepRap wiki, behaviour
				//? was taken from Sprinter as of March 2012.
				//?
				//? While E does relative movements, it doesn't change its
				//? position in the coordinate system. See also comment on G90.
				//?

				// No wait_queue() needed.
				next_target.option_e_relative = 0;
				break;

			case 83:
				//? --- M83 - Set E codes relative ---
				//?
				//? Counterpart to M82.
				//?

				// No wait_queue() needed.
				next_target.option_e_relative = 1;
				break;

			// M3/M101- extruder on
			case 3:
			case 101:
				//? --- M101: extruder on ---
				//?
				//? Undocumented.
				if (temp_achieved() == 0) {
					enqueue(NULL);
				}
				#ifdef DC_EXTRUDER
					heater_set(DC_EXTRUDER, DC_EXTRUDER_PWM);
				#elif E_STARTSTOP_STEPS > 0
					do {
						// backup feedrate, move E very quickly then restore feedrate
						backup_f = startpoint.F;
						startpoint.F = MAXIMUM_FEEDRATE_E;
						SpecialMoveE(E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E);
						startpoint.F = backup_f;
					} while (0);
				#endif
				break;

			// M102- extruder reverse

			// M5/M103- extruder off
			case 5:
			case 103:
				//? --- M103: extruder off ---
				//?
				//? Undocumented.
				#ifdef DC_EXTRUDER
					heater_set(DC_EXTRUDER, 0);
				#elif E_STARTSTOP_STEPS > 0
					do {
						// backup feedrate, move E very quickly then restore feedrate
						backup_f = startpoint.F;
						startpoint.F = MAXIMUM_FEEDRATE_E;
						SpecialMoveE(-E_STARTSTOP_STEPS, MAXIMUM_FEEDRATE_E);
						startpoint.F = backup_f;
					} while (0);
				#endif
				break;

			case 104:
				//? --- M104: Set Extruder Temperature (Fast) ---
				//?
				//? Example: M104 S190
				//?
        //? Set the temperature of the current extruder to 190<sup>o</sup>C
        //? and return control to the host immediately (''i.e.'' before that
        //? temperature has been reached by the extruder). For waiting, see M116.
        //?
        //? Teacup supports an optional P parameter as a zero-based temperature
        //? sensor index to address (e.g. M104 P1 S100 will set the temperature
        //? of the heater connected to the second temperature sensor rather
        //? than the extruder temperature).
        //?
				if ( ! next_target.seen_S)
					break;
        #ifdef HEATER_EXTRUDER
          if ( ! next_target.seen_P)
            next_target.P = HEATER_EXTRUDER;
        // else use the first available device
        #endif
				temp_set(next_target.P, next_target.S);
				break;

			case 105:
        //? --- M105: Get Temperature(s) ---
				//?
				//? Example: M105
				//?
        //? Request the temperature of the current extruder and the build base
        //? in degrees Celsius. For example, the line sent to the host in
        //? response to this command looks like
				//?
				//? <tt>ok T:201 B:117</tt>
				//?
        //? Teacup supports an optional P parameter as a zero-based temperature
        //? sensor index to address.
				//?
				#ifdef ENFORCE_ORDER
					queue_wait();
				#endif
				if ( ! next_target.seen_P)
					next_target.P = TEMP_SENSOR_none;
				temp_print(next_target.P);
				break;

			case 7:
			case 106:
				//? --- M106: Set Fan Speed / Set Device Power ---
				//?
				//? Example: M106 S120
				//?
				//? Control the cooling fan (if any).
				//?
        //? Teacup supports an optional P parameter as a zero-based heater
        //? index to address. The heater index can differ from the temperature
        //? sensor index, see config.h.

				#ifdef ENFORCE_ORDER
					// wait for all moves to complete
					queue_wait();
				#endif
        #ifdef HEATER_FAN
          if ( ! next_target.seen_P)
            next_target.P = HEATER_FAN;
        // else use the first available device
        #endif
				if ( ! next_target.seen_S)
					break;
        heater_set(next_target.P, next_target.S);
				break;

			case 110:
				//? --- M110: Set Current Line Number ---
				//?
				//? Example: N123 M110
				//?
				//? Set the current line number to 123.  Thus the expected next line after this command will be 124.
				//? This is a no-op in Teacup.
				//?
				break;

			#ifdef	DEBUG
			case 111:
				//? --- M111: Set Debug Level ---
				//?
				//? Example: M111 S6
				//?
				//? Set the level of debugging information transmitted back to the host to level 6.  The level is the OR of three bits:
				//?
				//? <Pre>
				//? #define         DEBUG_PID       1
				//? #define         DEBUG_DDA       2
				//? #define         DEBUG_POSITION  4
				//? </pre>
				//?
				//? This command is only available in DEBUG builds of Teacup.

				if ( ! next_target.seen_S)
					break;
				debug_flags = next_target.S;
				break;
			#endif

			case 114:
				//? --- M114: Get Current Position ---
				//?
				//? Example: M114
				//?
				//? This causes the RepRap machine to report its current X, Y, Z and E coordinates to the host.
				//?
				//? For example, the machine returns a string such as:
				//?
				//? <tt>ok C: X:0.00 Y:0.00 Z:0.00 E:0.00</tt>
				//?
				#ifdef ENFORCE_ORDER
					// wait for all moves to complete
					queue_wait();
				#endif
				update_current_position();
				sersendf_P(PSTR("X:%lq,Y:%lq,Z:%lq,E:%lq,F:%lu"),
				                current_position.X, current_position.Y,
				                current_position.Z, current_position.E,
				                current_position.F);

				#ifdef	DEBUG
					if (DEBUG_POSITION && (debug_flags & DEBUG_POSITION)) {
						sersendf_P(PSTR(",c:%lu}\nEndpoint: X:%ld,Y:%ld,Z:%ld,E:%ld,F:%lu,c:%lu}"),
						                movebuffer[mb_tail].c, movebuffer[mb_tail].endpoint.X,
						                movebuffer[mb_tail].endpoint.Y, movebuffer[mb_tail].endpoint.Z,
						                movebuffer[mb_tail].endpoint.E, movebuffer[mb_tail].endpoint.F,
						#ifdef ACCELERATION_REPRAP
							movebuffer[mb_tail].end_c
						#else
							movebuffer[mb_tail].c
						#endif
						);
						print_queue();
					}
				#endif /* DEBUG */

				// newline is sent from gcode_parse after we return
				break;

			case 115:
				//? --- M115: Get Firmware Version and Capabilities ---
				//?
				//? Example: M115
				//?
				//? Request the Firmware Version and Capabilities of the current microcontroller
				//? The details are returned to the host computer as key:value pairs separated by spaces and terminated with a linefeed.
				//?
				//? sample data from firmware:
				//?  FIRMWARE_NAME:Teacup FIRMWARE_URL:http://github.com/triffid/Teacup_Firmware/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1 TEMP_SENSOR_COUNT:1 HEATER_COUNT:1
				//?

				sersendf_P(PSTR("FIRMWARE_NAME:Teacup FIRMWARE_URL:http://github.com/triffid/Teacup_Firmware/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:%d TEMP_SENSOR_COUNT:%d HEATER_COUNT:%d"), 1, NUM_TEMP_SENSORS, NUM_HEATERS);
				// newline is sent from gcode_parse after we return
				break;

			case 116:
				//? --- M116: Wait ---
				//?
				//? Example: M116
				//?
				//? Wait for temperatures and other slowly-changing variables to arrive at their set values.

				enqueue(NULL);
				break;

      case 119:
        //? --- M119: report endstop status ---
        //? Report the current status of the endstops configured in the
        //? firmware to the host.
        power_on();
        endstops_on();
        delay_ms(10); // allow the signal to stabilize
        #if defined(X_MIN_PIN)
          sersendf_P(PSTR("x_min:%d "), x_min());
        #endif
        #if defined(X_MAX_PIN)
          sersendf_P(PSTR("x_max:%d "), x_max());
        #endif
        #if defined(Y_MIN_PIN)
          sersendf_P(PSTR("y_min:%d "), y_min());
        #endif
        #if defined(Y_MAX_PIN)
          sersendf_P(PSTR("y_max:%d "), y_max());
        #endif
        #if defined(Z_MIN_PIN)
          sersendf_P(PSTR("z_min:%d "), z_min());
        #endif
        #if defined(Z_MAX_PIN)
          sersendf_P(PSTR("z_max:%d "), z_max());
        #endif
        #if ! (defined(X_MIN_PIN) || defined(X_MAX_PIN) || \
               defined(Y_MIN_PIN) || defined(Y_MAX_PIN) || \
               defined(Z_MIN_PIN) || defined(Z_MAX_PIN))
          sersendf_P(PSTR("no endstops defined"));
        #endif
        endstops_off();
        break;

      #ifdef EECONFIG
			case 130:
				//? --- M130: heater P factor ---
				//? Undocumented.
        #ifdef HEATER_EXTRUDER
          if ( ! next_target.seen_P)
            next_target.P = HEATER_EXTRUDER;
        // else use the first available device
        #endif
				if (next_target.seen_S)
					pid_set_p(next_target.P, next_target.S);
				break;

			case 131:
				//? --- M131: heater I factor ---
				//? Undocumented.
        #ifdef HEATER_EXTRUDER
          if ( ! next_target.seen_P)
            next_target.P = HEATER_EXTRUDER;
        #endif
				if (next_target.seen_S)
					pid_set_i(next_target.P, next_target.S);
				break;

			case 132:
				//? --- M132: heater D factor ---
				//? Undocumented.
        #ifdef HEATER_EXTRUDER
          if ( ! next_target.seen_P)
            next_target.P = HEATER_EXTRUDER;
        #endif
				if (next_target.seen_S)
					pid_set_d(next_target.P, next_target.S);
				break;

			case 133:
				//? --- M133: heater I limit ---
				//? Undocumented.
        #ifdef HEATER_EXTRUDER
          if ( ! next_target.seen_P)
            next_target.P = HEATER_EXTRUDER;
        #endif
				if (next_target.seen_S)
					pid_set_i_limit(next_target.P, next_target.S);
				break;

			case 134:
				//? --- M134: save PID settings to eeprom ---
				//? Undocumented.
				heater_save_settings();
				break;
      #endif /* EECONFIG */

			#ifdef	DEBUG
			case 136:
				//? --- M136: PRINT PID settings to host ---
				//? Undocumented.
				//? This comand is only available in DEBUG builds.
				if ( ! next_target.seen_P)
					next_target.P = HEATER_EXTRUDER;
				heater_print(next_target.P);
				break;
			#endif

			case 140:
				//? --- M140: Set heated bed temperature ---
				//? Undocumented.
				#ifdef	HEATER_BED
					if ( ! next_target.seen_S)
						break;
					temp_set(HEATER_BED, next_target.S);
				#endif
				break;

			#ifdef	DEBUG
			case 240:
				//? --- M240: echo off ---
				//? Disable echo.
				//? This command is only available in DEBUG builds.
				debug_flags &= ~DEBUG_ECHO;
				serial_writestr_P(PSTR("Echo off"));
				// newline is sent from gcode_parse after we return
				break;

			case 241:
				//? --- M241: echo on ---
				//? Enable echo.
				//? This command is only available in DEBUG builds.
				debug_flags |= DEBUG_ECHO;
				serial_writestr_P(PSTR("Echo on"));
				// newline is sent from gcode_parse after we return
				break;

			#endif /* DEBUG */

				// unknown mcode: spit an error
			default:
				sersendf_P(PSTR("E: Bad M-code %d"), next_target.M);
				// newline is sent from gcode_parse after we return
		} // switch (next_target.M)
	} // else if (next_target.seen_M)
} // process_gcode_command()