diff --git a/src/cpu.rs b/src/cpu.rs
index 55fb7f15440a1a22f8c5579d5c98ef8e7f9ed40d..bbdb384b597e0c1d149e5be04ed34d7a3d132f01 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -1,4 +1,4 @@
-use crate::mmu::Mmu;
+use crate::{mmu::Mmu, ppu::Ppu};
 
 pub const PREFIX: u8 = 0xcb;
 
@@ -525,7 +525,7 @@ impl Cpu {
             instruction = &INSTRUCTIONS[opcode as usize];
         }
 
-        let (instruction_fn, instruction_size, instruction_str) = instruction;
+        let (instruction_fn, instruction_time, instruction_str) = instruction;
 
         println!(
             "{}\t(0x{:02x})\t${:04x} {}",
@@ -533,7 +533,11 @@ impl Cpu {
         );
 
         instruction_fn(self);
-        self.ticks = self.ticks.wrapping_add(*instruction_size as u32);
+        self.ticks = self.ticks.wrapping_add(*instruction_time as u32);
+
+        // calls the clock in the PPU to update its own
+        // execution lifecycle by one set of ticks
+        self.ppu().clock(*instruction_time);
     }
 
     #[inline(always)]
@@ -541,11 +545,26 @@ impl Cpu {
         &mut self.mmu
     }
 
+    #[inline(always)]
+    pub fn ppu(&mut self) -> &mut Ppu {
+        self.mmu().ppu()
+    }
+
+    #[inline(always)]
+    pub fn ticks(&self) -> u32 {
+        self.ticks
+    }
+
     #[inline(always)]
     pub fn pc(&self) -> u16 {
         self.pc
     }
 
