Пример #1
0
/**
 * Process a switch that has transitioned states.  All debouncing
 * is fully completed prior to this call.
 *
 * The transition is first latched, so that polling the switch level
 * will return the new state.  At the same time, IRQ-level scanning
 * is restarted, so that further transitions can be detected.
 *
 * Second, if the transition requires scheduling, a task is started
 * to handle it.  Eligibility depends on whether or not the switch
 * is declared as an edge switch (meaning it is scheduled on both
 * types of transitions) and whether or not it is an opto (i.e.
 * do we schedule open-to-closed or closed-to-open?)
 *
 * The switch is also known not to be in the debounce queue prior to this
 * function being called.
 */
void switch_transitioned (const U8 sw)
{
	/* Latch the transition.  sw_logical is still an open/closed level.
	 * By clearing the stable/unstable bits, IRQ will begin scanning
	 * for new transitions at this point. */
	disable_irq ();
	bit_toggle (sw_logical, sw);
	bit_off (sw_stable, sw);
	bit_off (sw_unstable, sw);
	enable_irq ();

	/* See if the transition requires scheduling.  It does if the
	   switch is declared 'edge' (it schedules when becoming active
		or inactive), otherwise only becoming active.  Because most
		switches are not edge, check for the active state first. */
	if (switch_poll_logical (sw) || bit_test (mach_edge_switches, sw))
	{
#ifdef CONFIG_BPT
		/* One extra condition : do not schedule any switches when the
		system is paused */
		if (db_paused != 0)
			return;
#endif

		/* Start a task to process the switch event.
		This task may sleep if necessary, but it should be as fast as possible
		and push long-lived operations into separate background tasks.
		It is possible for more than one instance of a task to exist for the same
		switch, if valid debounced transitions occur quickly. */
		task_pid_t tp = task_create_gid (GID_SW_HANDLER, switch_sched_task);
		task_set_arg (tp, sw);
	}
}
Пример #2
0
/**
 * This task runs during a switch stress test.  During a game,
 * it randomly invokes switch handlers as if the switches had actually
 * been activated by the pinball.
 */
void switch_stress_task (void)
{
	U8 sw;
	const switch_info_t *swinfo;
	task_pid_t tp;

	/* Delay a few seconds before starting the simulation.  This allows
	time for the Start Button to be used to add players, instead of simulating
	endball. */
	task_sleep_sec (3);

	task_create_peer (switch_stress_flipper_task);
	for (;;)
	{
		task_sleep (TIME_100MS);
		if (in_test)
			continue;

		/* Choose a switch at random.  Skip certain well-known switches that are
		 * never to be activated. */
		sw = random_scaled (NUM_SWITCHES);
#ifdef SW_ALWAYS_CLOSED
		if (sw == SW_ALWAYS_CLOSED)
			continue;
#endif
#ifdef MACHINE_OUTHOLE_SWITCH
		if (sw == MACHINE_OUTHOLE_SWITCH)
			continue;
#endif

		/* Lookup the switch properties.  Skip switches which aren't normally
		 * activated on the playfield.  For switches in a ball container,
		 * simulate device entry there, otherwise simulate a switch event. */
		swinfo = switch_lookup (sw);

		if (SW_HAS_DEVICE (swinfo))
		{
			device_t *dev = device_entry (SW_GET_DEVICE (swinfo));
			if (trough_dev_p (dev))
			{
				/* Don't always trigger the trough device.  The probability
				of a ball drain is treated as proportional to the number of
				balls in play.  So in big multiballs, we allow this to happen
				more frequently.
					We need to do this occasionally so that multiball modes
				will eventually end, else nothing else gets tested. */
				if (random () < CONFIG_STRESS_DRAIN_PROB * live_balls)
					switch_stress_drain ();
			}
			else if (dev->max_count < dev->size)
			{
				/* Don't throw an enter event if the device thinks
				it is full: it has "locked" as many balls as it
				can hold.  The device code will throw a fatal if
				it sees this, which should never happen with real
				balls. */
				dbprintf ("Sim. enter dev %d\n", dev->devno);
				device_call_op (dev, enter);
				task_sleep (TIME_1S);
			}
		}
		else if (swinfo->flags & SW_PLAYFIELD)
		{
			/* Simulate the switch */
			tp = task_create_gid (GID_SW_HANDLER, switch_sched_task);
			task_set_arg (tp, sw);
		}
	}
}
Пример #3
0
task_pid_t timer_start (task_gid_t gid, U16 ticks, task_function_t fn)
{
	task_pid_t tp = task_create_gid (gid, fn);
	task_set_arg (tp, ticks);
	return (tp);
}