diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c
index 0d6ada635cdaafcaebe70f8f20f7c95f3e803b15..b452e223ec6baea09acc2abd4d7ec2a2b6f05eb2 100644
--- a/stmhal/modmachine.c
+++ b/stmhal/modmachine.c
@@ -35,6 +35,7 @@
 #include "irq.h"
 #include "rng.h"
 #include "storage.h"
+#include "pin.h"
 #include "timer.h"
 #include "usb.h"
 
@@ -409,9 +410,11 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = {
 
     { MP_OBJ_NEW_QSTR(MP_QSTR_disable_irq),         (mp_obj_t)&pyb_disable_irq_obj },
     { MP_OBJ_NEW_QSTR(MP_QSTR_enable_irq),          (mp_obj_t)&pyb_enable_irq_obj },
+
+    { MP_OBJ_NEW_QSTR(MP_QSTR_Pin),                 (mp_obj_t)&pin_type },
+
 #if 0
     { MP_OBJ_NEW_QSTR(MP_QSTR_RTC),                 (mp_obj_t)&pyb_rtc_type },
-    { MP_OBJ_NEW_QSTR(MP_QSTR_Pin),                 (mp_obj_t)&pin_type },
     { MP_OBJ_NEW_QSTR(MP_QSTR_ADC),                 (mp_obj_t)&pyb_adc_type },
     { MP_OBJ_NEW_QSTR(MP_QSTR_I2C),                 (mp_obj_t)&pyb_i2c_type },
     { MP_OBJ_NEW_QSTR(MP_QSTR_SPI),                 (mp_obj_t)&pyb_spi_type },
diff --git a/stmhal/pin.c b/stmhal/pin.c
index 9f40b11d672f4ad4dfe123d505e150634a18bd10..3aba949759ef076d77f0fad9e6ae2a30fab3d66b 100644
--- a/stmhal/pin.c
+++ b/stmhal/pin.c
@@ -260,6 +260,24 @@ STATIC mp_obj_t pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
     return (mp_obj_t)pin;
 }
 
+// fast method for getting/setting pin value
+STATIC mp_obj_t pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
+    mp_arg_check_num(n_args, n_kw, 0, 1, false);
+    pin_obj_t *self = self_in;
+    if (n_args == 0) {
+        // get pin
+        return MP_OBJ_NEW_SMALL_INT(GPIO_read_pin(self->gpio, self->pin));
+    } else {
+        // set pin
+        if (mp_obj_is_true(args[0])) {
+            GPIO_set_pin(self->gpio, self->pin_mask);
+        } else {
+            GPIO_clear_pin(self->gpio, self->pin_mask);
+        }
+        return mp_const_none;
+    }
+}
+
 /// \classmethod mapper([fun])
 /// Get or set the pin mapper function.
 STATIC mp_obj_t pin_mapper(mp_uint_t n_args, const mp_obj_t *args) {
@@ -310,50 +328,40 @@ STATIC mp_obj_t pin_debug(mp_uint_t n_args, const mp_obj_t *args) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_debug_fun_obj, 1, 2, pin_debug);
 STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_debug_obj, (mp_obj_t)&pin_debug_fun_obj);
 
