Ejemplo n.º 1
0
inline std::error_code SimulatedFailure::trigger(FailureType failure_type, std::error_code& ec) noexcept
{
    if (check_trigger(failure_type)) {
        ec = make_error_code(failure_type);
    }
    else {
        ec = std::error_code();
    }
    return ec;
}
Ejemplo n.º 2
0
static void sample(void *arg, long period)
{
    int n;

    ctrl_shm->watchdog = 0;
    if (ctrl_shm->state == RESET) {
	/* sampling interrupted, reset everything */
	ctrl_shm->curr = 0;
	ctrl_shm->start = ctrl_shm->curr;
	ctrl_shm->samples = 0;
	ctrl_shm->force_trig = 0;
	/* reset completed, set new state */
	ctrl_shm->state = IDLE;
    }
    ctrl_rt->mult_cntr++;
    if (ctrl_rt->mult_cntr < ctrl_shm->mult) {
	/* not time to do anything yet */
	return;
    }
    /* reset counter */
    ctrl_rt->mult_cntr = 0;
    /* run the sampling state machine */
    switch (ctrl_shm->state) {
    case IDLE:
	/* do nothing while waiting for INIT */
	break;
    case INIT:
	/* init start pointer, curr pointer, sample count */
	ctrl_shm->curr = 0;
	ctrl_shm->start = ctrl_shm->curr;
	ctrl_shm->samples = 0;
	ctrl_shm->force_trig = 0;
	ctrl_rt->auto_timer = 0;
	/* get info about channels */
	for (n = 0; n < 16; n++) {
	    ctrl_rt->data_addr[n] = SHMPTR(ctrl_shm->data_offset[n]);
	    ctrl_rt->data_type[n] = ctrl_shm->data_type[n];
	    ctrl_rt->data_len[n] = ctrl_shm->data_len[n];
	}
	/* set next state */
	ctrl_shm->state = PRE_TRIG;
	break;
    case PRE_TRIG:
	/* acquire a sample */
	capture_sample();
	/* increment sample counter */
	ctrl_shm->samples++;
	/* check if all pre-trigger samples captured */
	if (ctrl_shm->samples >= ctrl_shm->pre_trig) {
	    /* yes - start waiting for trigger */
	    ctrl_shm->state = TRIG_WAIT;
	    /* dummy call to preset 'compare_result' */
	    check_trigger();
	}
	break;
    case TRIG_WAIT:
	/* acquire a sample */
	capture_sample();
	/* increment sample counter */
	ctrl_shm->samples++;
	/* check if trigger condition met */
	if (check_trigger()) {
	    /* yes - start acquiring post trigger data */
	    ctrl_shm->state = POST_TRIG;
	} else {
	    /* no, discard oldest pre-trig sample */
	    ctrl_shm->samples--;
	    ctrl_shm->start += ctrl_shm->sample_len;
	    /* is there a valid sample here, or end of buffer? */
	    if ((ctrl_shm->start + ctrl_shm->sample_len) > ctrl_shm->buf_len) {
		/* end of buffer, wrap back to beginning */
		ctrl_shm->start = 0;
	    }
	}
	break;
    case POST_TRIG:
	/* acquire a sample */
	capture_sample();
	/* increment sample counter */
	ctrl_shm->samples++;
	/* check if all post-trigger samples captured */
	if (ctrl_shm->samples >= ctrl_shm->rec_len) {
	    /* yes - stop sampling and cleanup */
	    ctrl_shm->state = DONE;
	}
	break;
    case DONE:
	/* do nothing while GUI displays waveform */
	break;
    default:
	/* shouldn't get here - if we do, set a legal state */
	ctrl_shm->state = IDLE;
	break;
    }
    /* done */
}
Ejemplo n.º 3
0
gboolean trigger_init(void)
{
  const gchar *udev_path = NULL;
  struct udev_device *dev;
  int ret = 0;
	
  /* Create the udev object */
  udev = udev_new();
  if (!udev) 
  {
    log_err("Can't create udev\n");
    return 1;
  }
  
  udev_path = check_trigger();
  if(udev_path)
	dev = udev_device_new_from_syspath(udev, udev_path);
  else
  {
    log_err("No trigger path. Not starting trigger.\n");
    return 1;	
  }
  if (!dev) 
  {
    log_err("Unable to find the trigger device.");
    return 1;
  }
  else
  {
    dev_name = udev_device_get_sysname(dev);
    log_debug("device name = %s\n", dev_name);
  } 
  mon = udev_monitor_new_from_netlink (udev, "udev");
  if (!mon) 
  {
    log_err("Unable to monitor the netlink\n");
    /* communicate failure, mainloop will exit and call appropriate clean-up */
    return 1;
  }
  ret = udev_monitor_filter_add_match_subsystem_devtype(mon, get_trigger_subsystem(), NULL);
  if(ret != 0)
  {
    log_err("Udev match failed.\n");
    return 1;
  }
  ret = udev_monitor_enable_receiving (mon);
  if(ret != 0)
  { 
     log_err("Failed to enable monitor recieving.\n");
     return 1;
  }

  /* check if we are already connected */
  udev_parse(dev);
  
  iochannel = g_io_channel_unix_new(udev_monitor_get_fd(mon));
  watch_id = g_io_add_watch_full(iochannel, 0, G_IO_IN, monitor_udev, NULL, notify_issue);

  /* everything went well */
  log_debug("Trigger enabled!\n");
  return 0;
}
Ejemplo n.º 4
0
Archivo: apply.c Proyecto: atrinik/dwc
/**
 * Main apply handler.
 *
 * Checks for unpaid items before applying.
 * @param op ::object causing tmp to be applied.
 * @param tmp ::object being applied.
 * @param aflag Special (always apply/unapply) flags. Nothing is done
 * with them in this function - they are passed to apply_special().
 * @retval 0 Player or monster can't apply objects of that type.
 * @retval 1 Has been applied, or there was an error applying the object.
 * @retval 2 Objects of that type can't be applied if not in
 * inventory. */
