Exemplo n.º 1
0
void main(void)
{
  board_init();
  NVIC_Configuration();
  timer_init();
  state = 0;
#ifdef DEBUG
  debug_printf("hello world\n");
#endif

  while (1) {
    switch (state) {
      case 0:
        if (get_button()) {
          state = 1;
          set_leds(state);
        }
        break;
      case 1:
        if (get_button()) {
          state = 0;
          set_leds(state);
        }
        break;
    }
  }
}
Exemplo n.º 2
0
void pause_menu(const char *s) {
	clear_display();
	put_string_display(s, 0, 0);
	while (!(get_button(0) || get_button(1)))
		delay(20);
		while (get_button(0) || get_button(1))
			;
}
Exemplo n.º 3
0
void
UInputMessageProcessor::send(const XboxGenericMsg& msg_in, int msec_delta)
{
    if (!m_config->empty())
    {
        XboxGenericMsg msg = msg_in;

        if (m_rumble_test)
        {
            log_debug("rumble: " << get_axis(msg, XBOX_AXIS_LT) << " " << get_axis(msg, XBOX_AXIS_RT));

            set_rumble(get_axis(msg, XBOX_AXIS_LT),
                       get_axis(msg, XBOX_AXIS_RT));
        }

        // handling switching of configurations
        if (m_config_toggle_button != XBOX_BTN_UNKNOWN)
        {
            bool last = get_button(m_oldmsg, m_config_toggle_button);
            bool cur  = get_button(msg, m_config_toggle_button);

            if (cur && cur != last)
            {
                // reset old mapping to zero to not get stuck keys/axis
                m_config->get_config()->get_uinput().reset_all_outputs();

                // switch to the next input mapping
                m_config->next_config();

                log_info("switched to config: " << m_config->get_current_config());
            }
        }

        // run the controller message through all modifier
        for(std::vector<ModifierPtr>::iterator i = m_config->get_config()->get_modifier().begin();
                i != m_config->get_config()->get_modifier().end();
                ++i)
        {
            (*i)->update(msec_delta, msg);
        }

        m_config->get_config()->get_uinput().update(msec_delta);

        // send current Xbox state to uinput
        if (memcmp(&msg, &m_oldmsg, sizeof(XboxGenericMsg)) != 0)
        {
            // Only send a new event out if something has changed,
            // this is useful since some controllers send events
            // even if nothing has changed, deadzone can cause this
            // too
            m_oldmsg = msg;

            m_config->get_config()->get_uinput().send(msg);
        }
    }
}
Exemplo n.º 4
0
int tilt_get_button(int *b, int *s)
{
    int ch = BUTTON_NC;

    if (mutex)
    {
        SDL_mutexP(mutex);
        {
            if      ((ch = get_button(&state.A)))
            {
                *b = config_get_d(CONFIG_JOYSTICK_BUTTON_A);
                *s = (ch == BUTTON_DN);
            }
            else if ((ch = get_button(&state.B)))
            {
                *b = config_get_d(CONFIG_JOYSTICK_BUTTON_B);
                *s = (ch == BUTTON_DN);
            }
            else if ((ch = get_button(&state.plus)))
            {
                *b = config_get_d(CONFIG_JOYSTICK_BUTTON_R1);
                *s = (ch == BUTTON_DN);
            }
            else if ((ch = get_button(&state.minus)))
            {
                *b = config_get_d(CONFIG_JOYSTICK_BUTTON_L1);
                *s = (ch == BUTTON_DN);
            }
            else if ((ch = get_button(&state.home)))
            {
                *b = config_get_d(CONFIG_JOYSTICK_BUTTON_START);
                *s = (ch == BUTTON_DN);
            }
            else if ((ch = get_button(&state.L)))
            {
                *b = config_get_d(CONFIG_JOYSTICK_DPAD_L);
                *s = (ch == BUTTON_DN);
            }
            else if ((ch = get_button(&state.R)))
            {
                *b = config_get_d(CONFIG_JOYSTICK_DPAD_R);
                *s = (ch == BUTTON_DN);
            }
            else if ((ch = get_button(&state.U)))
            {
                *b = config_get_d(CONFIG_JOYSTICK_DPAD_U);
                *s = (ch == BUTTON_DN);
            }
            else if ((ch = get_button(&state.D)))
            {
                *b = config_get_d(CONFIG_JOYSTICK_DPAD_D);
                *s = (ch == BUTTON_DN);
            }
        }
        SDL_mutexV(mutex);
    }
    return ch;
}
Exemplo n.º 5
0
/*---------------------------------------------------------------------------
     TITLE   : update
     WORK    : 
     ARG     : void
     RET     : void
---------------------------------------------------------------------------*/
void cKEY::update( void )
{
	uint8_t i;

	for( i=0; i<5; i++ )
	{
		switch( pin_state[i] )
		{
			case 0:				
				pin_press[i] = 0;

				if( get_button(i) == LOW )
				{
					tTime[i] = millis();
					pin_state[i] = 1;
				}
				break;

			case 1:
				if( get_button(i) == HIGH ) 
				{
					pin_state[i] = 0;
				}
				if( millis()-tTime[i] > trigger_time )
				{
					pin_press[i] = 1;
					pin_state[i] = 2;	
				}
				break;

			case 2:				
				if( get_button(i) == HIGH ) 
				{
					pin_state[i] = 0;
				}
				if( pin_press[i] == 0 )
				{
					tTime[i] = millis();
					pin_state[i] = 3;
				}			
				break;

			case 3:
				if( millis()-tTime[i] > trigger_time )
				{
					pin_state[i] = 0;	
				}				
				break;
		}		
	}
}
Exemplo n.º 6
0
/**************************************************************************//**
 * @brief  Main function
 *****************************************************************************/
int main(void)
{
	// Chip errata
	CHIP_Init();

	setup_utilities();

	CMU_ClockEnable(cmuClock_GPIO, true);

	// Set up the user interface buttons
	GPIO_PinModeSet(BUTTON_PORT, SET_BUTTON_PIN, gpioModeInput,  0);

	while (1)
	{
		if (get_button())
		{
			set_led(0, 1);
			delay(DELAY_VALUE);
			set_led(1, 1);
		}
		else
		{
			set_led(0, 0);
			set_led(1, 0);
		}
	}
}
Exemplo n.º 7
0
/**
 * Move button to the specified left and top coordinates.
 *
 * The coordinates SHOULD BE in pixels of the screen (i.e. after scaling!)
 *
 * @param ch
 * @param left    Number of pixels from the left (in screen pixels)
 * @param top     Number of pixels from the top (in screen pixels)
 */