-/// \method init(mode, pull=Pin.PULL_NONE, af=-1)
-/// Initialise the pin:
-///
-///   - `mode` can be one of:
-///     - `Pin.IN` - configure the pin for input;
-///     - `Pin.OUT_PP` - configure the pin for output, with push-pull control;
-///     - `Pin.OUT_OD` - configure the pin for output, with open-drain control;
-///     - `Pin.AF_PP` - configure the pin for alternate function, pull-pull;
-///     - `Pin.AF_OD` - configure the pin for alternate function, open-drain;
-///     - `Pin.ANALOG` - configure the pin for analog.
-///   - `pull` can be one of:
-///     - `Pin.PULL_NONE` - no pull up or down resistors;
-///     - `Pin.PULL_UP` - enable the pull-up resistor;
-///     - `Pin.PULL_DOWN` - enable the pull-down resistor.
-///   - when mode is Pin.AF_PP or Pin.AF_OD, then af can be the index or name
-///     of one of the alternate functions associated with a pin.
-///
-/// Returns: `None`.
-STATIC const mp_arg_t pin_init_args[] = {
-    { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
-    { MP_QSTR_pull,                   MP_ARG_INT, {.u_int = GPIO_NOPULL}},
-    { MP_QSTR_af,                     MP_ARG_INT, {.u_int = -1}},
-};
-#define PIN_INIT_NUM_ARGS MP_ARRAY_SIZE(pin_init_args)
+// init(mode, pull=None, af=-1, *, value, alt)
+STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+    static const mp_arg_t allowed_args[] = {
+        { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
+        { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}},
+        { MP_QSTR_af, MP_ARG_INT, {.u_int = -1}}, // legacy
+        { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
+        { MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}},
+    };
 
-STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
     // parse args
-    mp_arg_val_t vals[PIN_INIT_NUM_ARGS];
-    mp_arg_parse_all(n_args, args, kw_args, PIN_INIT_NUM_ARGS, pin_init_args, vals);
+    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+    mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
 
     // get io mode
-    uint mode = vals[0].u_int;
+    uint mode = args[0].u_int;
     if (!IS_GPIO_MODE(mode)) {
         nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin mode: %d", mode));
     }
 
     // get pull mode
-    uint pull = vals[1].u_int;
+    uint pull = GPIO_NOPULL;
+    if (args[1].u_obj != mp_const_none) {
+        pull = mp_obj_get_int(args[1].u_obj);
+    }
     if (!IS_GPIO_PULL(pull)) {
         nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin pull: %d", pull));
     }
 
-    // get af (alternate function)
-    mp_int_t af = vals[2].u_int;
+    // get af (alternate function); alt-arg overrides af-arg
+    mp_int_t af = args[4].u_int;
+    if (af == -1) {
+        af = args[2].u_int;
+    }
     if ((mode == GPIO_MODE_AF_PP || mode == GPIO_MODE_AF_OD) && !IS_GPIO_AF(af)) {
         nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin af: %d", af));
     }
@@ -361,6 +369,15 @@ STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, mp_uint_t n_args, con
     // enable the peripheral clock for the port of this pin
     mp_hal_gpio_clock_enable(self->gpio);
 
+    // if given, set the pin value before initialising to prevent glitches
+    if (args[3].u_obj != MP_OBJ_NULL) {
+        if (mp_obj_is_true(args[3].u_obj)) {
+            GPIO_set_pin(self->gpio, self->pin_mask);
+        } else {
+            GPIO_clear_pin(self->gpio, self->pin_mask);
+        }
+    }
+
     // configure the GPIO as requested
     GPIO_InitTypeDef GPIO_InitStructure;
     GPIO_InitStructure.Pin = self->pin_mask;
@@ -386,19 +403,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(pin_init_obj, 1, pin_obj_init);
 ///   anything that converts to a boolean.  If it converts to `True`, the pin
 ///   is set high, otherwise it is set low.
 STATIC mp_obj_t pin_value(mp_uint_t n_args, const mp_obj_t *args) {
-    pin_obj_t *self = args[0];
-    if (n_args == 1) {
-        // get pin
-        return MP_OBJ_NEW_SMALL_INT(GPIO_read_pin(self->gpio, self->pin));
-    } else {
-        // set pin
-        if (mp_obj_is_true(args[1])) {
-            GPIO_set_pin(self->gpio, self->pin_mask);
-        } else {
-            GPIO_clear_pin(self->gpio, self->pin_mask);
-        }
-        return mp_const_none;
-    }
+    return pin_call(args[0], n_args - 1, 0, args + 1);
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_value_obj, 1, 2, pin_value);
 
@@ -524,24 +529,21 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = {
     { MP_OBJ_NEW_QSTR(MP_QSTR_cpu),     (mp_obj_t)&pin_cpu_pins_obj_type },
 
     // class constants
-    /// \constant IN - initialise the pin to input mode
-    /// \constant OUT_PP - initialise the pin to output mode with a push-pull drive
-    /// \constant OUT_OD - initialise the pin to output mode with an open-drain drive
-    /// \constant AF_PP - initialise the pin to alternate-function mode with a push-pull drive
-    /// \constant AF_OD - initialise the pin to alternate-function mode with an open-drain drive
-    /// \constant ANALOG - initialise the pin to analog mode
-    /// \constant PULL_NONE - don't enable any pull up or down resistors on the pin
-    /// \constant PULL_UP - enable the pull-up resistor on the pin
-    /// \constant PULL_DOWN - enable the pull-down resistor on the pin
     { MP_OBJ_NEW_QSTR(MP_QSTR_IN),        MP_OBJ_NEW_SMALL_INT(GPIO_MODE_INPUT) },
+    { MP_OBJ_NEW_QSTR(MP_QSTR_OUT),       MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_PP) },
+    { MP_OBJ_NEW_QSTR(MP_QSTR_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_OD) },
+    { MP_OBJ_NEW_QSTR(MP_QSTR_ALT),       MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP) },
+    { MP_OBJ_NEW_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_OD) },
+    { MP_OBJ_NEW_QSTR(MP_QSTR_ANALOG),    MP_OBJ_NEW_SMALL_INT(GPIO_MODE_ANALOG) },
+    { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP),   MP_OBJ_NEW_SMALL_INT(GPIO_PULLUP) },
+    { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULLDOWN) },
+
+    // legacy class constants
     { MP_OBJ_NEW_QSTR(MP_QSTR_OUT_PP),    MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_PP) },
     { MP_OBJ_NEW_QSTR(MP_QSTR_OUT_OD),    MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_OD) },
     { MP_OBJ_NEW_QSTR(MP_QSTR_AF_PP),     MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP) },
     { MP_OBJ_NEW_QSTR(MP_QSTR_AF_OD),     MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_OD) },
