def get_commands(self, command_name, **kwargs):
        """get fe_command from command name and keyword arguments

        wrapper for build_commands()
        implements FEI4 specific behavior

        """
        chip_id = kwargs.pop("ChipID", self.chip_id_bitarray)
        commands = []
        if command_name == "zeros":
            bv = bitarray(endian='little')
            if "length" in kwargs:
                bv += bitarray(kwargs["length"], endian='little')  # initialized from int, bits may be random
            elif kwargs:
                raise ValueError("Unknown parameter(s): %s" % ", ".join(kwargs.iterkeys()))
            bv.setall(0)  # all bits to zero
            commands.append(bv)
        elif command_name == "ones":
            bv = bitarray(endian='little')
            if "length" in kwargs:
                bv += bitarray(kwargs["length"], endian='little')  # initialized from int, bits may be random
            elif kwargs:
                raise ValueError("Unknown parameter(s): %s" % ", ".join(kwargs.iterkeys()))
            bv.setall(1)  # all bits to one
            commands.append(bv)
        elif command_name == "WrRegister":
            register_addresses = self.get_global_register_attributes("addresses", **kwargs)
            register_bitsets = self.get_global_register_bitsets(register_addresses)
            commands.extend([self.build_command(command_name, Address=register_address, GlobalData=register_bitset, ChipID=chip_id, **kwargs) for register_address, register_bitset in zip(register_addresses, register_bitsets)])
        elif command_name == "RdRegister":
            register_addresses = self.get_global_register_attributes('addresses', **kwargs)
            commands.extend([self.build_command(command_name, Address=register_address, ChipID=chip_id) for register_address in register_addresses])
        elif command_name == "WrFrontEnd":
            registers = ["S0", "S1", "SR_Clr", "CalEn", "DIGHITIN_SEL", "GateHitOr", "ReadErrorReq", "StopClkPulse", "SR_Clock", "Efuse_Sense", "HITLD_IN", "Colpr_Mode", "Colpr_Addr"]
            if self.fei4a:
                registers.append("ReadSkipped")
            elif self.fei4b:
                registers.append("SR_Read")
            self.create_restore_point()
            dcs = kwargs.pop("dcs", range(40))  # set the double columns to latch
            # in case of empty list
            if not dcs:
                dcs = range(40)
            joint_write = kwargs.pop("joint_write", False)
            same_mask_for_all_dc = kwargs.pop("same_mask_for_all_dc", False)
            register_objects = self.get_pixel_register_objects(do_sort=['pxstrobe'], **kwargs)
            # prepare for writing pixel registers
            if not self.broadcast:
                self.set_global_register_value("Colpr_Mode", 0)  # write only to the addressed double-column
                self.set_global_register_value("Colpr_Addr", 40)  # ivalid address, grounded
                # Broadcasting ConfMode not necessary, writing registers is also possible in RunMode