int manual_apply(object *op, object *tmp, int aflag)
{
	if (tmp->head)
	{
		tmp = tmp->head;
	}

	if (op->type == PLAYER)
	{
		CONTR(op)->praying = 0;
	}

	if (QUERY_FLAG(tmp, FLAG_UNPAID) && !QUERY_FLAG(tmp, FLAG_APPLIED))
	{
		if (op->type == PLAYER)
		{
			new_draw_info(NDI_UNIQUE, op, "You should pay for it first.");
			return 1;
		}
		/* Monsters just skip unpaid items */
		else
		{
			return 0;
		}
	}

	/* Monsters must not apply random chests, nor magic_mouths with a counter */
	if (op->type != PLAYER && tmp->type == TREASURE)
	{
		return 0;
	}

	/* Trigger the APPLY event */
	if (!(aflag & AP_NO_EVENT) && trigger_event(EVENT_APPLY, op, tmp, NULL, NULL, aflag, 0, 0, SCRIPT_FIX_ACTIVATOR))
	{
		return 1;
	}

	aflag &= ~AP_NO_EVENT;

	/* Control apply by controling a set exp object level or player exp level */
	if (tmp->item_level)
	{
		int tmp_lev;

		if (tmp->item_skill)
		{
			tmp_lev = find_skill_exp_level(op, tmp->item_skill);
		}
		else
		{
			tmp_lev = op->level;
		}

		if (tmp->item_level > tmp_lev)
		{
			new_draw_info(NDI_UNIQUE, op, "The item level is too high to apply.");
			return 1;
		}
	}

	switch (tmp->type)
	{
		case HOLY_ALTAR:
			new_draw_info_format(NDI_UNIQUE, op, "You touch the %s.", tmp->name);

			if (change_skill(op, SK_PRAYING))
			{
				pray_at_altar(op, tmp);
			}
			else
			{
				new_draw_info(NDI_UNIQUE, op, "Nothing happens. It seems you miss the right skill.");
			}

			return 1;
			break;

		case HANDLE:
			new_draw_info(NDI_UNIQUE, op, "You turn the handle.");
			play_sound_map(op->map, op->x, op->y, SOUND_TURN_HANDLE, SOUND_NORMAL);
			tmp->value = tmp->value ? 0 : 1;
			SET_ANIMATION(tmp, ((NUM_ANIMATIONS(tmp) / NUM_FACINGS(tmp)) * tmp->direction) + tmp->value);
			update_object(tmp, UP_OBJ_FACE);
			push_button(tmp);

			return 1;

		case TRIGGER:
			if (check_trigger(tmp, op))
			{
				new_draw_info(NDI_UNIQUE, op, "You turn the handle.");
				play_sound_map(tmp->map, tmp->x, tmp->y, SOUND_TURN_HANDLE, SOUND_NORMAL);
			}
			else
			{
				new_draw_info(NDI_UNIQUE, op, "The handle doesn't move.");
			}

			return 1;

		case EXIT:
			if (op->type != PLAYER || !tmp->map)
			{
				return 0;
			}

			/* If no map path specified, we assume it is the map path of the exit. */
			if (!EXIT_PATH(tmp))
			{
				FREE_AND_ADD_REF_HASH(EXIT_PATH(tmp), tmp->map->path);
			}

			if (!EXIT_PATH(tmp) || !is_legal_2ways_exit(op, tmp) || (EXIT_Y(tmp) == -1 && EXIT_X(tmp) == -1))
			{
				new_draw_info_format(NDI_UNIQUE, op, "The %s is closed.", query_name(tmp, NULL));
			}
			else
			{
				/* Don't display messages for random maps. */
				if (tmp->msg && strncmp(EXIT_PATH(tmp), "/!", 2) && strncmp(EXIT_PATH(tmp), "/random/", 8))
				{
					new_draw_info(NDI_NAVY, op, tmp->msg);
				}

				enter_exit(op, tmp);
			}

			return 1;

		case SIGN:
			apply_sign(op, tmp);
			return 1;

		case BOOK:
			if (op->type == PLAYER)
			{
				apply_book(op, tmp);
				return 1;
			}

			return 0;

		case SKILLSCROLL:
			if (op->type == PLAYER)
			{
				apply_skillscroll(op, tmp);
				return 1;
			}

			return 0;

		case SPELLBOOK:
			if (op->type == PLAYER)
			{
				apply_spellbook(op, tmp);
				return 1;
			}

			return 0;

		case SCROLL:
			apply_scroll(op, tmp);
			return 1;

		case POTION:
			(void) apply_potion(op, tmp);
			return 1;

		case LIGHT_APPLY:
			apply_player_light(op, tmp);
			return 1;

		case LIGHT_REFILL:
			apply_player_light_refill(op, tmp);
			return 1;

		/* Eneq(@csd.uu.se): Handle apply on containers. */
		case CLOSE_CON:
			if (op->type == PLAYER)
			{
				(void) esrv_apply_container(op, tmp->env);
			}

			return 1;

		case CONTAINER:
			if (op->type == PLAYER)
			{
				(void) esrv_apply_container(op, tmp);
			}

			return 1;

		case TREASURE:
			apply_treasure(op, tmp);
			return 1;

		case WEAPON:
		case ARMOUR:
		case BOOTS:
		case GLOVES:
		case AMULET:
		case GIRDLE:
		case BRACERS:
		case SHIELD:
		case HELMET:
		case RING:
		case CLOAK:
		case WAND:
		case ROD:
		case HORN:
		case SKILL:
		case BOW:
		case SKILL_ITEM:
			/* Not in inventory */
			if (tmp->env != op)
			{
				return 2;
			}

			(void) apply_special(op, tmp, aflag);
			return 1;

		case DRINK:
		case FOOD:
		case FLESH:
			apply_food(op, tmp);
			return 1;

		case POISON:
			apply_poison(op, tmp);
			return 1;

		case SAVEBED:
			if (op->type == PLAYER)
			{
				apply_savebed(op);
				return 1;
			}

			return 0;

		case ARMOUR_IMPROVER:
			if (op->type == PLAYER)
			{
				apply_armour_improver(op, tmp);
				return 1;
			}

			return 0;

		case WEAPON_IMPROVER:
			apply_weapon_improver(op, tmp);
			return 1;

		case CLOCK:
			if (op->type == PLAYER)
			{
				timeofday_t tod;

				get_tod(&tod);
				new_draw_info_format(NDI_UNIQUE, op, "It is %d minute%s past %d o'clock %s", tod.minute + 1, ((tod.minute + 1 < 2) ? "" : "s"), ((tod.hour % (HOURS_PER_DAY / 2) == 0) ? (HOURS_PER_DAY / 2) : ((tod.hour) % (HOURS_PER_DAY / 2))), ((tod.hour >= (HOURS_PER_DAY / 2)) ? "pm" : "am"));
				return 1;
			}

			return 0;

		case POWER_CRYSTAL:
			apply_power_crystal(op, tmp);
			return 1;

		/* For lighting torches/lanterns/etc */
		case LIGHTER:
			if (op->type == PLAYER)
			{
				apply_lighter(op, tmp);
				return 1;
			}

			return 0;

		/* So the below default case doesn't execute for these objects,
		 * even if they have message. */
		case DOOR:
			return 0;

		/* Nothing from the above... but show a message if it has one. */
		default:
			if (tmp->msg)
			{
				new_draw_info(NDI_UNIQUE, op, tmp->msg);
				return 1;
			}

			return 0;
	}
}
Ejemplo n.º 5
0
Archivo: apply.c Proyecto: atrinik/dwc
/**
 * 'victim' moves onto 'trap' (trap has FLAG_WALK_ON or FLAG_FLY_ON set) or
 * 'victim' leaves 'trap' (trap has FLAG_WALK_OFF or FLAG_FLY_OFF) set.
 *
 * I added the flags parameter to give the single events more information
 * about whats going on:
 *
 * Most important is the "MOVE_APPLY_VANISHED" flag.
 * If set, a object has left a tile but "vanished" and not moved (perhaps
 * it exploded or something). This means that some events are not
 * triggered like trapdoors or teleporter traps for example which have a
 * "FLY/MOVE_OFF" set. This will avoid that they touch invalid objects.
 * @param trap Object victim moved on.
 * @param victim The object that moved on trap.
 * @param originator Player, monster or other object that caused 'victim'
 * to move onto 'trap'. Will receive messages caused by this action. May
 * be NULL, however, some types of traps require an originator to
 * function.
 * @param flags Flags. */