-    { MP_OBJ_NEW_QSTR(MP_QSTR_ANALOG),    MP_OBJ_NEW_SMALL_INT(GPIO_MODE_ANALOG) },
     { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_NONE), MP_OBJ_NEW_SMALL_INT(GPIO_NOPULL) },
-    { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP),   MP_OBJ_NEW_SMALL_INT(GPIO_PULLUP) },
-    { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULLDOWN) },
 
 #include "genhdr/pins_af_const.h"
 };
@@ -553,6 +555,7 @@ const mp_obj_type_t pin_type = {
     .name = MP_QSTR_Pin,
     .print = pin_print,
     .make_new = pin_make_new,
+    .call = pin_call,
     .locals_dict = (mp_obj_t)&pin_locals_dict,
 };
 
diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h
index 94e9b6440a4769ae313df2fbc6a2a0a2e92683f2..e2eabe3a3fd9800101cc2c0648e4ea2999a2fa39 100644
--- a/stmhal/qstrdefsport.h
+++ b/stmhal/qstrdefsport.h
@@ -144,6 +144,7 @@ Q(PinAF)
 Q(PinNamed)
 Q(init)
 Q(value)
+Q(alt)
 Q(low)
 Q(high)
 Q(name)
@@ -164,14 +165,18 @@ Q(pull)
 Q(index)
 Q(reg)
 Q(IN)
+Q(OUT)
+Q(OPEN_DRAIN)
+Q(ALT)
+Q(ALT_OPEN_DRAIN)
+Q(ANALOG)
+Q(PULL_UP)
+Q(PULL_DOWN)
 Q(OUT_PP)
 Q(OUT_OD)
 Q(AF_PP)
 Q(AF_OD)
-Q(ANALOG)
 Q(PULL_NONE)
-Q(PULL_UP)
-Q(PULL_DOWN)
 
 // for LED object
 Q(LED)