#                 commands.extend(self.get_commands("ConfMode", ChipID=8))  # set all chips to conf mode to receive commands#
                # set all other chips to invalid addresses, to make broadcasting of WrRegister command possible
                commands.extend(self.get_commands("WrRegister", name=["Colpr_Mode", "Colpr_Addr"], ChipID=8))  # braodcast
            self.set_global_register_value("S0", 0)
            self.set_global_register_value("S1", 0)
            self.set_global_register_value("SR_Clr", 0)
            self.set_global_register_value("CalEn", 0)
            self.set_global_register_value("DIGHITIN_SEL", 0)
            self.set_global_register_value("GateHitOr", 0)
            self.set_global_register_value("ReadErrorReq", 0)
            self.set_global_register_value("StopClkPulse", 0)
            self.set_global_register_value("SR_Clock", 0)
            self.set_global_register_value("Efuse_Sense", 0)
            self.set_global_register_value("HITLD_IN", 0)
            self.set_global_register_value("Colpr_Mode", 3 if same_mask_for_all_dc else 0)  # write only the addressed double-column
            self.set_global_register_value("Colpr_Addr", 0)
            if self.fei4a:
                self.set_global_register_value("ReadSkipped", 0)
            elif self.fei4b:
                self.set_global_register_value("SR_Read", 0)
            commands.extend(self.get_commands("WrRegister", name=registers))

            if joint_write:
                pxstrobes = 0
                first_read = True
                do_latch = False
                for register_object in register_objects:
                    if register_object['bitlength'] != 1:
                        raise ValueError('Pixel register %s: joint write not supported for pixel DACs' % register_object['name'])
                    pxstrobe = register_object['pxstrobe']
                    if not isinstance(pxstrobe, basestring):
                        do_latch = True
                        pxstrobes += 2 ** register_object['pxstrobe']
                    if first_read:
                        pixel_reg_value = register_object['value']
                        first_read = False
                    else:
                        if np.array_equal(pixel_reg_value, register_object['value']):
                            pixel_reg_value = register_object['value']
                        else:
                            raise ValueError('Pixel register %s: joint write not supported, pixel register values must be equal' % register_object['name'])
                if do_latch:
                    self.set_global_register_value("Latch_En", 1)
                else:
                    self.set_global_register_value("Latch_En", 0)
                self.set_global_register_value("Pixel_Strobes", pxstrobes)
                commands.extend(self.get_commands("WrRegister", name=["Pixel_Strobes", "Latch_En"]))
                for dc_no in (dcs[:1] if same_mask_for_all_dc else dcs):
                    self.set_global_register_value("Colpr_Addr", dc_no)
                    commands.extend(self.get_commands("WrRegister", name=["Colpr_Addr"]))
                    register_bitset = self.get_pixel_register_bitset(register_objects[0], 0, dc_no)
                    commands.extend([self.build_command(command_name, PixelData=register_bitset, ChipID=8, **kwargs)])  # broadcast
                    if do_latch:
                        commands.extend(self.get_commands("GlobalPulse", Width=0))
            else:
                for register_object in register_objects:
                    pxstrobe = register_object['pxstrobe']
                    if isinstance(pxstrobe, basestring):
                        do_latch = False
                        self.set_global_register_value("Pixel_Strobes", 0)  # no latch
                        self.set_global_register_value("Latch_En", 0)
                        commands.extend(self.get_commands("WrRegister", name=["Pixel_Strobes", "Latch_En"]))
                    else:
                        do_latch = True
                        self.set_global_register_value("Latch_En", 1)
                        commands.extend(self.get_commands("WrRegister", name=["Latch_En"]))
                    bitlength = register_object['bitlength']
                    for bit_no, pxstrobe_bit_no in (enumerate(range(bitlength)) if (register_object['littleendian'] is False) else enumerate(reversed(range(bitlength)))):
                        if do_latch:
                            self.set_global_register_value("Pixel_Strobes", 2 ** (pxstrobe + bit_no))
                            commands.extend(self.get_commands("WrRegister", name=["Pixel_Strobes"]))
                        for dc_no in (dcs[:1] if same_mask_for_all_dc else dcs):
                            self.set_global_register_value("Colpr_Addr", dc_no)
                            commands.extend(self.get_commands("WrRegister", name=["Colpr_Addr"]))
                            register_bitset = self.get_pixel_register_bitset(register_object, pxstrobe_bit_no, dc_no)
                            commands.extend([self.build_command(command_name, PixelData=register_bitset, ChipID=8, **kwargs)])  # broadcast
                            if do_latch:
                                commands.extend(self.get_commands("GlobalPulse", Width=0))
            self.restore(pixel_register=False)
            commands.extend(self.get_commands("WrRegister", name=registers))
        elif command_name == "RdFrontEnd":
            registers = ["Conf_AddrEnable", "S0", "S1", "SR_Clr", "CalEn", "DIGHITIN_SEL", "GateHitOr", "ReadErrorReq", "StopClkPulse", "SR_Clock", "Efuse_Sense", "HITLD_IN", "Colpr_Mode", "Colpr_Addr", "Pixel_Strobes", "Latch_En"]
            if self.fei4a:
                registers.append("ReadSkipped")
            elif self.fei4b:
                registers.append("SR_Read")
            self.create_restore_point()
            dcs = kwargs.pop("dcs", range(40))  # set the double columns to latch
            # in case of empty list
            if not dcs:
                dcs = range(40)
            register_objects = self.get_pixel_register_objects(**kwargs)
            self.set_global_register_value('Conf_AddrEnable', 1)
            self.set_global_register_value("S0", 0)
            self.set_global_register_value("S1", 0)
            self.set_global_register_value("SR_Clr", 0)
            if self.fei4b:
                self.set_global_register_value("SR_Read", 0)
            self.set_global_register_value("CalEn", 0)
            self.set_global_register_value("DIGHITIN_SEL", 0)
            self.set_global_register_value("GateHitOr", 0)
            if self.fei4a:
                self.set_global_register_value("ReadSkipped", 0)
            self.set_global_register_value("ReadErrorReq", 0)
            self.set_global_register_value("StopClkPulse", 0)
            self.set_global_register_value("SR_Clock", 0)
            self.set_global_register_value("Efuse_Sense", 0)
            self.set_global_register_value("HITLD_IN", 0)
            self.set_global_register_value("Colpr_Mode", 0)  # write only the addressed double-column
            self.set_global_register_value("Colpr_Addr", 0)
            self.set_global_register_value("Latch_En", 0)
            self.set_global_register_value("Pixel_Strobes", 0)
            commands.extend(self.get_commands("WrRegister", name=registers))
            for index, register_object in enumerate(register_objects):  # make sure that EnableDigInj is first read back, because it is not latched
                if register_object['name'] == 'EnableDigInj':
                    register_objects[0], register_objects[index] = register_objects[index], register_objects[0]
                    break
            for register_object in register_objects:
                pxstrobe = register_object['pxstrobe']
                bitlength = register_object['bitlength']
                for pxstrobe_bit_no in range(bitlength):
                    logging.debug('Pixel Register %s Bit %d', register_object['name'], pxstrobe_bit_no)
                    do_latch = True
                    try:
                        self.set_global_register_value("Pixel_Strobes", 2 ** (pxstrobe + pxstrobe_bit_no))
                    except TypeError:  # thrown for not latched digInjection
                        self.set_global_register_value("Pixel_Strobes", 0)  # do not latch
                        do_latch = False
                    commands.extend(self.get_commands("WrRegister", name=["Pixel_Strobes"]))
                    for dc_no in dcs:
                        self.set_global_register_value("Colpr_Addr", dc_no)
                        commands.extend(self.get_commands("WrRegister", name=["Colpr_Addr"]))
                        if do_latch is True:
                            self.set_global_register_value("S0", 1)
                            self.set_global_register_value("S1", 1)
                            self.set_global_register_value("SR_Clock", 1)
                            commands.extend(self.get_commands("WrRegister", name=["S0", "S1", "SR_Clock"]))
                            commands.extend(self.get_commands("GlobalPulse", Width=0))
                        self.set_global_register_value("S0", 0)
                        self.set_global_register_value("S1", 0)
                        self.set_global_register_value("SR_Clock", 0)
                        commands.extend(self.get_commands("WrRegister", name=["S0", "S1", "SR_Clock"]))
                        register_bitset = self.get_pixel_register_bitset(register_object, pxstrobe_bit_no if (register_object['littleendian'] is False) else register_object['bitlength'] - pxstrobe_bit_no - 1, dc_no)
                        if self.fei4b:
                            self.set_global_register_value("SR_Read", 1)
                            commands.extend(self.get_commands("WrRegister", name=["SR_Read"]))
                        commands.extend([self.build_command("WrFrontEnd", PixelData=register_bitset, ChipID=chip_id)])
                        if self.fei4b:
                            self.set_global_register_value("SR_Read", 0)
                            commands.extend(self.get_commands("WrRegister", name=["SR_Read"]))
            self.restore(pixel_register=False)
            commands.extend(self.get_commands("WrRegister", name=registers))
        else:
            commands.append(self.build_command(command_name, ChipID=chip_id, **kwargs))
        return commands
get fe_command from command name and keyword arguments

        wrapper for build_commands()
        implements FEI4 specific behavior