Esempio n. 1
0
void racetrack_reset_track_state(void) {
	racetrack_encoder_mask = 0;
	racetrack_stall_ticks_remaining = LANE_STALL_DETECT_TICKS;

	racetrack_lanes[LANE_LEFT].state = LANE_STOP;
	racetrack_lanes[LANE_RIGHT].state = LANE_STOP;

	racetrack_lanes[LANE_LEFT].encoder_count = 0;
	racetrack_lanes[LANE_RIGHT].encoder_count = 0;

	racetrack_lanes[LANE_LEFT].desired_encoder_count = 0;
	racetrack_lanes[LANE_RIGHT].desired_encoder_count = 0;

	racetrack_lanes[LANE_LEFT].desired_position = 0;
	racetrack_lanes[LANE_RIGHT].desired_position = 0;

	// cause the speed tick tester to re-evaluate on the next tick.
	racetrack_lanes[LANE_LEFT].speed_ticks_remaining = 1;
	racetrack_lanes[LANE_RIGHT].speed_ticks_remaining = 1;

	if (switch_poll_logical (SW_LEFT_RACE_ENCODER)) {
		racetrack_encoder_mask |= RT_EM_PREVIOUS_STATE_LEFT;
	}
	if (switch_poll_logical (SW_RIGHT_RACE_ENCODER)) {
		racetrack_encoder_mask |= RT_EM_PREVIOUS_STATE_RIGHT;
	}
}
Esempio n. 2
0
CALLSET_ENTRY (autofire, ball_search)
{
    /* The shooter divertor/autofire are both kicked here
    since there is a dependency between the two.  The main
    ball search routine is told not to kick either one of them. */
    if (switch_poll_logical (SW_AUTOFIRE2) || switch_poll_logical (SW_AUTOFIRE1))
    {
        callset_invoke (clear_autofire);
    }
}
Esempio n. 3
0
static inline void racetrack_state_car_return_run(void) {

	if (switch_poll_logical (SW_LEFT_RACE_START) && switch_poll_logical (SW_RIGHT_RACE_START)) {
		racetrack_state = RACETRACK_READY;
		return;
	}

	sol_disable(SOL_RACE_DIRECTION);

	// TODO check lane 'stalled' bits, if either one gets set then disable the racetrack?
}
Esempio n. 4
0
/**
 * Activate the autolaunch mechanism.  A ball must already have
 * been served from the trough ; this just fires the launch
 * solenoid.
 */
static void launch_ball_task (void)
{
#ifdef HAVE_AUTO_SERVE
	if (!switch_poll_logical (MACHINE_SHOOTER_SWITCH))
		task_sleep (TIME_500MS);

	do {
		sol_request_async (MACHINE_LAUNCH_SOLENOID);
		task_sleep (LAUNCH_DELAY);
	} while (switch_poll_logical (MACHINE_SHOOTER_SWITCH));
#endif
	task_exit ();
}
Esempio n. 5
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);
	}
}
Esempio n. 6
0
void abort_monitor_task (void)
{
	U8 count = 3;
	while (count > 0)
	{
		task_sleep (TIME_66MS);
		if (!switch_poll_logical (SW_LEFT_BUTTON)
			|| !switch_poll_logical (SW_RIGHT_BUTTON))
		{
			task_exit ();
		}
		count--;
	}
	callset_invoke (flipper_abort);
	task_exit ();
}
Esempio n. 7
0
/* Return the number of balls currently present in the device */
U8 device_recount (device_t *dev)
{
	U8 i;
	U8 count = 0;

	/* Everytime a recount occurs, we remember the previous
	value that was counted.  By comparing these two, we can
	tell if something changed. */
	dev->previous_count = dev->actual_count;

	for (i=0; i < dev->size; i++)
	{
		switchnum_t sw = dev->props->sw[i];
		U8 level = switch_poll_logical (sw);
		if (level)
			count++;
	}

	/* Each device keeps a 'virtual count' of balls that it knows
	are in the device but which are not seen by any switches.
	The core system cannot determine what this count should be, but
	just includes it in the overall count.  See APIs for below for
	game code to update the virtual count. */
	count += dev->virtual_count;

	dev->actual_count = count;
	return (count);
}
Esempio n. 8
0
/** Task that is restarted anytime a flipper button is initially
 * pressed.  It polls the flipper switches continously to
 * see if it is being held down for the amount of time necessary
 * to start the status report.
 */