void
KeyboardControl::move_button(TCHAR ch, PixelScalar left, PixelScalar top)
{
  ButtonWindow *kb = get_button(ch);
  if (kb)
    kb->Move(left, top);
}
Exemplo n.º 8
0
/**
 * Move button to the specified left and top coordinates.
 *
 * The coordinates SHOULD BE in pixels of the screen (i.e. after scaling!)
 *
 * @param ch
 * @param left    Number of pixels from the left (in screen pixels)
 * @param top     Number of pixels from the top (in screen pixels)
 */
void
KeyboardControl::move_button(TCHAR ch, int left, int top)
{
  ButtonWindow *kb = get_button(ch);
  if (kb)
    kb->move(left, top);
}
Exemplo n.º 9
0
void Sub::default_js_buttons()
{
    JSButton::button_function_t defaults[16][2] = {
        {JSButton::button_function_t::k_none,                   JSButton::button_function_t::k_none},
        {JSButton::button_function_t::k_mode_manual,            JSButton::button_function_t::k_none},
        {JSButton::button_function_t::k_mode_depth_hold,        JSButton::button_function_t::k_none},
        {JSButton::button_function_t::k_mode_stabilize,         JSButton::button_function_t::k_none},

        {JSButton::button_function_t::k_disarm,                 JSButton::button_function_t::k_none},
        {JSButton::button_function_t::k_shift,                  JSButton::button_function_t::k_none},
        {JSButton::button_function_t::k_arm,                    JSButton::button_function_t::k_none},
        {JSButton::button_function_t::k_mount_center,           JSButton::button_function_t::k_none},

        {JSButton::button_function_t::k_input_hold_set,         JSButton::button_function_t::k_none},
        {JSButton::button_function_t::k_mount_tilt_down,        JSButton::button_function_t::k_none},
        {JSButton::button_function_t::k_mount_tilt_up,          JSButton::button_function_t::k_none},
        {JSButton::button_function_t::k_gain_inc,               JSButton::button_function_t::k_trim_pitch_dec},

        {JSButton::button_function_t::k_gain_dec,               JSButton::button_function_t::k_trim_pitch_inc},
        {JSButton::button_function_t::k_lights1_dimmer,         JSButton::button_function_t::k_trim_roll_dec},
        {JSButton::button_function_t::k_lights1_brighter,       JSButton::button_function_t::k_trim_roll_inc},
        {JSButton::button_function_t::k_none,                   JSButton::button_function_t::k_none},
    };

    for (int i = 0; i < 16; i++) {
        get_button(i)->set_default(defaults[i][0], defaults[i][1]);
    }
}
Exemplo n.º 10
0
/**
 * \brief Main entry of example application
 */
int main(void)
{
	/* Variable to store the last winner */
	uint8_t winner;

	system_init();
	delay_init();
	gfx_mono_init();

	init_buttons();
	init_display();

	/* Start game */
	while (true) {
		winner = 0;
		/* Wait for button interaction */
		while (get_button() == BUTTON_NONE) {
		}
		/* Draw empty board */
		setup_board();

		/* Start playing */
		for (int i = 0; i < 5; i++) {
			/* User's turn */
			user_turn();

			/* Check if the game is over */
			winner = we_have_a_winner();
			if (winner || i == 4) {
				break;
			}

			/* Add a delay for the opponent to "think" */
			delay_ms(500);
			/* Opponent's turn */
			opponent_turn();

			/* Check if the game is over */
			winner = we_have_a_winner();
			if (winner) {
				break;
			}
		}

		/* Game over, print winner and get ready for restart */
		if (winner == 1) {
			/* User won */
			gfx_mono_draw_string("You won!", STRING_X, 0, &sysfont);
			wins++;
		} else if (winner == 2) {
			gfx_mono_draw_string("You lost!", STRING_X, 0, &sysfont);
		} else {
			gfx_mono_draw_string("No winner!", STRING_X, 0, &sysfont);
		}

		gfx_mono_draw_string("Press a button", STRING_X, SQUARE3_Y, &sysfont);
		games++;
	}
}
Exemplo n.º 11
0
/**
 * Resizes the button to specified width and height values according to display pixels!
 *
 *
 * @param ch
 * @param width   Width measured in display pixels!
 * @param height  Height measured in display pixels!
 */
void
KeyboardControl::resize_button(TCHAR ch,
                               unsigned int width, unsigned int height)
{
  ButtonWindow *kb = get_button(ch);
  if (kb)
    kb->resize(width, height);
}
Exemplo n.º 12
0
/**
 * Resizes the button to specified width and height values according to display pixels!
 *
 *
 * @param ch
 * @param width   Width measured in display pixels!
 * @param height  Height measured in display pixels!
 */