+    #[inline(always)]
+    pub fn sp(&self) -> u16 {
+        self.sp
+    }
+
     #[inline(always)]
     fn af(&self) -> u16 {
         (self.a as u16) << 8 | self.f() as u16
diff --git a/src/gb.rs b/src/gb.rs
index 6d6739c07bc7ad2b825b7f2f7e8f712455f7f746..aa723ef215137c44cebde98a7855be183c6a3111 100644
--- a/src/gb.rs
+++ b/src/gb.rs
@@ -16,16 +16,16 @@ impl GameBoy {
         self.cpu.clock()
     }
 
-    pub fn cpu(&self) -> &Cpu {
-        &self.cpu
+    pub fn cpu(&mut self) -> &mut Cpu {
+        &mut self.cpu
     }
 
-    pub fn mmu(&mut self) -> &Mmu {
+    pub fn mmu(&mut self) -> &mut Mmu {
         self.cpu.mmu()
     }
 
-    pub fn ppu(&mut self) -> &Ppu {
-        self.mmu().ppu()
+    pub fn ppu(&mut self) -> &mut Ppu {
+        self.cpu.ppu()
     }
 
     pub fn load_boot(&mut self, path: &str) {
diff --git a/src/mmu.rs b/src/mmu.rs
index 758f953772887173a87861905118a3b7e3f200b4..ce015cb45188c855eb8388fdfd99c455a684f05d 100644
--- a/src/mmu.rs
+++ b/src/mmu.rs
@@ -26,8 +26,8 @@ impl Mmu {
         }
     }
 
-    pub fn ppu(&self) -> &Ppu {
-        &self.ppu
+    pub fn ppu(&mut self) -> &mut Ppu {
+        &mut self.ppu
     }
 
     pub fn read(&mut self, addr: u16) -> u8 {
diff --git a/src/ppu.rs b/src/ppu.rs
index adcb432238b9298eebeae9c1dcf4590c89d5dbf1..cc3c4ceac6a12d0acfede704c42e14944e3a4335 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -1,24 +1,63 @@
+use crate::cpu::Cpu;
+
 pub const VRAM_SIZE: usize = 8192;
 pub const HRAM_SIZE: usize = 128;
 pub const PALETTE_SIZE: usize = 4;
 pub const RGBA_SIZE: usize = 4;
+pub const SCREEN_WIDTH: usize = 160;
+pub const SCREEN_HEIGHT: usize = 154;
 
+/// Represents the Game Boy PPU (Pixel Processing Unit) and controls
+/// all of the logic behind the graphics processing and presentation.
+/// Should store both the VRAM and HRAM together with the internal
+/// graphic related registers.
+/// Outputs the screen as a monochromatic 8 bit frame buffer.
+///
+/// # Basic usage
+/// ```rust
+/// let ppu = Ppu::new();
+/// ppu.tick();
+/// ```
 pub struct Ppu {
+    /// The 8 bit based monochromatic frame buffer with the
+    /// processed set of pixels ready to be displayed on screen.
+    pub frame_buffer: [u8; SCREEN_WIDTH * SCREEN_HEIGHT],
+    /// Video dedicated memory (VRAM) where both the tiles and
+    /// the sprites are going to be stored.
     pub vram: [u8; VRAM_SIZE],
     pub hram: [u8; HRAM_SIZE],
-    pub palette: [[u8; RGBA_SIZE]; PALETTE_SIZE],
-    pub scy: u8,
-    pub scx: u8,
-    pub line: u8,
-    pub switch_bg: bool,
-    pub bg_map: bool,
-    pub bg_tile: bool,
-    pub switch_lcd: bool,
+    palette: [[u8; RGBA_SIZE]; PALETTE_SIZE],
+    /// The scroll Y register that controls the Y offset
+    /// of the background.
+    scy: u8,
+    /// The scroll X register that controls the X offset
+    /// of the background.
+    scx: u8,
+    /// The current scan line in processing, should
+    /// range between 0 (0x00) and 153 (0x99), representing
+    /// the 154 lines plus 10 extra v-blank lines.
+    line: u8,
+    switch_bg: bool,
+    bg_map: bool,
+    bg_tile: bool,
+    switch_lcd: bool,
+    mode: PpuMode,
+    /// Internal clock counter used to control the time in ticks
+    /// spent in each of the PPU modes.
+    mode_clock: u16,
+}
+
+pub enum PpuMode {
+    OamRead,
+    VramRead,
+    Hblank,
+    VBlank,
 }
 
 impl Ppu {
     pub fn new() -> Ppu {
         Ppu {
+            frame_buffer: [0u8; SCREEN_WIDTH * SCREEN_HEIGHT],
             vram: [0u8; VRAM_SIZE],
             hram: [0u8; HRAM_SIZE],
             palette: [[0u8; RGBA_SIZE]; PALETTE_SIZE],
@@ -29,10 +68,32 @@ impl Ppu {
             bg_map: false,
             bg_tile: false,
             switch_lcd: false,
+            mode: PpuMode::OamRead,
+            mode_clock: 0,
         }
     }
 
-    pub fn clock() {}
+    pub fn clock(&mut self, ticks: u8) {
+        self.mode_clock += ticks as u16;
+        match self.mode {
+            PpuMode::OamRead => {
+                if self.mode_clock >= 204 {
+                    self.mode_clock = 0;
+                    self.mode = PpuMode::VramRead;
+                }
+            }
+            PpuMode::VramRead => {
+                if self.mode_clock >= 172 {
+                    self.render_line();
+
+                    self.mode_clock = 0;
+                    self.mode = PpuMode::Hblank;
+                }
+            }
+            PpuMode::Hblank => todo!(),
+            PpuMode::VBlank => todo!(),
+        }
+    }
 
     pub fn read(&mut self, addr: u16) -> u8 {
         match addr & 0x00ff {
@@ -74,4 +135,8 @@ impl Ppu {
             addr => panic!("Writing in unknown PPU location 0x{:04x}", addr),
         }
     }
+
+    fn render_line(&self) {
+        //@todo implement the rendering of a line
+    }
 }