void status_report_monitor (void)
{
	/* A count of 40 equates to a 4s hold down period. */
	U8 count = 40;

	/* Wait until the player has kept the flipper button(s) down
	 * for an extended period of time.  Abort as soon as the
	 * flippers are released. */
	while (--count > 0)
	{
		if (!switch_poll_logical (SW_LEFT_BUTTON)
			&& !switch_poll_logical (SW_RIGHT_BUTTON))
			goto done;
		task_sleep (TIME_100MS);
	}

	/* OK, start the status report deff */
start:
	deff_start (DEFF_STATUS_REPORT);

	/* Wait until the flippers are released, or the status report
	 * deff terminates.  If the flippers are released, then
	 * exit the task.  If the status report finishes, go back to
	 * the beginning -- after another 5sec, it will get started
	 * again. */
	for (;;)
	{
		if (!switch_poll_logical (SW_LEFT_BUTTON)
			&& !switch_poll_logical (SW_RIGHT_BUTTON))
			break;

		if (deff_get_active () != DEFF_STATUS_REPORT)
		{
			task_sleep_sec (5);
			goto start;
		}

		task_sleep (TIME_100MS);
	}

	/* Stop the status report */
	deff_stop (DEFF_STATUS_REPORT);

done:
	task_exit ();
}
Esempio n. 9
0
CALLSET_ENTRY (outhole, ball_search)
{
	while (switch_poll_logical (SW_OUTHOLE))
	{
		sol_request (SOL_OUTHOLE);
		task_sleep_sec (1);
	}
}
Esempio n. 10
0
void pb_test_draw (void)
{
	dmd_alloc_low_clean ();
	font_render_string_center (&font_mono5, 64, 0, "POWERBALL TEST");

	if (pb_location == PB_MISSING)
		sprintf ("LOST");
	else if (pb_location & PB_IN_LOCK)
		sprintf ("LOCK");
	else if (pb_location & PB_IN_TROUGH)
		sprintf ("TROUGH");
	else if (pb_location & PB_IN_GUMBALL)
		sprintf ("GUMBALL");
	else if (pb_location & PB_IN_PLAY)
		sprintf ("P.F.");
	else if (pb_location & PB_MAYBE_IN_PLAY)
		sprintf ("NOT SURE");
	else
		sprintf ("ERROR");
	font_render_string_left (&font_mono5, 0, 6, sprintf_buffer);

	if (pb_location & (PB_IN_LOCK | PB_IN_TROUGH))
	{
		sprintf ("POS. %d", pb_depth);
		font_render_string_right (&font_mono5, 127, 6, sprintf_buffer);
	}

	sprintf ("TROUGH SW. %s",
		switch_poll_logical (SW_TROUGH_PROXIMITY) ? "CLOSED" : "OPEN");
	font_render_string_left (&font_mono5, 0, 12, sprintf_buffer);

	sprintf ("SLOT SW. %s",
		switch_poll_logical (SW_SLOT_PROXIMITY) ? "CLOSED" : "OPEN");
	font_render_string_left (&font_mono5, 0, 18, sprintf_buffer);

	switch (pb_test_command)
	{
		case KICK_TROUGH: sprintf ("REL. TROUGH"); break;
		case KICK_LOCK: sprintf ("REL. LOCK"); break;
		case RELEASE_GUMBALL: sprintf ("REL. GUMBALL"); break;
		case LOAD_GUMBALL: sprintf ("LOAD GUMBALL"); break;
	}
	font_render_string_left (&font_mono5, 0, 24, sprintf_buffer);

	dmd_show_low ();
}
Esempio n. 11
0
bool sssmb_can_divert_to_plunger (void)
{
	if (global_flag_test (GLOBAL_FLAG_SSSMB_RUNNING)
		&& sssmb_ramps_to_divert == 0
		&& !switch_poll_logical (SW_SHOOTER))
		return TRUE;
	else
		return FALSE;
}
Esempio n. 12
0
CALLSET_ENTRY (trivial, sw_plunger)
{
	if (!switch_poll_logical (SW_PLUNGER))
	{
		sample_start (SND_BURNOUT_01, SL_2S);
		// @TODO leff_start (LEFF_SHOOTER);
	}
	callset_invoke (sw_shooter);
}
Esempio n. 13
0
/* Function to wait 6 seconds or until the autofire is detected as loaded */
static inline void autofire_ball_catch_wait (void)
{
    U8 timeout = 60; /* 6 seconds */
    while (!switch_poll_logical (SW_AUTOFIRE2)
            && --timeout != 0)
    {
        task_sleep (TIME_100MS);
    }
}
Esempio n. 14
0
CALLSET_ENTRY (trivial, sw_right_plunger)
{
	if (!switch_poll_logical (SW_RIGHT_PLUNGER))
	{
		sample_start (SND_PLUNGE, SL_2S);
		leff_start (LEFF_SHOOTER);
	}
	callset_invoke (sw_shooter);
}
Esempio n. 15
0
CALLSET_ENTRY (coin_door, sw_coin_door_closed)
{
	/* Be kind and ignore slam tilt switch briefly after the
	coin door is opened/closed */
	event_can_follow (sw_coin_door_closed, sw_slam_tilt, TIME_5S);

	if (switch_poll_logical (SW_COIN_DOOR_CLOSED))
		coin_door_closed ();
	else
		coin_door_opened ();
}
Esempio n. 16
0
/** Display effect when locating missing balls prior to game start */
void locating_balls_deff (void)
{
	/* For Funhouse/Road Show, if a ball is sitting in the left plunger
	lane, announce that, as ball search isn't going to fix it. */
#ifdef MACHINE_LEFT_SHOOTER_SWITCH
	if (switch_poll_logical (MACHINE_LEFT_SHOOTER_SWITCH))
		generic_deff ("CLEAR BALL FROM", "LEFT SHOOTER");
	else
#else
	generic_deff ("LOCATING BALLS", "PLEASE WAIT...");
#endif
}
Esempio n. 17
0
void amode_right_button_detect (void)
{
	/* Exit early if the player releases the button or presses the other
	 * button at the same time */
	U8 hold = TIME_5S / TIME_100MS;
	while (hold > 0)
	{
		if (!switch_poll_logical (SW_RIGHT_BUTTON)
				|| switch_poll_logical (SW_LEFT_BUTTON))
		{
			task_exit ();
		}
		task_sleep (TIME_100MS);
		hold--;
	}

#ifdef MACHINE_AMODE_FLIPPER_SOUND_CODE
	sound_send (MACHINE_AMODE_FLIPPER_SOUND_CODE);
#endif
	/* Switch to the scores page on the next page change */
	amode_show_scores_long = TRUE;
}
Esempio n. 18
0
/**
 * If we see the shooter at any other time than a trough kick,
 * we will autolaunch it but not if the door is open or we are
 * in tournament mode.
 */