void
KeyboardControl::resize_button(TCHAR ch,
                               UPixelScalar width, UPixelScalar height)
{
  ButtonWindow *kb = get_button(ch);
  if (kb)
    kb->Resize(width, height);
}
Exemplo n.º 13
0
gboolean update_applet(void *data)
{
	if (!redraw_applet)
		return TRUE;
	i3_ws *child;
	GtkWidget *b = (GtkWidget*)data;
	gtk_container_foreach(GTK_CONTAINER(b), (GtkCallback)gtk_widget_destroy, NULL);

	pthread_mutex_lock(&workspace_mutex);
	TAILQ_FOREACH(child, workspaces, tailq) {
		GtkWidget *w = get_button(child);
		gtk_container_add(GTK_CONTAINER(b), w);
	}
static GtkWidget *get_button_label(button_theme_t *theme)
{
    assert(theme != NULL);

    if (theme->button_label == NULL)
    {
        GtkWidget *button = get_button(theme);
        theme->button_label = pgtk_label_new(NULL);
        pgtk_container_add((GtkContainer *)button, theme->button_label);
    }

    return theme->button_label;
}
Exemplo n.º 15
0
void
KeyboardControl::move_buttons_to_row(const TCHAR* buttons, int row, int offset)
{
  if (string_is_empty(buttons))
    return;

  ButtonWindow *kb;
  for (unsigned i = 0; i < _tcslen(buttons); i++) {
    kb = get_button(buttons[i]);
    if (!kb)
      continue;

    kb->move(i * button_width + offset, row * button_height);
  }
}
Exemplo n.º 16
0
int main(void)
{

	setup();
	//puts("Hello!");

	while (true)
	{
		if (get_button())
		{

		}
	}

}
Exemplo n.º 17
0
/* Get the flags from the inspector; i.e. whether to sign or encrypt a
   message.  Returns 0 on success.  */
int
get_inspector_composer_flags (LPDISPATCH inspector,
                              bool *r_sign, bool *r_encrypt)
{
  LPDISPATCH button;
  int rc = 0;

  button = get_button (inspector, "GpgOL_Inspector_Sign");
  if (!button)
    {
      log_error ("%s:%s: Sign button not found", SRCNAME, __func__);
      rc = -1;
    }
  else
    {
      *r_sign = get_oom_int (button, "State") == msoButtonDown;
      button->Release ();
    }

  button = get_button (inspector, "GpgOL_Inspector_Encrypt");
  if (!button)
    {
      log_error ("%s:%s: Encrypt button not found", SRCNAME, __func__);
      rc = -1;
    }
  else
    {
      *r_encrypt = get_oom_int (button, "State") == msoButtonDown;
      button->Release ();
    }
  
  if (!rc)
    log_debug ("%s:%s: sign=%d encrypt=%d",
               SRCNAME, __func__, *r_sign, *r_encrypt);
  return rc;
}
Exemplo n.º 18
0
void
KeyboardControl::move_buttons_to_row(const TCHAR* buttons, int row,
                                     PixelScalar offset)
{
  if (StringIsEmpty(buttons))
    return;

  ButtonWindow *kb;
  for (unsigned i = 0; buttons[i] != _T('\0'); i++) {
    kb = get_button(buttons[i]);
    if (!kb)
      continue;

    kb->Move(i * button_width + offset, row * button_height);
  }
}
Exemplo n.º 19
0
/**
 *   \brief This will start a sleep operation.
 *
 *   \param val Used for remembering the new menu to display after a wakeup.
*/
void
menu_run_sleep(uint8_t *val)
{
    /* Turn off LED, LCD, ADC, Timer 1, SPI */
    led_off();
    lcd_deinit();
 	key_deinit();
    PRR |= (1 << PRTIM1) | (1 << PRSPI);

    /* Tell the 1284P to turn off the radio and sleep */
	sleep_count=0;
    uart_serial_send_frame(SEND_SLEEP, 1, (uint8_t *)&sleep_count);

    /* Turn off UART when transmission is complete */
	while(!(UCSR0A & (1 << TXC0)));
    _delay_us(10000); //deinit trash clears done flag on 1284p
	uart_deinit();

    /* Go to sleep until button is pushed */
    sleep_now(0);

    /* Yawn, waking up, turn on LCD with Raven Logo */
    lcd_init();
    lcd_symbol_set(LCD_SYMBOL_RAVEN);

	/* Disable interrupts before powering everything up */
    cli();
    key_init();
    PRR &= ~((1 << PRTIM1) | (1 << PRSPI));
 	uart_init();

    /* Enable interrupts, Wake up 1284p and radio */
	sei();
    sleep_wakeup();
//	uart_init();//flush receive buffer

    /* Wait for buttons up */
    while (key_state_get() != KEY_NO_KEY)
        ;
    if (is_button()){
        get_button();
    }
}
Exemplo n.º 20
0
static int
set_one_button (LPDISPATCH inspector, const char *tag, bool down)
{
  LPDISPATCH button;
  int rc = 0;

  button = get_button (inspector, tag);
  if (!button)
    {
      log_error ("%s:%s: `%s' not found", SRCNAME, __func__, tag);
      rc = -1;
    }
  else
    {
      if (put_oom_int (button, "State", down? msoButtonDown : msoButtonUp))
        rc = -1;
      button->Release ();
    }
  return rc;
}
Exemplo n.º 21
0
/**
 * \brief User turn
 * Waits for the user to push buttons and select a new square
 */
static void user_turn(void)
{
	static uint8_t square_num = 0;
	enum button button_pushed;
	highlight_square(square_num);

	while (true) {

		/* Wait for button interaction */
		do {
			button_pushed = get_button();
		} while (button_pushed == BUTTON_NONE);

		switch (button_pushed) {
		case BUTTON_1:
			/* Left */
			if (square_num > 0) {
				square_num--;
				highlight_square(square_num);
			}
			break;
		case BUTTON_2:
			if (occupied_squares[square_num / 3][square_num % 3] == NONE) {
				/* Select square and draw circle */
				occupied_squares[square_num / 3][square_num % 3] = USER;
				draw_circle(square_num);
				return;
			}
			/* Do not break, skip to next square */
		case BUTTON_3:
			/* Right */
			if (square_num < 8) {
				square_num++;
				highlight_square(square_num);
			}
			break;
		default:
			break;
		}
	}
}
Exemplo n.º 22
0
/**
 *   \brief This will start a sleep with wakes for temperature measurement and web requests.
 *
 *   \param val Used for remembering the new menu to display after a wakeup.
*/
void
menu_run_doze(uint8_t *val)
{
    /* Turn off LED, LCD */
    led_off();
    lcd_deinit();

    /* Debounce */
    while (key_state_get() != KEY_NO_KEY) ;
     
    /* Stay in doze loop until button is pressed*/
    while (ENTER_PORT & (1<<ENTER_PIN)) {
 
     /* Tell 1284p to sleep for 4 seconds */
	 /* It will ignore the request if TCP/IP sessions are active */
     /* Alter these timings as desired, or comment out to sleep only the 3290p */
		sleep_count=4;
        uart_serial_send_frame(SEND_SLEEP, 1, (uint8_t *)&sleep_count);

     /* Wait for transmission complete, then sleep 3290p for 5 seconds */
 		while(!(UCSR0A & (1 << TXC0)));
//		uart_deinit();
        sleep_now(sleep_count+1);
//		uart_init();

    /* 1284p should be awake by now, update temperature and give it time to process */
		menu_send_temp();
	    _delay_us(20000);
 	}

    /* Wake LCD, turn on Raven logo */
    lcd_init();
    lcd_symbol_set(LCD_SYMBOL_RAVEN);
    sleep_wakeup();
    /* Wait for buttons up */
    while (key_state_get() != KEY_NO_KEY)
        ;
    if (is_button()){
        get_button();
    }
}
static HRESULT draw_button(button_theme_t *theme, cairo_t *cr, int state_id, int width, int height)
{
    GtkStateFlags state = get_push_button_state_flags(state_id);
    GtkStyleContext *context;

    assert(theme != NULL);

    context = pgtk_widget_get_style_context(get_button(theme));
    pgtk_style_context_save(context);

    pgtk_style_context_set_state(context, state);

    if (state_id == PBS_DEFAULTED)
        pgtk_style_context_add_class(context, GTK_STYLE_CLASS_DEFAULT);

    pgtk_render_background(context, cr, 0, 0, width, height);
    pgtk_render_frame(context, cr, 0, 0, width, height);

    pgtk_style_context_restore(context);

    return S_OK;
}
Exemplo n.º 24
0
void Sub::handle_jsbutton_release(uint8_t button, bool shift) {

    // Act based on the function assigned to this button
    switch (get_button(button)->function(shift)) {
    case JSButton::button_function_t::k_relay_1_momentary:
        relay.off(0);
        break;
    case JSButton::button_function_t::k_relay_2_momentary:
        relay.off(1);
        break;
    case JSButton::button_function_t::k_relay_3_momentary:
        relay.off(2);
        break;
    case JSButton::button_function_t::k_relay_4_momentary:
        relay.off(3);
        break;
    case JSButton::button_function_t::k_servo_1_min_momentary:
    case JSButton::button_function_t::k_servo_1_max_momentary:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_1 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_1, chan->get_trim()); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_2_min_momentary:
    case JSButton::button_function_t::k_servo_2_max_momentary:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_2 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_2, chan->get_trim()); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_3_min_momentary:
    case JSButton::button_function_t::k_servo_3_max_momentary:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_3 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_3, chan->get_trim()); // 1-indexed
    }
        break;
    }
}
Exemplo n.º 25
0
bool confirm(int confirmButton, const char *fmt, ...) {
    char s[512];
    memset(s, 0, 512);
    va_list args;
    va_start(args, fmt);
    vsprintf(s, fmt, args);
    va_end(args);

    while (aptMainLoop()) {
        hidScanInput();
        u32 key = hidKeysDown();
        if (key & BIT(confirmButton)) {
            return true;
        } else if (key) {
            return false;
        }

        drawBg();
        gfxDrawText(GFX_TOP, GFX_LEFT, &fontDefault, s, MENU_MIN_X + 16, MENU_MIN_Y + 16);
        gfxDrawText(GFX_TOP, GFX_LEFT, &fontDefault, "Press any key to cancel...", MENU_MIN_X + 16, MENU_MIN_Y + 64);
        gfxDrawTextf(GFX_TOP, GFX_LEFT, &fontDefault, MENU_MIN_X + 16, MENU_MIN_Y + 84, "Press (%s) to confirm...", get_button(confirmButton));
        gfxSwap();
    }
}
U16 cgi_func (U8 *env, U8 *buf, U16 buflen, U32 *pcgi) {
  /* This function is called by HTTP server script interpreter to make a    */
  /* formated output for 'stdout'. It returns the number of bytes written   */
  /* to the output buffer. Hi-bit of return value (len is or-ed with 0x8000)*/
  /* is a repeat flag for the system script interpreter. If this bit is set */
  /* to 1, the system will call the 'cgi_func()' again for the same script  */
  /* line with parameter 'pcgi' pointing to a 4-byte buffer. This buffer    */
  /* can be used for storing different status variables for this function.  */
  /* It is set to 0 by HTTP Server on first call and is not altered by      */
  /* HTTP server for repeated calls. This function should NEVER write more  */
  /* than 'buflen' bytes to the buffer.                                     */
  /* Parameters:                                                            */
  /*   env    - environment variable string                                 */
  /*   buf    - HTTP transmit buffer                                        */
  /*   buflen - length of this buffer (500-1400 bytes - depends on MSS)     */
  /*   pcgi   - pointer to session local buffer used for repeated loops     */
  /*            This is a U32 variable - size is 4 bytes. Value is:         */
  /*            - on 1st call = 0                                           */
  /*            - 2nd call    = as set by this function on first call       */
  TCP_INFO *tsoc;
  U32 len = 0;
  U8 id, *lang;
  static U32 adv;

  switch (env[0]) {
    /* Analyze the environment string. It is the script 'c' line starting */
    /* at position 2. What you write to the script file is returned here. */
    case 'a' :
      /* Network parameters - file 'network.cgi' */
      switch (env[2]) {
        case 'i':
          /* Write the local IP address. The format string is included */
          /* in environment string of the script line.                 */
          len = sprintf((char *)buf,(const char *)&env[4],LocM.IpAdr[0],
                        LocM.IpAdr[1],LocM.IpAdr[2],LocM.IpAdr[3]);
          break;
        case 'm':
          /* Write local Net mask. */
          len = sprintf((char *)buf,(const char *)&env[4],LocM.NetMask[0],
                        LocM.NetMask[1],LocM.NetMask[2],LocM.NetMask[3]);
          break;
        case 'g':
          /* Write default gateway address. */
          len = sprintf((char *)buf,(const char *)&env[4],LocM.DefGW[0],
                        LocM.DefGW[1],LocM.DefGW[2],LocM.DefGW[3]);
          break;
        case 'p':
          /* Write primary DNS server address. */
          len = sprintf((char *)buf,(const char *)&env[4],LocM.PriDNS[0],
                        LocM.PriDNS[1],LocM.PriDNS[2],LocM.PriDNS[3]);
          break;
        case 's':
          /* Write secondary DNS server address. */
          len = sprintf((char *)buf,(const char *)&env[4],LocM.SecDNS[0],
                        LocM.SecDNS[1],LocM.SecDNS[2],LocM.SecDNS[3]);
          break;
      }
      break;

    case 'b':
      /* LED control - file 'led.cgi' */
      if (env[2] == 'c') {
        /* Select Control */
        len = sprintf((char *)buf,(const char *)&env[4],LEDrun ? "" : "selected",
                                                        LEDrun ? "selected" : "");
        break;
      }
      /* LED CheckBoxes */
      id = env[2] - '0';
      if (id > 7) {
        id = 0;
      }
      id = 1 << id;
      len = sprintf((char *)buf,(const char *)&env[4],(P2 & id) ? "checked" : "");
      break;

    case 'c':
      /* TCP status - file 'tcp.cgi' */
      while ((len + 150) < buflen) {
        tsoc = &tcp_socket[MYBUF(pcgi)->xcnt];
        MYBUF(pcgi)->xcnt++;
        /* 'sprintf' format string is defined here. */
        len += sprintf((char *)(buf+len),"<tr align=\"center\">");
        if (tsoc->State <= TCP_STATE_CLOSED) {
          len += sprintf ((char *)(buf+len),
                          "<td>%d</td><td>%s</td><td>-</td><td>-</td>"
                          "<td>-</td><td>-</td></tr>\r\n",
                          MYBUF(pcgi)->xcnt,state[tsoc->State]);
        }
        else if (tsoc->State == TCP_STATE_LISTEN) {
          len += sprintf ((char *)(buf+len),
                          "<td>%d</td><td>%s</td><td>-</td><td>-</td>"
                          "<td>%d</td><td>-</td></tr>\r\n",
                          MYBUF(pcgi)->xcnt,state[tsoc->State],tsoc->LocPort);
        }
        else {
          len += sprintf ((char *)(buf+len),
                          "<td>%d</td><td>%s</td><td>%d.%d.%d.%d</td>"
                          "<td>%d</td><td>%d</td><td>%d</td></tr>\r\n",
                          MYBUF(pcgi)->xcnt,state[tsoc->State],
                          tsoc->RemIpAdr[0],tsoc->RemIpAdr[1],
                          tsoc->RemIpAdr[2],tsoc->RemIpAdr[3],
                          tsoc->RemPort,tsoc->LocPort,tsoc->AliveTimer);
        }
        /* Repeat for all TCP Sockets. */
        if (MYBUF(pcgi)->xcnt == tcp_NumSocks) {
          break;
        }
      }
      if (MYBUF(pcgi)->xcnt < tcp_NumSocks) {
        /* Hi bit is a repeat flag. */
        len |= 0x8000;
      }
      break;

    case 'd':
      /* System password - file 'system.cgi' */
      switch (env[2]) {
        case '1':
          len = sprintf((char *)buf,(const char *)&env[4],
                        http_EnAuth ? "Enabled" : "Disabled");
          break;
        case '2':
          len = sprintf((char *)buf,(const char *)&env[4],http_auth_passw);
          break;
      }
      break;

    case 'e':
      /* Browser Language - file 'language.cgi' */
      lang = http_get_lang();
      if (strcmp ((const char *)lang, "en") == 0) {
        lang = "English";
      }
      else if (strcmp ((const char *)lang, "en-us") == 0) {
        lang = "English USA";
      }
      else if (strcmp ((const char *)lang, "en-gb") == 0) {
        lang = "English GB";
      }
      else if (strcmp ((const char *)lang, "de") == 0) {
        lang = "German";
      }
      else if (strcmp ((const char *)lang, "de-ch") == 0) {
        lang = "German CH";
      }
      else if (strcmp ((const char *)lang, "de-at") == 0) {
        lang = "German AT";
      }
      else if (strcmp ((const char *)lang, "fr") == 0) {
        lang = "French";
      }
      else if (strcmp ((const char *)lang, "sl") == 0) {
        lang = "Slovene";
      }
      else {
        lang = "Unknown";
      }
      len = sprintf((char *)buf,(const char *)&env[2],lang,http_get_lang());
      break;

    case 'f':
      /* LCD Module control - file 'lcd.cgi' */
      switch (env[2]) {
        case '1':
          len = sprintf((char *)buf,(const char *)&env[4],lcd_text[0]);
          break;
        case '2':
          len = sprintf((char *)buf,(const char *)&env[4],lcd_text[1]);
          break;
      }
      break;

    case 'g':
      /* AD Input - file 'ad.cgi' */
      switch (env[2]) {
        case '1':
          adv = AD_in (0);
          len = sprintf((char *)buf,(const char *)&env[4],adv);
          break;
        case '2':
          len = sprintf((char *)buf,(const char *)&env[4],(float)adv*3.3/4096);
          break;
        case '3':
          adv = (adv * 100) / 4096;
          len = sprintf((char *)buf,(const char *)&env[4],adv);
          break;
      }
      break;

    case 'x':
      /* AD Input - xml file 'ad.cgx' */
      adv = AD_in (0);
      len = sprintf((char *)buf,(const char *)&env[1],adv);
      break;

    case 'y':
      /* Button state - xml file 'button.cgx' */
      len = sprintf((char *)buf,"<checkbox><id>button%c</id><on>%s</on></checkbox>",
                    env[1],(get_button () & (1 << (env[1]-'0'))) ? "true" : "false");
      break;
  }
  return ((U16)len);
}
Exemplo n.º 27
0
static void read_key (int mode) {
  /* Read ARM Digital Input */
  if (mode == MIB_READ) {
    KeyIn = get_button();
  }
}
Exemplo n.º 28
0
enum plugin_status plugin_start(const void* parameter)
{
    int button;
    int i;
    (void)parameter;

