Skip to content

Commit b8a717a

Browse files
authored
Merge pull request #1769 from avanwinkle/pt-sov-dev
FAST Retro Platform: System11 Support
2 parents 7c1d679 + 790b5b0 commit b8a717a

File tree

8 files changed

+116
-67
lines changed

8 files changed

+116
-67
lines changed

mpf/devices/driver.py

+2
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,8 @@ def timed_enable(self, timed_enable_ms: int = None, hold_power: float = None, pu
382382
# Let the PSU wait for both the pulse _and_ the timed enable
383383
wait_ms = self._notify_psu_and_get_wait_ms(pulse_duration + hold_duration, max_wait_ms)
384384

385+
self.info_log("Pulsing Driver for %sms (%s pulse_power) with timed enable for %sms (%s hold_power)",
386+
pulse_duration, pulse_power, hold_duration, hold_power)
385387
# TODO: Detect a NotImplementedError and simulate a timed_enable
386388
# with a software timer and enable+disable
387389
self.hw_driver.timed_enable(PulseSettings(pulse_power, pulse_duration),

mpf/platforms/fast/communicators/base.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def __init__(self, platform, processor, config):
6060
else:
6161
self.watchdog_cmd = None
6262

63-
self.configure_logging(logger=f'[{self.remote_processor}]', console_level=config['debug'],
63+
self.configure_logging(logger=f'FAST [{self.remote_processor}]', console_level=config['debug'],
6464
file_level=config['debug'], url_base='https://fastpinball.com/mpf/error')
6565
# TODO change these to not be hardcoded
6666
# TODO do something with the URL endpoint
@@ -349,10 +349,14 @@ def _dispatch_incoming_msg(self, msg):
349349
self.no_response_waiting.set()
350350

351351
# if the msg_header matches the first chars of the self.pause_sending_until, unpause sending
352+
# Note that the msg_header includes the colon (e.g. "DL:", "SA:") and therefore
353+
# pause_sending_until must also include the colon.
352354
if self.pause_sending_flag.is_set() and self.pause_sending_until.startswith(msg_header):
353355
self._resume_sending()
354356

355357
def pause_sending(self, msg_header):
358+
if __debug__:
359+
assert len(msg_header) >= 3, f"Confirmation headers should be at least three characters, received '{msg_header}'"
356360
self.pause_sending_until = msg_header
357361
self.pause_sending_flag.set()
358362

@@ -409,7 +413,8 @@ async def _socket_writer(self):
409413
if self.pause_sending_flag.is_set():
410414
await self.pause_sending_flag.wait()
411415

412-
except:
416+
except Exception as e:
417+
self.log.error(e)
413418
return # TODO better way to catch shutting down?
414419

415420
def write_to_port(self, msg, log_msg=None):

mpf/platforms/fast/communicators/net_neuron.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ async def reset_drivers(self):
116116

117117
# self.drivers contains a list of all drivers, not just ones defined in the config
118118
for driver in self.drivers:
119-
await self.send_and_wait_for_response_processed(f'{self.DRIVER_CMD}:{Util.int_to_hex_string(driver.number)}', self.DRIVER_CMD)
119+
await self.send_and_wait_for_response_processed(f'{self.DRIVER_CMD}:{Util.int_to_hex_string(driver.number)}', f"{self.DRIVER_CMD}:")
120120

121121
self.platform.drivers_initialized = True
122122

mpf/platforms/fast/fast.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,10 @@ def __init__(self, machine):
7979
else:
8080
self.raise_config_error(f'Unknown machine_type "{self.machine_type}" configured fast.', 6)
8181

82+
# Even though System11 uses ticks, that's handled on the Overlay and not needed here.
83+
self.features['tickless'] = True
8284
# Most FAST platforms don't use ticks, but System11 does
83-
self.features['tickless'] = self.machine_type != 'sys11'
85+
#self.features['tickless'] = self.machine_type != 'sys11'
8486
self.features['max_pulse'] = 25500
8587

8688
self.serial_connections = dict()

mpf/platforms/fast/fast_defines.py

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
(11914, 4156): ('aud', 'FAST Audio Interface'),
1313
(11914, 4157): ('exp', 'FAST Expansion Board'),
1414
(11914, 4158): ('dsp', 'FAST Display Controller'),
15+
(5824, 1163): ('net', 'FAST Retro Controller'), # Teensyduino
1516
(1027, 24593): ('net', 'FAST Nano Controller'), # FTDI Quad RS232-HS
1617
}
1718

mpf/platforms/fast/fast_driver.py

+30-7
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class FASTDriver:
3131
"""Base class for drivers connected to a FAST Controller."""
3232

3333
__slots__ = ["log", "communicator", "number", "hw_number", "autofire_config", "baseline_driver_config",
34-
"current_driver_config", "mode_param_mapping", "platform_settings"]
34+
"config", "current_driver_config", "mode_param_mapping", "platform_settings"]
3535

3636
def __init__(self, communicator: FastSerialCommunicator, hw_number: int) -> None:
3737
"""Initialize the driver object.
@@ -42,6 +42,7 @@ def __init__(self, communicator: FastSerialCommunicator, hw_number: int) -> None
4242
self.communicator = communicator
4343
self.number = hw_number # must be int to work with the rest of MPF
4444
self.hw_number = Util.int_to_hex_string(hw_number) # hex version the FAST hw actually uses
45+
self.config = None
4546
self.autofire_config = None
4647
self.platform_settings = dict()
4748

@@ -56,6 +57,7 @@ def __init__(self, communicator: FastSerialCommunicator, hw_number: int) -> None
5657
'12': ['pwm1_ms', 'pwm1_power', 'pwm2_ms', 'pwm2_power', 'kick_ms'],
5758
'18': ['pwm1_ms', 'pwm1_power', 'pwm2_power', 'recycle_ms', None],
5859
'20': ['off_switch', 'pwm1_ms', 'pwm1_power', 'pwm2_power', 'rest_ms'],
60+
'25': ['relay_on_report_ms', 'relay_off_report_ms'],
5961
'30': ['delay_ms_x10', 'pwm1_ms', 'pwm2_ms', 'pwm2_power', 'recycle_ms'],
6062
'70': ['pwm1_ms', 'pwm1_power', 'pwm2_ms_x100', 'pwm2_power', 'recycle_ms'],
6163
'75': ['off_switch', 'pwm1_ms', 'pwm2_ms_x100', 'pwm2_power', 'recycle_ms'],
@@ -73,7 +75,7 @@ def set_initial_config(self, mpf_config: DriverConfig, platform_settings):
7375
7476
This will not be called for drivers that are not in the MPF config.
7577
"""
76-
78+
self.config = mpf_config
7779
self.platform_settings = platform_settings
7880
self.current_driver_config = self.convert_mpf_config_to_fast(mpf_config, platform_settings)
7981
self.baseline_driver_config = copy(self.current_driver_config)
@@ -144,8 +146,8 @@ def clear_bit(self, hex_string, bit):
144146
return Util.int_to_hex_string(num)
145147

146148
def send_config_to_driver(self, one_shot: bool = False, wait_to_confirm: bool = False):
147-
self.log.debug("Sending config to driver %s. one_shot: %s. wait_to_confirm: %s",
148-
self.number, one_shot, wait_to_confirm)
149+
self.log.debug("Sending config to driver %s (0x%s). one_shot: %s. wait_to_confirm: %s",
150+
self.number, self.hw_number, one_shot, wait_to_confirm)
149151

150152
if one_shot:
151153
trigger = self.set_bit(self.current_driver_config.trigger, 3)
@@ -157,7 +159,7 @@ def send_config_to_driver(self, one_shot: bool = False, wait_to_confirm: bool =
157159
f'{self.current_driver_config.param2},{self.current_driver_config.param3},{self.current_driver_config.param4},'
158160
f'{self.current_driver_config.param5}')
159161
if wait_to_confirm:
160-
self.communicator.send_with_confirmation(msg, f'{self.communicator.DRIVER_CMD}')
162+
self.communicator.send_with_confirmation(msg, f'{self.communicator.DRIVER_CMD}:')
161163
else:
162164
self.communicator.send_and_forget(msg)
163165

@@ -354,17 +356,38 @@ def clear_autofire(self):
354356
self.autofire_config = None
355357
self.communicator.send_and_forget(f'{self.communicator.TRIGGER_CMD}:{self.hw_number},02')
356358

359+
def set_relay(self, relay_switch, debounce_closed_ms, debounce_open_ms):
360+
"""Set an AC Relay rule with virtual switch."""
361+
362+
self.log.debug("Setting A/C Relay for driver %s (0x%s) and switch %s (0x%s)",
363+
self.number, self.hw_number, relay_switch.number, relay_switch.hw_number)
364+
self.current_driver_config = FastDriverConfig(number=self.hw_number, trigger='81',
365+
switch_id=relay_switch.hw_number,
366+
mode='25',
367+
param1=Util.int_to_hex_string(debounce_closed_ms),
368+
param2=Util.int_to_hex_string(debounce_open_ms),
369+
param3='00',
370+
param4='00',
371+
param5='00')
372+
self.send_config_to_driver(wait_to_confirm=True)
373+
357374
def enable(self, pulse_settings: PulseSettings, hold_settings: HoldSettings):
358375
"""Enable (turn on) this driver."""
359376

360-
self.log.debug("Enabling (turning on) driver %s with pulse_settings: %s and hold_settings: %s.",
361-
self.number, pulse_settings, hold_settings)
377+
self.log.debug("Enabling (turning on) driver %s (0x%s) mode %s with pulse_settings: %s and hold_settings: %s.",
378+
self.number, self.hw_number, self.current_driver_config.mode, pulse_settings, hold_settings)
362379

363380
self._check_and_clear_delay()
364381

365382
reconfigured = False
366383
mode = self.current_driver_config.mode
367384

385+
# AC Relays have special behavior
386+
if mode == '25':
387+
self.log.debug(" - A/C Relay activating!")
388+
self.communicator.send_and_forget(f'{self.communicator.TRIGGER_CMD}:{self.hw_number},03')
389+
return
390+
368391
pwm1_ms = Util.int_to_hex_string(pulse_settings.duration)
369392
pwm1_power = Util.float_to_pwm8_hex_string(pulse_settings.power)
370393
pwm2_power = Util.float_to_pwm8_hex_string(hold_settings.power)

mpf/platforms/fast/fast_port_detector.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,14 @@ async def _connect_task(self, port, baud):
7070

7171
total_attempts = 5
7272
attempts = 0
73-
while True:
73+
while attempts < total_attempts:
7474
writer.write(b'ID:\r')
7575

7676
# Wait for a response with 1-second timeout
7777
try:
7878
data = await asyncio.wait_for(reader.read(100), timeout=1.0)
7979
except asyncio.TimeoutError:
80-
attempts += 1
81-
if attempts < total_attempts:
82-
continue # retry
83-
else:
84-
self.platform.debug_log("Unable to get ID: on port %s after %s retries.", port, total_attempts)
80+
pass
8581

8682
if data:
8783
data = data.decode('utf-8', errors='ignore')
@@ -91,6 +87,9 @@ async def _connect_task(self, port, baud):
9187
self._report_success(processor, port)
9288
writer.close()
9389
return
90+
attempts += 1
91+
self.platform.debug_log("Unable to get ID: on port %s after %s retries.", port, total_attempts)
92+
return
9493

9594
def _report_success(self, processor, port):
9695
self.results[processor] = port

0 commit comments

Comments
 (0)