diff --git a/examples/sdl/src/main.rs b/examples/sdl/src/main.rs
index 437fdbb0fa9863ad431adb3d294b88abff6ba84e..ecc0eeaeeadf5465b04dff2eea934847d71545e1 100644
--- a/examples/sdl/src/main.rs
+++ b/examples/sdl/src/main.rs
@@ -1,10 +1,11 @@
 use boytacean::{
     gb::GameBoy,
+    pad::PadKey,
     ppu::{DISPLAY_HEIGHT, DISPLAY_WIDTH},
 };
 use sdl2::{
-    event::Event, image::LoadSurface, pixels::PixelFormatEnum, surface::Surface, video::Window,
-    AudioSubsystem, EventPump, TimerSubsystem, VideoSubsystem,
+    event::Event, image::LoadSurface, keyboard::Keycode, pixels::PixelFormatEnum, surface::Surface,
+    video::Window, AudioSubsystem, EventPump, TimerSubsystem, VideoSubsystem,
 };
 
 /// The base title to be used in the window.
@@ -112,6 +113,17 @@ fn main() {
         while let Some(event) = graphics.event_pump.poll_event() {
             match event {
                 Event::Quit { .. } => break 'main,
+
+                Event::KeyDown {
+                    keycode: Some(keycode),
+                    ..
+                } => game_boy.key_press(key_to_pad(keycode)),
+
+                Event::KeyUp {
+                    keycode: Some(keycode),
+                    ..
+                } => game_boy.key_lift(key_to_pad(keycode)),
+
                 _ => (),
             }
         }
@@ -146,3 +158,17 @@ fn main() {
         graphics.timer_subsystem.delay(17);
     }
 }
+
+fn key_to_pad(keycode: Keycode) -> PadKey {
+    match keycode {
+        Keycode::Up => PadKey::Up,
+        Keycode::Down => PadKey::Down,
+        Keycode::Left => PadKey::Left,
+        Keycode::Right => PadKey::Right,
+        Keycode::Space => PadKey::Start,
+        Keycode::Return => PadKey::Select,
+        Keycode::A => PadKey::A,
+        Keycode::S => PadKey::B,
+        _ => PadKey::A,
+    }
+}
diff --git a/src/cpu.rs b/src/cpu.rs
index 6afaf341ce4a223e0559ef20acf2f894098f813e..e56b8e5f2ba55ba83eeb4130c1818b043f980049 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -3,6 +3,7 @@ use core::panic;
 use crate::{
     inst::{EXTENDED, INSTRUCTIONS},
     mmu::Mmu,
+    pad::Pad,
     ppu::Ppu,
 };
 
@@ -177,6 +178,11 @@ impl Cpu {
         self.mmu().ppu()
     }
 
+    #[inline(always)]
+    pub fn pad(&mut self) -> &mut Pad {
+        self.mmu().pad()
+    }
+
     #[inline(always)]
     pub fn halted(&self) -> bool {
         self.halted
diff --git a/src/gb.rs b/src/gb.rs
index 715b9600295497ad1b5fc83805c009edfb9905c0..b58146b668921115368ef86be340f7302646fa51 100644
--- a/src/gb.rs
+++ b/src/gb.rs
@@ -2,7 +2,7 @@ use crate::{
     cpu::Cpu,
     data::{BootRom, DMG_BOOT, DMG_BOOTIX, MGB_BOOTIX, SGB_BOOT},
     mmu::Mmu,
-    pad::Pad,
+    pad::{Pad, PadKey},
     ppu::{Ppu, Tile, FRAME_BUFFER_SIZE},
     util::read_file,
 };
@@ -35,6 +35,14 @@ impl GameBoy {
         self.cpu.reset();
     }
 
+    pub fn key_press(&mut self, key: PadKey) {
+        self.pad().key_press(key);
+    }
+
+    pub fn key_lift(&mut self, key: PadKey) {
+        self.pad().key_lift(key);
+    }
+
     pub fn pc(&self) -> u16 {
         self.cpu.pc()
     }
@@ -132,6 +140,10 @@ impl GameBoy {
         self.cpu.ppu()
     }
 
+    pub fn pad(&mut self) -> &mut Pad {
+        self.cpu.pad()
+    }
+
     pub fn frame_buffer(&mut self) -> &Box<[u8; FRAME_BUFFER_SIZE]> {
         &(self.ppu().frame_buffer)
     }
diff --git a/src/mmu.rs b/src/mmu.rs
index 71db7029136b1d53bb87f02c184ed9b54eb9ce91..342928043ac038f4a0fd4fa8a591c4be487da70d 100644
--- a/src/mmu.rs
+++ b/src/mmu.rs
@@ -45,6 +45,10 @@ impl Mmu {
         &mut self.ppu
     }
 
+    pub fn pad(&mut self) -> &mut Pad {
+        &mut self.pad
+    }
+
     pub fn boot_active(&self) -> bool {
         self.boot_active
     }
diff --git a/src/pad.rs b/src/pad.rs
index f147fb5029b40c8325648ea14881dcebcf535d4d..5d14fd259bb4814255d5bfdcbf2f35458ffb0f73 100644
--- a/src/pad.rs
+++ b/src/pad.rs
@@ -1,3 +1,6 @@
+#[cfg(feature = "wasm")]
+use wasm_bindgen::prelude::*;
+
 pub struct Pad {
     down: bool,
     up: bool,
@@ -16,6 +19,7 @@ pub enum PadSelection {
     Direction,
 }
 
+#[cfg_attr(feature = "wasm", wasm_bindgen)]
 pub enum PadKey {
     Up,
     Down,
@@ -87,4 +91,30 @@ impl Pad {
             addr => panic!("Writing to unknown Pad location 0x{:04x}", addr),
         }
     }
+
+    pub fn key_press(&mut self, key: PadKey) {
+        match key {
+            PadKey::Up => self.up = true,
+            PadKey::Down => self.down = true,
+            PadKey::Left => self.left = true,
+            PadKey::Right => self.right = true,
+            PadKey::Start => self.start = true,
+            PadKey::Select => self.select = true,
+            PadKey::A => self.a = true,
+            PadKey::B => self.b = true,
+        }
+    }
+
+    pub fn key_lift(&mut self, key: PadKey) {
+        match key {
+            PadKey::Up => self.up = false,
+            PadKey::Down => self.down = false,
+            PadKey::Left => self.left = false,
+            PadKey::Right => self.right = false,
+            PadKey::Start => self.start = false,
+            PadKey::Select => self.select = false,
+            PadKey::A => self.a = false,
+            PadKey::B => self.b = false,
+        }
+    }
 }