    if (!can_play()) {
        rb->splash(4*HZ, "No track to resume! This plugin will resume a track "
                         "at a specific time. Therefore, you need to first play"
                         " one, and then pause it and start the plugin again.");
        quit = true;
    }

    while(!quit) {
        button = get_button();

        if (button == PLA_EXIT || button == PLA_CANCEL)
            quit = true;

        FOR_NB_SCREENS(i) {
            draw(rb->screens[i]);
        }
        if (waiting) {
            if (rem_seconds() <= 0) {
                quit = done = true;
                play();
            }
        }
        else {
            switch (button) {
                case PLA_UP:
                case PLA_UP_REPEAT:
#ifdef HAVE_SCROLLWHEEL
                case PLA_SCROLL_FWD:
                case PLA_SCROLL_FWD_REPEAT:
#endif
                    alarm[current] = (alarm[current] + 1) % maxval[current];
                    break;
                case PLA_DOWN:
                case PLA_DOWN_REPEAT:
#ifdef HAVE_SCROLLWHEEL
                case PLA_SCROLL_BACK:
                case PLA_SCROLL_BACK_REPEAT:
#endif
                    alarm[current] = (alarm[current] + maxval[current] - 1)
                        % maxval[current];
                    break;

                case PLA_LEFT:
                case PLA_LEFT_REPEAT:
                case PLA_RIGHT:
                case PLA_RIGHT_REPEAT:
                    current = (current + 1) % 2;
                    break;

                case PLA_SELECT:
                case PLA_SELECT_REPEAT: {
                    if (rem_seconds() < 0)
                        tomorrow = true;

                    waiting = true;
                    break;
                }

                default:
                    if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
                        quit = usb = true;
                    break;
            }
        }
    }

