Add a Linear Advance 1.0->1.5 compatibility layer

Allow existing gcode using LA10 to transparently take advantage of LA15
by using a simple linear conversion function based on experimental
results with the MK3 implementation of linear advance.

Autodetect LA10 values based on the first M900 instruction contained in
the print. In order to support printing mixed files without resetting
the printer we also reset the autodetection status when starting a new
SD print and/or when explicitly disabling LA.

Since we cannot reliably detect whether a new print is started when
printing via USB, also reset the detection status when homing in G28,
which is generally performed once at each print. Note that this doesn't
clear the previous K value, it only allows a subsequent M900 to provide
LA10 values when printed after a LA15 file.
This commit is contained in:
Yuri D'Elia 2019-12-21 22:48:30 +01:00
parent 8d60e4d6db
commit 7b29ce29b4
4 changed files with 106 additions and 3 deletions

View file

@ -287,6 +287,7 @@
#ifdef LIN_ADVANCE
#define LIN_ADVANCE_K 0 // Unit: mm compression per 1mm/s extruder speed
//#define LA_NOCOMPAT // Disable Linear Advance 1.0 compatibility
//#define LA_LIVE_K // Allow adjusting K in the Tune menu
//#define LA_DEBUG // If enabled, this will generate debug information output over USB.
//#define LA_DEBUG_LOGIC // @wavexx: setup logic channels for isr debugging

View file

@ -83,6 +83,9 @@
#include "Dcodes.h"
#include "AutoDeplete.h"
#ifndef LA_NOCOMPAT
#include "la10compat.h"
#endif
#ifdef SWSPI
#include "swspi.h"
@ -2068,12 +2071,23 @@ static float probe_pt(float x, float y, float z_before) {
*/
inline void gcode_M900() {
st_synchronize();
const float newK = code_seen('K') ? code_value_float() : -1;
#ifdef LA_NOCOMPAT
if (newK >= 0 && newK < 10)
extruder_advance_K = newK;
extruder_advance_K = newK;
else
SERIAL_ECHOLNPGM("K out of allowed range!");
SERIAL_ECHOLNPGM("K out of allowed range!");
#else
if (newK == 0) {
la10c_reset();
extruder_advance_K = 0;
}
else if(newK > 0)
extruder_advance_K = la10c_value(newK);
else
SERIAL_ECHOLNPGM("K out of allowed range!");
#endif
SERIAL_ECHO_START;
SERIAL_ECHOPGM("Advance K=");
@ -4136,6 +4150,9 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
// --------------------------------------------
case 28:
{
#ifndef LA_NOCOMPAT
la10c_reset();
#endif
long home_x_value = 0;
long home_y_value = 0;
long home_z_value = 0;
@ -5372,6 +5389,9 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
else
{
failstats_reset_print();
#ifndef LA_NOCOMPAT
la10c_reset();
#endif
card.startFileprint();
starttime=_millis();
}
@ -5465,6 +5485,9 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
if(code_seen('S'))
if(strchr_pointer<namestartpos) //only if "S" is occuring _before_ the filename
card.setIndex(code_value_long());
#ifndef LA_NOCOMPAT
la10c_reset();
#endif
card.startFileprint();
if(!call_procedure)
starttime=_millis(); //procedure calls count as normal print time.

40
Firmware/la10compat.cpp Normal file
View file

@ -0,0 +1,40 @@
#include "la10compat.h"
#include "Marlin.h"
static LA10C_MODE la10c_mode = LA10C_UNKNOWN;
void la10c_mode_change(LA10C_MODE mode)
{
if(mode == la10c_mode) return;
SERIAL_ECHOPGM("LA10C: Linear Advance mode: ");
switch(mode)
{
case LA10C_UNKNOWN: SERIAL_ECHOLNPGM("UNKNOWN"); break;
case LA10C_LA15: SERIAL_ECHOLNPGM("1.5"); break;
case LA10C_LA10: SERIAL_ECHOLNPGM("1.0"); break;
}
la10c_mode = mode;
}
// Approximate a LA10 value to a LA15 equivalent.
static float la10c_convert(float k)
{
float new_K = k * 0.004 - 0.06;
return (new_K < 0? 0: new_K);
}
float la10c_value(float k)
{
if(la10c_mode == LA10C_UNKNOWN)
la10c_mode_change(k < 10? LA10C_LA15: LA10C_LA10);
if(la10c_mode == LA10C_LA15)
return k;
else
return la10c_convert(k);
}

39
Firmware/la10compat.h Normal file
View file

@ -0,0 +1,39 @@
// la10compat: LA10->LA15 conversion
//
// When the current mode is UNKNOWN autodetection is active and any K<10
// will set the mode to LA15, LA10 is set otherwise. When LA10
// compatbility mode is active the K factor is converted to a LA15
// equivalent (that is, the return value is always a LA15 value).
//
// Once the interpretation mode has been set it is kept until the mode
// is explicitly reset. This is done to handle transparent fallback for
// old firmware revisions in combination with the following gcode
// sequence:
//
// M900 K0.01 ; set LA15 value (interpreted by any firmware)
// M900 K10 ; set LA10 value (ignored by LA15 firmware)
//
// A LA15 firmware without this module will only parse the first
// correctly, rejecting the second. A LA10 FW will parse both, but keep
// the last value. Since the LA15 value, if present, corresponds to the
// truth value, the compatibility stub needs to "lock" onto the first
// seen value for the current print.
//
// The mode needs to be carefully reset for each print in order for
// diffent versions of M900 to be interpreted independently.
#pragma once
enum __attribute__((packed)) LA10C_MODE
{
LA10C_UNKNOWN = 0,
LA10C_LA15 = 1,
LA10C_LA10 = 2
};
// Explicitly set/reset the interpretation mode for la10c_value()
void la10c_mode_change(LA10C_MODE mode);
static inline void la10c_reset() { la10c_mode_change(LA10C_UNKNOWN); }
// Return a LA15 K value according to the supplied value and mode
float la10c_value(float k);