CALLSET_ENTRY (serve, sw_shooter) {
#ifdef MACHINE_SHOOTER_SWITCH
	if (!switch_poll_logical (MACHINE_SHOOTER_SWITCH))		return;
	ball_search_timer_reset ();
	if (	valid_playfield
		&& !tournament_mode_enabled
		&& !global_flag_test (GLOBAL_FLAG_COIN_DOOR_OPENED)
		&& !MB_SERVING) {
		task_sleep (MACHINE_SHOOTER_SWITCH_DELAY);
		launch_ball ();
	}//end of if
#endif
} //end of function
Esempio n. 19
0
CALLSET_ENTRY (skill_menu, any_pf_switch) {
	dbprintf ("skill_menu: any_pf_switch\n");
	if (skill_menu_enabled == 0) {
		return;
	}
	// wait for the ball to be fired off the plunger switch, which is marked as a playfield switch so
	// that ball-search does not start when a ball is resting on it.
	if (switch_poll_logical (SW_PLUNGER)) {
		return;
	}

	skill_menu_select();
}
Esempio n. 20
0
/** Called at game start time to see if it is OK to
 * start a game.  This routine should check that all
 * balls are accounted for, and at least 1 ball is
 * in the trough. */
bool device_check_start_ok (void)
{
	U8 truly_missing_balls;

	/* Reset any kickout locks, just in case */
	kickout_unlock_all ();

	/* If any balls are missing, don't allow the game to start
	 * without first trying a device probe.
	 *
	 * If the device probe is already in progress, then just
	 * return right away. */
	if (task_find_gid (GID_DEVICE_PROBE))
		return FALSE;

	truly_missing_balls = missing_balls;
#ifdef MACHINE_SHOOTER_SWITCH
	if (switch_poll_logical (MACHINE_SHOOTER_SWITCH))
		truly_missing_balls--;
#endif

	/* If some balls are unaccounted for, and not on the shooter,
	 * then start a device probe and a ball search.  Alert the user
	 * by displaying a message.
	 *
	 * After 3 probes, allow the game to start anyway.  However,
	 * if no balls are accounted for anywhere, then don't do that.
	 */
	if (truly_missing_balls > 0)
	{
		dbprintf ("%d balls missing.\n", truly_missing_balls);
		if ((++device_game_start_errors <= 3) || (counted_balls == 0))
		{
			task_recreate_gid (GID_DEVICE_PROBE, device_probe);
			ball_search_now ();
			deff_start (DEFF_LOCATING_BALLS);
			return FALSE;
		}
		else
			return TRUE;
	}

	/* All checks pass : OK to start game now */
	return TRUE;
}
Esempio n. 21
0
static bool coin_door_warning_needed (void)
{
#ifdef CONFIG_COIN_DOOR_WARNING
	static bool already_warned = 0;

	if (already_warned && switch_poll_logical (SW_COIN_DOOR_CLOSED))
		return 0;

	if (!already_warned)
	{
		deff_start (DEFF_COIN_DOOR_BUTTONS);
		already_warned = 1;
	}
	return 1;
#else
	return 0;
#endif
}
Esempio n. 22
0
void shooter_update (void)
{
#ifdef MACHINE_SHOOTER_SWITCH
    /* A ball seen on the shooter switch means it is definitely there.
     * If not seen, it might be out of the plunger lane, or it may just be
     * "on its way up".  During that interval, still consider the ball
     * at the plunger, so delay clearing the flag.
     */
    if (switch_poll_logical (MACHINE_SHOOTER_SWITCH))
    {
        task_kill_gid (GID_SHOOTER_CLEAR);
        global_flag_on (GLOBAL_FLAG_BALL_AT_PLUNGER);
    }
    else
    {
        task_create_gid1 (GID_SHOOTER_CLEAR, shooter_clear_monitor);
    }
#endif
}
Esempio n. 23
0
CALLSET_ENTRY (skill, sw_shooter)
{
	/* Because the shooter switch is declared as an 'edge' switch,
	an event is generated on both transitions.  Check the current
	state of the switch to see which transition occurred. */
	if (!in_live_game)
		return;

	if (!switch_poll_logical (SW_SHOOTER))
	{
		sound_send (SND_SHOOTER_PULL);
		leff_restart (LEFF_STROBE_UP);
		timer_restart_free (GID_SHOOTER_SOUND_DEBOUNCE, TIME_3S);
	}
	else
	{
		leff_stop (LEFF_STROBE_UP);
	}
}
Esempio n. 24
0
/* Called whenever the far left trough switch is tripped.
The sole purpose of this to determine when there are too 
many balls in the trough, and one needs to be fired into the
gumball out of the way.  If a ball remains on this switch for
3 seconds, then it is assumed there are 4 balls in the trough
and one must be loaded. */
void sw_far_left_trough_monitor (void)
{
	U8 timeout = TIME_3S / TIME_200MS;
	device_t *dev = device_entry (DEVNO_TROUGH);

 	while (task_find_gid (GID_DEVICE_PROBE))
		task_sleep_sec (1);

	dbprintf ("Far left trough check\n");
	/* Poll the switch for up to 3 seconds.  If it ever opens,
	then abort.  It must stay closed and the trough must
	remain full in order for us to continue. */
	while (timeout > 0)
	{
		task_sleep (TIME_200MS);
		if ((!switch_poll_logical (SW_FAR_LEFT_TROUGH))
			|| (dev->actual_count != dev->size))
		{
			dbprintf ("Far left trough not stable\n");
			task_exit ();
		}
		timeout--;
	}

	/* If a ball is known to be in play, then delay the
	load */
	while (valid_playfield)
	{
		dbprintf ("Far left trough : waiting to load\n");
		task_sleep_sec (1);
	}

	/* Start the load */
	dbprintf ("Far left trough stable : loading gumball\n");
	if (hold_balls_in_autofire)
	{
		autofire_add_ball ();
	}
	else
		gumball_load_from_trough ();
	task_exit ();
}
Esempio n. 25
0
CALLSET_ENTRY (tilt, sw_slam_tilt)
{
	/* Ignore slam tilt switch entirely while coin door is open,
	and configured for tournament mode.  This is to avoid inadvertent slam tilts
	while dealing with problems. */
	if (system_config.tournament_mode && !switch_poll_logical (SW_COIN_DOOR_CLOSED))
		return;

	/* Ignore right after a coin door open/close */
	if (nonball_event_did_follow (sw_coin_door_closed, sw_slam_tilt))
		return;

	/* Kill the current game */
	stop_game ();

	/* Disable coins briefly, the whole point of the slam tilt */
	event_can_follow (sw_slam_tilt, sw_coin, TIME_5S);

	/* Start the slam tilt effect */
	callset_invoke (slam_tilt);
	deff_start (DEFF_SLAM_TILT);
	leff_restart (LEFF_TILT);

	/* Audit the event */
	audit_increment (&system_audits.slam_tilts);

	/* When slamtilt penalty adjustment is enabled, remove a credit. */
	if (price_config.slamtilt_penalty)
		remove_credit ();

	while (deff_get_active () == DEFF_SLAM_TILT)
		task_sleep (TIME_66MS);

	/* TODO: wait for slam switch to become stable, to avoid
	 * endless restarts */
	 warm_reboot ();
}
Esempio n. 26
0
/** Request that a new ball be autolaunched into play. */
void autofire_add_ball (void)
{
    autofire_request_count++;

    if (!in_game || switch_poll_logical (SW_FAR_LEFT_TROUGH))
    {
        /* For special situations.  If not in game, the
        kick_attempt hook won't be called to open for trough.
        If far left trough is set, the kick will appear failed
        because the trough count won't change (even though a
        ball was successfully kicked).  In these cases, do it
        manually.  However, you get no retry capability here. */
        autofire_open_for_trough ();
        /* Wait for divertor to open */
        task_sleep_sec (2);
        sol_request (SOL_BALL_SERVE);
    }
    else
    {
        /* The normal way to kick a ball from the trough.
         * dev_trough_kick_attempt will be called next */
        device_request_kick (device_entry (DEVNO_TROUGH));
    }
}
Esempio n. 27
0
/** A monitor task that checks whether or not a ball search is
necessary.  This task periodically bumps a counter, which is
normally reset as scoring switches are triggered.  If the
counter reaches a threshold, and ball search is allowed to run,
then it is initiated.
	This task is also responsible for incrementing the ball time
statistic, when ball search is not necessary. */
void ball_search_monitor_task (void)
{
	ball_search_timer_reset ();
	while (in_game)
	{
		task_sleep (TIME_1S);

		/* Step the ball search timer as long as a game
		 * is in progess.  But don't allow a ball search in
		 * some situations:
		 *
		 * - ball is on the shooter switch
		 * - either flipper button is held
		 */
		if (in_live_game && !in_bonus && (live_balls || !valid_playfield)
#ifdef MACHINE_SHOOTER_SWITCH
				&& !switch_poll_logical (MACHINE_SHOOTER_SWITCH)
#endif
				&& !switch_poll_logical (SW_LEFT_BUTTON)
				&& !switch_poll_logical (SW_RIGHT_BUTTON))
		{
			ball_time++;
			ball_search_timer_step ();
			if (ball_search_timed_out ())
			{
				ball_search_count = 0;
				while (ball_search_timer != 0)
				{
					if ((ball_search_count >= 5) && chase_ball_enabled ())
					{
						/* If chase ball is enabled, after the 5th ball search
						we will force endball. */
						audit_increment (&system_audits.chase_balls);
						end_ball ();
						return;
					}
					else
					{
						/* Perform a ball search */
						ball_search_run ();
					}

					/* After the third ball search, cancel the tilt lamp
					effect, to help the player find the missing ball. */
					if (ball_search_count == 3)
						leff_stop (LEFF_TILT);


					if (ball_search_count < 10)
					{
						/* Delay a small amount for the first few ball searches */
						task_sleep_sec (12);
					}
					else
					{
						/* Delay longer after many ball searches */
						task_sleep_sec (20);
					}

					/* After a while, just give up -- but don't do that in tournament
					mode or on free play; this is just to keep a location game from cycling
					continuously. */
					if (ball_search_count >= 25 &&
							!price_config.free_play && !system_config.tournament_mode)
					{
						fatal (ERR_BALL_SEARCH_TIMEOUT);
					}
				}

				/* A ball was seen -- clear the counter and exit */
				ball_search_count = 0;
			}
		}
	}
	task_exit ();
}
Esempio n. 28
0
CALLSET_ENTRY (skill_menu, sw_plunger) {
	if (!switch_poll_logical (SW_PLUNGER)) {
		dbprintf ("skill_menu: sw_plunger\n");
		skill_menu_select();
	}
}
Esempio n. 29
0
CALLSET_ENTRY (eject, amode_start) 		{
	if (switch_poll_logical (SW_EJECT) ) 	sol_request (SOL_EJECT); //request to fire the eject sol
}//end of function
Esempio n. 30
0
CALLSET_ENTRY (outhole, init)
{
	if (switch_poll_logical (SW_OUTHOLE))
		sol_request (SOL_OUTHOLE);
}