    return (usb) ? PLUGIN_USB_CONNECTED
                 : (done ? PLUGIN_GOTO_WPS : PLUGIN_OK);
}
Exemplo n.º 29
0
void Sub::transform_manual_control_to_rc_override(int16_t x, int16_t y, int16_t z, int16_t r, uint16_t buttons)
{

    int16_t channels[11];

    float rpyScale = 0.4*gain; // Scale -1000-1000 to -400-400 with gain
    float throttleScale = 0.8*gain*g.throttle_gain; // Scale 0-1000 to 0-800 times gain
    int16_t rpyCenter = 1500;
    int16_t throttleBase = 1500-500*throttleScale;

    bool shift = false;

    // Neutralize camera tilt speed setpoint
    cam_tilt = 1500;

    // Detect if any shift button is pressed
    for (uint8_t i = 0 ; i < 16 ; i++) {
        if ((buttons & (1 << i)) && get_button(i)->function() == JSButton::button_function_t::k_shift) {
            shift = true;
        }
    }

    // Act if button is pressed
    // Only act upon pressing button and ignore holding. This provides compatibility with Taranis as joystick.
    for (uint8_t i = 0 ; i < 16 ; i++) {
        if ((buttons & (1 << i))) {
            handle_jsbutton_press(i,shift,(buttons_prev & (1 << i)));
        }
    }

    buttons_prev = buttons;

    // Set channels to override
    if (!roll_pitch_flag) {
        channels[0] = 1500 + pitchTrim; // pitch
        channels[1] = 1500 + rollTrim;  // roll
    } else {
        // adjust roll and pitch with joystick input instead of forward and lateral
        channels[0] = constrain_int16((x+pitchTrim)*rpyScale+rpyCenter,1100,1900);
        channels[1] = constrain_int16((y+rollTrim)*rpyScale+rpyCenter,1100,1900);
    }

    channels[2] = constrain_int16((z+zTrim)*throttleScale+throttleBase,1100,1900); // throttle
    channels[3] = constrain_int16(r*rpyScale+rpyCenter,1100,1900);                 // yaw

    if (!roll_pitch_flag) {
        // adjust forward and lateral with joystick input instead of roll and pitch
        channels[4] = constrain_int16((x+xTrim)*rpyScale+rpyCenter,1100,1900); // forward for ROV
        channels[5] = constrain_int16((y+yTrim)*rpyScale+rpyCenter,1100,1900); // lateral for ROV
    } else {
        // neutralize forward and lateral input while we are adjusting roll and pitch
        channels[4] = constrain_int16(xTrim*rpyScale+rpyCenter,1100,1900); // forward for ROV
        channels[5] = constrain_int16(yTrim*rpyScale+rpyCenter,1100,1900); // lateral for ROV
    }

    channels[6] = 0;             // Unused
    channels[7] = cam_tilt;      // camera tilt
    channels[8] = lights1;       // lights 1
    channels[9] = lights2;       // lights 2
    channels[10] = video_switch; // video switch

    // Store old x, y, z values for use in input hold logic
    x_last = x;
    y_last = y;
    z_last = z;

    hal.rcin->set_overrides(channels, 10);
}
Exemplo n.º 30
0
void Sub::handle_jsbutton_press(uint8_t button, bool shift, bool held)
{
    // Act based on the function assigned to this button
    switch (get_button(button)->function(shift)) {
    case JSButton::button_function_t::k_arm_toggle:
        if (motors.armed()) {
            init_disarm_motors();
        } else {
            init_arm_motors(true);
        }
        break;
    case JSButton::button_function_t::k_arm:
        init_arm_motors(true);
        break;
    case JSButton::button_function_t::k_disarm:
        init_disarm_motors();
        break;

    case JSButton::button_function_t::k_mode_manual:
        set_mode(MANUAL, MODE_REASON_TX_COMMAND);
        break;
    case JSButton::button_function_t::k_mode_stabilize:
        set_mode(STABILIZE, MODE_REASON_TX_COMMAND);
        break;
    case JSButton::button_function_t::k_mode_depth_hold:
        set_mode(ALT_HOLD, MODE_REASON_TX_COMMAND);
        break;
    case JSButton::button_function_t::k_mode_auto:
        set_mode(AUTO, MODE_REASON_TX_COMMAND);
        break;
    case JSButton::button_function_t::k_mode_guided:
        set_mode(GUIDED, MODE_REASON_TX_COMMAND);
        break;
    case JSButton::button_function_t::k_mode_circle:
        set_mode(CIRCLE, MODE_REASON_TX_COMMAND);
        break;
    case JSButton::button_function_t::k_mode_acro:
        set_mode(ACRO, MODE_REASON_TX_COMMAND);
        break;
    case JSButton::button_function_t::k_mode_poshold:
        set_mode(POSHOLD, MODE_REASON_TX_COMMAND);
        break;

    case JSButton::button_function_t::k_mount_center:
        camera_mount.set_angle_targets(0, 0, 0);
        // for some reason the call to set_angle_targets changes the mode to mavlink targeting!
        camera_mount.set_mode(MAV_MOUNT_MODE_RC_TARGETING);
        break;
    case JSButton::button_function_t::k_mount_tilt_up:
        cam_tilt = 1900;
        break;
    case JSButton::button_function_t::k_mount_tilt_down:
        cam_tilt = 1100;
        break;
    case JSButton::button_function_t::k_camera_trigger:
        break;
    case JSButton::button_function_t::k_camera_source_toggle:
        if (!held) {
            static bool video_toggle = false;
            video_toggle = !video_toggle;
            if (video_toggle) {
                video_switch = 1900;
                gcs().send_text(MAV_SEVERITY_INFO,"Video Toggle: Source 2");
            } else {
                video_switch = 1100;
                gcs().send_text(MAV_SEVERITY_INFO,"Video Toggle: Source 1");
            }
        }
        break;
    case JSButton::button_function_t::k_mount_pan_right:
        // Not implemented
        break;
    case JSButton::button_function_t::k_mount_pan_left:
        // Not implemented
        break;
    case JSButton::button_function_t::k_lights1_cycle:
        if (!held) {
            static bool increasing = true;
            RC_Channel* chan = RC_Channels::rc_channel(8);
            uint16_t min = chan->get_radio_min();
            uint16_t max = chan->get_radio_max();
            uint16_t step = (max - min) / g.lights_steps;
            if (increasing) {
                lights1 = constrain_float(lights1 + step, min, max);
            } else {
                lights1 = constrain_float(lights1 - step, min, max);
            }
            if (lights1 >= max || lights1 <= min) {
                increasing = !increasing;
            }
        }
        break;
    case JSButton::button_function_t::k_lights1_brighter:
        if (!held) {
            RC_Channel* chan = RC_Channels::rc_channel(8);
            uint16_t min = chan->get_radio_min();
            uint16_t max = chan->get_radio_max();
            uint16_t step = (max - min) / g.lights_steps;
            lights1 = constrain_float(lights1 + step, min, max);
        }
        break;
    case JSButton::button_function_t::k_lights1_dimmer:
        if (!held) {
            RC_Channel* chan = RC_Channels::rc_channel(8);
            uint16_t min = chan->get_radio_min();
            uint16_t max = chan->get_radio_max();
            uint16_t step = (max - min) / g.lights_steps;
            lights1 = constrain_float(lights1 - step, min, max);
        }
        break;
    case JSButton::button_function_t::k_lights2_cycle:
        if (!held) {
            static bool increasing = true;
            RC_Channel* chan = RC_Channels::rc_channel(9);
            uint16_t min = chan->get_radio_min();
            uint16_t max = chan->get_radio_max();
            uint16_t step = (max - min) / g.lights_steps;
            if (increasing) {
                lights2 = constrain_float(lights2 + step, min, max);
            } else {
                lights2 = constrain_float(lights2 - step, min, max);
            }
            if (lights2 >= max || lights2 <= min) {
                increasing = !increasing;
            }
        }
        break;
    case JSButton::button_function_t::k_lights2_brighter:
        if (!held) {
            RC_Channel* chan = RC_Channels::rc_channel(9);
            uint16_t min = chan->get_radio_min();
            uint16_t max = chan->get_radio_max();
            uint16_t step = (max - min) / g.lights_steps;
            lights2 = constrain_float(lights2 + step, min, max);
        }
        break;
    case JSButton::button_function_t::k_lights2_dimmer:
        if (!held) {
            RC_Channel* chan = RC_Channels::rc_channel(9);
            uint16_t min = chan->get_radio_min();
            uint16_t max = chan->get_radio_max();
            uint16_t step = (max - min) / g.lights_steps;
            lights2 = constrain_float(lights2 - step, min, max);
        }
        break;
    case JSButton::button_function_t::k_gain_toggle:
        if (!held) {
            static bool lowGain = false;
            lowGain = !lowGain;
            if (lowGain) {
                gain = 0.5f;
            } else {
                gain = 1.0f;
            }
            gcs().send_text(MAV_SEVERITY_INFO,"#Gain: %2.0f%%",(double)gain*100);
        }
        break;
    case JSButton::button_function_t::k_gain_inc:
        if (!held) {
            // check that our gain parameters are in correct range, update in eeprom and notify gcs if needed
            g.minGain.set_and_save(constrain_float(g.minGain, 0.10, 0.80));
            g.maxGain.set_and_save(constrain_float(g.maxGain, g.minGain, 1.0));
            g.numGainSettings.set_and_save(constrain_int16(g.numGainSettings, 1, 10));

            if (g.numGainSettings == 1) {
                gain = constrain_float(g.gain_default, g.minGain, g.maxGain);
            } else {
                gain = constrain_float(gain + (g.maxGain-g.minGain)/(g.numGainSettings-1), g.minGain, g.maxGain);
            }

            gcs().send_text(MAV_SEVERITY_INFO,"#Gain is %2.0f%%",(double)gain*100);
        }
        break;
    case JSButton::button_function_t::k_gain_dec:
        if (!held) {
            // check that our gain parameters are in correct range, update in eeprom and notify gcs if needed
            g.minGain.set_and_save(constrain_float(g.minGain, 0.10, 0.80));
            g.maxGain.set_and_save(constrain_float(g.maxGain, g.minGain, 1.0));
            g.numGainSettings.set_and_save(constrain_int16(g.numGainSettings, 1, 10));

            if (g.numGainSettings == 1) {
                gain = constrain_float(g.gain_default, g.minGain, g.maxGain);
            } else {
                gain = constrain_float(gain - (g.maxGain-g.minGain)/(g.numGainSettings-1), g.minGain, g.maxGain);
            }

            gcs().send_text(MAV_SEVERITY_INFO,"#Gain is %2.0f%%",(double)gain*100);
        }
        break;
    case JSButton::button_function_t::k_trim_roll_inc:
        rollTrim = constrain_float(rollTrim+10,-200,200);
        break;
    case JSButton::button_function_t::k_trim_roll_dec:
        rollTrim = constrain_float(rollTrim-10,-200,200);
        break;
    case JSButton::button_function_t::k_trim_pitch_inc:
        pitchTrim = constrain_float(pitchTrim+10,-200,200);
        break;
    case JSButton::button_function_t::k_trim_pitch_dec:
        pitchTrim = constrain_float(pitchTrim-10,-200,200);
        break;
    case JSButton::button_function_t::k_input_hold_set:
        if(!motors.armed()) {
            break;
        }
        if (!held) {
            zTrim = abs(z_last-500) > 50 ? z_last-500 : 0;
            xTrim = abs(x_last) > 50 ? x_last : 0;
            yTrim = abs(y_last) > 50 ? y_last : 0;
            bool input_hold_engaged_last = input_hold_engaged;
            input_hold_engaged = zTrim || xTrim || yTrim;
            if (input_hold_engaged) {
                gcs().send_text(MAV_SEVERITY_INFO,"#Input Hold Set");
            } else if (input_hold_engaged_last) {
                gcs().send_text(MAV_SEVERITY_INFO,"#Input Hold Disabled");
            }
        }
        break;
    case JSButton::button_function_t::k_relay_1_on:
        relay.on(0);
        break;
    case JSButton::button_function_t::k_relay_1_off:
        relay.off(0);
        break;
    case JSButton::button_function_t::k_relay_1_toggle:
        if (!held) {
            relay.toggle(0);
        }
        break;
    case JSButton::button_function_t::k_relay_2_on:
        relay.on(1);
        break;
    case JSButton::button_function_t::k_relay_2_off:
        relay.off(1);
        break;
    case JSButton::button_function_t::k_relay_2_toggle:
        if (!held) {
            relay.toggle(1);
        }
        break;
    case JSButton::button_function_t::k_relay_3_on:
        relay.on(2);
        break;
    case JSButton::button_function_t::k_relay_3_off:
        relay.off(2);
        break;
    case JSButton::button_function_t::k_relay_3_toggle:
        if (!held) {
            relay.toggle(2);
        }
        break;
    case JSButton::button_function_t::k_relay_4_on:
        relay.on(3);
        break;
    case JSButton::button_function_t::k_relay_4_off:
        relay.off(3);
        break;
    case JSButton::button_function_t::k_relay_4_toggle:
        if (!held) {
            relay.toggle(3);
        }
        break;

    ////////////////////////////////////////////////
    // Servo functions
    // TODO: initialize
    case JSButton::button_function_t::k_servo_1_inc:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_1 - 1); // 0-indexed
        uint16_t pwm_out = hal.rcout->read(SERVO_CHAN_1 - 1); // 0-indexed
        pwm_out = constrain_int16(pwm_out + 50, chan->get_output_min(), chan->get_output_max());
        ServoRelayEvents.do_set_servo(SERVO_CHAN_1, pwm_out); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_1_dec:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_1 - 1); // 0-indexed
        uint16_t pwm_out = hal.rcout->read(SERVO_CHAN_1 - 1); // 0-indexed
        pwm_out = constrain_int16(pwm_out - 50, chan->get_output_min(), chan->get_output_max());
        ServoRelayEvents.do_set_servo(SERVO_CHAN_1, pwm_out); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_1_min:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_1 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_1, chan->get_output_min()); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_1_max:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_1 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_1, chan->get_output_max()); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_1_center:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_1 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_1, chan->get_trim()); // 1-indexed
    }
        break;

    case JSButton::button_function_t::k_servo_2_inc:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_2 - 1); // 0-indexed
        uint16_t pwm_out = hal.rcout->read(SERVO_CHAN_2 - 1); // 0-indexed
        pwm_out = constrain_int16(pwm_out + 50, chan->get_output_min(), chan->get_output_max());
        ServoRelayEvents.do_set_servo(SERVO_CHAN_2, pwm_out); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_2_dec:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_2 - 1); // 0-indexed
        uint16_t pwm_out = hal.rcout->read(SERVO_CHAN_2 - 1); // 0-indexed
        pwm_out = constrain_int16(pwm_out - 50, chan->get_output_min(), chan->get_output_max());
        ServoRelayEvents.do_set_servo(SERVO_CHAN_2, pwm_out); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_2_min:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_2 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_2, chan->get_output_min()); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_2_max:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_2 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_2, chan->get_output_max()); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_2_center:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_2 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_2, chan->get_trim()); // 1-indexed
    }
        break;

    case JSButton::button_function_t::k_servo_3_inc:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_3 - 1); // 0-indexed
        uint16_t pwm_out = hal.rcout->read(SERVO_CHAN_3 - 1); // 0-indexed
        pwm_out = constrain_int16(pwm_out + 50, chan->get_output_min(), chan->get_output_max());
        ServoRelayEvents.do_set_servo(SERVO_CHAN_3, pwm_out); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_3_dec:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_3 - 1); // 0-indexed
        uint16_t pwm_out = hal.rcout->read(SERVO_CHAN_3 - 1); // 0-indexed
        pwm_out = constrain_int16(pwm_out - 50, chan->get_output_min(), chan->get_output_max());
        ServoRelayEvents.do_set_servo(SERVO_CHAN_3, pwm_out); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_3_min:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_3 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_3, chan->get_output_min()); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_3_max:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_3 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_3, chan->get_output_max()); // 1-indexed
    }
        break;
    case JSButton::button_function_t::k_servo_3_center:
    {
        SRV_Channel* chan = SRV_Channels::srv_channel(SERVO_CHAN_3 - 1); // 0-indexed
        ServoRelayEvents.do_set_servo(SERVO_CHAN_3, chan->get_trim()); // 1-indexed
    }
        break;

    case JSButton::button_function_t::k_roll_pitch_toggle:
        if (!held) {
            roll_pitch_flag = !roll_pitch_flag;
        }
        break;

    case JSButton::button_function_t::k_custom_1:
        // Not implemented
        break;
    case JSButton::button_function_t::k_custom_2:
        // Not implemented
        break;
    case JSButton::button_function_t::k_custom_3:
        // Not implemented
        break;
    case JSButton::button_function_t::k_custom_4:
        // Not implemented
        break;
    case JSButton::button_function_t::k_custom_5:
        // Not implemented
        break;
    case JSButton::button_function_t::k_custom_6:
        // Not implemented
        break;
    }
}