@@ -144,6 +144,11 @@ inline static bool motion_is_lasercut (motion_mode_t motion)
144144 return motion == MotionMode_Linear || motion == MotionMode_CwArc || motion == MotionMode_CcwArc || motion == MotionMode_CubicSpline || motion == MotionMode_QuadraticSpline ;
145145}
146146
147+ inline static bool no_word_value (char letter )
148+ {
149+ return letter == '\0' || (letter >= 'A' && letter <= 'Z' ) || letter == '$' ;
150+ }
151+
147152parser_state_t * gc_get_state (void )
148153{
149154 return & gc_state ;
@@ -348,6 +353,21 @@ void gc_init (void)
348353 grbl .on_parser_init (& gc_state );
349354}
350355
356+ #if N_SYS_SPINDLE > 1
357+
358+ inline static bool is_single_spindle_block (parser_block_t * gc_block , modal_groups_t command_words )
359+ {
360+ return gc_block -> words .s ||
361+ (command_words .G1 && (gc_block -> modal .motion == MotionMode_SpindleSynchronized ||
362+ gc_block -> modal .motion == MotionMode_RigidTapping ||
363+ gc_block -> modal .motion == MotionMode_Threading )) ||
364+ (command_words .G5 && gc_block -> modal .feed_mode == FeedMode_UnitsPerRev ) ||
365+ command_words .G14 ||
366+ (command_words .M9 && gc_block -> override_command == Override_SpindleSpeed );
367+ }
368+
369+ #endif
370+
351371// Set dynamic laser power mode to PPI (Pulses Per Inch)
352372// Returns true if driver uses hardware implementation.
353373// Driver support for pulsing the laser on signal is required for this to work.
@@ -487,54 +507,6 @@ void gc_output_message (char *message)
487507
488508static ngc_param_t ngc_params [NGC_N_ASSIGN_PARAMETERS_PER_BLOCK ];
489509
490- static status_code_t read_parameter (char * line , uint_fast8_t * char_counter , float * value )
491- {
492- char c = * (line + * char_counter );
493- status_code_t status = Status_OK ;
494-
495- if (c == '#' ) {
496-
497- (* char_counter )++ ;
498-
499- if (* (line + * char_counter ) == '<' ) {
500-
501- (* char_counter )++ ;
502- char * pos = line = line + * char_counter ;
503-
504- while (* line && * line != '>' ) {
505- if (* line == ' ' ) {
506- char * s1 = line , * s2 = line + 1 ;
507- while (* s2 )
508- * s1 ++ = * s2 ++ ;
509- * (-- s2 ) = '\0' ;
510- } else
511- line ++ ;
512- }
513-
514- * char_counter += line - pos + 1 ;
515-
516- if (* line == '>' ) {
517- * line = '\0' ;
518- if (!ngc_named_param_get (pos , value ))
519- status = Status_BadNumberFormat ;
520- * line = '>' ;
521- } else
522- status = Status_BadNumberFormat ;
523-
524- } else if (read_float (line , char_counter , value )) {
525- if (!ngc_param_get ((ngc_param_id_t )* value , value ))
526- status = Status_BadNumberFormat ;
527- } else
528- status = Status_BadNumberFormat ;
529-
530- } else if (c == '[' )
531- status = ngc_eval_expression (line , char_counter , value );
532- else if (!read_float (line , char_counter , value ))
533- * value = NAN ;
534-
535- return status ;
536- }
537-
538510static int8_t get_format (char c , int8_t pos , uint8_t * decimals )
539511{
540512 static uint8_t d ;
@@ -611,7 +583,7 @@ static void substitute_parameters (char *comment, char **message)
611583 parse_format = 1 ;
612584 else if (c == '#' ) {
613585 char_counter -- ;
614- if (read_parameter (comment , & char_counter , & value ) == Status_OK )
586+ if (ngc_read_parameter (comment , & char_counter , & value , true ) == Status_OK )
615587 len += strlen (decimals ? ftoa (value , decimals ) : trim_float (ftoa (value , decimals )));
616588 else
617589 len += 3 ; // "N/A"
@@ -642,7 +614,7 @@ static void substitute_parameters (char *comment, char **message)
642614 fmt [0 ] = c ;
643615 } else if (c == '#' ) {
644616 char_counter -- ;
645- if (read_parameter (comment , & char_counter , & value ) == Status_OK )
617+ if (ngc_read_parameter (comment , & char_counter , & value , true ) == Status_OK )
646618 strcat (s , decimals ? ftoa (value , decimals ) : trim_float (ftoa (value , decimals )));
647619 else
648620 strcat (s , "N/A" );
@@ -1006,7 +978,7 @@ status_code_t gc_execute_block (char *block)
1006978 float value ;
1007979 uint32_t int_value = 0 ;
1008980 uint_fast16_t mantissa = 0 ;
1009- bool is_user_mcode = false ;
981+ user_mcode_type_t user_mcode = UserMCode_Unsupported ;
1010982 word_bit_t word_bit = { .parameter = {0 }, .modal_group = {0 } }; // Bit-value for assigning tracking variables
1011983
1012984 while ((letter = block [char_counter ++ ]) != '\0' ) { // Loop until no more g-code words in block.
@@ -1034,7 +1006,7 @@ status_code_t gc_execute_block (char *block)
10341006 * s ++ = '\0' ;
10351007 s ++ ;
10361008 char_counter += s - name ;
1037- if ((status = read_parameter (block , & char_counter , & value )) != Status_OK )
1009+ if ((status = ngc_read_real_value (block , & char_counter , & value )) != Status_OK )
10381010 FAIL (status ); // [Expected parameter value]
10391011 if (!ngc_named_param_set (name , value ))
10401012 FAIL (Status_BadNumberFormat ); // [Expected equal sign]
@@ -1043,13 +1015,16 @@ status_code_t gc_execute_block (char *block)
10431015 } else {
10441016
10451017 float param ;
1046- if (!read_float (block , & char_counter , & param ))
1047- FAIL (Status_BadNumberFormat ); // [Expected parameter number]
10481018
1049- if (block [char_counter ++ ] != '=' )
1019+ if ((status = ngc_read_real_value (block , & char_counter , & param )) != Status_OK ) {
1020+ FAIL (status ); // [Expected parameter number]
1021+ } else if (!ngc_param_is_rw ((ngc_param_id_t )param ))
1022+ FAIL (Status_GcodeValueOutOfRange ); // [Parameter does not exist or is read only]
1023+
1024+ if (block [char_counter ++ ] != '=' )
10501025 FAIL (Status_BadNumberFormat ); // [Expected equal sign]
10511026
1052- if ((status = read_parameter (block , & char_counter , & value )) != Status_OK )
1027+ if ((status = ngc_read_real_value (block , & char_counter , & value )) != Status_OK )
10531028 FAIL (status ); // [Expected parameter value]
10541029
10551030 if (ngc_param_count < NGC_N_ASSIGN_PARAMETERS_PER_BLOCK && ngc_param_is_rw ((ngc_param_id_t )param )) {
@@ -1070,13 +1045,15 @@ status_code_t gc_execute_block (char *block)
10701045 if ((letter < 'A' && letter != '$' ) || letter > 'Z' )
10711046 FAIL (Status_ExpectedCommandLetter ); // [Expected word letter]
10721047
1073- if ((status = read_parameter (block , & char_counter , & value )) != Status_OK )
1048+ if (user_mcode == UserMCode_NoValueWords && no_word_value (block [char_counter ]))
1049+ value = NAN ;
1050+ else if ((status = ngc_read_real_value (block , & char_counter , & value )) != Status_OK )
10741051 return status ;
10751052
10761053 if (gc_state .skip_blocks && letter != 'O' )
10771054 return Status_OK ;
10781055
1079- if (! is_user_mcode && isnanf (value ))
1056+ if (user_mcode != UserMCode_NoValueWords && isnanf (value ))
10801057 FAIL (Status_BadNumberFormat ); // [Expected word value]
10811058
10821059 g65_words .value = 0 ;
@@ -1085,11 +1062,11 @@ status_code_t gc_execute_block (char *block)
10851062 if ((letter < 'A' && letter != '$' ) || letter > 'Z' )
10861063 FAIL (Status_ExpectedCommandLetter ); // [Expected word letter]
10871064
1088- if (!read_float (block , & char_counter , & value )) {
1089- if (is_user_mcode ) // Valueless parameters allowed for user defined M-codes.
1090- value = NAN ; // Parameter validation deferred to implementation.
1065+ if (!read_float (block , & char_counter , & value )) {
1066+ if (user_mcode == UserMCode_NoValueWords ) // Valueless parameters allowed for user defined M-codes.
1067+ value = NAN ; // Parameter validation deferred to implementation.
10911068 else
1092- FAIL (Status_BadNumberFormat ); // [Expected word value]
1069+ FAIL (Status_BadNumberFormat ); // [Expected word value]
10931070 }
10941071
10951072#endif
@@ -1118,7 +1095,7 @@ status_code_t gc_execute_block (char *block)
11181095
11191096 case 'G' : // Determine 'G' command and its modal group
11201097
1121- is_user_mcode = false ;
1098+ user_mcode = UserMCode_Unsupported ;
11221099 word_bit .modal_group .mask = 0 ;
11231100
11241101 switch (int_value ) {
@@ -1358,7 +1335,7 @@ status_code_t gc_execute_block (char *block)
13581335 if (mantissa > 0 )
13591336 FAIL (Status_GcodeCommandValueNotInteger ); // [No Mxx.x commands]
13601337
1361- is_user_mcode = false ;
1338+ user_mcode = UserMCode_Unsupported ;
13621339 word_bit .modal_group .mask = 0 ;
13631340
13641341 switch (int_value ) {
@@ -1474,8 +1451,8 @@ status_code_t gc_execute_block (char *block)
14741451 break ;
14751452
14761453 default :
1477- if (hal .user_mcode .check && (gc_block . user_mcode = hal .user_mcode .check ((user_mcode_t )int_value ))) {
1478- is_user_mcode = true ;
1454+ if (grbl .user_mcode .check && (user_mcode = grbl .user_mcode .check ((user_mcode_t )int_value ))) {
1455+ gc_block . user_mcode = ( user_mcode_t ) int_value ;
14791456 word_bit .modal_group .M10 = On ;
14801457 } else
14811458 FAIL (Status_GcodeUnsupportedCommand ); // [Unsupported M command]
@@ -1824,7 +1801,7 @@ status_code_t gc_execute_block (char *block)
18241801 if (command_words .M10 && gc_block .user_mcode ) {
18251802
18261803 user_words .mask = gc_block .words .mask ;
1827- if ((int_value = (uint_fast16_t )hal .user_mcode .validate (& gc_block , & gc_block . words )))
1804+ if ((int_value = (uint_fast16_t )grbl .user_mcode .validate (& gc_block )))
18281805 FAIL ((status_code_t )int_value );
18291806 user_words .mask ^= gc_block .words .mask ; // Flag "taken" words for execution
18301807
@@ -1909,13 +1886,7 @@ status_code_t gc_execute_block (char *block)
19091886
19101887 // [4. Set spindle speed and address spindle ]: S or D is negative (done.)
19111888 if (gc_block .words .$ ) {
1912- bool single_spindle_only = gc_block .words .s ||
1913- (command_words .G0 && (gc_block .modal .motion == MotionMode_SpindleSynchronized ||
1914- gc_block .modal .motion == MotionMode_RigidTapping ||
1915- gc_block .modal .motion == MotionMode_Threading )) ||
1916- (command_words .G5 && gc_block .modal .feed_mode == FeedMode_UnitsPerRev ) ||
1917- command_words .G14 ||
1918- (command_words .M9 && gc_block .override_command == Override_SpindleSpeed );
1889+ bool single_spindle_only = is_single_spindle_block (& gc_block , command_words );
19191890 if (command_words .M7 || single_spindle_only ) {
19201891 if (gc_block .values .$ < (single_spindle_only ? 0 : -1 ))
19211892 FAIL (single_spindle_only ? Status_NegativeValue : Status_GcodeValueOutOfRange );
@@ -1936,6 +1907,11 @@ status_code_t gc_execute_block (char *block)
19361907 gc_block .words .$ = Off ;
19371908 }
19381909 }
1910+ #if N_SYS_SPINDLE > 1
1911+ // For now, remove when downstream code can handle multiple spindles?
1912+ else if (command_words .M7 || is_single_spindle_block (& gc_block , command_words ))
1913+ sspindle = & gc_state .modal .spindle [0 ];
1914+ #endif
19391915
19401916 if (gc_block .modal .feed_mode == FeedMode_UnitsPerRev && (sspindle == NULL || !sspindle -> hal -> get_data ))
19411917 FAIL (Status_GcodeUnsupportedCommand ); // [G95 not supported]
@@ -3538,7 +3514,7 @@ status_code_t gc_execute_block (char *block)
35383514 gc_block .values .o = single_meaning_value .o ;
35393515 gc_block .values .s = single_meaning_value .s ;
35403516 gc_block .values .t = single_meaning_value .t ;
3541- hal .user_mcode .execute (state_get (), & gc_block );
3517+ grbl .user_mcode .execute (state_get (), & gc_block );
35423518 gc_block .words .mask = 0 ;
35433519 }
35443520
@@ -3960,7 +3936,7 @@ status_code_t gc_execute_block (char *block)
39603936 idx = N_SYS_SPINDLE ;
39613937 spindle_t * spindle ;
39623938 do {
3963- if ((spindle = & gc_state .modal .spindle [-- idx ])) {
3939+ if ((spindle = & gc_state .modal .spindle [-- idx ])-> hal ) {
39643940 spindle -> css = NULL ;
39653941 spindle -> state = (spindle_state_t ){0 };
39663942 spindle -> rpm_mode = SpindleSpeedMode_RPM ; // NOTE: not compliant with linuxcnc (?);
0 commit comments