void move_apply(object *trap, object *victim, object *originator, int flags)
{
	static int recursion_depth = 0;

	/* move_apply() is the most likely candidate for causing unwanted and
	 * possibly unlimited recursion. */
	/* The following was changed because it was causing perfeclty correct
	 * maps to fail.  1)  it's not an error to recurse:
	 * rune detonates, summoning monster.  monster lands on nearby rune.
	 * nearby rune detonates.  This sort of recursion is expected and
	 * proper.  This code was causing needless crashes. */
	if (recursion_depth >= 500)
	{
		LOG(llevDebug, "WARNING: move_apply(): aborting recursion [trap arch %s, name %s; victim arch %s, name %s]\n", trap->arch->name, trap->name, victim->arch->name, victim->name);
		return;
	}

	if (trap->head)
	{
		trap = trap->head;
	}

	/* Trigger the TRIGGER event */
	if (trigger_event(EVENT_TRIGGER, victim, trap, originator, NULL, 0, 0, 0, SCRIPT_FIX_NOTHING))
	{
		return;
	}

	recursion_depth++;

	switch (trap->type)
	{
		/* these objects can trigger other objects connected to them.
		 * We need to check them at map loading time and other special
		 * events to be sure to have a 100% working map state. */
		case BUTTON:
		case PEDESTAL:
			update_button(trap);
			break;

		case TRIGGER_BUTTON:
		case TRIGGER_PEDESTAL:
		case TRIGGER_ALTAR:
			check_trigger(trap, victim);
			break;

		case CHECK_INV:
			check_inv(victim, trap);
			break;

		/* these objects trigger to but they are "instant".
		 * We don't need to check them when loading. */
		case ALTAR:
			/* sacrifice victim on trap */
			apply_altar(trap, victim, originator);
			break;

		case CONVERTER:
			if (!(flags & MOVE_APPLY_VANISHED))
			{
				convert_item(victim, trap);
			}

			break;

		case PLAYERMOVER:
			break;

		/* should be walk_on/fly_on only */
		case SPINNER:
			if (victim->direction)
			{
				if ((victim->direction = victim->direction + trap->direction) > 8)
				{
					victim->direction = (victim->direction % 8) + 1;
				}

				update_turn_face(victim);
			}

			break;

		case DIRECTOR:
			if (victim->direction)
			{
				victim->direction = trap->direction;
				update_turn_face(victim);
			}

			break;

		/* no need to hit anything */
		case MMISSILE:
			if (IS_LIVE(victim) && !(flags&MOVE_APPLY_VANISHED))
			{
				tag_t trap_tag = trap->count;
				hit_player(victim, trap->stats.dam, trap, AT_MAGIC);

				if (!was_destroyed(trap, trap_tag))
				{
					remove_ob(trap);
				}

				check_walk_off(trap, NULL, MOVE_APPLY_VANISHED);
			}

			break;

		case THROWN_OBJ:
			if (trap->inv == NULL || (flags & MOVE_APPLY_VANISHED))
			{
				break;
			}

		/* fallthrough */
		case ARROW:
			/* bad bug: monster throw a object, make a step forwards, step on object ,
			 * trigger this here and get hit by own missile - and will be own enemy.
			 * Victim then is his own enemy and will start to kill herself (this is
			 * removed) but we have not synced victim and his missile. To avoid senseless
			 * action, we avoid hits here */
			if ((IS_LIVE(victim) && trap->speed) && trap->owner != victim)
			{
				hit_with_arrow(trap, victim);
			}

			break;

		case CONE:
		case LIGHTNING:
			break;

		case BULLET:
			if ((QUERY_FLAG(victim, FLAG_NO_PASS) || IS_LIVE(victim)) && !(flags & MOVE_APPLY_VANISHED))
			{
				check_fired_arch(trap);
			}

			break;

		case TRAPDOOR:
		{
			int max, sound_was_played;
			object *ab;

			if ((flags & MOVE_APPLY_VANISHED))
			{
				break;
			}

			if (!trap->value)
			{
				sint32 tot;

				for (ab = trap->above, tot = 0; ab != NULL; ab = ab->above)
				{
					if (!QUERY_FLAG(ab, FLAG_FLYING))
					{
						tot += (ab->nrof ? ab->nrof : 1) * ab->weight + ab->carrying;
					}
				}

				if (!(trap->value = (tot > trap->weight) ? 1 : 0))
				{
					break;
				}

				SET_ANIMATION(trap, (NUM_ANIMATIONS(trap) / NUM_FACINGS(trap)) * trap->direction + trap->value);
				update_object(trap, UP_OBJ_FACE);
			}

			for (ab = trap->above, max = 100, sound_was_played = 0; --max && ab && !QUERY_FLAG(ab, FLAG_FLYING); ab = ab->above)
			{
				if (!sound_was_played)
				{
					play_sound_map(trap->map, trap->x, trap->y, SOUND_FALL_HOLE, SOUND_NORMAL);
					sound_was_played = 1;
				}

				if (ab->type == PLAYER)
				{
					new_draw_info(NDI_UNIQUE, ab, "You fall into a trapdoor!");
				}

				transfer_ob(ab, EXIT_X(trap), EXIT_Y(trap), trap->last_sp, ab, trap);
			}

			break;
		}


		case PIT:
			/* Pit not open? */
			if ((flags & MOVE_APPLY_VANISHED) || trap->stats.wc > 0)
			{
				break;
			}

			play_sound_map(victim->map, victim->x, victim->y, SOUND_FALL_HOLE, SOUND_NORMAL);

			if (victim->type == PLAYER)
			{
				new_draw_info(NDI_UNIQUE, victim, "You fall through the hole!\n");
			}

			transfer_ob(victim->head ? victim->head : victim, EXIT_X(trap), EXIT_Y(trap), trap->last_sp, victim, trap);

			break;

		case EXIT:
			/* If no map path specified, we assume it is the map path of the exit. */
			if (!EXIT_PATH(trap))
			{
				FREE_AND_ADD_REF_HASH(EXIT_PATH(trap), trap->map->path);
			}

			if (!(flags & MOVE_APPLY_VANISHED) && victim->type == PLAYER && EXIT_PATH(trap) && EXIT_Y(trap) != -1 && EXIT_X(trap) != -1)
			{
				/* Basically, don't show exits leading to random maps the players output. */
				if (trap->msg && strncmp(EXIT_PATH(trap), "/!", 2) && strncmp(EXIT_PATH(trap), "/random/", 8))
				{
					new_draw_info(NDI_NAVY, victim, trap->msg);
				}

				enter_exit(victim, trap);
			}

			break;

		case SHOP_MAT:
			if (!(flags & MOVE_APPLY_VANISHED))
			{
				apply_shop_mat(trap, victim);
			}

			break;

		/* Drop a certain amount of gold, and have one item identified */
		case IDENTIFY_ALTAR:
			if (!(flags & MOVE_APPLY_VANISHED))
			{
				apply_identify_altar(victim, trap, originator);
			}

			break;

		case SIGN:
			/* Only player should be able read signs */
			if (victim->type == PLAYER)
			{
				apply_sign(victim, trap);
			}

			break;

		case CONTAINER:
			if (victim->type == PLAYER)
			{
				(void) esrv_apply_container(victim, trap);
			}

			break;

		case RUNE:
			if (!(flags & MOVE_APPLY_VANISHED) && trap->level && IS_LIVE(victim))
			{
				spring_trap(trap, victim);
			}

			break;

#if 0
		/* we don't have this atm. */
		case DEEP_SWAMP:
			if (!(flags & MOVE_APPLY_VANISHED))
			{
				walk_on_deep_swamp(trap, victim);
			}

			break;
#endif

		default:
			LOG(llevDebug, "name %s, arch %s, type %d with fly/walk on/off not handled in move_apply()\n", trap->name, trap->arch->name, trap->type);
			break;
	}

	recursion_depth--;
}
Ejemplo n.º 6
0
/**
 * Drive instruction handler function.
 *
 * Very long but versitile function used to drive around the world
 * (maybe not in 80 days).
 * @param[in,out] order The order which specifies what exactly
 * should be done.
 * @todo The function is partially really ugly. Refactor it.
 */
