@@ -383,6 +383,112 @@ def param_watchlist(self, master, args):
383383 for pattern in self .watch_patterns :
384384 self .mpstate .console .writeln ("> %s" % (pattern ))
385385
386+ def param_bitmask_modify (self , master , args ):
387+ '''command for performing bitmask actions on a parameter'''
388+
389+ BITMASK_ACTIONS = ['toggle' , 'set' , 'clear' ]
390+
391+ # Ensure we have at least an action and a parameter
392+ if len (args ) < 2 :
393+ print ("Not enough arguments" )
394+ print (f"param bitmask <{ '/' .join (BITMASK_ACTIONS )} > <parameter> [bit-index]" )
395+ return
396+
397+ action = args [0 ]
398+ if action not in BITMASK_ACTIONS :
399+ print (f"action must be one of: { ', ' .join (BITMASK_ACTIONS )} " )
400+ return
401+
402+ # Grab the parameter argument, and check it exists
403+ param = args [1 ]
404+ if not param .upper () in self .mav_param :
405+ print (f"Unable to find parameter { param .upper ()} " )
406+ return
407+ uname = param .upper ()
408+
409+ htree = self .param_help .param_help_tree ()
410+ if htree is None :
411+ # No help tree is available
412+ print ("Download parameters first" )
413+ return
414+
415+ # Take the help tree and check if parameter is a bitmask
416+ phelp = htree [uname ]
417+ bitmask_values = self .param_help .get_bitmask_from_help (phelp )
418+ if bitmask_values is None :
419+ print (f"Parameter { uname } is not a bitmask" )
420+ return
421+
422+ # Find the type of the parameter
423+ ptype = None
424+ if uname in self .param_types :
425+ # Get the type of the parameter
426+ ptype = self .param_types [uname ]
427+
428+ # Now grab the value for the parameter
429+ value = int (self .mav_param .get (uname ))
430+ if value is None :
431+ print (f"Could not get a value for parameter { uname } " )
432+ return
433+
434+ # The next argument is the bit_index - if it exists, handle it
435+ bit_index = None
436+ if len (args ) >= 3 :
437+ try :
438+ # If the bit index is available lets grab it
439+ arg_bit_index = args [2 ]
440+ # Try to convert it to int
441+ bit_index = int (arg_bit_index )
442+ except ValueError :
443+ print (f"Invalid bit index: { arg_bit_index } \n " )
444+
445+ if bit_index is None :
446+ # No bit index was specified, but the parameter and action was.
447+ # Print the available bitmask information.
448+ print ("%s: %s" % (uname , phelp .get ('humanName' )))
449+ s = "%-16.16s %s" % (uname , value )
450+ print (s )
451+
452+ # Generate the bitmask enabled list
453+ remaining_bits = value
454+ out_v = []
455+ if bitmask_values is not None and len (bitmask_values ):
456+ for (n , v ) in bitmask_values .items ():
457+ if bit_index is None or bit_index == int (n ):
458+ out_v .append (f"\t { int (n ):3d} [{ 'x' if value & (1 << int (n )) else ' ' } ] : { v } " )
459+ remaining_bits &= ~ (1 << int (n ))
460+
461+ # Loop bits 0 to 31, checking if they are remaining, and append
462+ for i in range (32 ):
463+ if (remaining_bits & (1 << i )) and ((bit_index is None ) or (bit_index == i )):
464+ out_v .append (f"\t { i :3d} [{ 'x' if value & (1 << i ) else ' ' } ] : Unknownbit{ i } " )
465+
466+ if out_v is not None and len (out_v ) > 0 :
467+ print ("\n Bitmask: " )
468+ print ("\n " .join (out_v ))
469+
470+ # Finally, inform user of the error we experienced
471+ if bit_index is None :
472+ print ("bit index is not specified" )
473+
474+ # We don't have enough information to modify the bitmask, so bail
475+ return
476+
477+ # We have enough information to try perform an action
478+ if action == "toggle" :
479+ value = value ^ (1 << bit_index )
480+ elif action == "set" :
481+ value = value | (1 << bit_index )
482+ elif action == "clear" :
483+ value = value & ~ (1 << bit_index )
484+ else :
485+ # We cannot toggle, set or clear
486+ print ("Invalid bitmask action" )
487+ return
488+
489+ # Update the parameter
490+ self .mav_param .mavset (master , uname , value , retries = 3 , parm_type = ptype )
491+
386492 def param_revert (self , master , args ):
387493 '''handle param revert'''
388494 defaults = self .default_params
@@ -417,7 +523,7 @@ def param_revert(self, master, args):
417523 def handle_command (self , master , mpstate , args ):
418524 '''handle parameter commands'''
419525 param_wildcard = "*"
420- usage = "Usage: param <fetch|ftp|save|savechanged|revert|set|show|load|preload|forceload|ftpload|diff|download|check|help|watch|unwatch|watchlist>" # noqa
526+ usage = "Usage: param <fetch|ftp|save|savechanged|revert|set|show|load|preload|forceload|ftpload|diff|download|check|help|watch|unwatch|watchlist|bitmask >" # noqa
421527 if len (args ) < 1 :
422528 print (usage )
423529 return
@@ -494,7 +600,8 @@ def handle_command(self, master, mpstate, args):
494600 # mpstate.module('rally').set_last_change(time.time())
495601 # need to redraw loiter points
496602 mpstate .module ('wp' ).wploader .last_change = time .time ()
497-
603+ elif args [0 ] == "bitmask" :
604+ self .param_bitmask_modify (master , args [1 :])
498605 elif args [0 ] == "load" :
499606 if len (args ) < 2 :
500607 print ("Usage: param load <filename> [wildcard]" )
@@ -664,12 +771,14 @@ def __init__(self, mpstate, **kwargs):
664771 self .pstate = {}
665772 self .check_new_target_system ()
666773 self .menu_added_console = False
774+ bitmask_indexes = "|" .join (str (x ) for x in range (32 ))
667775 self .add_command (
668776 'param' , self .cmd_param , "parameter handling" , [
669777 "<download|status>" ,
670778 "<set|show|fetch|ftp|help|apropos|revert> (PARAMETER)" ,
671779 "<load|save|savechanged|diff|forceload|ftpload> (FILENAME)" ,
672780 "<set_xml_filepath> (FILEPATH)" ,
781+ f"<bitmask> <toggle|set|clear> (PARAMETER) <{ bitmask_indexes } >"
673782 ],
674783 )
675784 if mp_util .has_wxpython :
0 commit comments