Add Marlin firmware. Has initial configuration for CoreXY and 1 servo.
Update CAD file with improved clearances for Pilot G2 cartridge clearances after first print.
This commit is contained in:
		
							
								
								
									
										304
									
								
								Marlin Firmware/buildroot/share/scripts/MarlinMesh.scad
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								Marlin Firmware/buildroot/share/scripts/MarlinMesh.scad
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,304 @@
 | 
			
		||||
 /**************************************\
 | 
			
		||||
 *                                      *
 | 
			
		||||
 *   OpenSCAD Mesh Display              *
 | 
			
		||||
 *   by Thinkyhead - April 2017         *
 | 
			
		||||
 *                                      *
 | 
			
		||||
 *   Copy the grid output from Marlin,  *
 | 
			
		||||
 *   paste below as shown, and use      *
 | 
			
		||||
 *   OpenSCAD to see a visualization    *
 | 
			
		||||
 *   of your mesh.                      *
 | 
			
		||||
 *                                      *
 | 
			
		||||
 \**************************************/
 | 
			
		||||
 | 
			
		||||
$t = 0.15; // comment out during animation!
 | 
			
		||||
X = 0; Y = 1;
 | 
			
		||||
L = 0; R = 1; F = 2; B = 3;
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Sample Mesh - Replace with your own
 | 
			
		||||
//
 | 
			
		||||