void drive_instruction(order_t *order) {
	// Extract the type of triggers to be used
	uint8_t trigger_type_left = order->data[0] & 0x30;
	uint8_t trigger_type_right = order->data[0] & 0xc0;
	// Import the option for ABS
	extern uint8_t ACTIVE_BRAKE_WHEN_TRIGGER_REACHED;
	if (DEBUG_ENABLE) {
		debug_write_integer(PSTR("order_functions.c : drive_instruction() :  trigger_type_left = "), trigger_type_left);
		debug_write_integer(PSTR("order_functions.c : drive_instruction() :  trigger_type_right = "), trigger_type_right);
	}

	// This if shouldn't be taken, just to make sure
	if (order->status & ORDER_STATUS_DONE) {
		if (DEBUG_ENABLE) {
			debug_write_string_p(PSTR("order_functions.c : drive_instruction() :  status = ORDER_STATUS_DONE\n"));
		}
		return;
	}

	// Instruciton is already running
	if (order->status & ORDER_STATUS_STARTED) {
		// Local variable to save the checkTrigger return value for debug output
		uint16_t result = 0;
		if (DEBUG_ENABLE) {
			debug_write_string_p(PSTR("order_functions.c : drive_instruction() :  status = ORDER_STATUS_STARTED\n"));
		}
		// Check Left trigger
		result = check_trigger(trigger_type_left, WHEEL_LEFT);
		if (DEBUG_ENABLE) {
			debug_write_integer(PSTR("order_functions.c : drive_instruction() :  checkTrigger(LEFT) = "), result);
		}
		// Left Trigger reached in this Iteration?
		if (!(order->status & ORDER_STATUS_TRIGGER_LEFT_REACHED) &&
				result == 0) {
			// Set the Trigger reached flag
			order->status |= ORDER_STATUS_TRIGGER_LEFT_REACHED;
			// set the ABS ref position
			drive_brake_active_set(WHEEL_LEFT);
			if (DEBUG_ENABLE) {
				debug_write_string_p(PSTR("order_functions.c : drive_instruction() :  status = ORDER_STATUS_TRIGGER_LEFT_REACHED\n"));
			}
		}
		// Right trigger reached
		result = check_trigger(trigger_type_right, WHEEL_RIGHT);
		if (DEBUG_ENABLE) {
			debug_write_integer(PSTR("order_functions.c : drive_instruction() :  checkTrigger(RIGHT) = "), result);
		}
		// Right Trigger reached in this Iteration?
		if (!(order->status & ORDER_STATUS_TRIGGER_RIGHT_REACHED) &&
				result == 0 ) {
			// Set the Trigger reached flag
			order->status |= ORDER_STATUS_TRIGGER_RIGHT_REACHED;
			// set the ABS ref position
			drive_brake_active_set(WHEEL_RIGHT);
			if (DEBUG_ENABLE) {
				debug_write_string_p(PSTR("order_functions.c : drive_instruction() :  status = ORDER_STATUS_TRIGGER_RIGHT_REACHED\n"));
			}
		}
		// If in PID with D mode one reached trigger equals all trigger reached
		if ((order->status & ORDER_STATUS_TRIGGER_RIGHT_REACHED ||
			order->status & ORDER_STATUS_TRIGGER_LEFT_REACHED) &&
			trigger_type_left == 0x30) {
			order->status |= ORDER_STATUS_TRIGGER_LEFT_REACHED + ORDER_STATUS_TRIGGER_RIGHT_REACHED;
		}
		// both triggers reached, ergo order is done 
		if (order->status & ORDER_STATUS_TRIGGER_RIGHT_REACHED && 
			order->status & ORDER_STATUS_TRIGGER_LEFT_REACHED) {
			if (DEBUG_ENABLE) {
				debug_write_string_p(PSTR("order_functions.c : drive_instruction() :  All trigger reached\n"));
			}
			order->status |= ORDER_STATUS_DONE;	
			// stop the wheels
			drive_use_pid(WHEEL_BOTH, 0);
			wheel_clear_difference();
		}
	
		// When it is wanted, we will use active breaking on the wheel where the trigger has been reached
		if (ACTIVE_BRAKE_WHEN_TRIGGER_REACHED) {
			if (order->status & ORDER_STATUS_TRIGGER_LEFT_REACHED) {
				drive_brake_active(WHEEL_LEFT);
			} else if (order->status & ORDER_STATUS_TRIGGER_RIGHT_REACHED) {
				drive_brake_active(WHEEL_RIGHT);
			}
		}
		// Use error-correction while driving every 100 ms
		if (local_time_flags & TIMER_100MS) {
			if (trigger_type_left == 0x30) { // Use function for both wheels to use PID mode with D
				drive_use_pid(WHEEL_BOTH, order->data[1]);
			} else {
				// Only drive the wheels if the triggers haven't been reached
				if (!(order->status & ORDER_STATUS_TRIGGER_LEFT_REACHED)) {
					drive_use_pid(WHEEL_LEFT, order->data[1]);
				}
				if (!(order->status & ORDER_STATUS_TRIGGER_RIGHT_REACHED)) {
					drive_use_pid(WHEEL_RIGHT, order->data[2]);
				}
			}
		}
	} else { //Instruction isn't running
		// Build the values for the specified triggers, even if there aren't any triggers present
		int16_t trigger_value_left = 0;
		int16_t trigger_value_right = 0;
		if (DEBUG_ENABLE) {
			debug_write_string_p(PSTR("order_functions.c : drive_instruction() :  Start execution\n"));
			debug_write_integer(PSTR("order_functions.c : drive_instruction() : speed_left = "), order->data[1]);
			debug_write_integer(PSTR("order_functions.c : drive_instruction() : speed_right = "), order->data[2]);
		}

		// -128 is not a accepted speed, so we correct it down by 1
		if (order->data[1] == 128) {
			order->data[1] = -127;
		}
		if (order->data[2] == 128) {
			order->data[2] = -127;
		}

		trigger_value_left = ((order->data[3] << 8) + order->data[4]);
		trigger_value_right = ((order->data[5] << 8) + order->data[6]);

		if (trigger_type_right == 0xc0) { // Set new differential correction
			trigger_value_left = (order->data[1] << 8) + order->data[2];
			wheel_write_difference(trigger_value_left);
			// We are done with this order
			order->status |= ORDER_STATUS_DONE;
			return;
		}
		if (trigger_type_left == 0x30) { // PID with differential correction
			trigger_value_left = trigger_value_right = ((order->data[2] << 8) + order->data[3]);
		}
		// Set the triggers for each wheel
		if (DEBUG_ENABLE) {
			debug_write_integer(PSTR("order_functions.c : drive_instruction() :  trigger_value_left = "), trigger_value_left);
			debug_write_integer(PSTR("order_functions.c : drive_instruction() :  trigger_value_right = "), trigger_value_right);
		}
		// Set the Trigger values
		set_trigger(trigger_type_left, WHEEL_LEFT, trigger_value_left);
		set_trigger(trigger_type_right, WHEEL_RIGHT, trigger_value_right);
		// Set Status to started as setup is complete
		order->status |= ORDER_STATUS_STARTED;
	}
}
Ejemplo n.º 7
0
inline void SimulatedFailure::trigger(FailureType failure_type)
{
    if (check_trigger(failure_type))
        throw SimulatedFailure(make_error_code(failure_type));
}