diff --git a/code/Cargo.lock b/code/Cargo.lock
index 8499c420d19c9f991ea53b5c9d8dc44f1b143422..c3316ff5cbfc94e452634d6bb43ced38de8148ed 100644
--- a/code/Cargo.lock
+++ b/code/Cargo.lock
@@ -23,6 +23,7 @@ dependencies = [
  "stm32f4 0.13.0",
  "stm32f4xx-hal",
  "usb-device",
+ "usbd-hid",
 ]
 
 [[package]]
@@ -60,9 +61,9 @@ checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
 
 [[package]]
 name = "byteorder"
-version = "1.4.3"
+version = "1.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
 
 [[package]]
 name = "cast"
@@ -164,6 +165,12 @@ dependencies = [
  "void",
 ]
 
+[[package]]
+name = "encode_unicode"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+
 [[package]]
 name = "generic-array"
 version = "0.12.4"
@@ -344,6 +351,22 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 
+[[package]]
+name = "serde"
+version = "1.0.124"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
+
+[[package]]
+name = "ssmarshal"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3e6ad23b128192ed337dfa4f1b8099ced0c2bf30d61e551b65fda5916dbb850"
+dependencies = [
+ "encode_unicode",
+ "serde",
+]
+
 [[package]]
 name = "stable_deref_trait"
 version = "1.2.0"
@@ -449,6 +472,41 @@ version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6be90410d4772074ea49525e2e753b65920b94b57eee21a6ef7b6a6fe6296245"
 
+[[package]]
+name = "usbd-hid"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bab0c5efbec0d66d9fd77b64be7a186f7cfff99d9baaae3b7c312538c20ede02"
+dependencies = [
+ "serde",
+ "ssmarshal",
+ "usb-device",
+ "usbd-hid-macros",
+]
+
+[[package]]
+name = "usbd-hid-descriptors"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e00430c0b39caf3957aba6c2b2824f8e70e1ac0278941418bf1fe35f9566d64"
+dependencies = [
+ "bitfield",
+]
+
+[[package]]
+name = "usbd-hid-macros"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b854699aa737a7176d3a0019032350deab561da90a237b69efe3d5ded3732efe"
+dependencies = [
+ "byteorder",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "syn",
+ "usbd-hid-descriptors",
+]
+
 [[package]]
 name = "vcell"
 version = "0.1.3"
diff --git a/code/Cargo.toml b/code/Cargo.toml
index fbede03661387d654bfdb89def8e34f34fc71617..af9967acdf8dd4f70aefcd40a79cdde7e17d8e02 100644
--- a/code/Cargo.toml
+++ b/code/Cargo.toml
@@ -12,6 +12,7 @@ cortex-m-semihosting = "0.3.7"
 cortex-m-rtic = "0.5.5"
 embedded-hal = "0.2.4"
 usb-device = "0.2.7"
+usbd-hid = "0.5.0"
 
 # Panic handlers, comment all but one to generate doc!
 #panic-halt = "0.2.0"
diff --git a/code/examples/rtt_rtic_usb_mouse.rs b/code/examples/rtt_rtic_usb_mouse.rs
index ddd04db8b70e19938463f8bdb7a595f41df3ddf1..7d425ae907f94310e7276026d1985a753074dca0 100644
--- a/code/examples/rtt_rtic_usb_mouse.rs
+++ b/code/examples/rtt_rtic_usb_mouse.rs
@@ -28,8 +28,11 @@ use stm32f4xx_hal::{
     otg_fs::{UsbBus, UsbBusType, USB},
     prelude::*,
 };
-use usb_device::bus;
-use usb_device::prelude::*;
+use usb_device::{bus::{self, UsbBusAllocator}, prelude::*};
+use usbd_hid::{
+    descriptor::{generator_prelude::*, MouseReport},
+    hid_class::HIDClass,
+};
 
 #[allow(unused)]
 pub mod hid {
@@ -211,8 +214,6 @@ pub mod hid {
     }
 }
 
-use hid::HIDClass;
-
 // PMW3389
 use app::{DwtDelay, pmw3389::{self, Register}, pmw3389e};
 use rtt_target::{rprintln, rtt_init_print};
