99#include  <string.h>  // memset 
1010#include  "compiler.h"  // __visible 
1111#include  "itersolve.h"  // struct stepper_kinematics 
12+ #include  "list.h"  // list_node 
1213#include  "pyhelper.h"  // errorf 
1314#include  "trapq.h"  // move_get_distance 
1415
16+ struct  pa_params  {
17+     double  pressure_advance , active_print_time ;
18+     struct  list_node  node ;
19+ };
20+ 
1521// Without pressure advance, the extruder stepper position is: 
1622//     extruder_position(t) = nominal_position(t) 
1723// When pressure advance is enabled, additional filament is pushed 
@@ -52,17 +58,25 @@ extruder_integrate_time(double base, double start_v, double half_accel
5258
5359// Calculate the definitive integral of extruder for a given move 
5460static  double 
55- pa_move_integrate (struct  move  * m , double   pressure_advance 
61+ pa_move_integrate (struct  move  * m , struct   list_head   * pa_list 
5662                  , double  base , double  start , double  end , double  time_offset )
5763{
5864    if  (start  <  0. )
5965        start  =  0. ;
6066    if  (end  >  m -> move_t )
6167        end  =  m -> move_t ;
62-     // Calculate base position and velocity with pressure advance  
68+     // Determine pressure_advance value  
6369    int  can_pressure_advance  =  m -> axes_r .y  !=  0. ;
64-     if  (!can_pressure_advance )
65-         pressure_advance  =  0. ;
70+     double  pressure_advance  =  0. ;
71+     if  (can_pressure_advance ) {
72+         struct  pa_params  * pa  =  list_last_entry (pa_list , struct  pa_params , node );
73+         while  (unlikely (pa -> active_print_time  >  m -> print_time ) && 
74+                 !list_is_first (& pa -> node , pa_list )) {
75+             pa  =  list_prev_entry (pa , node );
76+         }
77+         pressure_advance  =  pa -> pressure_advance ;
78+     }
79+     // Calculate base position and velocity with pressure advance 
6680    base  +=  pressure_advance  *  m -> start_v ;
6781    double  start_v  =  m -> start_v  +  pressure_advance  *  2.  *  m -> half_accel ;
6882    // Calculate definitive integral 
@@ -75,35 +89,36 @@ pa_move_integrate(struct move *m, double pressure_advance
7589// Calculate the definitive integral of the extruder over a range of moves 
7690static  double 
7791pa_range_integrate (struct  move  * m , double  move_time 
78-                    , double   pressure_advance , double  hst )
92+                    , struct   list_head   * pa_list , double  hst )
7993{
8094    // Calculate integral for the current move 
8195    double  res  =  0. , start  =  move_time  -  hst , end  =  move_time  +  hst ;
8296    double  start_base  =  m -> start_pos .x ;
83-     res  +=  pa_move_integrate (m , pressure_advance , 0. , start , move_time , start );
84-     res  -=  pa_move_integrate (m , pressure_advance , 0. , move_time , end , end );
97+     res  +=  pa_move_integrate (m , pa_list , 0. , start , move_time , start );
98+     res  -=  pa_move_integrate (m , pa_list , 0. , move_time , end , end );
8599    // Integrate over previous moves 
86100    struct  move  * prev  =  m ;
87101    while  (unlikely (start  <  0. )) {
88102        prev  =  list_prev_entry (prev , node );
89103        start  +=  prev -> move_t ;
90104        double  base  =  prev -> start_pos .x  -  start_base ;
91-         res  +=  pa_move_integrate (prev , pressure_advance , base , start 
105+         res  +=  pa_move_integrate (prev , pa_list , base , start 
92106                                 , prev -> move_t , start );
93107    }
94108    // Integrate over future moves 
95109    while  (unlikely (end  >  m -> move_t )) {
96110        end  -=  m -> move_t ;
97111        m  =  list_next_entry (m , node );
98112        double  base  =  m -> start_pos .x  -  start_base ;
99-         res  -=  pa_move_integrate (m , pressure_advance , base , 0. , end , end );
113+         res  -=  pa_move_integrate (m , pa_list , base , 0. , end , end );
100114    }
101115    return  res ;
102116}
103117
104118struct  extruder_stepper  {
105119    struct  stepper_kinematics  sk ;
106-     double  pressure_advance , half_smooth_time , inv_half_smooth_time2 ;
120+     struct  list_head  pa_list ;
121+     double  half_smooth_time , inv_half_smooth_time2 ;
107122};
108123
109124static  double 
@@ -116,22 +131,45 @@ extruder_calc_position(struct stepper_kinematics *sk, struct move *m
116131        // Pressure advance not enabled 
117132        return  m -> start_pos .x  +  move_get_distance (m , move_time );
118133    // Apply pressure advance and average over smooth_time 
119-     double  area  =  pa_range_integrate (m , move_time , es -> pressure_advance , hst );
134+     double  area  =  pa_range_integrate (m , move_time , & es -> pa_list , hst );
120135    return  m -> start_pos .x  +  area  *  es -> inv_half_smooth_time2 ;
121136}
122137
123138void  __visible 
124- extruder_set_pressure_advance (struct  stepper_kinematics  * sk 
139+ extruder_set_pressure_advance (struct  stepper_kinematics  * sk ,  double   print_time 
125140                              , double  pressure_advance , double  smooth_time )
126141{
127142    struct  extruder_stepper  * es  =  container_of (sk , struct  extruder_stepper , sk );
128-     double  hst  =  smooth_time  *  .5 ;
143+     double  hst  =  smooth_time  *  .5 ,  old_hst   =   es -> half_smooth_time ;
129144    es -> half_smooth_time  =  hst ;
130145    es -> sk .gen_steps_pre_active  =  es -> sk .gen_steps_post_active  =  hst ;
146+ 
147+     // Cleanup old pressure advance parameters 
148+     double  cleanup_time  =  sk -> last_flush_time  -  (old_hst  >  hst  ? old_hst  : hst );
149+     struct  pa_params  * first_pa  =  list_first_entry (
150+             & es -> pa_list , struct  pa_params , node );
151+     while  (!list_is_last (& first_pa -> node , & es -> pa_list )) {
152+         struct  pa_params  * next_pa  =  list_next_entry (first_pa , node );
153+         if  (next_pa -> active_print_time  >= cleanup_time ) break ;
154+         list_del (& first_pa -> node );
155+         first_pa  =  next_pa ;
156+     }
157+ 
131158    if  (! hst )
132159        return ;
133160    es -> inv_half_smooth_time2  =  1.  / (hst  *  hst );
134-     es -> pressure_advance  =  pressure_advance ;
161+ 
162+     if  (list_last_entry (& es -> pa_list , struct  pa_params , node )-> pressure_advance 
163+             ==  pressure_advance ) {
164+         // Retain old pa_params 
165+         return ;
166+     }
167+     // Add new pressure advance parameters 
168+     struct  pa_params  * pa  =  malloc (sizeof (* pa ));
169+     memset (pa , 0 , sizeof (* pa ));
170+     pa -> pressure_advance  =  pressure_advance ;
171+     pa -> active_print_time  =  print_time ;
172+     list_add_tail (& pa -> node , & es -> pa_list );
135173}
136174
137175struct  stepper_kinematics  *  __visible 
@@ -141,5 +179,22 @@ extruder_stepper_alloc(void)
141179    memset (es , 0 , sizeof (* es ));
142180    es -> sk .calc_position_cb  =  extruder_calc_position ;
143181    es -> sk .active_flags  =  AF_X ;
182+     list_init (& es -> pa_list );
183+     struct  pa_params  * pa  =  malloc (sizeof (* pa ));
184+     memset (pa , 0 , sizeof (* pa ));
185+     list_add_tail (& pa -> node , & es -> pa_list );
144186    return  & es -> sk ;
145187}
188+ 
189+ void  __visible 
190+ extruder_stepper_free (struct  stepper_kinematics  * sk )
191+ {
192+     struct  extruder_stepper  * es  =  container_of (sk , struct  extruder_stepper , sk );
193+     while  (!list_empty (& es -> pa_list )) {
194+         struct  pa_params  * pa  =  list_first_entry (
195+                 & es -> pa_list , struct  pa_params , node );
196+         list_del (& pa -> node );
197+         free (pa );
198+     }
199+     free (sk );
200+ }
0 commit comments