2626#if PLASMA_ENABLE
2727
2828#include <math.h>
29+ #include <stdio.h>
2930#include <stdint.h>
3031#include <stdbool.h>
3132#include <string.h>
@@ -54,6 +55,31 @@ typedef enum {
5455 Plasma_ModeArcOK
5556} plasma_mode_t ;
5657
58+ typedef struct material
59+ {
60+ uint32_t id ; // nu
61+ char name [50 ]; // na
62+ bool thc_status ; // th
63+ union {
64+ float params [12 ];
65+ struct {
66+ float pierce_height ; // ph
67+ float pierce_delay ; // pd
68+ float cut_height ; // ch
69+ float feed_rate ; // fr
70+ float kerf_width ; // kw
71+ float cut_amps ; // ca
72+ float cut_voltage ; // cv
73+ float end_pause ; // pe
74+ float gas_pressure ; // gp
75+ float cut_mode ; // cm
76+ float jump_height ; // jh
77+ float jump_delay ; // jd
78+ };
79+ };
80+ struct material * next ;
81+ } material_t ;
82+
5783typedef union {
5884 uint8_t flags ;
5985 struct {
@@ -137,6 +163,8 @@ static st2_motor_t *z_motor;
137163static void (* volatile stateHandler )(void ) = state_idle ;
138164static plasma_mode_t mode = Plasma_ModeOff ;
139165static xbar_t arc_ok , cutter_down , cutter_up , parc_voltage ;
166+ static uint32_t mat_number = 1000000 ;
167+ static material_t * materials = NULL , * material = NULL , tmp_material ;
140168
141169static settings_changed_ptr settings_changed ;
142170static driver_reset_ptr driver_reset = NULL ;
@@ -148,6 +176,47 @@ static on_report_options_ptr on_report_options;
148176static on_spindle_selected_ptr on_spindle_selected ;
149177static on_execute_realtime_ptr on_execute_realtime = NULL ;
150178static on_realtime_report_ptr on_realtime_report = NULL ;
179+ static on_gcode_message_ptr on_gcode_comment ;
180+ static user_mcode_ptrs_t user_mcode ;
181+
182+ static uint32_t strnumentries (const char * s , const char delimiter )
183+ {
184+ char * p = (char * )s ;
185+ uint32_t entries = * s ? 1 : 0 ;
186+
187+ while (entries && (p = strchr (p , delimiter ))) {
188+ p ++ ;
189+ entries ++ ;
190+ }
191+
192+ return entries ;
193+ }
194+
195+ static int32_t strlookup (const char * s1 , const char * s2 , const char delimiter )
196+ {
197+ bool found = false;
198+ char * e , * p = (char * )s2 ;
199+ uint32_t idx = strnumentries (s2 , delimiter ), len = strlen (s1 );
200+ int32_t entry = 0 ;
201+
202+ while (idx -- ) {
203+
204+ if ((e = strchr (p , delimiter )))
205+ found = (e - p ) == len && !strncmp (p , s1 , e - p );
206+ else
207+ found = strlen (p ) == len && !strcmp (p , s1 );
208+
209+ if (found || e == NULL )
210+ break ;
211+ else {
212+ p = e + 1 ;
213+ entry ++ ;
214+ }
215+ }
216+
217+ return found ? entry : -1 ;
218+ }
219+
151220
152221// --- Virtual ports start
153222
@@ -361,6 +430,168 @@ static void add_virtual_ports (void *data)
361430 }
362431}
363432
433+ static material_t * find_material (uint32_t id )
434+ {
435+ material_t * material = materials , * found = NULL ;
436+
437+ if (material ) do {
438+ if (material -> id == id )
439+ found = material ;
440+ } while (found == NULL && (material = material -> next ));
441+
442+ return found ;
443+ }
444+
445+ static user_mcode_type_t mcode_check (user_mcode_t mcode )
446+ {
447+ return mcode == Plasma_SelectMaterial
448+ ? UserMCode_Normal
449+ : (user_mcode .check ? user_mcode .check (mcode ) : UserMCode_Unsupported );
450+ }
451+
452+ static status_code_t mcode_validate (parser_block_t * gc_block )
453+ {
454+ status_code_t state = Status_OK ;
455+
456+ if (gc_block -> user_mcode == Plasma_SelectMaterial ) {
457+ if (gc_block -> words .p ) {
458+ if (!isintf (gc_block -> values .p ))
459+ state = Status_BadNumberFormat ;
460+ else if (gc_block -> words .p && !(gc_block -> values .p == -1.0f || find_material ((uint32_t )gc_block -> values .p )))
461+ state = Status_GcodeValueOutOfRange ;
462+ else
463+ gc_block -> words .p = Off ;
464+ }
465+ } else
466+ state = Status_Unhandled ;
467+
468+ return state == Status_Unhandled && user_mcode .validate ? user_mcode .validate (gc_block ) : state ;
469+ }
470+
471+ static void mcode_execute (uint_fast16_t state , parser_block_t * gc_block )
472+ {
473+ if (gc_block -> user_mcode == Plasma_SelectMaterial ) {
474+ if ((material = gc_block -> values .p == -1.0f ? NULL : find_material ((uint32_t )gc_block -> values .p ))) {
475+ char command [30 ];
476+ sprintf (command , "G1Z%.3fF%.1f" , material -> pierce_height , material -> feed_rate );
477+ // grbl.enqueue_gcode(command);
478+ }
479+ } else if (user_mcode .execute )
480+ user_mcode .execute (state , gc_block );
481+ }
482+
483+ static status_code_t onGcodeComment (char * comment )
484+ {
485+ static const char params [] = "ph,pd,ch,fr,kw,ca,cv,pe,gp,cm,jh,jd,nu,na,th" ; // NOTE: must match layout of material_t
486+
487+ status_code_t status = Status_OK ;
488+
489+ if (strlen (comment ) > 5 && comment [0 ] == 'o' && comment [1 ] == '=' ) {
490+
491+ material_t new_material = {};
492+ char option = comment [2 ];
493+
494+ uint_fast8_t i ;
495+
496+ if (option == '0' )
497+ new_material .id = mat_number ++ ;
498+
499+ for (i = 0 ; i < 12 ; i ++ )
500+ new_material .params [i ] = NAN ;
501+
502+ char * param = strtok (comment + 4 , "," ), * eq ;
503+
504+ while (param && status == Status_OK ) {
505+
506+ while (* param == ' ' )
507+ param ++ ;
508+
509+ if ((eq = strchr (param , '=' ))) {
510+
511+ int32_t p ;
512+
513+ * eq = '\0' ;
514+
515+ switch ((p = strlookup (param , params , ',' ))) {
516+
517+ case -1 :
518+ status = Status_GcodeUnsupportedCommand ;
519+ break ;
520+
521+ case 12 :
522+ if (option != '0' ) {
523+ uint_fast8_t cc = 1 ;
524+ status = read_uint (eq , & cc , & new_material .id );
525+ }
526+ break ;
527+
528+ case 13 :
529+ strncpy (new_material .name , eq + 1 , sizeof (new_material .name ));
530+ new_material .name [sizeof (new_material .name ) - 1 ] = '\0' ;
531+ break ;
532+
533+ case 14 :
534+ new_material .thc_status = eq [1 ] != '0' ;
535+ break ;
536+
537+ default :
538+ {
539+ uint_fast8_t cc = 1 ;
540+ if (!read_float (eq , & cc , & new_material .params [p ]))
541+ status = Status_BadNumberFormat ;
542+ }
543+ break ;
544+ }
545+ * eq = '=' ;
546+ }
547+ param = strtok (NULL , "," );
548+ }
549+
550+ if (isnanf (new_material .pierce_height ) ||
551+ isnanf (new_material .pierce_delay ) ||
552+ isnanf (new_material .cut_height ) ||
553+ isnanf (new_material .feed_rate ))
554+ status = Status_GcodeValueWordMissing ;
555+
556+ if (status == Status_OK ) switch (option ) {
557+
558+ case '0' :
559+ material = & tmp_material ;
560+ memcpy (material , & new_material , sizeof (material_t ));
561+ break ;
562+
563+ case '1' :
564+ case '2' :
565+ material_t * m = find_material (new_material .id );
566+ bool add = m == NULL ;
567+ if (option == '2' || m == NULL ) {
568+ if (m == NULL )
569+ m = malloc (sizeof (material_t ));
570+ if (m ) {
571+ memcpy (m , & new_material , sizeof (material_t ));
572+ if (materials == NULL )
573+ materials = m ;
574+ else if (add ) {
575+ material_t * last = materials ;
576+ while (last -> next )
577+ last = last -> next ;
578+ last -> next = m ;
579+ }
580+ } // else error....
581+ }
582+ break ;
583+
584+ default :
585+ status = Status_GcodeUnsupportedCommand ;
586+ break ;
587+ }
588+
589+ } else if (on_gcode_comment )
590+ status = on_gcode_comment (comment );
591+
592+ return status ;
593+ }
594+
364595// --- Virtual ports end
365596
366597static void set_target_voltage (float v )
@@ -412,7 +643,10 @@ static void state_thc_delay (void)
412643 } else {
413644 pidf_reset (& pid );
414645 st2_set_position (z_motor , 0LL );
415- set_target_voltage (parc_voltage .get_value (& parc_voltage ) * plasma .arc_voltage_scale - plasma .arc_voltage_offset );
646+ if (material && !isnanf (material -> cut_voltage ))
647+ set_target_voltage (material -> cut_voltage );
648+ else
649+ set_target_voltage (parc_voltage .get_value (& parc_voltage ) * plasma .arc_voltage_scale - plasma .arc_voltage_offset );
416650 stateHandler = state_vad_lock ;
417651 stateHandler ();
418652 }
@@ -567,7 +801,7 @@ static void arcSetState (spindle_ptrs_t *spindle, spindle_state_t state, float r
567801 if ((thc .arc_ok = hal .port .wait_on_input (Port_Digital , port_arc_ok , WaitMode_High , plasma .arc_fail_timeout ) != -1 )) {
568802 report_message ("arc ok" , Message_Plain );
569803 retries = 0 ;
570- thc_delay = hal .get_elapsed_ticks () + (uint32_t )ceilf (1000.0f * plasma .thc_delay ); // handle overflow!
804+ thc_delay = hal .get_elapsed_ticks () + (uint32_t )ceilf (1000.0f * ( material ? material -> pierce_delay : plasma .thc_delay ) ); // handle overflow!
571805 stateHandler = state_thc_delay ;
572806 } else if (!(-- retries )) {
573807 thc .torch_on = Off ;
@@ -984,7 +1218,7 @@ static void onReportOptions (bool newopt)
9841218 * s1 ++ = ')' ;
9851219 * s1 = '\0' ;
9861220
987- report_plugin (buf , "0.18 " );
1221+ report_plugin (buf , "0.19 " );
9881222
9891223 } else if (mode != Plasma_ModeOff )
9901224 hal .stream .write (",THC" );
@@ -1028,9 +1262,18 @@ void plasma_init (void)
10281262
10291263 settings_register (& setting_details );
10301264
1265+ memcpy (& user_mcode , & grbl .user_mcode , sizeof (user_mcode_ptrs_t ));
1266+
1267+ grbl .user_mcode .check = mcode_check ;
1268+ grbl .user_mcode .validate = mcode_validate ;
1269+ grbl .user_mcode .execute = mcode_execute ;
1270+
10311271 on_report_options = grbl .on_report_options ;
10321272 grbl .on_report_options = onReportOptions ;
10331273
1274+ on_gcode_comment = grbl .on_gcode_comment ;
1275+ grbl .on_gcode_comment = onGcodeComment ;
1276+
10341277/*
10351278 control_interrupt_callback = hal.control_interrupt_callback;
10361279 hal.control_interrupt_callback = trap_control_interrupts;
0 commit comments