mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-11-04 07:12:33 +01:00 
			
		
		
		
	Fixup dekunukem/duckypad (#21298)
				
					
				
			This commit is contained in:
		
							parent
							
								
									a68e9f0116
								
							
						
					
					
						commit
						74fbd5a031
					
				@ -20,62 +20,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#define RGB_MATRIX_LED_COUNT 15
 | 
			
		||||
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
 | 
			
		||||
#define RGB_MATRIX_LED_COUNT 15
 | 
			
		||||
#define RGB_MATRIX_KEYPRESSES
 | 
			
		||||
#define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_SOLID_REACTIVE_SIMPLE
 | 
			
		||||
#define RGB_MATRIX_DEFAULT_HUE 221
 | 
			
		||||
// RGB Matrix Animation modes. Explicitly enabled
 | 
			
		||||
// For full list of effects, see:
 | 
			
		||||
// https://docs.qmk.fm/#/feature_rgb_matrix?id=rgb-matrix-effects
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_ALPHAS_MODS
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_BREATHING
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_BAND_SAT
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_BAND_VAL
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_CYCLE_ALL
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_CYCLE_OUT_IN
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_CYCLE_SPIRAL
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_DUAL_BEACON
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_RAINBOW_BEACON
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_RAINDROPS
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_HUE_BREATHING
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_HUE_PENDULUM
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_HUE_WAVE
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_PIXEL_RAIN
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_PIXEL_FLOW
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_PIXEL_FRACTAL
 | 
			
		||||
// enabled only if RGB_MATRIX_FRAMEBUFFER_EFFECTS is defined
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_TYPING_HEATMAP
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_DIGITAL_RAIN
 | 
			
		||||
// enabled only of RGB_MATRIX_KEYPRESSES or RGB_MATRIX_KEYRELEASES is defined
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_SPLASH
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_MULTISPLASH
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_SOLID_SPLASH
 | 
			
		||||
#    define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define I2C1_SCL_PIN B8
 | 
			
		||||
 | 
			
		||||
@ -20,32 +20,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
#include "quantum.h"
 | 
			
		||||
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
 | 
			
		||||
led_config_t g_led_config = { {
 | 
			
		||||
    { 2, 1, 0, 3, 4, 5, 8, 7, 6, 9, 10, 11, 14, 13, 12, NO_LED, NO_LED }
 | 
			
		||||
}, {
 | 
			
		||||
    {224, 0},
 | 
			
		||||
    {112, 0},
 | 
			
		||||
    {0, 0},
 | 
			
		||||
    {0, 16},
 | 
			
		||||
    {112, 16},
 | 
			
		||||
    {224, 16},
 | 
			
		||||
    {224, 32},
 | 
			
		||||
    {112, 32},
 | 
			
		||||
    {0, 32},
 | 
			
		||||
    {0, 48},
 | 
			
		||||
    {112, 48},
 | 
			
		||||
    {224, 48},
 | 
			
		||||
    {224, 64},
 | 
			
		||||
    {112, 64},
 | 
			
		||||
    {0, 64},
 | 
			
		||||
}, {
 | 
			
		||||
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 | 
			
		||||
} };
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void keyboard_pre_init_kb(void) {
 | 
			
		||||
    setPinOutput(A0);
 | 
			
		||||
    writePinHigh(A0);
 | 
			
		||||
@ -55,3 +29,21 @@ void keyboard_pre_init_kb(void) {
 | 
			
		||||
 | 
			
		||||
    keyboard_pre_init_user();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef OLED_ENABLE
 | 
			
		||||
#    define LOGO_SIZE 384
 | 
			
		||||
bool oled_task_kb(void) {
 | 
			
		||||
    if (!oled_task_user()) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    static const char PROGMEM ducky_logo[LOGO_SIZE] = {
 | 
			
		||||
      // clang-format off
 | 
			
		||||
      0, 0, 0, 0,128,128,128,128,128, 0, 0,252,252,252, 0, 0, 0,128,128,128, 0, 0, 0, 0, 0,128,128,128, 0, 0, 0, 0, 0,128,128,128,128,128, 0, 0, 0, 0, 0,252,252,252, 0, 0, 0, 0, 0,128,128,128,128,128,128, 0, 0, 0, 0, 0, 0,128,128,128,128, 0,248,248,248, 56, 56, 56, 56, 56, 56,120,240,224,192, 0, 0,128,128,128,128,128,128, 0, 0, 0, 0, 0, 0, 0, 0,128,128,128,128,128, 0, 0,252,252,252, 0, 0, 0, 0, 0,232, 24, 24,232, 0, 24, 48, 48, 24, 0,232, 24, 24,232, 0, 0,
 | 
			
		||||
      0,248,254,255,143, 7, 3, 3, 3, 7,142,255,255,255, 0, 0, 0,255,255,255, 0, 0, 0, 0, 0,255,255,255, 0,248,254,255,143, 7, 3, 3, 3, 3,143, 7, 2, 0, 0,255,255,255,240,120,252,254,231,131, 1, 0, 1, 7, 63,254,240,192, 0,224,252,127, 31, 3, 0, 0,255,255,255,112,112,112,112,112,112, 56, 63, 31, 15,193,231,243,115, 51, 51, 51, 55,255,255,252, 0, 0,248,254,255,143, 7, 3, 3, 3, 7,142,255,255,255, 0, 0, 0, 0, 0, 21,127,127,252,252,252,253,253,252,252,252,255,255,255, 0, 0,
 | 
			
		||||
      0, 0, 3, 7, 15, 15, 14, 14, 14, 7, 3, 15, 15, 15, 0, 0, 0, 3, 7, 15, 15, 14, 14, 6, 3, 15, 15, 15, 0, 0, 3, 7, 7, 15, 14, 14, 14, 14, 7, 7, 2, 0, 0, 15, 15, 15, 0, 0, 0, 1, 3, 15, 15, 12,136,224,224,224,247,127,127, 31, 3, 0, 0, 0, 0, 0, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 15, 14, 14, 14, 6, 3, 15, 15, 15, 0, 0, 0, 3, 7, 15, 15, 14, 14, 14, 7, 3, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 7, 11, 3, 11, 7, 11, 7, 7, 31, 0, 0
 | 
			
		||||
      //clang-format on
 | 
			
		||||
    };
 | 
			
		||||
    oled_write_raw_P(ducky_logo, LOGO_SIZE);
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -8,11 +8,79 @@
 | 
			
		||||
        "pid": "0x4450",
 | 
			
		||||
        "device_version": "0.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "features": {
 | 
			
		||||
      "extrakey": true,
 | 
			
		||||
      "rgb_matrix": true,
 | 
			
		||||
      "oled": true
 | 
			
		||||
    },
 | 
			
		||||
    "ws2812": {
 | 
			
		||||
        "pin": "A10"
 | 
			
		||||
    },
 | 
			
		||||
    "rgb_matrix": {
 | 
			
		||||
        "driver": "WS2812"
 | 
			
		||||
        "driver": "WS2812",
 | 
			
		||||
        "layout": [
 | 
			
		||||
            {"matrix": [0, 2], "x": 224, "y": 0, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 1], "x": 112, "y": 0, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 0], "x": 0, "y": 0, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 3], "x": 0, "y": 16, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 4], "x": 112, "y": 16, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 5], "x": 224, "y": 16, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 8], "x": 224, "y": 32, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 7], "x": 112, "y": 32, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 6], "x": 0, "y": 32, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 9], "x": 0, "y": 48, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 10], "x": 112, "y": 48, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 11], "x": 224, "y": 48, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 14], "x": 224, "y": 64, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 13], "x": 112, "y": 64, "flags": 4},
 | 
			
		||||
            {"matrix": [0, 12], "x": 0, "y": 64, "flags": 4}
 | 
			
		||||
        ],
 | 
			
		||||
        "animations": {
 | 
			
		||||
            "alphas_mods": true,
 | 
			
		||||
            "band_pinwheel_sat": true,
 | 
			
		||||
            "band_pinwheel_val": true,
 | 
			
		||||
            "band_sat": true,
 | 
			
		||||
            "band_spiral_sat": true,
 | 
			
		||||
            "band_spiral_val": true,
 | 
			
		||||
            "band_val": true,
 | 
			
		||||
            "breathing": true,
 | 
			
		||||
            "cycle_all": true,
 | 
			
		||||
            "cycle_left_right": true,
 | 
			
		||||
            "cycle_out_in": true,
 | 
			
		||||
            "cycle_out_in_dual": true,
 | 
			
		||||
            "cycle_pinwheel": true,
 | 
			
		||||
            "cycle_spiral": true,
 | 
			
		||||
            "cycle_up_down": true,
 | 
			
		||||
            "digital_rain": true,
 | 
			
		||||
            "dual_beacon": true,
 | 
			
		||||
            "gradient_left_right": true,
 | 
			
		||||
            "gradient_up_down": true,
 | 
			
		||||
            "hue_breathing": true,
 | 
			
		||||
            "hue_pendulum": true,
 | 
			
		||||
            "hue_wave": true,
 | 
			
		||||
            "jellybean_raindrops": true,
 | 
			
		||||
            "multisplash": true,
 | 
			
		||||
            "pixel_flow": true,
 | 
			
		||||
            "pixel_fractal": true,
 | 
			
		||||
            "pixel_rain": true,
 | 
			
		||||
            "rainbow_beacon": true,
 | 
			
		||||
            "rainbow_moving_chevron": true,
 | 
			
		||||
            "rainbow_pinwheels": true,
 | 
			
		||||
            "raindrops": true,
 | 
			
		||||
            "solid_color": true,
 | 
			
		||||
            "solid_multisplash": true,
 | 
			
		||||
            "solid_reactive": true,
 | 
			
		||||
            "solid_reactive_cross": true,
 | 
			
		||||
            "solid_reactive_multicross": true,
 | 
			
		||||
            "solid_reactive_multinexus": true,
 | 
			
		||||
            "solid_reactive_multiwide": true,
 | 
			
		||||
            "solid_reactive_nexus": true,
 | 
			
		||||
            "solid_reactive_simple": true,
 | 
			
		||||
            "solid_reactive_wide": true,
 | 
			
		||||
            "solid_splash": true,
 | 
			
		||||
            "splash": true,
 | 
			
		||||
            "typing_heatmap": true
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "processor": "STM32F072",
 | 
			
		||||
    "bootloader": "stm32-dfu",
 | 
			
		||||
 | 
			
		||||
@ -40,9 +40,10 @@ enum my_keycodes {
 | 
			
		||||
    Z12, Z13, Z14
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define _DEFAULT 0
 | 
			
		||||
#define _RGB 1
 | 
			
		||||
 | 
			
		||||
enum layers {
 | 
			
		||||
  _DEFAULT,
 | 
			
		||||
  _RGB
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 | 
			
		||||
  /*
 | 
			
		||||
 | 
			
		||||
@ -20,9 +20,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
#include QMK_KEYBOARD_H
 | 
			
		||||
 | 
			
		||||
#define LOGO_SIZE 384
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 | 
			
		||||
  LAYOUT(
 | 
			
		||||
      KC_KP_1, KC_KP_2, KC_KP_3,
 | 
			
		||||
@ -31,43 +28,5 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 | 
			
		||||
      KC_TRNS, KC_KP_0, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS
 | 
			
		||||
  ),
 | 
			
		||||
  LAYOUT(
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS
 | 
			
		||||
  ),
 | 
			
		||||
  LAYOUT(
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS
 | 
			
		||||
  ),
 | 
			
		||||
  LAYOUT(
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS, KC_TRNS,
 | 
			
		||||
      KC_TRNS, KC_TRNS
 | 
			
		||||
  ),
 | 
			
		||||
  )
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void render_logo(void) {
 | 
			
		||||
   static const char PROGMEM ducky_logo[LOGO_SIZE] = {
 | 
			
		||||
      0, 0, 0, 0,128,128,128,128,128, 0, 0,252,252,252, 0, 0, 0,128,128,128, 0, 0, 0, 0, 0,128,128,128, 0, 0, 0, 0, 0,128,128,128,128,128, 0, 0, 0, 0, 0,252,252,252, 0, 0, 0, 0, 0,128,128,128,128,128,128, 0, 0, 0, 0, 0, 0,128,128,128,128, 0,248,248,248, 56, 56, 56, 56, 56, 56,120,240,224,192, 0, 0,128,128,128,128,128,128, 0, 0, 0, 0, 0, 0, 0, 0,128,128,128,128,128, 0, 0,252,252,252, 0, 0, 0, 0, 0,232, 24, 24,232, 0, 24, 48, 48, 24, 0,232, 24, 24,232, 0, 0,
 | 
			
		||||
      0,248,254,255,143, 7, 3, 3, 3, 7,142,255,255,255, 0, 0, 0,255,255,255, 0, 0, 0, 0, 0,255,255,255, 0,248,254,255,143, 7, 3, 3, 3, 3,143, 7, 2, 0, 0,255,255,255,240,120,252,254,231,131, 1, 0, 1, 7, 63,254,240,192, 0,224,252,127, 31, 3, 0, 0,255,255,255,112,112,112,112,112,112, 56, 63, 31, 15,193,231,243,115, 51, 51, 51, 55,255,255,252, 0, 0,248,254,255,143, 7, 3, 3, 3, 7,142,255,255,255, 0, 0, 0, 0, 0, 21,127,127,252,252,252,253,253,252,252,252,255,255,255, 0, 0,
 | 
			
		||||
      0, 0, 3, 7, 15, 15, 14, 14, 14, 7, 3, 15, 15, 15, 0, 0, 0, 3, 7, 15, 15, 14, 14, 6, 3, 15, 15, 15, 0, 0, 3, 7, 7, 15, 14, 14, 14, 14, 7, 7, 2, 0, 0, 15, 15, 15, 0, 0, 0, 1, 3, 15, 15, 12,136,224,224,224,247,127,127, 31, 3, 0, 0, 0, 0, 0, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 7, 15, 14, 14, 14, 6, 3, 15, 15, 15, 0, 0, 0, 3, 7, 15, 15, 14, 14, 14, 7, 3, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 7, 11, 3, 11, 7, 11, 7, 7, 31, 0, 0
 | 
			
		||||
   };
 | 
			
		||||
   oled_write_raw_P(ducky_logo, LOGO_SIZE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool oled_task_user(void) {
 | 
			
		||||
  render_logo();
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1 @@
 | 
			
		||||
VIA_ENABLE = yes
 | 
			
		||||
RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow
 | 
			
		||||
RGB_MATRIX_ENABLE = no
 | 
			
		||||
 | 
			
		||||
@ -1,17 +1 @@
 | 
			
		||||
# Build Options
 | 
			
		||||
#  change yes to no to disable
 | 
			
		||||
#
 | 
			
		||||
BOOTMAGIC_ENABLE = no       # Enable Bootmagic Lite
 | 
			
		||||
MOUSEKEY_ENABLE = no        # Mouse keys
 | 
			
		||||
EXTRAKEY_ENABLE = yes       # Audio control and System control
 | 
			
		||||
CONSOLE_ENABLE = no         # Console for debug
 | 
			
		||||
COMMAND_ENABLE = no         # Commands for debug and configuration
 | 
			
		||||
NKRO_ENABLE = no            # Enable N-Key Rollover
 | 
			
		||||
BACKLIGHT_ENABLE = no       # Enable keyboard backlight functionality
 | 
			
		||||
RGBLIGHT_ENABLE = no        # Enable keyboard RGB underglow
 | 
			
		||||
AUDIO_ENABLE = no           # Audio output
 | 
			
		||||
 | 
			
		||||
RGB_MATRIX_ENABLE = yes
 | 
			
		||||
 | 
			
		||||
OLED_ENABLE = yes
 | 
			
		||||
OLED_DRIVER = SSD1306
 | 
			
		||||
# This file intentionally left blank
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user