def getCoilStates(self): """ Gets the current state of the coils. """ self.__checkBridgeOK() pycoils = self.game.proc.drivers vpcoils = [False]*64 if(self.Sys11 == True): ACState = pycoils[12+39].curr_state for i in range(0,len(vpcoils)): if i < 33: if(self.Sys11!=True): if i<=28: vpcoils[i] = pycoils[i+39].curr_state elif i<=32: vpcoils[i] = False # Unused? else: # do the relay lying here... if i<=8: vpcoils[i] = pycoils[i+39].curr_state and (ACState == False) elif i<=24: vpcoils[i] = pycoils[i+39].curr_state elif i<=32: vpcoils[i] = pycoils[i+39].curr_state and (ACState == True) # Use the machine's Hold coils for the VP flippers # since they stay on until the button is released elif i == 34: vpcoils[i] = pycoils[pinproc.decode(self.game.machine_type, "FURH")].curr_state elif i == 36: vpcoils[i] = pycoils[pinproc.decode(self.game.machine_type, "FULH")].curr_state elif i<44: if self.game.machine_type == pinproc.MachineTypeWPC95: vpcoils[i] = pycoils[i+31].curr_state else: vpcoils[i] = pycoils[i+107].curr_state elif i == 46: vpcoils[i] = pycoils[pinproc.decode(self.game.machine_type, "FLRH")].curr_state elif i == 48: vpcoils[i] = pycoils[pinproc.decode(self.game.machine_type, "FLLH")].curr_state else: vpcoils[i] = pycoils[i+108].curr_state return vpcoils
def SetSwitch(self, number, value): """ Set the value of the requested switch. """ if self.GameIsDead: raise COMException(desc=self.ErrorMsg, scode=winerror.E_FAIL) # All of the 'None' logic is error handling for unexpected # cases when None is passed in as a parameter. This seems to # only happen with the original VP scripts when the switch data # is corrupted by making COM calls into this object. This # appears to be a pywin32 bug. if value == None: return self.Switch(number) if number == None: return self.Switch(number) if number != None: self.lastSwitch = number self.switch[self.lastSwitch] = value if self.Sys11 == True: if self.lastSwitch < 1: prNumber = self.VPSwitchDedToPRSwitch(abs(self.lastSwitch)) elif self.lastSwitch == 82: prNumber = pinproc.decode(self.game.machine_type, "SF1") elif self.lastSwitch == 84: prNumber = pinproc.decode(self.game.machine_type, "SF2") elif self.lastSwitch < 65: # number = number -1 prNumber = (((number / 8) + 1) * 10) + ((number % 8)) prNumber = self.VPSwitchMatrixToPRSwitch(prNumber) else: prNumber = 0 else: if self.lastSwitch < 10: prNumber = self.VPSwitchDedToPRSwitch(self.lastSwitch) elif self.lastSwitch < 110: prNumber = self.VPSwitchMatrixToPRSwitch(self.lastSwitch) elif self.lastSwitch < 120: prNumber = self.VPSwitchFlipperToPRSwitch(self.lastSwitch) else: prNumber = 0 if not self.game.switches.has_key(prNumber): return False if self.game.switches[prNumber].type == "NC": self.AddSwitchEvent(prNumber, not value) else: self.AddSwitchEvent(prNumber, value) return True
def PROC_OSC_message_handler(self, addr, tags, data, client_address): """ receives OSC messages and acts on them by setting switches.""" print("recvd OSC message " + str(addr)) # need to add supprt for "sync" instruction which we'll call when switching tabs in touchOSC #strip out the switch name switchname = addr.split("/")[-1] # This is the OSC address, not the IP address. Strip out the characters after the final "/" if switchname in self.game.switches: switch_number = self.game.switches[switchname].number else: switch_number = pinproc.decode(self.game.machine_type, switchname) # I'm kind of cheating by using desktop.key_events here, but I guess this is ok? if data[0] == 1.0: # close the switch self.game.desktop.key_events.append({'type': pinproc.EventTypeSwitchClosedDebounced, 'value': switch_number}) elif data[0] == 0.0: # open the switch self.game.desktop.key_events.append({'type': pinproc.EventTypeSwitchOpenDebounced, 'value': switch_number}) # since we just got a message from a client, let's set up a connection to it if not self.do_we_have_a_client: if not self.clientIP: # if a client IP wasn't specified, use the one that just communicated with us now self.clientIP = client_address[0] self.clientTuple = (self.clientIP, self.clientPort) self.setup_OSC_client(self.clientTuple)
def GetMech(self, number): """ Currently unused. Game specific mechanism handling will be called through this method. """ if self.GameIsDead: raise COMException(desc=self.ErrorMsg, scode=winerror.E_FAIL) if self.GameName == "t2_l8": # if the coil associated with this mech is on if self.game.proc.drivers[pinproc.decode(self.game.machine_type, "C11")].curr_state == True: # check the direction self.game.logging_enabled = True logging.getLogger("vpcom").info("Coil # %d " % number) if self.direction == 1: self.pos = self.pos + 0.5 if self.pos >= 41: self.direction = -1 else: self.pos = self.pos - 0.5 if self.pos <= 0: self.direction = 1 if self.pos == 0: self.SetSwitch(33, True) elif self.pos == 1: self.SetSwitch(33, False) elif self.pos == 27: self.SetSwitch(32, True) elif (self.pos == 28) or (self.pos == 26): self.SetSwitch(32, False) return self.pos return 0
def GetMech(self, number): """ Currently unused. Game specific mechanism handling will be called through this method. """ self.__checkBridgeOK() if(self.GameName=="t2_l8"): # if the coil associated with this mech is on if(self.game.proc.drivers[pinproc.decode(self.game.machine_type, "C11")].curr_state == True) : # check the direction self.game.logging_enabled = True logging.getLogger('vpcom').info("Coil # %d " % number ) if(self.direction == 1): self.pos = self.pos + .5 if(self.pos >= 41): self.direction = -1 else: self.pos = self.pos - .5 if(self.pos <= 0): self.direction = 1 if(self.pos == 0): self.SetSwitch(33, True) elif(self.pos == 1): self.SetSwitch(33, False) elif(self.pos == 27): self.SetSwitch(32, True) elif((self.pos == 28) or (self.pos == 26)): self.SetSwitch(32, False) return self.pos return 0
def process_switch(self, switchname, data): """Processes a switch event received from the OSC client""" if switchname in self.game.switches: switch_number = self.game.switches[switchname].number else: switch_number = pinproc.decode(self.game.machine_type, switchname) if self.game.switches[switchname].type == 'NC': # Need to 'flip' the switch if the machine YAML file configures # it to be normally closed if data[0] == 1.0: data[0] = 0.0 elif data[0] == 0.0: data[0] = 1.0 # I'm kind of cheating by using desktop.key_events here, but I guess this is ok? if data[0] == 1.0: # close the switch self.game.desktop.key_events.append( {'type': pinproc.EventTypeSwitchClosedDebounced, 'value': switch_number}) elif data[0] == 0.0: # open the switch self.game.desktop.key_events.append( {'type': pinproc.EventTypeSwitchOpenDebounced, 'value': switch_number})
def VPSwitchMatrixToPRSwitch(self, number): """ Helper method to find the P-ROC number of a matrix switch. """ vpNumber = ((number / 10)*8) + ((number%10) - 1) vpIndex = vpNumber / 8 vpOffset = vpNumber % 8 + 1 if vpIndex < 10: switch = 'S' + str(vpIndex) + str(vpOffset) return pinproc.decode(self.game.machine_type,switch) else: return number
def open(self): #if self.is_open(): # return value = pinproc.decode("wpc", self.id) # FIXME: Hard-coded to WPC p.commands.put({ "command": "switch", "type": pinproc.EventTypeSwitchOpenDebounced, "value": value })
def getGIStates(self): """ Gets the current state of the GI strings. """ vpgi = [False]*5 for i in range(0,5): numStr = 'G0' + str(i+1) prNumber = pinproc.decode(self.game.machine_type, numStr) vpgi[i] = self.game.proc.drivers[prNumber].curr_state return vpgi
def getGIStates(self): """ Gets the current state of the GI strings. """ if self.GameIsDead: raise COMException(desc=self.ErrorMsg, scode=winerror.E_FAIL) vpgi = [False] * 5 for i in range(0, 5): numStr = "G0" + str(i + 1) prNumber = pinproc.decode(self.game.machine_type, numStr) vpgi[i] = self.game.proc.drivers[prNumber].curr_state return vpgi
def set_initial_switches(self): """sets up the initial switches that should be closed, then marks the client to sync Should I add some logic here to only do this with fakepinproc? """ for switchname in self.closed_switches: # run through the list of closed_switches passed to the mode as args if switchname in self.game.switches: # convert the names to switch numbers switch_number = self.game.switches[switchname].number else: switch_number = pinproc.decode(self.game.machine_type, switchname) self.game.desktop.key_events.append({'type': pinproc.EventTypeSwitchClosedDebounced, 'value': switch_number}) # add these switch close events to the queue self.client_needs_sync = True # Now that this is done we set the flag to sync the client
def PROC_OSC_message_handler(self, addr, tags, data, client_address): """ receives OSC messages and acts on them by setting switches.""" #print("GOING THROUGH DEFAULT HANDLER %s " % addr) # print("recvd OSC message " + str(addr) +" tags:"+ str(tags) +" data:"+ str(data)) # need to add supprt for "sync" instruction which we'll call when switching tabs in touchOSC #strip out the switch name switchname = addr.split( "/" )[-1] # This is the OSC address, not the IP address. Strip out the characters after the final "/" if switchname in self.game.switches: switch_number = self.game.switches[switchname].number #print("switch_number is local -> %d" % switch_number) else: switch_number = pinproc.decode(self.game.machine_type, switchname) #print("switch_number is lookedup -> %d" % switch_number) # I'm kind of cheating by using desktop.key_events here, but I guess this is ok? if data[0] == 1.0: # close the switch self.game.desktop.key_events.append({ 'type': pinproc.EventTypeSwitchClosedDebounced, 'value': switch_number }) elif data[0] == 0.0: # open the switch self.game.desktop.key_events.append({ 'type': pinproc.EventTypeSwitchOpenDebounced, 'value': switch_number }) # since we just got a message from a client, let's set up a connection to it if not self.do_we_have_a_client: if not self.clientIP: # if a client IP wasn't specified, use the one that just communicated with us now self.clientIP = client_address[0] self.clientTuple = (self.clientIP, self.clientPort) # print(self.clientTuple) # print("OSC attempting connection back to client") self.OSC_client = OSC.OSCClient() self.OSC_client.connect(self.clientTuple) self.do_we_have_a_client = True else: # print("We do have a client...") pass if (self.do_we_have_a_client): # print("OSC sending back back to client") OSC_message = OSC.OSCMessage() OSC_message.setAddress(addr) OSC_message.append("OK") self.OSC_client.send(OSC_message)
def __init__(self, machine_type): super(BasicGame, self).__init__(machine_type) self.aux_port = auxport.AuxPort(self) if self.machine_type == pinproc.MachineTypeWPCAlphanumeric: self.alpha_display = alphanumeric.AlphanumericDisplay(self.aux_port) else: self.dmd = DisplayController(self, width=128, height=32, message_font=font_named('Font07x5.dmd')) self.score_display = ScoreDisplay(self, 0) self.desktop = Desktop() if self.dmd: self.dmd.frame_handlers.append(self.set_last_frame) key_map_config = config.value_for_key_path(keypath='keyboard_switch_map', default={}) for k, v in key_map_config.items(): self.desktop.add_key_map(ord(str(k)), pinproc.decode(machine_type, v))
def PROC_OSC_message_handler(self, addr, tags, data, client_address): """ receives OSC messages and acts on them by setting switches.""" #print("GOING THROUGH DEFAULT HANDLER %s " % addr) # print("recvd OSC message " + str(addr) +" tags:"+ str(tags) +" data:"+ str(data)) # need to add supprt for "sync" instruction which we'll call when switching tabs in touchOSC #strip out the switch name switchname = addr.split("/")[-1] # This is the OSC address, not the IP address. Strip out the characters after the final "/" if switchname in self.game.switches: switch_number = self.game.switches[switchname].number #print("switch_number is local -> %d" % switch_number) else: switch_number = pinproc.decode(self.game.machine_type, switchname) #print("switch_number is lookedup -> %d" % switch_number) if(self.game.switches[switchname].type == 'NC'): # use desktop.key_events here, but I guess this is ok? if data[0] == 1.0: # normally closed, so this means open the switch self.game.desktop.key_events.append({'type': pinproc.EventTypeSwitchOpenDebounced, 'value': switch_number}) elif data[0] == 0.0: # close the switch self.game.desktop.key_events.append({'type': pinproc.EventTypeSwitchClosedDebounced, 'value': switch_number}) else: # use desktop.key_events here, but I guess this is ok? if data[0] == 1.0: # close the switch self.game.desktop.key_events.append({'type': pinproc.EventTypeSwitchClosedDebounced, 'value': switch_number}) elif data[0] == 0.0: # open the switch self.game.desktop.key_events.append({'type': pinproc.EventTypeSwitchOpenDebounced, 'value': switch_number}) # since we just got a message from a client, let's set up a connection to it if not self.do_we_have_a_client: if not self.clientIP: # if a client IP wasn't specified, use the one that just communicated with us now self.clientIP = client_address[0] self.clientTuple = (self.clientIP, self.clientPort) # print(self.clientTuple) # print("OSC attempting connection back to client") self.OSC_client = OSC.OSCClient() self.OSC_client.connect(self.clientTuple) self.do_we_have_a_client = True else: # print("We do have a client...") pass if(self.do_we_have_a_client): # print("OSC sending back back to client") OSC_message = OSC.OSCMessage() OSC_message.setAddress(addr) OSC_message.append("OK") self.OSC_client.send(OSC_message)
def getCoilStates(self): """ Gets the current state of the coils. """ pycoils = self.game.proc.drivers vpcoils = [False]*64 for i in range(0,len(vpcoils)): if i<=28: vpcoils[i] = pycoils[i+39].curr_state elif i<33: vpcoils[i] = False # Unused? # Use the machine's Hold coils for the VP flippers # since they stay on until the button is released elif i == 34: vpcoils[i] = pycoils[pinproc.decode(self.game.machine_type, "FURH")].curr_state elif i == 36: vpcoils[i] = pycoils[pinproc.decode(self.game.machine_type, "FULH")].curr_state elif i<44: if self.game.machine_type == pinproc.MachineTypeWPC95: vpcoils[i] = pycoils[i+31].curr_state else: vpcoils[i] = pycoils[i+107].curr_state elif i == 46: vpcoils[i] = pycoils[pinproc.decode(self.game.machine_type, "FLRH")].curr_state elif i == 48: vpcoils[i] = pycoils[pinproc.decode(self.game.machine_type, "FLLH")].curr_state else: vpcoils[i] = pycoils[i+108].curr_state return vpcoils
def load_config(self, path): super(BasicGame,self).load_config(path) # Setup the key mappings from the config.yaml. # We used to do this in __init__, but at that time the # configuration isn't loaded so we can't peek into self.switches. key_map_config = config.value_for_key_path(keypath='keyboard_switch_map', default={}) if self.desktop: for k, v in key_map_config.items(): switch_name = str(v) if self.switches.has_key(switch_name): switch_number = self.switches[switch_name].number else: switch_number = pinproc.decode(self.machine_type, switch_name) self.desktop.add_key_map(ord(str(k)), switch_number)
def load_trigger(self, button, value): code = value.get('number') value = pinproc.decode("wpc", code) opto = p.switches[code].type == "NC" if button['bg'] == 'red': button['activebackground'] = 'green' button['bg'] = 'green' event = (pinproc.EventTypeSwitchOpenDebounced if not opto else pinproc.EventTypeSwitchClosedDebounced) self.desktop.trigger({ "type": event, "value": pinproc.decode('wpc', code) }) else: button['activebackground'] = 'red' button['bg'] = 'red' event = (pinproc.EventTypeSwitchClosedDebounced if not opto else pinproc.EventTypeSwitchOpenDebounced) self.desktop.trigger({ "type": event, "value": pinproc.decode('wpc', code) })
def set_initial_switches(self): """sets up the initial switches that should be closed, then marks the client to sync Should I add some logic here to only do this with fakepinproc? """ if ('pinproc_class' in procgame.config.values and procgame.config.values['pinproc_class'] == 'procgame.fakepinproc.FakePinPROC'): for switchname in self.closed_switches: # run through the list of closed_switches passed to the mode as args if switchname in self.game.switches: # convert the names to switch numbers switch_number = self.game.switches[switchname].number else: switch_number = pinproc.decode(self.game.machine_type, switchname) self.game.desktop.key_events.append({ 'type': pinproc.EventTypeSwitchClosedDebounced, 'value': switch_number }) # add these switch close events to the queue self.client_needs_sync = True # Now that this is done we set the flag to sync the client
def load_config(self, path): super(BasicGame,self).load_config(path) # Setup the key mappings from the config.yaml. # We used to do this in __init__, but at that time the # configuration isn't loaded so we can't peek into self.switches. key_map_config = config.value_for_key_path(keypath='keyboard_switch_map', default={}) if self.desktop: for k, v in key_map_config.items(): switch_name = str(v) if self.switches.has_key(switch_name): switch_number = self.switches[switch_name].number else: switch_number = pinproc.decode(self.machine_type, switch_name) if(type(k)!=int): # letter keys are added as letters (obv) self.desktop.add_key_map(ord(str(k)), switch_number) elif(k<10): # 0-9 as keys self.desktop.add_key_map(ord(str(k)), switch_number) else: # numbers used as bindings for specials -- examples below self.desktop.add_key_map(k, switch_number)
def set_initial_closed_switches(self): """If FakePinProc is being used, sets up the initial switches that should be closed, then marks the client to sync """ if ('pinproc_class' in procgame.config.values and procgame.config.values['pinproc_class'] == 'procgame.fakepinproc.FakePinPROC'): for switchname in self.closed_switches: # run through the list of closed_switches passed to the mode as args if switchname in self.game.switches: # convert the names to switch numbers switch_number = self.game.switches[switchname].number else: switch_number = pinproc.decode(self.game.machine_type, switchname) self.game.desktop.key_events.append({ 'type': pinproc.EventTypeSwitchClosedDebounced, # add these switch close events to the queue 'value': switch_number}) self.client_needs_sync = True # Now that this is done we set the
def load_config(self, path): super(BasicGame, self).load_config(path) # Setup the key mappings from the config.yaml. # We used to do this in __init__, but at that time the # configuration isn't loaded so we can't peek into self.switches. key_map_config = config.value_for_key_path( keypath='keyboard_switch_map', default={}) if self.desktop: for k, v in key_map_config.items(): switch_name = str(v) if self.switches.has_key(switch_name): switch_number = self.switches[switch_name].number else: switch_number = pinproc.decode(self.machine_type, switch_name) if (type(k) != int): # letter keys are added as letters (obv) self.desktop.add_key_map(ord(str(k)), switch_number) elif (k < 10): # 0-9 as keys self.desktop.add_key_map(ord(str(k)), switch_number) else: # numbers used as bindings for specials -- examples below self.desktop.add_key_map(k, switch_number)
def VPSwitchFlipperToPRSwitch(self, number): """ Helper method to find the P-ROC number of a flipper switch. """ vpNumber = number - 110 switch = 'SF' + str(vpNumber) return pinproc.decode(self.game.machine_type, switch)
def VPSwitchDedToPRSwitch(self, number): """ Helper method to find the P-ROC number of a direct switch. """ vpNumber = number switch = 'SD' + str(vpNumber) return pinproc.decode(self.game.machine_type, switch)
def load_config(self, filename): """Reads the YAML machine configuration file into memory. Configures the switches, lamps, and coils members. Enables notifyHost for the open and closed debounced states on each configured switch. """ self.logger.info('Loading machine configuration from "%s"...', filename) self.config = config_named(filename) if not self.config: raise ValueError, 'load_config(filename="%s") could not be found. Did you set config_path?' % (filename) pairs = [('PRCoils', self.coils, Driver), ('PRLamps', self.lamps, Driver), ('PRSwitches', self.switches, Switch)] new_virtual_drivers = [] polarity = self.machine_type == pinproc.MachineTypeSternWhitestar or self.machine_type == pinproc.MachineTypeSternSAM for section, collection, klass in pairs: sect_dict = self.config[section] for name in sect_dict: item_dict = sect_dict[name] number = pinproc.decode(self.machine_type, str(item_dict['number'])) item = None if 'bus' in item_dict and item_dict['bus'] == 'AuxPort': item = VirtualDriver(self, name, number, polarity) new_virtual_drivers += [number] else: item = klass(self, name, number) if 'type' in item_dict: item.type = item_dict['type'] collection.add(name, item) # In the P-ROC, VirtualDrivers will conflict with regular drivers on the same group. # So if any VirtualDrivers were added, the regular drivers in that group must be changed # to VirtualDrivers as well. for virtual_driver in new_virtual_drivers: base_group_number = virtual_driver/8 for collection in [self.coils, self.lamps]: items_to_remove = [] for item in collection: if item.number/8 == base_group_number: items_to_remove += [{name:item.name,number:item.number}] for item in items_to_remove: print "Removing %s from %s" % (item[name],str(collection)) collection.remove(item[name], item[number]) print "Adding %s to VirtualDrivers" % (item[name]) collection.add(item[name], VirtualDriver(self, item[name], item[number], polarity)) if 'PRBallSave' in self.config: sect_dict = self.config['PRBallSave'] self.ballsearch_coils = sect_dict['pulseCoils'] self.ballsearch_stopSwitches = sect_dict['stopSwitches'] self.ballsearch_resetSwitches = sect_dict['resetSwitches'] # We want to receive events for all of the defined switches: self.logger.info("Programming switch rules...") for switch in self.switches: self.proc.switch_update_rule(switch.number, 'closed_debounced', {'notifyHost':True, 'reloadActive':False}, [], False) self.proc.switch_update_rule(switch.number, 'open_debounced', {'notifyHost':True, 'reloadActive':False}, [], False) # Configure the initial switch states: states = self.proc.switch_get_states() for sw in self.switches: sw.set_state(states[sw.number] == 1) sect_dict = self.config['PRGame'] self.num_balls_total = sect_dict['numBalls']
def enable_flippers(self, enable): #return True """Enables or disables the flippers AND bumpers.""" if self.machine_type == pinproc.MachineTypeWPC or self.machine_type == pinproc.MachineTypeWPC95 or self.machine_type == pinproc.MachineTypeWPCAlphanumeric: for flipper in self.config['PRFlippers']: self.logger.info("Programming flipper %s", flipper) main_coil = self.coils[flipper+'Main'] hold_coil = self.coils[flipper+'Hold'] switch_num = self.switches[flipper].number # Chck to see if the flipper should be activated now. #if enable: # if self.switches[flipper].is_active(): # self.coils[flipper+'Main'].pulse(34) # self.coils[flipper+'Hold'].pulse(0) # else: self.coils[flipper+'Hold'].disable() #else: self.coils[flipper+'Hold'].disable() drivers = [] if enable: drivers += [pinproc.driver_state_pulse(main_coil.state(), 34)] drivers += [pinproc.driver_state_pulse(hold_coil.state(), 0)] self.proc.switch_update_rule(switch_num, 'closed_nondebounced', {'notifyHost':False, 'reloadActive':False}, drivers, len(drivers) > 0) drivers = [] if enable: drivers += [pinproc.driver_state_disable(main_coil.state())] drivers += [pinproc.driver_state_disable(hold_coil.state())] self.proc.switch_update_rule(switch_num, 'open_nondebounced', {'notifyHost':False, 'reloadActive':False}, drivers, len(drivers) > 0) if not enable: main_coil.disable() hold_coil.disable() # Enable the flipper relay on wpcAlphanumeric machines if self.machine_type == pinproc.MachineTypeWPCAlphanumeric: # 79 corresponds to the circuit on the power/driver board. It will be 79 for all WPCAlphanumeric machines. flipperRelayPRNumber = 79 if enable: self.coils[79].pulse(0) else: self.coils[79].disable() elif self.machine_type == pinproc.MachineTypeSternWhitestar or self.machine_type == pinproc.MachineTypeSternSAM: for flipper in self.config['PRFlippers']: print(" programming flipper %s" % (flipper)) main_coil = self.coils[flipper+'Main'] switch_num = pinproc.decode(self.machine_type, str(self.switches[flipper].number)) # Check to see if the flipper should be activated now. #if enable: # if self.switches[flipper].is_active(): # self.coils[flipper+'Main'].patter(3, 22, 34) # else: self.coils[flipper+'Main'].disable() #else: self.coils[flipper+'Main'].disable() drivers = [] if enable: drivers += [pinproc.driver_state_patter(main_coil.state(), 2, 18, 34)] self.proc.switch_update_rule(switch_num, 'closed_nondebounced', {'notifyHost':False, 'reloadActive':False}, drivers, len(drivers) > 0) drivers = [] if enable: drivers += [pinproc.driver_state_disable(main_coil.state())] self.proc.switch_update_rule(switch_num, 'open_nondebounced', {'notifyHost':False, 'reloadActive':False}, drivers, len(drivers) > 0) if not enable: main_coil.disable() for bumper in self.config['PRBumpers']: switch_num = self.switches[bumper].number coil = self.coils[bumper] drivers = [] if enable: drivers += [pinproc.driver_state_pulse(coil.state(), 20)] self.proc.switch_update_rule(switch_num, 'closed_nondebounced', {'notifyHost':False, 'reloadActive':True}, drivers, False)
def configure_switch(self, config): """Configures a P3-ROC switch. Args: config: Dictionary of settings for the switch. In the case of the P3-ROC, it uses the following: number : The number (or number string) for the switch as specified in the machine configuration file. debounce : Boolean which specifies whether the P3-ROC should debounce this switch first before sending open and close notifications to the host computer. Returns: switch : A reference to the switch object that was just created. proc_num : Integer of the actual hardware switch number the P3-ROC uses to refer to this switch. Typically your machine configuration files would specify a switch number like `SD12` or `7/5`. This `proc_num` is an int between 0 and 255. state : An integer of the current hardware state of the switch, used to set the initial state state in the machine. A value of 0 means the switch is open, and 1 means it's closed. Note this state is the physical state of the switch, so if you configure the switch to be normally-closed (i.e. "inverted" then your code will have to invert it too.) MPF handles this automatically if the switch type is 'NC'. """ if self.machine_type == pinproc.MachineTypePDB: proc_num = self.pdbconfig.get_proc_number("switch", str(config["number"])) if proc_num == -1: self.log.error("Switch %s cannot be controlled by the P3-ROC. " "Ignoring.", str(config["number"])) return else: proc_num = pinproc.decode(self.machine_type, str(config["number"])) switch = PROCSwitch(proc_num) # The P3-ROC needs to be configured to notify the host computers of # switch events. (That notification can be for open or closed, # debounced or nondebounced.) self.log.debug( "Configuring switch's host notification settings. P3-ROC" "number: %s, debounce: %s", proc_num, config["debounce"], ) if config["debounce"] is False or proc_num >= pinproc.SwitchNeverDebounceFirst: self.proc.switch_update_rule( proc_num, "closed_nondebounced", {"notifyHost": True, "reloadActive": False}, [], False ) self.proc.switch_update_rule( proc_num, "open_nondebounced", {"notifyHost": True, "reloadActive": False}, [], False ) else: self.proc.switch_update_rule( proc_num, "closed_debounced", {"notifyHost": True, "reloadActive": False}, [], False ) self.proc.switch_update_rule( proc_num, "open_debounced", {"notifyHost": True, "reloadActive": False}, [], False ) return switch, proc_num
def pulse(n, t=20): """docstring for pulse""" pr.driver_pulse(pinproc.decode(machine_type, str(n)), t)
def process_config(self): """Called by :meth:`load_config` and :meth:`load_config_stream` to process the values in :attr:`config`.""" pairs = [('PRCoils', self.coils, Driver), ('PRLamps', self.lamps, Driver), ('PRSwitches', self.switches, Switch), ('PRLEDs', self.leds, LED) ] new_virtual_drivers = [] polarity = self.machine_type == pinproc.MachineTypeSternWhitestar or self.machine_type == pinproc.MachineTypeSternSAM or self.machine_type == pinproc.MachineTypePDB # Because PDBs can be configured in many different ways, we need to traverse # the YAML settings to see how many PDBs are being used. Then we can configure # the P-ROC appropriately to use those PDBs. Only then can we relate the YAML # coil/lamp #'s to P-ROC numbers for the collections. if self.machine_type == pinproc.MachineTypePDB: pdb_config = PDBConfig(self.proc, self.config) for section, collection, klass in pairs: if section in self.config: sect_dict = self.config[section] for name in sect_dict: item_dict = sect_dict[name] # Find the P-ROC number for each item in the YAML sections. For PDB's # the number is based on the PDB configuration determined above. For # other machine types, pinproc's decode() method can provide the number. if self.machine_type == pinproc.MachineTypePDB: number = pdb_config.get_proc_number(section, str(item_dict['number'])) if number == -1: self.logger.error('%s Item: %s cannot be controlled by the P-ROC. Ignoring...', section, name) continue else: number = pinproc.decode(self.machine_type, str(item_dict['number'])) item = None if ('bus' in item_dict and item_dict['bus'] == 'AuxPort') or number >= pinproc.DriverCount: item = VirtualDriver(self, name, number, polarity) new_virtual_drivers += [number] else: yaml_number = str(item_dict['number']) if klass==LED: number = yaml_number item = klass(self, name, number) item.yaml_number = yaml_number if 'label' in item_dict: item.label = item_dict['label'] if 'type' in item_dict: item.type = item_dict['type'] if 'tags' in item_dict: tags = item_dict['tags'] if type(tags) == str: item.tags = tags.split(',') elif type(tags) == list: item.tags = tags else: self.logger.warning('Configuration item named "%s" has unexpected tags type %s. Should be list or comma-delimited string.' % (name, type(tags))) if klass==Switch: if (('debounce' in item_dict and item_dict['debounce'] == False) or number >= pinproc.SwitchNeverDebounceFirst): item.debounce = False if klass==Driver: if ('pulseTime' in item_dict): item.default_pulse_time = item_dict['pulseTime'] if ('polarity' in item_dict): item.reconfigure(item_dict['polarity']) if klass==LED: if ('polarity' in item_dict): item.invert = not item_dict['polarity'] collection.add(name, item) # In the P-ROC, VirtualDrivers will conflict with regular drivers on the same group. # So if any VirtualDrivers were added, the regular drivers in that group must be changed # to VirtualDrivers as well. for virtual_driver in new_virtual_drivers: base_group_number = virtual_driver/8 for collection in [self.coils, self.lamps]: items_to_remove = [] for item in collection: if item.number/8 == base_group_number: items_to_remove += [{name:item.name,number:item.number}] for item in items_to_remove: self.logger.info( "Removing %s from %s" , item[name],str(collection)) collection.remove(item[name], item[number]) self.logger.info("Adding %s to VirtualDrivers",item[name]) collection.add(item[name], VirtualDriver(self, item[name], item[number], polarity)) if 'PRBallSave' in self.config: sect_dict = self.config['PRBallSave'] self.ballsearch_coils = sect_dict['pulseCoils'] self.ballsearch_stopSwitches = sect_dict['stopSwitches'] self.ballsearch_resetSwitches = sect_dict['resetSwitches'] # We want to receive events for all of the defined switches: self.logger.info("Programming switch rules...") for switch in self.switches: if switch.debounce: self.proc.switch_update_rule(switch.number, 'closed_debounced', {'notifyHost':True, 'reloadActive':False}, [], False) self.proc.switch_update_rule(switch.number, 'open_debounced', {'notifyHost':True, 'reloadActive':False}, [], False) else: self.proc.switch_update_rule(switch.number, 'closed_nondebounced', {'notifyHost':True, 'reloadActive':False}, [], False) self.proc.switch_update_rule(switch.number, 'open_nondebounced', {'notifyHost':True, 'reloadActive':False}, [], False) # Configure the initial switch states: states = self.proc.switch_get_states() for sw in self.switches: sw.set_state(states[sw.number] == 1) sect_dict = self.config['PRGame'] self.num_balls_total = sect_dict['numBalls'] self.logger.info("LEDS...") for led in self.leds: self.logger.info(" LED name=%s; number=%s" % (led.name,led.yaml_number))
def pulse(n, t = 20): """docstring for pulse""" pr.driver_pulse(pinproc.decode(machine_type, str(n)), t)