diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h
index ebf66a9f4a93cb658c79223c059e38d27e998331..b3a9837d2a6e8d17544e5bd5ed4dc40b4ab8c68c 100644
--- a/epicardium/epicardium.h
+++ b/epicardium/epicardium.h
@@ -543,7 +543,7 @@ API(API_GPIO_WRITE_PIN, int epic_gpio_write_pin(uint8_t pin, bool on));
  * :param uint8_t pin: ID of the pin to get the configuration of. Use on of the IDs defined in :c:type:`gpio_pin`.
  * :returns: ``-EINVAL`` if ``pin`` is not valid, an integer value otherwise.
  */
-API(API_GPIO_READ_PIN, uint32_t epic_gpio_read_pin(uint8_t pin));
+API(API_GPIO_READ_PIN, int epic_gpio_read_pin(uint8_t pin));
 
 /**
  * LEDs
diff --git a/epicardium/modules/gpio.c b/epicardium/modules/gpio.c
index b6bc4f2cf343ba940d28f3420e6bccdccec9375c..83a4c4cf04ff827ad52638c77ccbe6a80195ad20 100644
--- a/epicardium/modules/gpio.c
+++ b/epicardium/modules/gpio.c
@@ -21,27 +21,27 @@ int epic_gpio_set_pin_mode(uint8_t pin, uint8_t mode)
 
 	gpio_cfg_t *cfg = &gpio_configs[pin];
 
-	bool is_input  = (mode & GPIO_MODE_IN) == GPIO_MODE_IN;
-	bool is_output = (mode & GPIO_MODE_OUT) == GPIO_MODE_OUT;
-
-	// Pins can't be input and output at the same time.
-	if (is_input && is_output)
+	if (mode & GPIO_MODE_IN) {
+		cfg->func = GPIO_FUNC_IN;
+		if (mode & GPIO_MODE_OUT) {
+			return -EINVAL;
+		}
+	} else if (mode & GPIO_MODE_OUT) {
+		cfg->func = GPIO_FUNC_OUT;
+		if (mode & GPIO_MODE_IN) {
+			return -EINVAL;
+		}
+	} else {
 		return -EINVAL;
+	}
 
-	uint32_t func_value = 0;
-	if (is_input)
-		func_value |= GPIO_FUNC_IN;
-	if (is_output)
-		func_value |= GPIO_FUNC_OUT;
-
-	uint32_t pad_value = 0;
-	if (mode & GPIO_PULL_UP)
-		pad_value |= GPIO_PAD_PULL_UP;
-	if (mode & GPIO_PULL_DOWN)
-		pad_value |= GPIO_PAD_PULL_DOWN;
-
-	cfg->func = func_value;
-	cfg->pad  = pad_value;
+	if (mode & GPIO_PULL_UP) {
+		cfg->pad = GPIO_PAD_PULL_UP;
+	} else if (mode & GPIO_PULL_DOWN) {
+		cfg->pad = GPIO_PAD_PULL_DOWN;
+	} else {
+		cfg->pad = GPIO_PAD_NONE;
+	}
 
 	if (GPIO_Config(cfg) != E_NO_ERROR)
 		return -EINVAL;
@@ -55,13 +55,13 @@ int epic_gpio_get_pin_mode(uint8_t pin)
 
 	gpio_cfg_t *cfg = &gpio_configs[pin];
 	int res         = 0;
-	if ((cfg->func & GPIO_FUNC_IN) == GPIO_FUNC_IN)
+	if (cfg->func == GPIO_FUNC_IN)
 		res |= GPIO_MODE_IN;
-	if ((cfg->func & GPIO_FUNC_OUT) == GPIO_FUNC_OUT)
+	else if (cfg->func == GPIO_FUNC_OUT)
 		res |= GPIO_MODE_OUT;
-	if ((cfg->pad & GPIO_PAD_PULL_UP) == GPIO_PAD_PULL_UP)
+	if (cfg->pad == GPIO_PAD_PULL_UP)
 		res |= GPIO_PULL_UP;
-	if ((cfg->pad & GPIO_PAD_PULL_DOWN) == GPIO_PAD_PULL_DOWN)
+	else if (cfg->pad == GPIO_PAD_PULL_DOWN)
 		res |= GPIO_PULL_DOWN;
 
 	return res;
@@ -73,7 +73,7 @@ int epic_gpio_write_pin(uint8_t pin, bool on)
 		return -EINVAL;
 
 	gpio_cfg_t *cfg = &gpio_configs[pin];
-	if ((cfg->func & GPIO_FUNC_IN) == GPIO_FUNC_IN)
+	if (cfg->func == GPIO_FUNC_IN)
 		return -EINVAL;
 
 	if (on)
@@ -84,16 +84,16 @@ int epic_gpio_write_pin(uint8_t pin, bool on)
 	return 0;
 }
 
-uint32_t epic_gpio_read_pin(uint8_t pin)
+int epic_gpio_read_pin(uint8_t pin)
 {
 	if (pin < GPIO_WRISTBAND_1 || pin > GPIO_WRISTBAND_4)
 		return -EINVAL;
 
 	gpio_cfg_t *cfg = &gpio_configs[pin];
-	if ((cfg->func & GPIO_FUNC_OUT) == GPIO_FUNC_OUT) {
-		return GPIO_OutGet(cfg);
-	} else if ((cfg->func & GPIO_FUNC_IN) == GPIO_FUNC_IN) {
-		return GPIO_InGet(cfg);
+	if (cfg->func == GPIO_FUNC_OUT) {
+		return GPIO_OutGet(cfg) != 0;
+	} else if (cfg->func == GPIO_FUNC_IN) {
+		return GPIO_InGet(cfg) != 0;
 	} else {
 		return -EINVAL;
 	}
diff --git a/pycardium/modules/gpio.c b/pycardium/modules/gpio.c
index c92d1023470655383a0d33c1cb6b29d13825c19a..adfe8bdd0245ee12dd466fb4391c80f9e68038ff 100644
--- a/pycardium/modules/gpio.c
+++ b/pycardium/modules/gpio.c
@@ -28,10 +28,10 @@ static MP_DEFINE_CONST_FUN_OBJ_1(gpio_get_mode, mp_gpio_get_mode);
 
 static mp_obj_t mp_gpio_read(mp_obj_t pin_obj)
 {
-	int pin        = mp_obj_get_int(pin_obj);
-	uint32_t value = epic_gpio_read_pin(pin);
-	if (value == -EINVAL)
-		mp_raise_OSError(EINVAL);
+	int pin   = mp_obj_get_int(pin_obj);
+	int value = epic_gpio_read_pin(pin);
+	if (value < 0)
+		mp_raise_OSError(-value);
 
 	return MP_OBJ_NEW_SMALL_INT(value);
 };