@@ -253,7 +254,7 @@ const APP: () = {
 
     #[init(schedule = [poll, tick])]
     fn init(mut cx: init::Context) -> init::LateResources {
-        static mut USB_BUS: Option<bus::UsbBusAllocator<UsbBusType>> = None;
+        static mut USB_BUS: Option<UsbBusAllocator<UsbBusType>> = None;
         static mut EP_MEMORY: [u32; 1024] = [0; 1024];
         cx.core.DCB.enable_trace();
         DWT::unlock();
@@ -277,16 +278,6 @@ const APP: () = {
         let gpioc = device.GPIOC.split();
         let gpiob = device.GPIOB.split();
 
-<<<<<<< HEAD
-        let mb2 = gpioc.pc6.into_pull_up_input();
-        let mb1 = gpioc.pc7.into_pull_up_input();
-
-        let mb5 = gpiob.pb15.into_pull_up_input();
-        let mb4 = gpiob.pb14.into_pull_up_input();
-
-        let dpib1 = gpiob.pb13.into_pull_up_input();
-        let dpib2 = gpiob.pb12.into_pull_up_input();
-=======
         // Buttons
         let mb2 = gpioc.pc6.into_pull_up_input();
         let mb1 = gpioc.pc7.into_pull_up_input();
@@ -316,7 +307,6 @@ const APP: () = {
 
         // set in burst mode
         pmw3389.write_register(Register::MotionBurst, 0x00);
->>>>>>> 3043b359af07960fb4472e373824f552897ee4aa
 
         // Pull the D+ pin down to send a RESET condition to the USB bus.
         let mut usb_dp = gpioa.pa12.into_push_pull_output();
@@ -336,7 +326,7 @@ const APP: () = {
 
         *USB_BUS = Some(UsbBus::new(usb, EP_MEMORY));
 
-        let hid = HIDClass::new(USB_BUS.as_ref().unwrap());
+        let hid = HIDClass::new(USB_BUS.as_ref().unwrap(), MouseReport::desc(), 1);
 
         let usb_dev = UsbDeviceBuilder::new(USB_BUS.as_ref().unwrap(), UsbVidPid(0xc410, 0x0000))
             .manufacturer("Albatraoz")
@@ -361,7 +351,7 @@ const APP: () = {
 
     #[idle]
     fn idle(_cx: idle::Context) -> ! {
-        // rprintln!("idle");
+        rprintln!("idle");
         loop {
             continue;
         }
@@ -385,6 +375,7 @@ const APP: () = {
     #[task(resources = [hid, POS_X, POS_Y, OLD_POS_X, OLD_POS_Y, MB1, MB2], schedule = [tick])]
     fn tick(mut cx: tick::Context) {
         cx.schedule.tick(cx.scheduled + (84_000).cycles()).unwrap();
+        let res = cx.resources;
         let pos_x = cx.resources.POS_X;
         let pos_y = cx.resources.POS_Y;
         let old_pos_x = cx.resources.OLD_POS_X;
@@ -396,8 +387,18 @@ const APP: () = {
         let diff_x = *pos_x-*old_pos_x;
         let diff_y = *pos_y-*old_pos_y;
 
-        // Send to computer
-        hid.write(&hid::report(0x01 as u8,(diff_x) as i8, (diff_y) as i8));
+        let report = MouseReport {
+            x: diff_x as i8,
+            y: diff_y as i8,
+            buttons: res.MB1.is_low().unwrap().into(), // (into takes a bool into an integer)
+            wheel: 0,
+        };
+
+        rprintln!("Report: x:{}, y:{}", *pos_x, *pos_y);
+
+        // push the report
+        hid.push_input(&report).ok();
+
         
         *old_pos_x = *pos_x;
         *old_pos_y = *pos_y;
diff --git a/code/src/main.rs b/code/src/main.rs
index 792259654a49249056b0368a6cc45d2f3959069e..e75c8637851bb721629ef5f975a0edd29367d5ba 100644
--- a/code/src/main.rs
+++ b/code/src/main.rs
@@ -1,20 +1,231 @@
-#![no_std]
+// > cargo run usb-mouse
+// or
+// > cargo run usb-mouse --release
+
 #![no_main]
+#![no_std]
+
+
+use cortex_m::{asm::delay, peripheral::DWT};
+use embedded_hal::digital::v2::OutputPin;
+use embedded_hal::spi::MODE_3;
+use rtic::cyccnt::{Instant, U32Ext as _};
+use stm32f4xx_hal::{
+    dwt::Dwt,
+    gpio::{
+        Speed, Alternate, Input, Output, PullUp, PushPull,
+        gpioa::{PA15},
+        gpiob::{self,PB12, PB13, PB14, PB15},
+        gpioc::{self,PC6, PC7, PC10, PC11, PC12},
+    },
+    prelude::*,
+    rcc::Clocks,
+    spi::Spi,
+    stm32,
+    otg_fs::{UsbBus, UsbBusType, USB},
+    prelude::*,
+};
+use usb_device::{bus::UsbBusAllocator, prelude::*};
+use usbd_hid::{
+    descriptor::{generator_prelude::*, MouseReport},
+    hid_class::HIDClass,
+};
+
+use panic_rtt_target as _;
+use rtt_target::{rprintln, rtt_init_print};
+
+// PMW3389
+use app::{DwtDelay, pmw3389::{self, Register}, pmw3389e};
+
+type PMW3389T = pmw3389::Pmw3389<
+    Spi<
+        stm32f4xx_hal::stm32::SPI3,
+        (
+            PC10<Alternate<stm32f4xx_hal::gpio::AF6>>,
+            PC11<Alternate<stm32f4xx_hal::gpio::AF6>>,
+            PC12<Alternate<stm32f4xx_hal::gpio::AF6>>,
+        ),
+    >,
+    PA15<Output<PushPull>>,
+>;
+
+#[rtic::app(device = stm32f4xx_hal::stm32, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
+const APP: () = {
+    struct Resources {
+        usb_dev: UsbDevice<'static, UsbBusType>,
+        hid: HIDClass<'static, UsbBusType>,
+
+        pmw3389: PMW3389T,
+
+        POS_X: i8,
+        POS_Y: i8,
+        OLD_POS_X: i64,
+        OLD_POS_Y: i64,
+
+        MB2: gpioc::PC6<Input<PullUp>>,
+        MB1: gpioc::PC7<Input<PullUp>>,
+        DPIB1: gpiob::PB13<Input<PullUp>>,
+        DPIB2: gpiob::PB12<Input<PullUp>>,
+        MB5: gpiob::PB15<Input<PullUp>>,
+        MB4: gpiob::PB14<Input<PullUp>>,
+    }
+
+    #[init(schedule = [poll])]
+    fn init(mut cx: init::Context) -> init::LateResources {
+        static mut EP_MEMORY: [u32; 1024] = [0; 1024];
+        static mut USB_BUS: Option<UsbBusAllocator<UsbBusType>> = None;
+
+        rtt_init_print!();
+        rprintln!("init");
+
+        cx.core.DCB.enable_trace();
+        DWT::unlock();
+        cx.core.DWT.enable_cycle_counter();
+
+        let mut core = cx.core;
+        let device = cx.device;
+
+        let rcc = device.RCC.constrain();
+
+        let clocks = rcc
+            .cfgr
+            .sysclk(84.mhz())
+            .pclk1(42.mhz())
+            .pclk2(64.mhz())
+            .freeze();
+
+        // assert!(clocks.usbclk_valid());
+
+        let gpioa = device.GPIOA.split();
+        let gpioc = device.GPIOC.split();
+        let gpiob = device.GPIOB.split();
+
+        // Buttons
+        let mb2 = gpioc.pc6.into_pull_up_input();
+        let mb1 = gpioc.pc7.into_pull_up_input();
+        let mb5 = gpiob.pb15.into_pull_up_input();
+        let mb4 = gpiob.pb14.into_pull_up_input();
+        let dpib1 = gpiob.pb13.into_pull_up_input();
+        let dpib2 = gpiob.pb12.into_pull_up_input();
 
-// pick a panicking behavior
-use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics
-// use panic_abort as _; // requires nightly
-// use panic_itm as _; // logs messages over ITM; requires ITM support
-// use panic_semihosting as _; // logs messages to the host stderr; requires a debugger
+        // Sensor communcation
+        let sck = gpioc.pc10.into_alternate_af6();
+        let miso = gpioc.pc11.into_alternate_af6();
+        let mosi = gpioc.pc12.into_alternate_af6();
+        let cs = gpioa.pa15.into_push_pull_output().set_speed(Speed::High);
 
-use cortex_m::asm;
-use cortex_m_rt::entry;
+        let spi = Spi::spi3(
+            device.SPI3,
+            (sck, miso, mosi),
+            MODE_3,
+            stm32f4xx_hal::time::KiloHertz(2000).into(),
+            clocks,
+        );
 
-#[entry]
-fn main() -> ! {
-    asm::nop(); // To not have main optimize to abort in release mode, remove when you add code
+        let mut delay_dwt = DwtDelay::new(&mut core.DWT, clocks);
+        let mut pmw3389 = pmw3389::Pmw3389::new(spi, cs, delay_dwt).unwrap();
+
+        // set in burst mode
+        pmw3389.write_register(Register::MotionBurst, 0x00);
+        //pmw3389.write_register(Register::ResolutionL, 255 as u8);
+        pmw3389.write_register(Register::ResolutionH, 0 as u8); // sets CPI 0 is lowest, don't know the number tho
+
+        let usb = USB {
+            usb_global: device.OTG_FS_GLOBAL,
+            usb_device: device.OTG_FS_DEVICE,
+            usb_pwrclk: device.OTG_FS_PWRCLK,
+            pin_dm: gpioa.pa11.into_alternate_af10(),
+            pin_dp: gpioa.pa12.into_alternate_af10(),
+        };
+
+
+        USB_BUS.replace(UsbBus::new(usb, EP_MEMORY));
+
+        let hid = HIDClass::new(USB_BUS.as_ref().unwrap(), MouseReport::desc(), 1);
+        let usb_dev = UsbDeviceBuilder::new(USB_BUS.as_ref().unwrap(), UsbVidPid(0xc410, 0x0000))
+            .manufacturer("")
+            .product("Vibora Rapido Muerta")
+            .serial_number("33-32-33")
+            .device_class(0)
+            .build();
+        
+        cx.schedule.poll(cx.start + (48_000).cycles()).ok();
+
+        init::LateResources {
+            usb_dev,
+            hid,
+            MB1:mb1, MB2:mb2, MB4:mb4, MB5:mb5, DPIB1:dpib1, DPIB2:dpib2,
+            pmw3389,
+            POS_X: 0, POS_Y: 0, OLD_POS_X: 0, OLD_POS_Y: 0,
+
+        }
+    }
+
+    #[task(resources = [pmw3389, POS_X, POS_Y], schedule = [poll], priority = 2)]
+    fn poll(mut cx: poll::Context) {
+        let pos_x = cx.resources.POS_X;
+        let pos_y = cx.resources.POS_Y;
+
+        let (x, y) = cx.resources.pmw3389.read_status().unwrap();
+        *pos_x = x as i8;
+        *pos_y = y as i8;
+
+        // task should run each Sclck/N times each second. 84M/8400 = 10_000
+        cx.schedule
+            .poll(cx.scheduled + (84_00).cycles())
+            .unwrap();
+    }
+
+    #[task(binds=OTG_FS, resources = [hid, usb_dev, POS_X, POS_Y, OLD_POS_X, OLD_POS_Y, MB1, MB2], priority = 2)]
+    fn on_usb(cx: on_usb::Context) {
+        // destruct the context
+        let (
+                usb_dev, 
+                hid,
+                mb1,
+                mb2,
+                pos_x,
+                pos_y,
+            ) = (
+                cx.resources.usb_dev, 
+                cx.resources.hid, 
+                cx.resources.MB1, 
+                cx.resources.MB2,
+                cx.resources.POS_X,
+                cx.resources.POS_Y,
+            );
+
+
+        let report = MouseReport {
+            x: *pos_x,
+            y: *pos_y,
+            buttons: ((
+                        mb2.is_low().unwrap() as u8) << 1 
+                        | mb1.is_low().unwrap() as u8), // buttons = 1 byte. MB1 = bit 1, MB2 = bit 2, etc etc
+            wheel: 0,
+        };
+
+        rprintln!("Report: x:{}, y:{}", *pos_x, *pos_y);
+
+        // push the report
+        hid.push_input(&report).ok();
+
+        // update the usb device state
+        if usb_dev.poll(&mut [hid]) {
+            return;
+        }
+    }
+
+    extern "C" {
+        fn EXTI0();
+        fn EXTI1();
+    }
 
-    loop {
-        // your code goes here
+    #[idle]
+    fn idle(_cx: idle::Context) -> ! {
+        rprintln!("idle");
+        loop {
+            continue;
+        }
     }
-}
+};
diff --git a/code/src/pmw3389.rs b/code/src/pmw3389.rs
index a978c32dfeece778559228503d94d6cf1242b5cf..77c08e916c51eaccb4da1dbb0397394dec085a54 100644
--- a/code/src/pmw3389.rs
+++ b/code/src/pmw3389.rs
@@ -340,7 +340,7 @@ where
         // // set initial CPI resolution
         // // adns_write_reg(Config1, 0x15);
 
-        let cpi: u16 = 16000;
+        let cpi: u16 = 800;
         self.write_register(Register::ResolutionL, cpi as u8)?;
         self.write_register(Register::ResolutionH, (cpi >> 8) as u8)?;