measured_z = [
 | 
			
		||||
  [ -1.20, -1.13, -1.09, -1.03, -1.19 ],
 | 
			
		||||
  [ -1.16, -1.25, -1.27, -1.25, -1.08 ],
 | 
			
		||||
  [ -1.13, -1.26, -1.39, -1.31, -1.18 ],
 | 
			
		||||
  [ -1.09, -1.20, -1.26, -1.21, -1.18 ],
 | 
			
		||||
  [ -1.13, -0.99, -1.03, -1.06, -1.32 ]
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// An offset to add to all points in the mesh
 | 
			
		||||
//
 | 
			
		||||
zadjust     = 0;
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Mesh characteristics
 | 
			
		||||
//
 | 
			
		||||
bed_size = [ 200, 200 ];
 | 
			
		||||
 | 
			
		||||
mesh_inset  = [ 10, 10, 10, 10 ]; // L, F, R, B
 | 
			
		||||
 | 
			
		||||
mesh_bounds = [
 | 
			
		||||
  [ mesh_inset[L], mesh_inset[F] ],
 | 
			
		||||
  [ bed_size[X] - mesh_inset[R], bed_size[Y] - mesh_inset[B] ]
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
mesh_size = mesh_bounds[1] - mesh_bounds[0];
 | 
			
		||||
 | 
			
		||||
                      // NOTE: Marlin meshes already subtract the probe offset
 | 
			
		||||
NAN         = 0;      // Z to use for un-measured points
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Geometry
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
max_z_scale   = 100;   // Scale at Time 0.5
 | 
			
		||||
min_z_scale   = 10;    // Scale at Time 0.0 and 1.0
 | 
			
		||||
thickness     = 0.5;   // thickness of the mesh triangles
 | 
			
		||||
tesselation   = 1;     // levels of tesselation from 0-2
 | 
			
		||||
alternation   = 2;     // direction change modulus (try it)
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Appearance
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
show_plane    = true;
 | 
			
		||||
show_labels   = true;
 | 
			
		||||
show_coords   = true;
 | 
			
		||||
arrow_length  = 5;
 | 
			
		||||
 | 
			
		||||
label_font_lg = "Arial";
 | 
			
		||||
label_font_sm = "Arial";
 | 
			
		||||
mesh_color    = [1,1,1,0.5];
 | 
			
		||||
plane_color   = [0.4,0.6,0.9,0.6];
 | 
			
		||||
 | 
			
		||||
//================================================ Derive useful values
 | 
			
		||||
 | 
			
		||||
big_z = max_2D(measured_z,0);
 | 
			
		||||
lil_z = min_2D(measured_z,0);
 | 
			
		||||
 | 
			
		||||
mean_value = (big_z + lil_z) / 2.0;
 | 
			
		||||
 | 
			
		||||
mesh_points_y = len(measured_z);
 | 
			
		||||
mesh_points_x = len(measured_z[0]);
 | 
			
		||||
 | 
			
		||||
xspace = mesh_size[X] / (mesh_points_x - 1);
 | 
			
		||||
yspace = mesh_size[Y] / (mesh_points_y - 1);
 | 
			
		||||
 | 
			
		||||
// At $t=0 and $t=1 scale will be 100%
 | 
			
		||||
z_scale_factor = min_z_scale + (($t > 0.5) ? 1.0 - $t : $t) * (max_z_scale - min_z_scale) * 2;
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Min and max recursive functions for 1D and 2D arrays
 | 
			
		||||
// Return the smallest or largest value in the array
 | 
			
		||||
//
 | 
			
		||||
function some_1D(b,i) = (i<len(b)-1) ? (b[i] && some_1D(b,i+1)) : b[i] != 0;
 | 
			
		||||
function some_2D(a,j) = (j<len(a)-1) ? some_2D(a,j+1) : some_1D(a[j], 0);
 | 
			
		||||
function min_1D(b,i) = (i<len(b)-1) ? min(b[i], min_1D(b,i+1)) : b[i];
 | 
			
		||||
function min_2D(a,j) = (j<len(a)-1) ? min_2D(a,j+1) : min_1D(a[j], 0);
 | 
			
		||||
function max_1D(b,i) = (i<len(b)-1) ? max(b[i], max_1D(b,i+1)) : b[i];
 | 
			
		||||
function max_2D(a,j) = (j<len(a)-1) ? max_2D(a,j+1) : max_1D(a[j], 0);
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Get the corner probe points of a grid square.
 | 
			
		||||
//
 | 
			
		||||
// Input  : x,y grid indexes
 | 
			
		||||
// Output : An array of the 4 corner points
 | 
			
		||||
//
 | 
			
		||||
function grid_square(x,y) = [
 | 
			
		||||
  [x * xspace, y * yspace, z_scale_factor * (measured_z[y][x] - mean_value)],
 | 
			
		||||
  [x * xspace, (y+1) * yspace, z_scale_factor * (measured_z[y+1][x] - mean_value)],
 | 
			
		||||
  [(x+1) * xspace, (y+1) * yspace, z_scale_factor * (measured_z[y+1][x+1] - mean_value)],
 | 
			
		||||
  [(x+1) * xspace, y * yspace, z_scale_factor * (measured_z[y][x+1] - mean_value)]
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
// The corner point of a grid square with Z centered on the mean
 | 
			
		||||
function pos(x,y,z) = [x * xspace, y * yspace, z_scale_factor * (z - mean_value)];
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Draw the point markers and labels
 | 
			
		||||
//
 | 
			
		||||
module point_markers(show_home=true) {
 | 
			
		||||
  // Mark the home position 0,0
 | 
			
		||||
  if (show_home)
 | 
			
		||||
    translate([1,1]) color([0,0,0,0.25])
 | 
			
		||||
      cylinder(r=1, h=z_scale_factor, center=true);
 | 
			
		||||
 | 
			
		||||
  for (x=[0:mesh_points_x-1], y=[0:mesh_points_y-1]) {
 | 
			
		||||
    z = measured_z[y][x] - zadjust;
 | 
			
		||||
    down = z < mean_value;
 | 
			
		||||
    xyz = pos(x, y, z);
 | 
			
		||||
    translate([ xyz[0], xyz[1] ]) {
 | 
			
		||||
 | 
			
		||||
      // Show the XY as well as the Z!
 | 
			
		||||
      if (show_coords) {
 | 
			
		||||
        color("black")
 | 
			
		||||
        translate([0,0,0.5]) {
 | 
			
		||||
          $fn=8;
 | 
			
		||||
          rotate([0,0]) {
 | 
			
		||||
            posx = floor(mesh_bounds[0][X] + x * xspace);
 | 
			
		||||
            posy = floor(mesh_bounds[0][Y] + y * yspace);
 | 
			
		||||
            text(str(posx, ",", posy), 2, label_font_sm, halign="center", valign="center");
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      translate([ 0, 0, xyz[2] ]) {
 | 
			
		||||
        // Label each point with the Z
 | 
			
		||||
        v = z - mean_value;
 | 
			
		||||
        if (show_labels) {
 | 
			
		||||
 | 
			
		||||
          color(abs(v) < 0.1 ? [0,0.5,0] : [0.25,0,0])
 | 
			
		||||
          translate([0,0,down?-10:10]) {
 | 
			
		||||
 | 
			
		||||
            $fn=8;
 | 
			
		||||
            rotate([90,0])
 | 
			
		||||
              text(str(z), 6, label_font_lg, halign="center", valign="center");
 | 
			
		||||
 | 
			
		||||
            if (v)
 | 
			
		||||
              translate([0,0,down?-6:6]) rotate([90,0])
 | 
			
		||||
                text(str(down || !v ? "" : "+", v), 3, label_font_sm, halign="center", valign="center");
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Show an arrow pointing up or down
 | 
			
		||||
        if (v) {
 | 
			
		||||
          rotate([0, down ? 180 : 0]) translate([0,0,-1])
 | 
			
		||||
            cylinder(
 | 
			
		||||
              r1=0.5,
 | 
			
		||||
              r2=0.1,
 | 
			
		||||
              h=arrow_length, $fn=12, center=1
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
          color([1,0,1,0.4]) sphere(r=1.0, $fn=20, center=1);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Split a square on the diagonal into
 | 
			
		||||
// two triangles and render them.
 | 
			
		||||
//
 | 
			
		||||
//     s : a square
 | 
			
		||||
//   alt : a flag to split on the other diagonal
 | 
			
		||||
//
 | 
			
		||||
module tesselated_square(s, alt=false) {
 | 
			
		||||
  add = [0,0,thickness];
 | 
			
		||||
  p1 = [
 | 
			
		||||
    s[0], s[1], s[2], s[3],
 | 
			
		||||
    s[0]+add, s[1]+add, s[2]+add, s[3]+add
 | 
			
		||||
  ];
 | 
			
		||||
  f1 = alt
 | 
			
		||||
      ? [ [0,1,3], [4,5,1,0], [4,7,5], [5,7,3,1], [7,4,0,3] ]
 | 
			
		||||
      : [ [0,1,2], [4,5,1,0], [4,6,5], [5,6,2,1], [6,4,0,2] ];
 | 
			
		||||
  f2 = alt
 | 
			
		||||
      ? [ [1,2,3], [5,6,2,1], [5,6,7], [6,7,3,2], [7,5,1,3] ]
 | 
			
		||||
      : [ [0,2,3], [4,6,2,0], [4,7,6], [6,7,3,2], [7,4,0,3] ];
 | 
			
		||||
 | 
			
		||||
  // Use the other diagonal
 | 
			
		||||
  polyhedron(points=p1, faces=f1);
 | 
			
		||||
  polyhedron(points=p1, faces=f2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The simplest mesh display
 | 
			
		||||
 */
 | 
			
		||||
module simple_mesh(show_plane=show_plane) {
 | 
			
		||||
  if (show_plane) color(plane_color) cube([mesh_size[X], mesh_size[Y], thickness]);
 | 
			
		||||
  color(mesh_color)
 | 
			
		||||
    for (x=[0:mesh_points_x-2], y=[0:mesh_points_y-2])
 | 
			
		||||
      tesselated_square(grid_square(x, y));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Subdivide the mesh into smaller squares.
 | 
			
		||||
 */
 | 
			
		||||
module bilinear_mesh(show_plane=show_plane,tesselation=tesselation) {
 | 
			
		||||
  if (show_plane) color(plane_color) translate([-5,-5]) cube([mesh_size[X]+10, mesh_size[Y]+10, thickness]);
 | 
			
		||||
 | 
			
		||||
  if (some_2D(measured_z, 0)) {
 | 
			
		||||
 | 
			
		||||
    tesselation = tesselation % 4;
 | 
			
		||||
    color(mesh_color)
 | 
			
		||||
    for (x=[0:mesh_points_x-2], y=[0:mesh_points_y-2]) {
 | 
			
		||||
      square = grid_square(x, y);
 | 
			
		||||
      if (tesselation < 1) {
 | 
			
		||||
        tesselated_square(square,(x%alternation)-(y%alternation));
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        subdiv_4 = subdivided_square(square);
 | 
			
		||||
        if (tesselation < 2) {
 | 
			
		||||
          for (i=[0:3]) tesselated_square(subdiv_4[i],i%alternation);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          for (i=[0:3]) {
 | 
			
		||||
            subdiv_16 = subdivided_square(subdiv_4[i]);
 | 
			
		||||
            if (tesselation < 3) {
 | 
			
		||||
              for (j=[0:3]) tesselated_square(subdiv_16[j],j%alternation);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
              for (j=[0:3]) {
 | 
			
		||||
                subdiv_64 = subdivided_square(subdiv_16[j]);
 | 
			
		||||
                if (tesselation < 4) {
 | 
			
		||||
                  for (k=[0:3]) tesselated_square(subdiv_64[k]);
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Subdivision helpers
 | 
			
		||||
//
 | 
			
		||||
function ctrz(a) = (a[0][2]+a[1][2]+a[3][2]+a[2][2])/4;
 | 
			
		||||
function avgx(a,i) = (a[i][0]+a[(i+1)%4][0])/2;
 | 
			
		||||
function avgy(a,i) = (a[i][1]+a[(i+1)%4][1])/2;
 | 
			
		||||
function avgz(a,i) = (a[i][2]+a[(i+1)%4][2])/2;
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Convert one square into 4, applying bilinear averaging
 | 
			
		||||
//
 | 
			
		||||
// Input  : 1 square (4 points)
 | 
			
		||||
// Output : An array of 4 squares
 | 
			
		||||
//
 | 
			
		||||
function subdivided_square(a) = [
 | 
			
		||||
  [ // SW square
 | 
			
		||||
    a[0],                          // SW
 | 
			
		||||
    [a[0][0],avgy(a,0),avgz(a,0)], // CW
 | 
			
		||||
    [avgx(a,1),avgy(a,0),ctrz(a)], // CC
 | 
			
		||||
    [avgx(a,1),a[0][1],avgz(a,3)]  // SC
 | 
			
		||||
  ],
 | 
			
		||||
  [ // NW square
 | 
			
		||||
    [a[0][0],avgy(a,0),avgz(a,0)], // CW
 | 
			
		||||
    a[1],                          // NW
 | 
			
		||||
    [avgx(a,1),a[1][1],avgz(a,1)], // NC
 | 
			
		||||
    [avgx(a,1),avgy(a,0),ctrz(a)]  // CC
 | 
			
		||||
  ],
 | 
			
		||||
  [ // NE square
 | 
			
		||||
    [avgx(a,1),avgy(a,0),ctrz(a)], // CC
 | 
			
		||||
    [avgx(a,1),a[1][1],avgz(a,1)], // NC
 | 
			
		||||
    a[2],                          // NE
 | 
			
		||||
    [a[2][0],avgy(a,0),avgz(a,2)]  // CE
 | 
			
		||||
  ],
 | 
			
		||||
  [ // SE square
 | 
			
		||||
    [avgx(a,1),a[0][1],avgz(a,3)], // SC
 | 
			
		||||
    [avgx(a,1),avgy(a,0),ctrz(a)], // CC
 | 
			
		||||
    [a[2][0],avgy(a,0),avgz(a,2)], // CE
 | 
			
		||||
    a[3]                           // SE
 | 
			
		||||
  ]
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//================================================ Run the plan
 | 
			
		||||
 | 
			
		||||
translate([-mesh_size[X] / 2, -mesh_size[Y] / 2]) {
 | 
			
		||||
  $fn = 12;
 | 
			
		||||
  point_markers();
 | 
			
		||||
  bilinear_mesh();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										200
									
								
								Marlin Firmware/buildroot/share/scripts/config-labels.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								Marlin Firmware/buildroot/share/scripts/config-labels.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,200 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
#
 | 
			
		||||
# for python3.5 or higher
 | 
			
		||||
#-----------------------------------
 | 
			
		||||
# Within Marlin project MarlinFirmware/Configurations, this program visits all folders
 | 
			
		||||
# under .../config/examples/*, processing each Configuration.h, Configuration_adv.h,
 | 
			
		||||
# _Bootscreen.h, and _Statusscreen.h, to insert:
 | 
			
		||||
#    #define CONFIG_EXAMPLES_DIR "examples/<style>/<vendor>/<model>"
 | 
			
		||||
# ... or similar path leading to this file.
 | 
			
		||||
#
 | 
			
		||||
# Warning: The program modifies files in place, so be sure to back them up first if needed.
 | 
			
		||||
# Can be run multiple times if needed. Only modifies files which don't have
 | 
			
		||||
# correct #define CONFIG_EXAMPLES_DIR line.
 | 
			
		||||
#
 | 
			
		||||
# Invocation:
 | 
			
		||||
#-------------
 | 
			
		||||
# 1. Change directory to your MarlinFirmware/Configurations working copy
 | 
			
		||||
# 2. python3 config-labels.py
 | 
			
		||||
#
 | 
			
		||||
#-----------------------------------
 | 
			
		||||
# 2020-05-10 GMW original
 | 
			
		||||
# 2020-06-05 SRL style tweaks
 | 
			
		||||
#-----------------------------------
 | 
			
		||||
#
 | 
			
		||||
import sys,os
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
from distutils.dir_util import copy_tree  # for copy_tree, because shutil.copytree can't handle existing files, dirs
 | 
			
		||||
 | 
			
		||||
# Modify input_examples_dir and output_examples_dir for your installation
 | 
			
		||||
# No trailing slash
 | 
			
		||||
# Setting output_examples_dir = input_examples_dir causes the program to insert into the existing files.
 | 
			
		||||
 | 
			
		||||
input_examples_dir = r'config/examples'
 | 
			
		||||
# output_examples_dir   = input_examples_dir
 | 
			
		||||
output_examples_dir = r'config/examples'
 | 
			
		||||
 | 
			
		||||
#-------------------------------------
 | 
			
		||||
 | 
			
		||||
files_to_mod = ['Configuration.h', 'Configuration_adv.h', '_Bootscreen.h', '_Statusscreen.h']
 | 
			
		||||
 | 
			
		||||
macro_name     = 'CONFIG_EXAMPLES_DIR'
 | 
			
		||||
def_macro_name = '#define ' + macro_name
 | 
			
		||||
 | 
			
		||||
filenum = 0
 | 
			
		||||
different_out_dir = not (output_examples_dir == input_examples_dir)
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------
 | 
			
		||||
def process_file(subdir: str, filename: str):
 | 
			
		||||
#----------------------------------------------
 | 
			
		||||
	global filenum
 | 
			
		||||
	filenum += 1
 | 
			
		||||
 | 
			
		||||
	print(str(filenum) + '  ' + filename + ':  ' + subdir)
 | 
			
		||||
 | 
			
		||||
	def_line = (def_macro_name + ' "'  + subdir.replace('\\', '/')  + '"')
 | 
			
		||||
 | 
			
		||||
	#------------------------
 | 
			
		||||
	# Read file
 | 
			
		||||
	#------------------------
 | 
			
		||||
	lines = []
 | 
			
		||||
	infilepath = os.path.join(input_examples_dir, subdir, filename)
 | 
			
		||||
	try:
 | 
			
		||||
		# UTF-8 because some files contain unicode chars
 | 
			
		||||
		with open(infilepath, 'rt', encoding="utf-8") as infile:
 | 
			
		||||
			lines = infile.readlines()
 | 
			
		||||
 | 
			
		||||
	except Exception as e:
 | 
			
		||||
		print('Failed to read file: ' + str(e) )
 | 
			
		||||
		raise Exception
 | 
			
		||||
 | 
			
		||||
	lines = [line.rstrip('\r\n') for line in lines]
 | 
			
		||||
 | 
			
		||||
	#------------------------
 | 
			
		||||
	# Process lines
 | 
			
		||||
	#------------------------
 | 
			
		||||
	file_modified    = False
 | 
			
		||||
 | 
			
		||||
	# region state machine
 | 
			
		||||
	# -1 = before pragma once;
 | 
			
		||||
	# 0 = region to place define;
 | 
			
		||||
	# 1 = past region to place define
 | 
			
		||||
	region      = -1
 | 
			
		||||
 | 
			
		||||
	outlines = []
 | 
			
		||||
	for line in lines:
 | 
			
		||||
		outline = line
 | 
			
		||||
 | 
			
		||||
		if (region == -1) and (def_macro_name in line):
 | 
			
		||||
			outline       = None
 | 
			
		||||
			file_modified = True
 | 
			
		||||
 | 
			
		||||
		elif (region == -1) and ('pragma once' in line):
 | 
			
		||||
			region = 0
 | 
			
		||||
 | 
			
		||||
		elif (region == 0):
 | 
			
		||||
			if (line.strip() == ''):
 | 
			
		||||
				pass
 | 
			
		||||
			elif (def_macro_name in line):
 | 
			
		||||
				region = 1
 | 
			
		||||
				if line == def_line:   # leave it as is
 | 
			
		||||
					pass
 | 
			
		||||
				else:
 | 
			
		||||
					outline       = def_line
 | 
			
		||||
					file_modified = True
 | 
			
		||||
			else: # some other string
 | 
			
		||||
				outlines.append(def_line)
 | 
			
		||||
				outlines.append('')
 | 
			
		||||
				region = 1
 | 
			
		||||
				file_modified = True
 | 
			
		||||
 | 
			
		||||
		elif (region == 1):
 | 
			
		||||
			if (def_macro_name in line):
 | 
			
		||||
				outline       = None
 | 
			
		||||
				file_modified = True
 | 
			
		||||
			else:
 | 
			
		||||
				pass
 | 
			
		||||
 | 
			
		||||
		# end if
 | 
			
		||||
		if outline is not None:
 | 
			
		||||
			outlines.append(outline)
 | 
			
		||||
	# end for
 | 
			
		||||
 | 
			
		||||
	#-------------------------
 | 
			
		||||
	#     Output file
 | 
			
		||||
	#-------------------------
 | 
			
		||||
	outdir      = os.path.join(output_examples_dir, subdir)
 | 
			
		||||
	outfilepath = os.path.join(outdir, filename)
 | 
			
		||||
 | 
			
		||||
	if file_modified:
 | 
			
		||||
		# Note: no need to create output dirs, as the initial copy_tree
 | 
			
		||||
		# will do that.
 | 
			
		||||
 | 
			
		||||
		print('  writing ' + str(outfilepath))
 | 
			
		||||
		try:
 | 
			
		||||
			# Preserve unicode chars; Avoid CR-LF on Windows.
 | 
			
		||||
			with open(outfilepath, "w", encoding="utf-8", newline='\n') as outfile:
 | 
			
		||||
				outfile.write("\n".join(outlines))
 | 
			
		||||
				outfile.write("\n")
 | 
			
		||||
 | 
			
		||||
		except Exception as e:
 | 
			
		||||
			print('Failed to write file: ' + str(e) )
 | 
			
		||||
			raise Exception
 | 
			
		||||
	else:
 | 
			
		||||
		print('  no change for ' + str(outfilepath))
 | 
			
		||||
 | 
			
		||||
#----------
 | 
			
		||||
def main():
 | 
			
		||||
#----------
 | 
			
		||||
	global filenum
 | 
			
		||||
	global input_examples_dir
 | 
			
		||||
	global output_examples_dir
 | 
			
		||||
	filenum = 0
 | 
			
		||||
 | 
			
		||||
	#--------------------------------
 | 
			
		||||
	# Check for requirements
 | 
			
		||||
	#--------------------------------
 | 
			
		||||
	input_examples_dir  = input_examples_dir.strip()
 | 
			
		||||
	input_examples_dir  = input_examples_dir.rstrip('\\/')
 | 
			
		||||
	output_examples_dir = output_examples_dir.strip()
 | 
			
		||||
	output_examples_dir = output_examples_dir.rstrip('\\/')
 | 
			
		||||
 | 
			
		||||
	for dir in [input_examples_dir, output_examples_dir]:
 | 
			
		||||
		if not (os.path.exists(dir)):
 | 
			
		||||
			print('Directory not found: ' + dir)
 | 
			
		||||
			sys.exit(1)
 | 
			
		||||
 | 
			
		||||
	#--------------------------------
 | 
			
		||||
	# Copy tree if necessary.
 | 
			
		||||
	#--------------------------------
 | 
			
		||||
	# This includes files that are not otherwise included in the
 | 
			
		||||
	# insertion of the define statement.
 | 
			
		||||
	#
 | 
			
		||||
	if different_out_dir:
 | 
			
		||||
		print('Copying files to new directory: ' + output_examples_dir)
 | 
			
		||||
		try:
 | 
			
		||||
			copy_tree(input_examples_dir, output_examples_dir)
 | 
			
		||||
		except Exception as e:
 | 
			
		||||
			print('Failed to copy directory: ' + str(e) )
 | 
			
		||||
			raise Exception
 | 
			
		||||
 | 
			
		||||
	#-----------------------------
 | 
			
		||||
	# Find and process files
 | 
			
		||||
	#-----------------------------
 | 
			
		||||
	len_input_examples_dir = len(input_examples_dir);
 | 
			
		||||
	len_input_examples_dir += 1
 | 
			
		||||
 | 
			
		||||
	for filename in files_to_mod:
 | 
			
		||||
		input_path = Path(input_examples_dir)
 | 
			
		||||
		filepathlist = input_path.rglob(filename)
 | 
			
		||||
 | 
			
		||||
		for filepath in filepathlist:
 | 
			
		||||
			fulldirpath = str(filepath.parent)
 | 
			
		||||
			subdir      = fulldirpath[len_input_examples_dir:]
 | 
			
		||||
 | 
			
		||||
			process_file(subdir, filename)
 | 
			
		||||
 | 
			
		||||
#==============
 | 
			
		||||
print('--- Starting config-labels ---')
 | 
			
		||||
main()
 | 
			
		||||
print('--- Done ---')
 | 
			
		||||
@@ -0,0 +1,53 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
from __future__ import division
 | 
			
		||||
 | 
			
		||||
""" Generate the stepper delay lookup table for Marlin firmware. """
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
 | 
			
		||||
__author__ = "Ben Gamari <bgamari@gmail.com>"
 | 
			
		||||
__copyright__ = "Copyright 2012, Ben Gamari"
 | 
			
		||||
__license__ = "GPL"
 | 
			
		||||
 | 
			
		||||
parser = argparse.ArgumentParser(description=__doc__)
 | 
			
		||||
parser.add_argument('-f', '--cpu-freq', type=int, default=16, help='CPU clockrate in MHz (default=16)')
 | 
			
		||||
parser.add_argument('-d', '--divider', type=int, default=8, help='Timer/counter pre-scale divider (default=8)')
 | 
			
		||||
args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
cpu_freq = args.cpu_freq * 1000000
 | 
			
		||||
timer_freq = cpu_freq / args.divider
 | 
			
		||||
 | 
			
		||||
print("#ifndef SPEED_LOOKUPTABLE_H")
 | 
			
		||||
print("#define SPEED_LOOKUPTABLE_H")
 | 
			
		||||
print()
 | 
			
		||||
print('#include "MarlinCore.h"')
 | 
			
		||||
print()
 | 
			
		||||
 | 
			
		||||
print("const uint16_t speed_lookuptable_fast[256][2] PROGMEM = {")
 | 
			
		||||
a = [ timer_freq / ((i*256)+(args.cpu_freq*2)) for i in range(256) ]
 | 
			
		||||
b = [ a[i] - a[i+1] for i in range(255) ]
 | 
			
		||||
b.append(b[-1])
 | 
			
		||||
for i in range(32):
 | 
			
		||||
    print("  ", end=' ')
 | 
			
		||||
    for j in range(8):
 | 
			
		||||
        print("{%d, %d}," % (a[8*i+j], b[8*i+j]), end=' ')
 | 
			
		||||
    print()
 | 
			
		||||
print("};")
 | 
			
		||||
print()
 | 
			
		||||
 | 
			
		||||
print("const uint16_t speed_lookuptable_slow[256][2] PROGMEM = {")
 | 
			
		||||
a = [ timer_freq / ((i*8)+(args.cpu_freq*2)) for i in range(256) ]
 | 
			
		||||
b = [ a[i] - a[i+1] for i in range(255) ]
 | 
			
		||||
b.append(b[-1])
 | 
			
		||||
for i in range(32):
 | 
			
		||||
    print("  ", end=' ')
 | 
			
		||||
    for j in range(8):
 | 
			
		||||
        print("{%d, %d}," % (a[8*i+j], b[8*i+j]), end=' ')
 | 
			
		||||
    print()
 | 
			
		||||
print("};")
 | 
			
		||||
print()
 | 
			
		||||
 | 
			
		||||
print("#endif")
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,157 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
"""Thermistor Value Lookup Table Generator
 | 
			
		||||
 | 
			
		||||
Generates lookup to temperature values for use in a microcontroller in C format based on:
 | 
			
		||||
https://en.wikipedia.org/wiki/Steinhart-Hart_equation
 | 
			
		||||
 | 
			
		||||
The main use is for Arduino programs that read data from the circuit board described here:
 | 
			
		||||
https://reprap.org/wiki/Temperature_Sensor_v2.0
 | 
			
		||||
 | 
			
		||||
Usage: python createTemperatureLookupMarlin.py [options]
 | 
			
		||||
 | 
			
		||||
Options:
 | 
			
		||||
  -h, --help        show this help
 | 
			
		||||
  --rp=...          pull-up resistor
 | 
			
		||||
  --t1=ttt:rrr      low temperature temperature:resistance point (around 25 degC)
 | 
			
		||||
  --t2=ttt:rrr      middle temperature temperature:resistance point (around 150 degC)
 | 
			
		||||
  --t3=ttt:rrr      high temperature temperature:resistance point (around 250 degC)
 | 
			
		||||
  --num-temps=...   the number of temperature points to calculate (default: 36)
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
from __future__ import division
 | 
			
		||||
 | 
			
		||||
from math import *
 | 
			
		||||
import sys,getopt
 | 
			
		||||
 | 
			
		||||
"Constants"
 | 
			
		||||
ZERO   = 273.15                             # zero point of Kelvin scale
 | 
			
		||||
VADC   = 5                                  # ADC voltage
 | 
			
		||||
VCC    = 5                                  # supply voltage
 | 
			
		||||
ARES   = pow(2,10)                          # 10 Bit ADC resolution
 | 
			
		||||
VSTEP  = VADC / ARES                        # ADC voltage resolution
 | 
			
		||||
TMIN   = 0                                  # lowest temperature in table
 | 
			
		||||
TMAX   = 350                                # highest temperature in table
 | 
			
		||||
 | 
			
		||||
class Thermistor:
 | 
			
		||||
    "Class to do the thermistor maths"
 | 
			
		||||
    def __init__(self, rp, t1, r1, t2, r2, t3, r3):
 | 
			
		||||
        l1 = log(r1)
 | 
			
		||||
        l2 = log(r2)
 | 
			
		||||
        l3 = log(r3)
 | 
			
		||||
        y1 = 1.0 / (t1 + ZERO)              # adjust scale
 | 
			
		||||
        y2 = 1.0 / (t2 + ZERO)
 | 
			
		||||
        y3 = 1.0 / (t3 + ZERO)
 | 
			
		||||
        x = (y2 - y1) / (l2 - l1)
 | 
			
		||||
        y = (y3 - y1) / (l3 - l1)
 | 
			
		||||
        c = (y - x) / ((l3 - l2) * (l1 + l2 + l3))
 | 
			
		||||
        b = x - c * (l1**2 + l2**2 + l1*l2)
 | 
			
		||||
        a = y1 - (b + l1**2 *c)*l1
 | 
			
		||||
 | 
			
		||||
        if c < 0:
 | 
			
		||||
            print("//////////////////////////////////////////////////////////////////////////////////////")
 | 
			
		||||
            print("// WARNING: negative coefficient 'c'! Something may be wrong with the measurements! //")
 | 
			
		||||
            print("//////////////////////////////////////////////////////////////////////////////////////")
 | 
			
		||||
            c = -c
 | 
			
		||||
        self.c1 = a                         # Steinhart-Hart coefficients
 | 
			
		||||
        self.c2 = b
 | 
			
		||||
        self.c3 = c
 | 
			
		||||
        self.rp = rp                        # pull-up resistance
 | 
			
		||||
 | 
			
		||||
    def resol(self, adc):
 | 
			
		||||
        "Convert ADC reading into a resolution"
 | 
			
		||||
        res = self.temp(adc)-self.temp(adc+1)
 | 
			
		||||
        return res
 | 
			
		||||
 | 
			
		||||
    def voltage(self, adc):
 | 
			
		||||
        "Convert ADC reading into a Voltage"
 | 
			
		||||
        return adc * VSTEP                     # convert the 10 bit ADC value to a voltage
 | 
			
		||||
 | 
			
		||||
    def resist(self, adc):
 | 
			
		||||
        "Convert ADC reading into a resistance in Ohms"
 | 
			
		||||
        r = self.rp * self.voltage(adc) / (VCC - self.voltage(adc)) # resistance of thermistor
 | 
			
		||||
        return r
 | 
			
		||||
 | 
			
		||||
    def temp(self, adc):
 | 
			
		||||
        "Convert ADC reading into a temperature in Celcius"
 | 
			
		||||
        l = log(self.resist(adc))
 | 
			
		||||
        Tinv = self.c1 + self.c2*l + self.c3* l**3 # inverse temperature
 | 
			
		||||
        return (1/Tinv) - ZERO              # temperature
 | 
			
		||||
 | 
			
		||||
    def adc(self, temp):
 | 
			
		||||
        "Convert temperature into a ADC reading"
 | 
			
		||||
        x = (self.c1 - (1.0 / (temp+ZERO))) / (2*self.c3)
 | 
			
		||||
        y = sqrt((self.c2 / (3*self.c3))**3 + x**2)
 | 
			
		||||
        r = exp((y-x)**(1.0/3) - (y+x)**(1.0/3))
 | 
			
		||||
        return (r / (self.rp + r)) * ARES
 | 
			
		||||
 | 
			
		||||
def main(argv):
 | 
			
		||||
    "Default values"
 | 
			
		||||
    t1 = 25                                 # low temperature in Kelvin (25 degC)
 | 
			
		||||
    r1 = 100000                             # resistance at low temperature (10 kOhm)
 | 
			
		||||
    t2 = 150                                # middle temperature in Kelvin (150 degC)
 | 
			
		||||
    r2 = 1641.9                             # resistance at middle temperature (1.6 KOhm)
 | 
			
		||||
    t3 = 250                                # high temperature in Kelvin (250 degC)
 | 
			
		||||
    r3 = 226.15                             # resistance at high temperature (226.15 Ohm)
 | 
			
		||||
    rp = 4700;                              # pull-up resistor (4.7 kOhm)
 | 
			
		||||
    num_temps = 36;                         # number of entries for look-up table
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        opts, args = getopt.getopt(argv, "h", ["help", "rp=", "t1=", "t2=", "t3=", "num-temps="])
 | 
			
		||||
    except getopt.GetoptError as err:
 | 
			
		||||
        print(str(err))
 | 
			
		||||
        usage()
 | 
			
		||||
        sys.exit(2)
 | 
			
		||||
 | 
			
		||||
    for opt, arg in opts:
 | 
			
		||||
        if opt in ("-h", "--help"):
 | 
			
		||||
            usage()
 | 
			
		||||
            sys.exit()
 | 
			
		||||
        elif opt == "--rp":
 | 
			
		||||
            rp = int(arg)
 | 
			
		||||
        elif opt == "--t1":
 | 
			
		||||
            arg =  arg.split(':')
 | 
			
		||||
            t1 = float(arg[0])
 | 
			
		||||
            r1 = float(arg[1])
 | 
			
		||||
        elif opt == "--t2":
 | 
			
		||||
            arg =  arg.split(':')
 | 
			
		||||
            t2 = float(arg[0])
 | 
			
		||||
            r2 = float(arg[1])
 | 
			
		||||
        elif opt == "--t3":
 | 
			
		||||
            arg =  arg.split(':')
 | 
			
		||||
            t3 = float(arg[0])
 | 
			
		||||
            r3 = float(arg[1])
 | 
			
		||||
        elif opt == "--num-temps":
 | 
			
		||||
            num_temps = int(arg)
 | 
			
		||||
 | 
			
		||||
    t = Thermistor(rp, t1, r1, t2, r2, t3, r3)
 | 
			
		||||
    increment = int((ARES-1)/(num_temps-1));
 | 
			
		||||
    step = (TMIN-TMAX) / (num_temps-1)
 | 
			
		||||
    low_bound = t.temp(ARES-1);
 | 
			
		||||
    up_bound = t.temp(1);
 | 
			
		||||
    min_temp = int(TMIN if TMIN > low_bound else low_bound)
 | 
			
		||||
    max_temp = int(TMAX if TMAX < up_bound else up_bound)
 | 
			
		||||
    temps = list(range(max_temp, TMIN+step, step));
 | 
			
		||||
 | 
			
		||||
    print("// Thermistor lookup table for Marlin")
 | 
			
		||||
    print("// ./createTemperatureLookupMarlin.py --rp=%s --t1=%s:%s --t2=%s:%s --t3=%s:%s --num-temps=%s" % (rp, t1, r1, t2, r2, t3, r3, num_temps))
 | 
			
		||||
    print("// Steinhart-Hart Coefficients: a=%.15g, b=%.15g, c=%.15g " % (t.c1, t.c2, t.c3))
 | 
			
		||||
    print("// Theoretical limits of thermistor: %.2f to %.2f degC" % (low_bound, up_bound))
 | 
			
		||||
    print()
 | 
			
		||||
    print("const short temptable[][2] PROGMEM = {")
 | 
			
		||||
 | 
			
		||||
    for temp in temps:
 | 
			
		||||
        adc = t.adc(temp)
 | 
			
		||||
        print("    { OV(%7.2f), %4s }%s // v=%.3f\tr=%.3f\tres=%.3f degC/count" % (adc , temp, \
 | 
			
		||||
                        ',' if temp != temps[-1] else ' ', \
 | 
			
		||||
                        t.voltage(adc), \
 | 
			
		||||
                        t.resist( adc), \
 | 
			
		||||
                        t.resol(  adc) \
 | 
			
		||||
                    ))
 | 
			
		||||
    print("};")
 | 
			
		||||
 | 
			
		||||
def usage():
 | 
			
		||||
    print(__doc__)
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    main(sys.argv[1:])
 | 
			
		||||
@@ -0,0 +1,49 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
#
 | 
			
		||||
# findMissingTranslations.sh
 | 
			
		||||
#
 | 
			
		||||
# Locate all language strings needing an update based on English
 | 
			
		||||
#
 | 
			
		||||
# Usage: findMissingTranslations.sh [language codes]
 | 
			
		||||
#
 | 
			
		||||
# If no language codes are specified then all languages will be checked
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
LANGHOME="Marlin/src/lcd/language"
 | 
			
		||||
 | 
			
		||||
[ -d $LANGHOME ] && cd $LANGHOME
 | 
			
		||||
 | 
			
		||||
FILES=$(ls language_*.h | grep -v -E "(_en|_test)\.h" | sed -E 's/language_([^\.]+)\.h/\1/')
 | 
			
		||||
declare -A STRING_MAP
 | 
			
		||||
 | 
			
		||||
# Get files matching the given arguments
 | 
			
		||||
TEST_LANGS=$FILES
 | 
			
		||||
if [[ -n $@ ]]; then
 | 
			
		||||
  TEST_LANGS=""
 | 
			
		||||
  for K in "$@"; do
 | 
			
		||||
    for F in $FILES; do
 | 
			
		||||
      [[ "$F" != "${F%$K*}" ]] && TEST_LANGS="$TEST_LANGS $F"
 | 
			
		||||
    done
 | 
			
		||||
  done
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo -n "Building list of missing strings..."
 | 
			
		||||
 | 
			
		||||
for i in $(awk '/Language_Str/{print $3}' language_en.h); do
 | 
			
		||||
  [[ $i == "MSG_CUBED" ]] && continue
 | 
			
		||||
  LANG_LIST=""
 | 
			
		||||
  for j in $TEST_LANGS; do
 | 
			
		||||
    [[ $(grep -c " ${i} " language_${j}.h) -eq 0 ]] && LANG_LIST="$LANG_LIST $j"
 | 
			
		||||
  done
 | 
			
		||||
  [[ -z $LANG_LIST ]] && continue
 | 
			
		||||
  STRING_MAP[$i]=$LANG_LIST
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
echo
 | 
			
		||||
 | 
			
		||||
for K in $( printf "%s\n" "${!STRING_MAP[@]}" | sort ); do
 | 
			
		||||
  case "$#" in
 | 
			
		||||
    1 ) echo $K ;;
 | 
			
		||||
    * ) printf "%-35s :%s\n" "$K" "${STRING_MAP[$K]}" ;;
 | 
			
		||||
  esac
 | 
			
		||||
done
 | 
			
		||||
							
								
								
									
										188
									
								
								Marlin Firmware/buildroot/share/scripts/g29_auto.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								Marlin Firmware/buildroot/share/scripts/g29_auto.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,188 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
 | 
			
		||||
# This file is for preprocessing gcode and the new G29 Autobedleveling from Marlin
 | 
			
		||||
# It will analyse the first 2 Layer and return the maximum size for this part
 | 
			
		||||
# After this it will replace with g29_keyword = ';MarlinG29Script' with the new G29 LRFB
 | 
			
		||||
# the new file will be created in the same folder.
 | 
			
		||||
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
 | 
			
		||||
# your gcode-file/folder
 | 
			
		||||
folder = './'
 | 
			
		||||
my_file = 'test.gcode'
 | 
			
		||||
 | 
			
		||||
# this is the minimum of G1 instructions which should be between 2 different heights
 | 
			
		||||
min_g1 = 3
 | 
			
		||||
 | 
			
		||||
# maximum number of lines to parse, I don't want to parse the complete file
 | 
			
		||||
# only the first plane is we are interested in
 | 
			
		||||
max_g1 = 100000000
 | 
			
		||||
 | 
			
		||||
# g29 keyword
 | 
			
		||||
g29_keyword = 'g29'
 | 
			
		||||
g29_keyword = g29_keyword.upper()
 | 
			
		||||
 | 
			
		||||
# output filename
 | 
			
		||||
output_file = folder + 'g29_' + my_file
 | 
			
		||||
# input filename
 | 
			
		||||
input_file = folder + my_file
 | 
			
		||||
 | 
			
		||||
# minimum scan size
 | 
			
		||||
min_size = 40
 | 
			
		||||
probing_points = 3  # points x points
 | 
			
		||||
 | 
			
		||||
# other stuff
 | 
			
		||||
min_x = 500
 | 
			
		||||
min_y = min_x
 | 
			
		||||
max_x = -500
 | 
			
		||||
max_y = max_x
 | 
			
		||||
last_z = 0.001
 | 
			
		||||
 | 
			
		||||
layer = 0
 | 
			
		||||
lines_of_g1 = 0
 | 
			
		||||
 | 
			
		||||
gcode = []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# return only g1-lines
 | 
			
		||||
def has_g1(line):
 | 
			
		||||
    return line[:2].upper() == "G1"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# find position in g1 (x,y,z)
 | 
			
		||||
def find_axis(line, axis):
 | 
			
		||||
    found = False
 | 
			
		||||
    number = ""
 | 
			
		||||
    for char in line:
 | 
			
		||||
        if found:
 | 
			
		||||
            if char == ".":
 | 
			
		||||
                number += char
 | 
			
		||||
            elif char == "-":
 | 
			
		||||
                number += char
 | 
			
		||||
            else:
 | 
			
		||||
                try:
 | 
			
		||||
                    int(char)
 | 
			
		||||
                    number += char
 | 
			
		||||
                except ValueError:
 | 
			
		||||
                    break
 | 
			
		||||
        else:
 | 
			
		||||
            found = char.upper() == axis.upper()
 | 
			
		||||
    try:
 | 
			
		||||
        return float(number)
 | 
			
		||||
    except ValueError:
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# save the min or max-values for each axis
 | 
			
		||||
def set_mima(line):
 | 
			
		||||
    global min_x, max_x, min_y, max_y, last_z
 | 
			
		||||
 | 
			
		||||
    current_x = find_axis(line, 'x')
 | 
			
		||||
    current_y = find_axis(line, 'y')
 | 
			
		||||
 | 
			
		||||
    if current_x is not None:
 | 
			
		||||
        min_x = min(current_x, min_x)
 | 
			
		||||
        max_x = max(current_x, max_x)
 | 
			
		||||
    if current_y is not None:
 | 
			
		||||
        min_y = min(current_y, min_y)
 | 
			
		||||
        max_y = max(current_y, max_y)
 | 
			
		||||
 | 
			
		||||
    return min_x, max_x, min_y, max_y
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# find z in the code and return it
 | 
			
		||||
def find_z(gcode, start_at_line=0):
 | 
			
		||||
    for i in range(start_at_line, len(gcode)):
 | 
			
		||||
        my_z = find_axis(gcode[i], 'Z')
 | 
			
		||||
        if my_z is not None:
 | 
			
		||||
            return my_z, i
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def z_parse(gcode, start_at_line=0, end_at_line=0):
 | 
			
		||||
    i = start_at_line
 | 
			
		||||
    all_z = []
 | 
			
		||||
    line_between_z = []
 | 
			
		||||
    z_at_line = []
 | 
			
		||||
    # last_z = 0
 | 
			
		||||
    last_i = -1
 | 
			
		||||
 | 
			
		||||
    while len(gcode) > i:
 | 
			
		||||
        try:
 | 
			
		||||
            z, i = find_z(gcode, i + 1)
 | 
			
		||||
        except TypeError:
 | 
			
		||||
            break
 | 
			
		||||
 | 
			
		||||
        all_z.append(z)
 | 
			
		||||
        z_at_line.append(i)
 | 
			
		||||
        temp_line = i - last_i -1
 | 
			
		||||
        line_between_z.append(i - last_i - 1)
 | 
			
		||||
        # last_z = z
 | 
			
		||||
        last_i = i
 | 
			
		||||
        if 0 < end_at_line <= i or temp_line >= min_g1:
 | 
			
		||||
            # print('break at line {} at heigth {}'.format(i, z))
 | 
			
		||||
            break
 | 
			
		||||
 | 
			
		||||
    line_between_z = line_between_z[1:]
 | 
			
		||||
    return all_z, line_between_z, z_at_line
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# get the lines which should be the first layer
 | 
			
		||||
def get_lines(gcode, minimum):
 | 
			
		||||
    i = 0
 | 
			
		||||
    all_z, line_between_z, z_at_line = z_parse(gcode, end_at_line=max_g1)
 | 
			
		||||
    for count in line_between_z:
 | 
			
		||||
        i += 1
 | 
			
		||||
        if count > minimum:
 | 
			
		||||
            # print('layer: {}:{}'.format(z_at_line[i-1], z_at_line[i]))
 | 
			
		||||
            return z_at_line[i - 1], z_at_line[i]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
with open(input_file, 'r') as file:
 | 
			
		||||
    lines = 0
 | 
			
		||||
    for line in file:
 | 
			
		||||
        lines += 1
 | 
			
		||||
        if lines > 1000:
 | 
			
		||||
            break
 | 
			
		||||
        if has_g1(line):
 | 
			
		||||
            gcode.append(line)
 | 
			
		||||
file.close()
 | 
			
		||||
 | 
			
		||||
start, end = get_lines(gcode, min_g1)
 | 
			
		||||
for i in range(start, end):
 | 
			
		||||
    set_mima(gcode[i])
 | 
			
		||||
 | 
			
		||||
print('x_min:{} x_max:{}\ny_min:{} y_max:{}'.format(min_x, max_x, min_y, max_y))
 | 
			
		||||
 | 
			
		||||
# resize min/max - values for minimum scan
 | 
			
		||||
if max_x - min_x < min_size:
 | 
			
		||||
    offset_x = int((min_size - (max_x - min_x)) / 2 + 0.5)  # int round up
 | 
			
		||||
    # print('min_x! with {}'.format(int(max_x - min_x)))
 | 
			
		||||
    min_x = int(min_x) - offset_x
 | 
			
		||||
    max_x = int(max_x) + offset_x
 | 
			
		||||
if max_y - min_y < min_size:
 | 
			
		||||
    offset_y = int((min_size - (max_y - min_y)) / 2 + 0.5)  # int round up
 | 
			
		||||
    # print('min_y! with {}'.format(int(max_y - min_y)))
 | 
			
		||||
    min_y = int(min_y) - offset_y
 | 
			
		||||
    max_y = int(max_y) + offset_y
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
new_command = 'G29 L{0} R{1} F{2} B{3} P{4}\n'.format(min_x,
 | 
			
		||||
                                                      max_x,
 | 
			
		||||
                                                      min_y,
 | 
			
		||||
                                                      max_y,
 | 
			
		||||
                                                      probing_points)
 | 
			
		||||
 | 
			
		||||
out_file = open(output_file, 'w')
 | 
			
		||||
in_file = open(input_file, 'r')
 | 
			
		||||
 | 
			
		||||
for line in in_file:
 | 
			
		||||
    if line[:len(g29_keyword)].upper() == g29_keyword:
 | 
			
		||||
        out_file.write(new_command)
 | 
			
		||||
        print('write G29')
 | 
			
		||||
    else:
 | 
			
		||||
        out_file.write(line)
 | 
			
		||||
 | 
			
		||||
file.close()
 | 
			
		||||
out_file.close()
 | 
			
		||||
 | 
			
		||||
print('auto G29 finished')
 | 
			
		||||
							
								
								
									
										64
									
								
								Marlin Firmware/buildroot/share/scripts/gen-tft-image.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								Marlin Firmware/buildroot/share/scripts/gen-tft-image.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
#
 | 
			
		||||
# Marlin 3D Printer Firmware
 | 
			
		||||
# Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
 | 
			
		||||
#
 | 
			
		||||
# Based on Sprinter and grbl.
 | 
			
		||||
# Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
 | 
			
		||||
#
 | 
			
		||||
# This program is free software: you can redistribute it and/or modify
 | 
			
		||||
# it under the terms of the GNU General Public License as published by
 | 
			
		||||
# the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
# (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# Generate Marlin TFT Images from bitmaps/PNG/JPG
 | 
			
		||||
 | 
			
		||||
import sys,re,struct
 | 
			
		||||
from PIL import Image,ImageDraw
 | 
			
		||||
 | 
			
		||||
def image2bin(image, output_file):
 | 
			
		||||
	if output_file.endswith(('.c', '.cpp')):
 | 
			
		||||
		f = open(output_file, 'wt')
 | 
			
		||||
		is_cpp = True
 | 
			
		||||
		f.write("const uint16_t image[%d] = {\n" % (image.size[1] * image.size[0]))
 | 
			
		||||
	else:
 | 
			
		||||
		f = open(output_file, 'wb')
 | 
			
		||||
		is_cpp = False
 | 
			
		||||
	pixs = image.load()
 | 
			
		||||
	for y in range(image.size[1]):
 | 
			
		||||
		for x in range(image.size[0]):
 | 
			
		||||
			R = pixs[x, y][0] >> 3
 | 
			
		||||
			G = pixs[x, y][1] >> 2
 | 
			
		||||
			B = pixs[x, y][2] >> 3
 | 
			
		||||
			rgb = (R << 11) | (G << 5) | B
 | 
			
		||||
			if is_cpp:
 | 
			
		||||
				strHex = '0x{0:04X}, '.format(rgb)
 | 
			
		||||
				f.write(strHex)
 | 
			
		||||
			else:
 | 
			
		||||
				f.write(struct.pack("B", (rgb & 0xFF)))
 | 
			
		||||
				f.write(struct.pack("B", (rgb >> 8) & 0xFF))
 | 
			
		||||
		if is_cpp:
 | 
			
		||||
			f.write("\n")
 | 
			
		||||
	if is_cpp:
 | 
			
		||||
		f.write("};\n")
 | 
			
		||||
	f.close()
 | 
			
		||||
 | 
			
		||||
if len(sys.argv) <= 2:
 | 
			
		||||
	print("Utility to export a image in Marlin TFT friendly format.")
 | 
			
		||||
	print("It will dump a raw bin RGB565 image or create a CPP file with an array of 16 bit image pixels.")
 | 
			
		||||
	print("Usage: gen-tft-image.py INPUT_IMAGE.(png|bmp|jpg) OUTPUT_FILE.(cpp|bin)")
 | 
			
		||||
	print("Author: rhapsodyv")
 | 
			
		||||
	exit(1)
 | 
			
		||||
 | 
			
		||||
output_img = sys.argv[2]
 | 
			
		||||
img = Image.open(sys.argv[1])
 | 
			
		||||
image2bin(img, output_img)
 | 
			
		||||
							
								
								
									
										170
									
								
								Marlin Firmware/buildroot/share/scripts/pinsformat.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								Marlin Firmware/buildroot/share/scripts/pinsformat.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,170 @@
 | 
			
		||||
#!/usr/bin/env node
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Formatter script for pins_MYPINS.h files
 | 
			
		||||
//
 | 
			
		||||
// Usage: mffmt [infile] [outfile]
 | 
			
		||||
//
 | 
			
		||||
// With no parameters convert STDIN to STDOUT
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
const fs = require("fs");
 | 
			
		||||
 | 
			
		||||
// String lpad / rpad
 | 
			
		||||
String.prototype.lpad = function(len, chr) {
 | 
			
		||||
  if (!len) return this;
 | 
			
		||||
  if (chr === undefined) chr = ' ';
 | 
			
		||||
  var s = this+'', need = len - s.length;
 | 
			
		||||
  if (need > 0) s = new Array(need+1).join(chr) + s;
 | 
			
		||||
  return s;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
String.prototype.rpad = function(len, chr) {
 | 
			
		||||
  if (!len) return this;
 | 
			
		||||
  if (chr === undefined) chr = ' ';
 | 
			
		||||
  var s = this+'', need = len - s.length;
 | 
			
		||||
  if (need > 0) s += new Array(need+1).join(chr);
 | 
			
		||||
  return s;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const mpatt = [ '-?\\d+', 'P[A-I]\\d+', 'P\\d_\\d+' ],
 | 
			
		||||
      definePatt = new RegExp(`^\\s*(//)?#define\\s+[A-Z_][A-Z0-9_]+\\s+(${mpatt[0]}|${mpatt[1]}|${mpatt[2]})\\s*(//.*)?$`, 'gm'),
 | 
			
		||||
      ppad = [ 3, 4, 5 ],
 | 
			
		||||
      col_comment = 50,
 | 
			
		||||
      col_value_rj = col_comment - 3;
 | 
			
		||||
 | 
			
		||||
var mexpr = [];
 | 
			
		||||
for (let m of mpatt) mexpr.push(new RegExp('^' + m + '$'));
 | 
			
		||||
 | 
			
		||||
const argv = process.argv.slice(2), argc = argv.length;
 | 
			
		||||
 | 
			
		||||
var src_file = 0, src_name = 'STDIN', dst_file, do_log = false;
 | 
			
		||||
if (argc > 0) {
 | 
			
		||||
  let ind = 0;
 | 
			
		||||
  if (argv[0] == '-v') { do_log = true; ind++; }
 | 
			
		||||
  dst_file = src_file = src_name = argv[ind++];
 | 
			
		||||
  if (ind < argc) dst_file = argv[ind];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read from file or STDIN until it terminates
 | 
			
		||||
const filtered = process_text(fs.readFileSync(src_file).toString());
 | 
			
		||||
if (dst_file)
 | 
			
		||||
  fs.writeFileSync(dst_file, filtered);
 | 
			
		||||
else
 | 
			
		||||
  console.log(filtered);
 | 
			
		||||
 | 
			
		||||
// Find the pin pattern so non-pin defines can be skipped
 | 
			
		||||
function get_pin_pattern(txt) {
 | 
			
		||||
  var r, m = 0, match_count = [ 0, 0, 0 ];
 | 
			
		||||
  definePatt.lastIndex = 0;
 | 
			
		||||
  while ((r = definePatt.exec(txt)) !== null) {
 | 
			
		||||
    let ind = -1;
 | 
			
		||||
    if (mexpr.some((p) => {
 | 
			
		||||
      ind++;
 | 
			
		||||
      const didmatch = r[2].match(p);
 | 
			
		||||
      return r[2].match(p);
 | 
			
		||||
    }) ) {
 | 
			
		||||
      const m = ++match_count[ind];
 | 
			
		||||
      if (m >= 10) {
 | 
			
		||||
        return { match: mpatt[ind], pad:ppad[ind] };
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function process_text(txt) {
 | 
			
		||||
  if (!txt.length) return '(no text)';
 | 
			
		||||
  const patt = get_pin_pattern(txt);
 | 
			
		||||
  if (!patt) return txt;
 | 
			
		||||
  const pindefPatt = new RegExp(`^(\\s*(//)?#define)\\s+([A-Z_][A-Z0-9_]+)\\s+(${patt.match})\\s*(//.*)?$`),
 | 
			
		||||
         noPinPatt = new RegExp(`^(\\s*(//)?#define)\\s+([A-Z_][A-Z0-9_]+)\\s+(-1)\\s*(//.*)?$`),
 | 
			
		||||
          skipPatt = new RegExp('^(\\s*(//)?#define)\\s+(AT90USB|USBCON|BOARD_.+|.+_MACHINE_NAME|.+_SERIAL)\\s+(.+)\\s*(//.*)?$'),
 | 
			
		||||
         aliasPatt = new RegExp('^(\\s*(//)?#define)\\s+([A-Z_][A-Z0-9_]+)\\s+([A-Z_][A-Z0-9_()]+)\\s*(//.*)?$'),
 | 
			
		||||
        switchPatt = new RegExp('^(\\s*(//)?#define)\\s+([A-Z_][A-Z0-9_]+)\\s*(//.*)?$'),
 | 
			
		||||
         undefPatt = new RegExp('^(\\s*(//)?#undef)\\s+([A-Z_][A-Z0-9_]+)\\s*(//.*)?$'),
 | 
			
		||||
           defPatt = new RegExp('^(\\s*(//)?#define)\\s+([A-Z_][A-Z0-9_]+)\\s+([-_\\w]+)\\s*(//.*)?$'),
 | 
			
		||||
          condPatt = new RegExp('^(\\s*(//)?#(if|ifn?def|else|elif)(\\s+\\S+)*)\\s+(//.*)$'),
 | 
			
		||||
          commPatt = new RegExp('^\\s{20,}(//.*)?$');
 | 
			
		||||
  const col_value_lj = col_comment - patt.pad - 2;
 | 
			
		||||
  var r, out = '', check_comment_next = false;
 | 
			
		||||
  txt.split('\n').forEach((line) => {
 | 
			
		||||
    if (check_comment_next)
 | 
			
		||||
      check_comment_next = ((r = commPatt.exec(line)) !== null);
 | 
			
		||||
 | 
			
		||||
    if (check_comment_next)
 | 
			
		||||
      // Comments in column 45
 | 
			
		||||
      line = ''.rpad(col_comment) + r[1];
 | 
			
		||||
 | 
			
		||||
    else if ((r = pindefPatt.exec(line)) !== null) {
 | 
			
		||||
      //
 | 
			
		||||
      // #define MY_PIN [pin]
 | 
			
		||||
      //
 | 
			
		||||
      if (do_log) console.log("pin:", line);
 | 
			
		||||
      const pinnum = r[4].charAt(0) == 'P' ? r[4] : r[4].lpad(patt.pad);
 | 
			
		||||
      line = r[1] + ' ' + r[3];
 | 
			
		||||
      line = line.rpad(col_value_lj) + pinnum;
 | 
			
		||||
      if (r[5]) line = line.rpad(col_comment) + r[5];
 | 
			
		||||
    }
 | 
			
		||||
    else if ((r = noPinPatt.exec(line)) !== null) {
 | 
			
		||||
      //
 | 
			
		||||
      // #define MY_PIN -1
 | 
			
		||||
      //
 | 
			
		||||
      if (do_log) console.log("pin -1:", line);
 | 
			
		||||
      line = r[1] + ' ' + r[3];
 | 
			
		||||
      line = line.rpad(col_value_lj) + '-1';
 | 
			
		||||
      if (r[5]) line = line.rpad(col_comment) + r[5];
 | 
			
		||||
    }
 | 
			
		||||
    else if ((r = skipPatt.exec(line)) !== null) {
 | 
			
		||||
      //
 | 
			
		||||
      // #define SKIP_ME
 | 
			
		||||
      //
 | 
			
		||||
      if (do_log) console.log("skip:", line);
 | 
			
		||||
    }
 | 
			
		||||
    else if ((r = aliasPatt.exec(line)) !== null) {
 | 
			
		||||
      //
 | 
			
		||||
      // #define ALIAS OTHER
 | 
			
		||||
      //
 | 
			
		||||
      if (do_log) console.log("alias:", line);
 | 
			
		||||
      line = r[1] + ' ' + r[3];
 | 
			
		||||
      line += r[4].lpad(col_value_rj + 1 - line.length);
 | 
			
		||||
      if (r[5]) line = line.rpad(col_comment) + r[5];
 | 
			
		||||
    }
 | 
			
		||||
    else if ((r = switchPatt.exec(line)) !== null) {
 | 
			
		||||
      //
 | 
			
		||||
      // #define SWITCH
 | 
			
		||||
      //
 | 
			
		||||
      if (do_log) console.log("switch:", line);
 | 
			
		||||
      line = r[1] + ' ' + r[3];
 | 
			
		||||
      if (r[4]) line = line.rpad(col_comment) + r[4];
 | 
			
		||||
      check_comment_next = true;
 | 
			
		||||
    }
 | 
			
		||||
    else if ((r = defPatt.exec(line)) !== null) {
 | 
			
		||||
      //
 | 
			
		||||
      // #define ...
 | 
			
		||||
      //
 | 
			
		||||
      if (do_log) console.log("def:", line);
 | 
			
		||||
      line = r[1] + ' ' + r[3] + ' ';
 | 
			
		||||
      line += r[4].lpad(col_value_rj + 1 - line.length);
 | 
			
		||||
      if (r[5]) line = line.rpad(col_comment - 1) + ' ' + r[5];
 | 
			
		||||
    }
 | 
			
		||||
    else if ((r = undefPatt.exec(line)) !== null) {
 | 
			
		||||
      //
 | 
			
		||||
      // #undef ...
 | 
			
		||||
      //
 | 
			
		||||
      if (do_log) console.log("undef:", line);
 | 
			
		||||
      line = r[1] + ' ' + r[3];
 | 
			
		||||
      if (r[4]) line = line.rpad(col_comment) + r[4];
 | 
			
		||||
    }
 | 
			
		||||
    else if ((r = condPatt.exec(line)) !== null) {
 | 
			
		||||
      //
 | 
			
		||||
      // #if ...
 | 
			
		||||
      //
 | 
			
		||||
      if (do_log) console.log("cond:", line);
 | 
			
		||||
      line = r[1].rpad(col_comment) + r[5];
 | 
			
		||||
      check_comment_next = true;
 | 
			
		||||
    }
 | 
			
		||||
    out += line + '\n';
 | 
			
		||||
  });
 | 
			
		||||
  return out.replace(/\n\n+/g, '\n\n').replace(/\n\n$/g, '\n');
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user