diff --git a/examples/GPIO/GPIO.c b/examples/GPIO/GPIO.c
new file mode 100644
index 0000000000000000000000000000000000000000..ed430880241ba0eb164677bf5c2a07d2dd197917
--- /dev/null
+++ b/examples/GPIO/GPIO.c
@@ -0,0 +1,47 @@
+// blink, but with arduino-like HAL
+// Could be defined here, or in the processor defines.
+#define SYSTEM_CORE_CLOCK 48000000
+
+#include "ch32v003fun.h"
+#include "wiring_digital.h"
+#include <stdio.h>
+
+#define APB_CLOCK SYSTEM_CORE_CLOCK
+
+uint32_t count;
+
+int main() {
+  SystemInit48HSI();
+
+  // Enable GPIO ports
+  enablePort(port_C);
+  enablePort(port_D);
+
+  for (int i = pin_C0; i <= pin_C7; i++) {
+    pinMode(i, pinMode_O_pushPull);
+  }
+
+  // GPIO D4 Push-Pull
+  pinMode(pin_D4, pinMode_O_pushPull);
+
+  while (1) {
+    // Turn on pins
+    digitalWrite(pin_C0, high);
+    digitalWrite(pin_D4, high);
+    Delay_Ms(250);
+    // Turn off pins
+    digitalWrite(pin_C0, low);
+    digitalWrite(pin_D4, low);
+    Delay_Ms(250);
+    for (int i = pin_C0; i <= pin_C7; i++) {
+      digitalWrite(i, high);
+      Delay_Ms(50);
+    }
+    for (int i = pin_C7; i >= pin_C0; i--) {
+      digitalWrite(i, low);
+      Delay_Ms(50);
+    }
+    Delay_Ms(250);
+    count++;
+  }
+}
diff --git a/examples/GPIO/Makefile b/examples/GPIO/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..5090155f3f5f8a616ff580b733b6ef8b512906a4
--- /dev/null
+++ b/examples/GPIO/Makefile
@@ -0,0 +1,43 @@
+TARGET:=GPIO
+
+all : flash
+
+PREFIX:=riscv64-unknown-elf
+
+GPIO_Toggle:=EXAM/GPIO/GPIO_Toggle/User
+
+EVT:=../../ch32v003evt
+
+MINICHLINK:=../../minichlink
+CH32V003FUN:=../../ch32v003fun
+
+CFLAGS:= \
+	-g -Os -flto -ffunction-sections \
+	-static-libgcc \
+	-march=rv32ec \
+	-mabi=ilp32e \
+	-I/usr/include/newlib \
+	-I$(CH32V003FUN) \
+	-nostdlib \
+	-I. -DTINYVECTOR -Wall
+
+LDFLAGS:=-T $(CH32V003FUN)/ch32v003fun.ld -Wl,--gc-sections -L../../misc -lgcc
+
+SYSTEM_C:=$(CH32V003FUN)/ch32v003fun.c
+
+$(TARGET).elf : $(SYSTEM_C) $(TARGET).c wiring_digital.c
+	$(PREFIX)-gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
+
+$(TARGET).bin : $(TARGET).elf
+	$(PREFIX)-size $^
+	$(PREFIX)-objdump -S $^ > $(TARGET).lst
+	$(PREFIX)-objdump -t $^ > $(TARGET).map
+	$(PREFIX)-objcopy -O binary $< $(TARGET).bin
+	$(PREFIX)-objcopy -O ihex $< $(TARGET).hex
+
+flash : $(TARGET).bin
+	$(MINICHLINK)/minichlink -w $< flash -b
+
+clean :
+	rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).hex $(TARGET).lst $(TARGET).map $(TARGET).hex
+
diff --git a/examples/GPIO/README.md b/examples/GPIO/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a6c23799ff7e6df932b10774273f86094daac8b3
--- /dev/null
+++ b/examples/GPIO/README.md
@@ -0,0 +1,14 @@
+# GPIO Libaray
+On the shoulders of the Blink example, this Arduino-like GPIO library stands.
+
+All pins are adressable as outputs, inputs, with pull-up, etc.
+The pins are in an enum, so you can call them by their name and iterate over them.
+
+It's your responsibility to not blow up a pin.
+Only use one pin for one thing and you should be fine.
+
+# GPIO Example
+Connect LED + 1k resistor to each pin (C0 to C7 and D4) and GND.
+Marvel at the colorful glory.
+
+https://user-images.githubusercontent.com/104343143/231585338-725f1197-dfa0-484d-8707-f0824af80b7e.mp4
diff --git a/examples/GPIO/wiring_digital.c b/examples/GPIO/wiring_digital.c
new file mode 100644
index 0000000000000000000000000000000000000000..891441786b5890f97875bc253d39456c64903d99
--- /dev/null
+++ b/examples/GPIO/wiring_digital.c
@@ -0,0 +1,161 @@
+//#include <stdio.h>
+
+#include "wiring_digital.h"
+#include <stdint.h>
+
+
+
+enum GPIOports getPort (enum GPIOpins pin) {
+	if (pin <= pin_A2) {
+		return port_A;
+	}
+	else if (pin <= pin_C7) {
+		return port_C;
+	}
+	else if (pin <= pin_D7) {
+		return port_D;
+	}
+	return port_none;
+}
+
+
+
+void enablePort(enum GPIOports port) {
+	// Enable GPIOs
+	switch (port) {
+		case port_A:
+			RCC->APB2PCENR |= RCC_APB2Periph_GPIOA;
+			break;
+		case port_C:
+			RCC->APB2PCENR |= RCC_APB2Periph_GPIOC;
+			break;
+		case port_D:
+			RCC->APB2PCENR |= RCC_APB2Periph_GPIOD;
+			break;
+		case port_none:
+			break;
+	}
+}
+
+
+
+void pinMode(enum GPIOpins pin, enum GPIOpinMode mode) {
+	GPIO_TypeDef * GPIOx;
+	uint16_t PinOffset = 4;
+	
+	if (pin <= pin_A2) {
+		GPIOx = GPIOA;
+		PinOffset *= pin;
+	}
+	else if (pin <= pin_C7) {
+		GPIOx = GPIOC;
+		PinOffset *= (pin - 2);
+	}
+	else if (pin <= pin_D7) {
+		GPIOx = GPIOD;
+		PinOffset *= (pin - 10);
+	}
+	else {
+		return;
+	}
+
+	GPIOx->CFGLR &= ~(0b1111<<PinOffset);							// zero the 4 configuration bits
+	
+	uint8_t target_pin_state = pinState_nochange;					// by default, pin shall retain its state
+
+	uint8_t modeMask = 0;												// configuration mask
+
+	switch (mode) {
+		case pinMode_I_floating:
+			modeMask = GPIO_CNF_IN_FLOATING;
+			break;
+		case pinMode_I_pullUp:
+			modeMask = GPIO_CNF_IN_PUPD;
+			target_pin_state = pinState_high;
+			break;
+		case pinMode_I_pullDown:
+			modeMask = GPIO_CNF_IN_PUPD;
+			target_pin_state = pinState_low;
+			break;
+		case pinMode_I_analog:
+			modeMask = GPIO_CNF_IN_ANALOG;
+			break;
+		case pinMode_O_pushPull:
+			modeMask = GPIO_Speed_10MHz | GPIO_CNF_OUT_PP;
+			break;
+		case pinMode_O_openDrain:
+			modeMask = GPIO_Speed_10MHz | GPIO_CNF_OUT_OD;
+			break;
+		case pinMode_O_pushPullMux:
+			modeMask = GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF;
+			break;
+		case pinMode_O_openDrainMux:
+			modeMask = GPIO_Speed_10MHz | GPIO_CNF_OUT_OD_AF;
+			break;
+	}
+
+	// wirte mask to CFGR
+	GPIOx->CFGLR |= modeMask<<PinOffset;
+
+	// set pin state
+	if (target_pin_state > pinState_nochange) {
+		digitalWrite(pin, target_pin_state - 1);
+	}
+}
+
+
+
+void digitalWrite(enum GPIOpins pin, uint8_t value) {
+	// no checks given whether pin is currently being toggled by timer! your output trannys are in your hands! beware the magic smoke!
+	GPIO_TypeDef * GPIOx;
+	uint16_t PinOffset = 0;
+	
+	if (pin <= pin_A2) {
+		GPIOx = GPIOA;
+		PinOffset = pin;
+	}
+	else if (pin <= pin_C7) {
+		GPIOx = GPIOC;
+		PinOffset = (pin - 2);
+	}
+	else if (pin <= pin_D7) {
+		GPIOx = GPIOD;
+		PinOffset = (pin - 10);
+	}
+	else {
+		return;
+	}
+
+	if (value) {
+		GPIOx-> BSHR |= 1 << PinOffset;
+	}
+	else {
+		GPIOx-> BSHR |= 1 << (16 + PinOffset);
+	}
+}
+
+
+
+uint8_t digitalRead(uint8_t pin) {
+	GPIO_TypeDef * GPIOx;
+	uint16_t PinOffset = 0;
+	
+	if (pin <= pin_A2) {
+		GPIOx = GPIOA;
+		PinOffset = pin;
+	}
+	else if (pin <= pin_C7) {
+		GPIOx = GPIOC;
+		PinOffset = (pin - 2);
+	}
+	else if (pin <= pin_D7) {
+		GPIOx = GPIOD;
+		PinOffset = (pin - 10);
+	}
+	else {
+		return 0;
+	}
+
+	int8_t result = (GPIOx->INDR >> PinOffset) & 1;
+	return result;
+}
diff --git a/examples/GPIO/wiring_digital.h b/examples/GPIO/wiring_digital.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b7deeec0e3d32d46966540e3699cb02d91f15d2
--- /dev/null
+++ b/examples/GPIO/wiring_digital.h
@@ -0,0 +1,73 @@
+#ifndef WIRING_DIGITAL_H
+#define WIRING_DIGITAL_H
+
+#include "../../ch32v003fun/ch32v003fun.h"
+
+// Define the pins that will be used for GPIO
+#define MY_GPIO_PIN_1 1
+#define MY_GPIO_PIN_2 2
+// Add more pins as needed
+
+
+
+enum lowhigh {
+	low,
+	high,
+};
+
+
+
+enum GPIOports{
+	port_A,
+	port_C,
+	port_D,
+	port_none,
+};
+
+enum GPIOpins{
+	pin_A1,
+	pin_A2,
+	pin_C0,
+	pin_C1,
+	pin_C2,
+	pin_C3,
+	pin_C4,
+	pin_C5,
+	pin_C6,
+	pin_C7,
+	pin_D0,
+	pin_D1,
+	pin_D2,
+	pin_D3,
+	pin_D4,
+	pin_D5,
+	pin_D6,
+	pin_D7,
+	pin_none,
+};
+
+enum GPIOpinMode {
+	pinMode_I_floating,
+	pinMode_I_pullUp,			//pull-mode + ODR(1)
+	pinMode_I_pullDown,			//pull-mode + ODR(0)
+	pinMode_I_analog,
+	pinMode_O_pushPull,
+	pinMode_O_openDrain,
+	pinMode_O_pushPullMux,
+	pinMode_O_openDrainMux,
+};
+
+enum GPIOpinState {
+	pinState_nochange,
+	pinState_low,
+	pinState_high,
+};
+
+enum GPIOports getPort (enum GPIOpins pin);
+
+void enablePort(enum GPIOports port);
+void pinMode(enum GPIOpins pin, enum GPIOpinMode mode);
+void digitalWrite(enum GPIOpins pin, uint8_t value);
+uint8_t digitalRead(uint8_t pin);
+
+#endif					// WIRING_DIGITAL_H