diff --git a/src/cpu.rs b/src/cpu.rs
index 9be9b16944dfd31c5fd9c66401c6058f64551e71..4f3b03ed23e893233f20090081cb490b60d16b27 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -7,6 +7,7 @@ use crate::{
     mmu::Mmu,
     pad::Pad,
     ppu::Ppu,
+    serial::Serial,
     timer::Timer,
 };
 
@@ -297,6 +298,11 @@ impl Cpu {
         self.mmu().timer()
     }
 
+    #[inline(always)]
+    pub fn serial(&mut self) -> &mut Serial {
+        self.mmu().serial()
+    }
+
     #[inline(always)]
     pub fn halted(&self) -> bool {
         self.halted
diff --git a/src/gb.rs b/src/gb.rs
index 5fc389dc5f42b3f1f09b86c1a0e84c4e67b24209..327e15b47a8cb23c0229468fb541e03263ab2bc2 100644
--- a/src/gb.rs
+++ b/src/gb.rs
@@ -7,6 +7,7 @@ use crate::{
     pad::{Pad, PadKey},
     ppu::{Ppu, PpuMode, Tile, FRAME_BUFFER_SIZE},
     rom::Cartridge,
+    serial::Serial,
     timer::Timer,
     util::read_file,
 };
@@ -44,6 +45,9 @@ pub struct GameBoy {
     /// If the timer is enabled, it will be clocked.
     timer_enabled: bool,
 
+    /// If the serial is enabled, it will be clocked.
+    serial_enabled: bool,
+
     /// The current frequency at which the Game Boy
     /// emulator is being handled. This is a "hint" that
     /// may help components to adjust their internal
@@ -86,13 +90,15 @@ impl GameBoy {
         let apu = Apu::default();
         let pad = Pad::default();
         let timer = Timer::default();
-        let mmu = Mmu::new(ppu, apu, pad, timer);
+        let serial = Serial::default();
+        let mmu = Mmu::new(ppu, apu, pad, timer, serial);
         let cpu = Cpu::new(mmu);
         Self {
             cpu,
             ppu_enabled: true,
             apu_enabled: true,
             timer_enabled: true,
+            serial_enabled: true,
             clock_freq: GameBoy::CPU_FREQ,
         }
     }
@@ -100,6 +106,8 @@ impl GameBoy {
     pub fn reset(&mut self) {
         self.ppu().reset();
         self.apu().reset();
+        self.timer().reset();
+        self.serial().reset();
         self.mmu().reset();
         self.cpu.reset();
     }
@@ -115,6 +123,9 @@ impl GameBoy {
         if self.timer_enabled {
             self.timer_clock(cycles);
         }
+        if self.serial_enabled {
+            self.serial_clock(cycles);
+        }
         cycles
     }
 
@@ -142,6 +153,10 @@ impl GameBoy {
         self.timer().clock(cycles)
     }
 
+    pub fn serial_clock(&mut self, cycles: u8) {
+        self.serial().clock(cycles)
+    }
+
     pub fn ppu_ly(&mut self) -> u8 {
         self.ppu().ly()
     }
@@ -325,6 +340,14 @@ impl GameBoy {
         self.timer_enabled = value;
     }
 
+    pub fn serial_enabled(&self) -> bool {
+        self.serial_enabled
+    }
+
+    pub fn set_serial_enabled(&mut self, value: bool) {
+        self.serial_enabled = value;
+    }
+
     pub fn clock_freq(&self) -> u32 {
         self.clock_freq
     }
@@ -378,6 +401,10 @@ impl GameBoy {
         self.cpu.timer()
     }
 
+    pub fn serial(&mut self) -> &mut Serial {
+        self.cpu.serial()
+    }
+
     pub fn frame_buffer(&mut self) -> &[u8; FRAME_BUFFER_SIZE] {
         &(self.ppu().frame_buffer)
     }
diff --git a/src/lib.rs b/src/lib.rs
index 7decfab2b80948c67ae0c8c3765191dda99b7743..86a725760ebe3f191118a6f09f3bfa9e2070ca06 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,5 +11,6 @@ pub mod mmu;
 pub mod pad;
 pub mod ppu;
 pub mod rom;
+pub mod serial;
 pub mod timer;
 pub mod util;
diff --git a/src/mmu.rs b/src/mmu.rs
index bc4a9ddd43ca2d8a814f4d0af2c09bce448d2a6d..ff7b66b920d967bb6ac44eb58ac9357491f13597 100644
--- a/src/mmu.rs
+++ b/src/mmu.rs
@@ -1,4 +1,4 @@
-use crate::{apu::Apu, debugln, pad::Pad, ppu::Ppu, rom::Cartridge, timer::Timer};
+use crate::{apu::Apu, debugln, pad::Pad, ppu::Ppu, rom::Cartridge, serial::Serial, timer::Timer};
 
 pub const BOOT_SIZE: usize = 2304;
 pub const RAM_SIZE: usize = 8192;
@@ -26,6 +26,10 @@ pub struct Mmu {
     /// that is memory mapped.
     timer: Timer,
 
+    /// The serial data transfer controller to be used to control the
+    /// link cable connection, this component is memory mapped.
+    serial: Serial,
+
     /// The cartridge ROM that is currently loaded into the system,
     /// going to be used to access ROM and external RAM banks.
     rom: Cartridge,
@@ -49,12 +53,13 @@ pub struct Mmu {
 }
 
 impl Mmu {
-    pub fn new(ppu: Ppu, apu: Apu, pad: Pad, timer: Timer) -> Self {
+    pub fn new(ppu: Ppu, apu: Apu, pad: Pad, timer: Timer, serial: Serial) -> Self {
         Self {
             ppu,
             apu,
             pad,
             timer,
+            serial,
             rom: Cartridge::new(),
             boot_active: true,
             boot: [0u8; BOOT_SIZE],
@@ -91,6 +96,10 @@ impl Mmu {
         &mut self.timer
     }
 
+    pub fn serial(&mut self) -> &mut Serial {
+        &mut self.serial
+    }
+
     pub fn boot_active(&self) -> bool {
         self.boot_active
     }
diff --git a/src/serial.rs b/src/serial.rs
new file mode 100644
index 0000000000000000000000000000000000000000..cb51f2861a51d35faf99679ae70bfa5973235c38
--- /dev/null
+++ b/src/serial.rs
@@ -0,0 +1,79 @@
+use crate::warnln;
+
+pub struct Serial {
+    data: u8,
+    control: u8,
+    shift_clock: bool,
+    clock_speed: bool,
+    transferring: bool,
+}
+
+impl Serial {
+    pub fn new() -> Self {
+        Self {
+            data: 0x0,
+            control: 0x0,
+            shift_clock: false,
+            clock_speed: false,
+            transferring: false,
+        }
+    }
+
+    pub fn reset(&mut self) {
+        self.data = 0x0;
+        self.control = 0x0;
+        self.shift_clock = false;
+        self.clock_speed = false;
+        self.transferring = false;
+    }
+
+    pub fn clock(&mut self, cycles: u8) {}
+
+    pub fn read(&mut self, addr: u16) -> u8 {
+        match addr & 0x00ff {
+            0x01 => self.data,
+            0x02 => {
+                (if self.shift_clock { 0x01 } else { 0x00 }
+                    | if self.clock_speed { 0x02 } else { 0x00 }
+                    | if self.transferring { 0x80 } else { 0x00 })
+            }
+            _ => {
+                warnln!("Reding from unknown Timer location 0x{:04x}", addr);
+                0xff
+            }
+        }
+    }
+
+    pub fn write(&mut self, addr: u16, value: u8) {
+        match addr & 0x00ff {
+            0x01 => self.data = value,
+            0x02 => {
+                self.shift_clock = value & 0x01 == 0x01;
+                self.clock_speed = value & 0x02 == 0x02;
+                self.transferring = value & 0x80 == 0x80;
+            }
+            _ => warnln!("Writing to unknown Serial location 0x{:04x}", addr),
+        }
+    }
+
+    fn send(&self) -> bool {
+        if self.shift_clock {
+            true
+        } else {
+            self.data & 0x80 == 0x80
+        }
+    }
+
+    fn receive(&self, bit: bool) {
+        if !self.shift_clock {
+            //data = (data << 1) | bit;
+            //check_transfer();
+        }
+    }
+}
+
+impl Default for Serial {
+    fn default() -> Self {
+        Self::new()
+    }
+}