diff --git a/Cargo.lock b/Cargo.lock
index 8a16d3adecfb82827f44fbcf5f57bed9e3e3b10c..362737c0c4718f6c3ca110cae94ca0c2e1c87392 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -81,10 +81,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "card10-l0dable"
 version = "0.1.1"
 dependencies = [
- "bindgen 0.51.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "panic-abort 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "card10-sys 0.1.0",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 6d8aa70dd694f12552e3a67655523d92f6382b4f..121d83969b85dfca59a9a1a8bc616467b144fcff 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [workspace]
 members = [
   "card10-sys",
-  "l0dable",
+  "card10-l0dable",
   "example",
   "rkanoid",
 ]
diff --git a/README.md b/README.md
index 9ef549383fa6545a12e99f3aa9f8a5f3bce1704d..1bb02120c5cd1cf789872b54ea333826e04185b1 100644
--- a/README.md
+++ b/README.md
@@ -74,25 +74,25 @@ extension (e.g `example` must be renamed as `example.elf`).
 
 ## Crates
 
-| Crate    | Description                                               |
-| ----     | ---                                                       |
-| l0dable  | Helper crate for building l0dables                        |
-| example  | l0dable example                                           |
-| rkanoid  | Arkanoid clone                                            |
+| Crate           | Description                                               |
+| ----            | ---                                                       |
+| card10-l0dable  | Helper crate for building l0dables                        |
+| example         | l0dable example                                           |
+| rkanoid         | Arkanoid clone                                            |
 
 
 ## Misc
 
 ### How to update the firmware bindings
 
-1) Update the `c/` submodule to the latest firmware state.
+1) Update the `card10-sys/firmware` submodule to the latest firmware state.
 
 2) Rebuild the firmware as described above.
 
 3) Run the following script from the project root directory
 
    ```shell
-   python c/epicardium/api/genapi.py -H c/epicardium/epicardium.h -c l0dable/src/client.c -s l0dable/src/server.c
+   python card10-sys/firmware/epicardium/api/genapi.py -H card10-sys/firmware/epicardium/epicardium.h -c card10-sys/vendor/client.c -s card10-sys/vendor/server.c
    ```
 
 4) Rebuild your app :)
diff --git a/l0dable/Cargo.toml b/card10-l0dable/Cargo.toml
similarity index 65%
rename from l0dable/Cargo.toml
rename to card10-l0dable/Cargo.toml
index a23070dd8cb6fd28e007d21140e533e367ed41ed..96880ced0aa0403563f51380d63f891871e40e49 100644
--- a/l0dable/Cargo.toml
+++ b/card10-l0dable/Cargo.toml
@@ -14,20 +14,8 @@ keywords = [
     "l0dable",
 ]
 categories = ["no-std"]
-description = """
-make l0dables for the Card10 (CCCamp 2019) badge
-"""
-include = [
-    "**/*.rs",
-    "Cargo.toml",
-    "l0dable.ld",
-    "../c/",
-]
+description = "make l0dables for the Card10 (CCCamp 2019) badge"
 
 [dependencies]
-r0 = "0.2"
-panic-abort = "0.3"
+card10-sys = { path = "../card10-sys", version = "^0.1" }
 
-[build-dependencies]
-cc = "1.0"
-bindgen = "0.51"
diff --git a/l0dable/LICENSE-APACHE b/card10-l0dable/LICENSE-APACHE
similarity index 100%
rename from l0dable/LICENSE-APACHE
rename to card10-l0dable/LICENSE-APACHE
diff --git a/l0dable/LICENSE-MIT b/card10-l0dable/LICENSE-MIT
similarity index 100%
rename from l0dable/LICENSE-MIT
rename to card10-l0dable/LICENSE-MIT
diff --git a/l0dable/src/bhi160.rs b/card10-l0dable/src/bhi160.rs
similarity index 99%
rename from l0dable/src/bhi160.rs
rename to card10-l0dable/src/bhi160.rs
index 9569a4b1338a399a4a1320d5cdca94dfada8a647..1e68872e26517baadc095da4d307d1e008569b12 100644
--- a/l0dable/src/bhi160.rs
+++ b/card10-l0dable/src/bhi160.rs
@@ -4,7 +4,7 @@ use core::{
     mem::MaybeUninit,
 };
 
-use crate::{bindings::*, errno};
+use card10_sys::*;
 
 pub trait SensorType {
     /// sensor_type in C, sensor_id in Python
diff --git a/l0dable/src/bme680.rs b/card10-l0dable/src/bme680.rs
similarity index 87%
rename from l0dable/src/bme680.rs
rename to card10-l0dable/src/bme680.rs
index d2e3af27d6e4a32b07df92280c06d6ac259bee4f..719361a07a2306673187fb9b14d6b330da557cd8 100644
--- a/l0dable/src/bme680.rs
+++ b/card10-l0dable/src/bme680.rs
@@ -1,5 +1,5 @@
+use card10_sys::*;
 use core::mem::uninitialized;
-use super::bindings::*;
 
 pub struct BME680;
 pub type SensorData = bme680_sensor_data;
@@ -24,6 +24,8 @@ impl BME680 {
 
 impl Drop for BME680 {
     fn drop(&mut self) {
-        unsafe { epic_bme680_deinit(); }
+        unsafe {
+            epic_bme680_deinit();
+        }
     }
 }
diff --git a/l0dable/src/buttons.rs b/card10-l0dable/src/buttons.rs
similarity index 72%
rename from l0dable/src/buttons.rs
rename to card10-l0dable/src/buttons.rs
index 5bb633fef592b4209f44b5c814cd151038d5d3f5..dc033618c1ec0c727655572ca0811ee83a9fff83 100644
--- a/l0dable/src/buttons.rs
+++ b/card10-l0dable/src/buttons.rs
@@ -1,4 +1,4 @@
-use super::bindings::*;
+use card10_sys::*;
 
 pub struct Buttons {
     state: u32,
@@ -6,12 +6,11 @@ pub struct Buttons {
 
 impl Buttons {
     pub fn read() -> Self {
-        let mask =
-            epic_button_BUTTON_LEFT_BOTTOM |
-            epic_button_BUTTON_RIGHT_BOTTOM |
-            epic_button_BUTTON_LEFT_TOP |
-            epic_button_BUTTON_RIGHT_TOP |
-            epic_button_BUTTON_RESET;
+        let mask = epic_button_BUTTON_LEFT_BOTTOM
+            | epic_button_BUTTON_RIGHT_BOTTOM
+            | epic_button_BUTTON_LEFT_TOP
+            | epic_button_BUTTON_RIGHT_TOP
+            | epic_button_BUTTON_RESET;
         let state = unsafe { epic_buttons_read(mask as u8) }.into();
         Buttons { state }
     }
diff --git a/l0dable/src/display.rs b/card10-l0dable/src/display.rs
similarity index 72%
rename from l0dable/src/display.rs
rename to card10-l0dable/src/display.rs
index 84994cbc1bd5a9709ce3b68c6630c32b79bf4d61..c6ebb5e17934384f2076c5f99fb201b2f284de3a 100644
--- a/l0dable/src/display.rs
+++ b/card10-l0dable/src/display.rs
@@ -1,5 +1,5 @@
-use super::bindings::*;
 use super::framebuffer::FrameBuffer;
+use card10_sys::*;
 
 #[derive(Debug, Clone, Copy)]
 #[repr(C)]
@@ -32,9 +32,7 @@ impl Color {
 
     pub fn rgb8(r8: u8, g8: u8, b8: u8) -> Self {
         let c =
-            ((u16::from(r8) & 0xF8) << 8) |
-            ((u16::from(g8) & 0xFA) << 3) |
-            (u16::from(b8) & 0xF8);
+            ((u16::from(r8) & 0xF8) << 8) | ((u16::from(g8) & 0xFA) << 3) | (u16::from(b8) & 0xF8);
         Color(c)
     }
 
@@ -84,16 +82,22 @@ impl Display {
     pub const FONT_H: u16 = 20;
 
     pub fn open() -> Self {
-        unsafe { epic_disp_open(); }
+        unsafe {
+            epic_disp_open();
+        }
         Display
     }
 
     pub fn update(&self) {
-        unsafe { epic_disp_update(); }
+        unsafe {
+            epic_disp_update();
+        }
     }
 
     pub fn clear(&self, color: Color) {
-        unsafe { epic_disp_clear(color.0); }
+        unsafe {
+            epic_disp_clear(color.0);
+        }
     }
 
     /// s must be 0-terminated
@@ -109,19 +113,45 @@ impl Display {
         }
     }
 
-    pub fn line(&self, x1: u16, y1: u16, x2: u16, y2: u16, color: Color, linestyle: LineStyle, pixelsize: u16) {
+    pub fn line(
+        &self,
+        x1: u16,
+        y1: u16,
+        x2: u16,
+        y2: u16,
+        color: Color,
+        linestyle: LineStyle,
+        pixelsize: u16,
+    ) {
         unsafe {
             epic_disp_line(x1, y1, x2, y2, color.0, linestyle as u32, pixelsize);
         }
     }
 
-    pub fn rect(&self, x1: u16, y1: u16, x2: u16, y2: u16, color: Color, fillstyle: FillStyle, pixelsize: u16) {
+    pub fn rect(
+        &self,
+        x1: u16,
+        y1: u16,
+        x2: u16,
+        y2: u16,
+        color: Color,
+        fillstyle: FillStyle,
+        pixelsize: u16,
+    ) {
         unsafe {
             epic_disp_rect(x1, y1, x2, y2, color.0, fillstyle as u32, pixelsize);
         }
     }
 
-    pub fn circ(&self, x: u16, y: u16, rad: u16, color: Color, fillstyle: FillStyle, pixelsize: u16) {
+    pub fn circ(
+        &self,
+        x: u16,
+        y: u16,
+        rad: u16,
+        color: Color,
+        fillstyle: FillStyle,
+        pixelsize: u16,
+    ) {
         unsafe {
             epic_disp_circ(x, y, rad, color.0, fillstyle as u32, pixelsize);
         }
@@ -134,6 +164,8 @@ impl Display {
 
 impl Drop for Display {
     fn drop(&mut self) {
-        unsafe { epic_disp_close(); }
+        unsafe {
+            epic_disp_close();
+        }
     }
 }
diff --git a/l0dable/src/fmt_buffer.rs b/card10-l0dable/src/fmt_buffer.rs
similarity index 100%
rename from l0dable/src/fmt_buffer.rs
rename to card10-l0dable/src/fmt_buffer.rs
diff --git a/l0dable/src/framebuffer/font.rs b/card10-l0dable/src/framebuffer/font.rs
similarity index 100%
rename from l0dable/src/framebuffer/font.rs
rename to card10-l0dable/src/framebuffer/font.rs
diff --git a/l0dable/src/framebuffer/mod.rs b/card10-l0dable/src/framebuffer/mod.rs
similarity index 77%
rename from l0dable/src/framebuffer/mod.rs
rename to card10-l0dable/src/framebuffer/mod.rs
index 2794369303cb113abfbf582439776f112c712eec..7d1d07d93800a3dd1d30eac1368e79235281162a 100644
--- a/l0dable/src/framebuffer/mod.rs
+++ b/card10-l0dable/src/framebuffer/mod.rs
@@ -1,7 +1,7 @@
+use crate::Display;
+use card10_sys::*;
 use core::mem::{transmute, uninitialized};
 use core::ops::{Index, IndexMut};
-use crate::bindings::*;
-use crate::Display;
 
 mod font;
 pub use font::*;
@@ -13,14 +13,11 @@ pub struct FrameBuffer<'d> {
     buffer: disp_framebuffer,
 }
 
-
 impl<'d> FrameBuffer<'d> {
     pub fn uninitialized(display: &'d Display) -> Self {
         FrameBuffer {
             _display: display,
-            buffer: unsafe {
-                uninitialized()
-            },
+            buffer: unsafe { uninitialized() },
         }
     }
 
@@ -33,18 +30,26 @@ impl<'d> FrameBuffer<'d> {
     pub fn clear(&mut self, color: RawColor) {
         for y in 0..Display::H {
             for x in 0..Display::W {
-                let bytes: &mut RawColor = unsafe {
-                    transmute(&mut self.buffer.fb[y as usize][x as usize])
-                };
+                let bytes: &mut RawColor =
+                    unsafe { transmute(&mut self.buffer.fb[y as usize][x as usize]) };
                 *bytes = color;
             }
         }
     }
 
-    pub fn text<'a, 'f>(&'a mut self, x: isize, y: isize, font: &'f Font, color: RawColor) -> TextRenderer<'a, 'd, 'f> {
+    pub fn text<'a, 'f>(
+        &'a mut self,
+        x: isize,
+        y: isize,
+        font: &'f Font,
+        color: RawColor,
+    ) -> TextRenderer<'a, 'd, 'f> {
         TextRenderer {
             framebuffer: self,
-            x, y, font, color,
+            x,
+            y,
+            font,
+            color,
         }
     }
 }
@@ -54,9 +59,7 @@ impl<'d> Index<(u16, u16)> for FrameBuffer<'d> {
     fn index(&self, (x, y): (u16, u16)) -> &Self::Output {
         let x = usize::from(Display::W - 1 - x);
         let y = usize::from(Display::H - 1 - y);
-        unsafe {
-            transmute(&self.buffer.fb[y][x])
-        }
+        unsafe { transmute(&self.buffer.fb[y][x]) }
     }
 }
 
@@ -64,9 +67,7 @@ impl<'d> IndexMut<(u16, u16)> for FrameBuffer<'d> {
     fn index_mut(&mut self, (x, y): (u16, u16)) -> &mut Self::Output {
         let x = usize::from(Display::W - 1 - x);
         let y = usize::from(Display::H - 1 - y);
-        unsafe {
-            transmute(&mut self.buffer.fb[y][x])
-        }
+        unsafe { transmute(&mut self.buffer.fb[y][x]) }
     }
 }
 
diff --git a/l0dable/src/framebuffer/text.rs b/card10-l0dable/src/framebuffer/text.rs
similarity index 100%
rename from l0dable/src/framebuffer/text.rs
rename to card10-l0dable/src/framebuffer/text.rs
diff --git a/l0dable/src/fs.rs b/card10-l0dable/src/fs.rs
similarity index 76%
rename from l0dable/src/fs.rs
rename to card10-l0dable/src/fs.rs
index d5f89f29af5d934f0b581588865a584a4b6c1925..4148023db079a1f54e9d17314c1fcf34c9189077 100644
--- a/l0dable/src/fs.rs
+++ b/card10-l0dable/src/fs.rs
@@ -1,6 +1,7 @@
-use core::str::from_utf8_unchecked;
 use core::mem::uninitialized;
-use super::bindings::*;
+use core::str::from_utf8_unchecked;
+
+use card10_sys::*;
 
 type Result<T> = core::result::Result<T, Error>;
 
@@ -28,9 +29,7 @@ impl From<i32> for Error {
 
 pub fn read_dir(path: &str) -> Result<ReadDir> {
     let pathbuf = crate::str_to_cstr(path);
-    Error::check(|| unsafe {
-        epic_file_opendir(pathbuf.as_ptr())
-    }).map(|fd| ReadDir { fd })
+    Error::check(|| unsafe { epic_file_opendir(pathbuf.as_ptr()) }).map(|fd| ReadDir { fd })
 }
 
 pub struct ReadDir {
@@ -68,7 +67,7 @@ pub struct epic_stat {
     /// not u32 as generated by bindgen
     pub type_: epic_stat_type,
     pub size: u32,
-    pub name: [super::ctypes::c_char; 256usize],
+    pub name: [ctypes::c_char; 256usize],
     pub _reserved: [u8; 12usize],
 }
 
@@ -97,20 +96,15 @@ impl DirStat {
     }
 
     pub fn name(&self) -> &str {
-        let len = self.entry.name.iter().position(|b| *b == 0)
-            .unwrap_or(0);
-        unsafe {
-            from_utf8_unchecked(&self.entry.name[0..len])
-        }
+        let len = self.entry.name.iter().position(|b| *b == 0).unwrap_or(0);
+        unsafe { from_utf8_unchecked(&self.entry.name[0..len]) }
     }
 }
 
 pub fn rename(from: &str, to: &str) -> Result<()> {
     let frombuf = crate::str_to_cstr(from);
     let tobuf = crate::str_to_cstr(to);
-    Error::check(|| unsafe {
-        epic_file_rename(frombuf.as_ptr(), tobuf.as_ptr())
-    }).map(|_| ())
+    Error::check(|| unsafe { epic_file_rename(frombuf.as_ptr(), tobuf.as_ptr()) }).map(|_| ())
 }
 
 pub struct File {
@@ -121,21 +115,22 @@ impl File {
     pub fn open(path: &str) -> Result<File> {
         let pathbuf = crate::str_to_cstr(path);
         let modebuf = b"r\0";
-        Error::check(|| unsafe {
-            epic_file_open(pathbuf.as_ptr(), modebuf.as_ptr())
-        }).map(|fd| File { fd })
+        Error::check(|| unsafe { epic_file_open(pathbuf.as_ptr(), modebuf.as_ptr()) })
+            .map(|fd| File { fd })
     }
 
     pub fn read<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8]> {
-        let bytes = Error::check(|| unsafe {
-            epic_file_read(self.fd, buf.as_ptr() as *mut _, buf.len())
-        })? as usize;
+        let bytes =
+            Error::check(|| unsafe { epic_file_read(self.fd, buf.as_ptr() as *mut _, buf.len()) })?
+                as usize;
         Ok(&buf[0..bytes])
     }
 }
 
 impl Drop for File {
     fn drop(&mut self) {
-        unsafe { epic_file_close(self.fd); }
+        unsafe {
+            epic_file_close(self.fd);
+        }
     }
 }
diff --git a/card10-l0dable/src/lib.rs b/card10-l0dable/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..bf0bf40148f54a7db98b9395d38fd313b3dbba79
--- /dev/null
+++ b/card10-l0dable/src/lib.rs
@@ -0,0 +1,41 @@
+#![no_std]
+
+mod os;
+pub use os::*;
+mod display;
+pub use display::{Color, Display, FillStyle, LineStyle};
+mod buttons;
+pub mod framebuffer;
+pub use buttons::Buttons;
+pub mod uart;
+pub const UART: uart::Uart = uart::Uart;
+mod light_sensor;
+pub use light_sensor::LightSensor;
+mod rtc;
+pub mod trng;
+pub mod vibra;
+pub use rtc::{MilliSeconds, Seconds, Time};
+mod fmt_buffer;
+pub use fmt_buffer::{str_to_cstr, FmtBuffer};
+mod bme680;
+pub use bme680::BME680;
+mod bhi160;
+pub use bhi160::{
+    Accelerometer, Error as BHI160Error, Gyroscope, Orientation, Sensor as BHI160,
+    SensorData as BHI160Data,
+};
+pub mod fs;
+
+/// Type check the user-supplied entry function.
+#[macro_export]
+macro_rules! main {
+    ($path:path) => {
+        #[export_name = "main"]
+        pub unsafe fn __main() {
+            // type check the given path
+            let f: fn() = $path;
+
+            f()
+        }
+    };
+}
diff --git a/l0dable/src/light_sensor.rs b/card10-l0dable/src/light_sensor.rs
similarity index 87%
rename from l0dable/src/light_sensor.rs
rename to card10-l0dable/src/light_sensor.rs
index a6aa16745530505202b70ad07b757ef4ac0cad86..f68e0351f12e38cbbf3133fb592f549d0cffb1ee 100644
--- a/l0dable/src/light_sensor.rs
+++ b/card10-l0dable/src/light_sensor.rs
@@ -1,4 +1,4 @@
-use super::bindings::*;
+use card10_sys::*;
 
 pub struct LightSensor {
     // Prevent creation of this struct by all but this module.
@@ -25,6 +25,8 @@ impl LightSensor {
 
 impl Drop for LightSensor {
     fn drop(&mut self) {
-        unsafe { epic_light_sensor_stop(); }
+        unsafe {
+            epic_light_sensor_stop();
+        }
     }
 }
diff --git a/l0dable/src/os.rs b/card10-l0dable/src/os.rs
similarity index 93%
rename from l0dable/src/os.rs
rename to card10-l0dable/src/os.rs
index af7a2283924cf08464b0981f711d35b62753683c..e209671614d31cae2d746c3f1e733470d1f57693 100644
--- a/l0dable/src/os.rs
+++ b/card10-l0dable/src/os.rs
@@ -1,4 +1,4 @@
-use super::bindings::*;
+use card10_sys::*;
 
 pub fn exec(path: &str) -> ! {
     let mut pathbuf = super::str_to_cstr(path);
diff --git a/l0dable/src/rtc.rs b/card10-l0dable/src/rtc.rs
similarity index 97%
rename from l0dable/src/rtc.rs
rename to card10-l0dable/src/rtc.rs
index d7741f4006607c7aba72080a942f6afe196ea9c3..cdf25a58c8bfc9369e2d483fc84c51a9ac2053bf 100644
--- a/l0dable/src/rtc.rs
+++ b/card10-l0dable/src/rtc.rs
@@ -1,5 +1,5 @@
+use card10_sys::*;
 use core::ops::Sub;
-use super::bindings::*;
 
 pub trait Time {
     fn time() -> Self;
diff --git a/l0dable/src/trng.rs b/card10-l0dable/src/trng.rs
similarity index 81%
rename from l0dable/src/trng.rs
rename to card10-l0dable/src/trng.rs
index b4635fa72b3386139a87f035e25f8d67e0d61b26..7bceca95a893ee76481ca1f791309619f423bef9 100644
--- a/l0dable/src/trng.rs
+++ b/card10-l0dable/src/trng.rs
@@ -1,4 +1,4 @@
-use super::bindings::*;
+use card10_sys::*;
 
 pub fn read(dest: &mut [u8]) -> bool {
     unsafe { epic_trng_read(dest.as_mut_ptr(), dest.len()) != 0 }
diff --git a/l0dable/src/uart.rs b/card10-l0dable/src/uart.rs
similarity index 96%
rename from l0dable/src/uart.rs
rename to card10-l0dable/src/uart.rs
index b164a6c7cfaf65020a41b01b9b6f1339235480f5..7dd860e9614086f5ced9c1d16e09104c03306637 100644
--- a/l0dable/src/uart.rs
+++ b/card10-l0dable/src/uart.rs
@@ -1,6 +1,7 @@
-use super::bindings::*;
 use core::fmt::Write;
 
+use card10_sys::*;
+
 pub struct Uart;
 
 impl Write for Uart {
diff --git a/card10-l0dable/src/vibra.rs b/card10-l0dable/src/vibra.rs
new file mode 100644
index 0000000000000000000000000000000000000000..d2e4d53cd2c4af864dff5334d31bb292b670d814
--- /dev/null
+++ b/card10-l0dable/src/vibra.rs
@@ -0,0 +1,13 @@
+use card10_sys::*;
+
+pub fn set(status: bool) {
+    unsafe {
+        epic_vibra_set(status.into());
+    }
+}
+
+pub fn vibrate(millis: i32) {
+    unsafe {
+        epic_vibra_vibrate(millis);
+    }
+}
diff --git a/card10-sys/src/lib.rs b/card10-sys/src/lib.rs
index a1c7a99cd2953fbf358777341bdea5b46d46b250..16c72f12ca2f1d8f2662b41f0e3992431f00276c 100644
--- a/card10-sys/src/lib.rs
+++ b/card10-sys/src/lib.rs
@@ -9,20 +9,6 @@ use panic_abort as _;
 global_asm!(include_str!(concat!(env!("OUT_DIR"), "/crt.s")));
 include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
 
-/// Type check the user-supplied entry function.
-#[macro_export]
-macro_rules! main {
-    ($path:path) => {
-        #[export_name = "main"]
-        pub unsafe fn __main() {
-            // type check the given path
-            let f: fn() = $path;
-
-            f()
-        }
-    };
-}
-
 #[link_section = ".text.boot"]
 #[no_mangle]
 pub unsafe extern "C" fn Reset_Handler() -> ! {
diff --git a/example/Cargo.toml b/example/Cargo.toml
index b4143a9324e2f9ae3556faf45e659848a67496d2..8d7ab8a4cef7377ecf8ab90b959d4bb105c55c7e 100644
--- a/example/Cargo.toml
+++ b/example/Cargo.toml
@@ -5,7 +5,7 @@ version = "0.0.0"
 authors = ["Astro <astro@spaceboyz.net>"]
 
 [dependencies]
-card10-l0dable = { path = "../l0dable" }
+card10-l0dable = { path = "../card10-l0dable" }
 
 [build-dependencies]
 cc = "1.0"
diff --git a/l0dable/build.rs b/l0dable/build.rs
deleted file mode 100644
index ca52d6b9d9c9529fe25985e22ddaba2d9eb7b435..0000000000000000000000000000000000000000
--- a/l0dable/build.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-use std::env;
-use std::fs::File;
-use std::io::Write;
-use std::path::PathBuf;
-
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-
-    // Linker script
-    let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
-    File::create(out.join("l0dable.ld"))
-        .unwrap()
-        .write_all(include_bytes!("l0dable.ld"))
-        .unwrap();
-    println!("cargo:rustc-link-search={}", out.display());
-    println!("cargo:rerun-if-changed=l0dable.ld");
-
-    // Link against C code
-    cc::Build::new()
-        .target("thumbv7em-none-eabi")
-        .compiler("arm-none-eabi-gcc")
-        .define("TARGET", "MAX32665")
-        .define("TARGET_UC", "MAX32665")
-        .define("TARGET_LC", "max32665")
-        .define("TARGET_REV", "0x4131")
-        .define("BOARD", "card10")
-        .opt_level_str("s")
-        .debug(true)
-        .flag("-fPIE").flag("-pie")
-        .include("../c/epicardium")
-        .include("../c/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Include")
-        .include("../c/lib/sdk/Libraries/CMSIS/Include")
-        .include("../c/lib/sdk/Libraries/MAX32665PeriphDriver/Include")
-        .file("../c/lib/sdk/Libraries/MAX32665PeriphDriver/Source/sema.c")
-        .file("../c/lib/sdk/Libraries/MAX32665PeriphDriver/Source/mxc_assert.c")
-        .file("../c/l0dables/lib/hardware.c")
-        .file("../c/epicardium/api/caller.c")
-        .file("src/client.c")
-        .file("../c/lib/gfx/Fonts/font12.c")
-        .file("../c/lib/gfx/Fonts/font16.c")
-        .file("../c/lib/gfx/Fonts/font20.c")
-        .file("../c/lib/gfx/Fonts/font24.c")
-        .file("../c/lib/gfx/Fonts/font8.c")
-        .compile("card10");
-    println!("cargo:rerun-if-changed=src/client.c");
-
-    // Generate bindings to C code
-    let bindings = bindgen::Builder::default()
-        .clang_args(&[
-            "-Isrc",
-            "-I../c/epicardium",
-            "-I../c/lib/sdk/Libraries/CMSIS/Device/Maxim/MAX32665/Include",
-            "-I../c/lib/sdk/Libraries/CMSIS/Include",
-            "-I../c/lib/sdk/Libraries/MAX32665PeriphDriver/Include",
-        ])
-        .header("src/bindings.h")
-        .use_core()
-        .ctypes_prefix("super::ctypes")
-        .generate()
-        .expect("Unable to generate bindings");
-    println!("cargo:rerun-if-changed=src/bindings.h");
-
-    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
-    bindings
-        .write_to_file(out_path.join("bindings.rs"))
-        .expect("Couldn't write bindings!");
-}
diff --git a/l0dable/src/lib.rs b/l0dable/src/lib.rs
deleted file mode 100644
index b84440864108d6a9ee1da19f37fa3181a5f326e9..0000000000000000000000000000000000000000
--- a/l0dable/src/lib.rs
+++ /dev/null
@@ -1,137 +0,0 @@
-#![no_std]
-#![feature(global_asm)]
-
-use panic_abort as _;
-
-global_asm!(include_str!("crt.s"));
-
-/// Type check the user-supplied entry function.
-#[macro_export]
-macro_rules! main {
-    ($path:path) => {
-        #[export_name = "main"]
-        pub unsafe fn __main() {
-            // type check the given path
-            let f: fn() = $path;
-
-            f()
-        }
-    };
-}
-
-#[link_section = ".text.boot"]
-#[no_mangle]
-pub unsafe extern "C" fn Reset_Handler() -> ! {
-    extern "C" {
-        fn SystemInit();
-        // Boundaries of the .bss section, provided by the linker script
-        static mut __bss_start: u64;
-        static mut __bss_end: u64;
-    }
-
-    // Zeroes the .bss section
-    r0::zero_bss(&mut __bss_start, &mut __bss_end);
-    SystemInit();
-
-    extern "Rust" {
-        fn main();
-    }
-
-    main();
-    exit(0);
-}
-
-pub mod ctypes {
-    #![allow(non_camel_case_types)]
-
-    pub type c_short = i16;
-    pub type c_ushort = u16;
-    pub type c_int = i32;
-    pub type c_uint = u32;
-    pub type c_long = i32;
-    pub type c_ulong = u32;
-    pub type c_longlong = i64;
-    pub type c_ulonglong = u64;
-    pub type c_char = u8;
-    pub type c_schar = i8;
-    pub type c_uchar = u8;
-    pub use core::ffi::c_void;
-}
-
-pub mod errno {
-    #![allow(non_snake_case)]
-    use crate::ctypes::c_int;
-
-    pub const EPERM: c_int = 1; // Operation not permitted
-    pub const ENOENT: c_int = 2; // No such file or directory
-    pub const ESRCH: c_int = 3; // No such process
-    pub const EINTR: c_int = 4; // Interrupted system call
-    pub const EIO: c_int = 5; // I/O error
-    pub const ENXIO: c_int = 6; // No such device or address
-    pub const E2BIG: c_int = 7; // Argument list too long
-    pub const ENOEXEC: c_int = 8; // Exec format error
-    pub const EBADF: c_int = 9; // Bad file number
-    pub const ECHILD: c_int = 10; // No child processes
-    pub const EAGAIN: c_int = 11; // Try again
-    pub const ENOMEM: c_int = 12; //Out of memory
-    pub const EACCES: c_int = 13; //Permission denied
-    pub const EFAULT: c_int = 14; //Bad address
-    pub const ENOTBLK: c_int = 15; //Block device required
-    pub const EBUSY: c_int = 16; //Device or resource busy
-    pub const EEXIST: c_int = 17; //File exists
-    pub const EXDEV: c_int = 18; //Cross-device link
-    pub const ENODEV: c_int = 19; //No such device
-    pub const ENOTDIR: c_int = 20; //Not a directory
-    pub const EISDIR: c_int = 21; //Is a directory
-    pub const EINVAL: c_int = 22; //Invalid argument
-    pub const ENFILE: c_int = 23; //File table overflow
-    pub const EMFILE: c_int = 24; //Too many open files
-    pub const ENOTTY: c_int = 25; //Not a typewriter
-    pub const ETXTBSY: c_int = 26; //Text file busy
-    pub const EFBIG: c_int = 27; //File too large
-    pub const ENOSPC: c_int = 28; //No space left on device
-    pub const ESPIPE: c_int = 29; //Illegal seek
-    pub const EROFS: c_int = 30; //Read-only file system
-    pub const EMLINK: c_int = 31; //Too many links
-    pub const EPIPE: c_int = 32; //Broken pipe
-    pub const EDOM: c_int = 33; //Math argument out of domain of func
-    pub const ERANGE: c_int = 34; //Math result not representable
-    pub const EAFNOSUPPORT: c_int = 97; //Address family not supported by protocol
-    pub const ECONNRESET: c_int = 104; //Connection timed out
-    pub const ETIMEDOUT: c_int = 110; //Connection timed out
-    pub const EINPROGRESS: c_int = 115; //Operation now in progress
-}
-
-pub mod bindings {
-    #![allow(non_upper_case_globals)]
-    #![allow(non_camel_case_types)]
-    #![allow(non_snake_case)]
-
-    include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
-}
-
-mod os;
-pub use os::*;
-mod display;
-pub use display::{Display, Color, LineStyle, FillStyle};
-pub mod framebuffer;
-mod buttons;
-pub use buttons::Buttons;
-pub mod uart;
-pub const UART: uart::Uart = uart::Uart;
-mod light_sensor;
-pub use light_sensor::LightSensor;
-pub mod vibra;
-pub mod trng;
-mod rtc;
-pub use rtc::{Seconds, MilliSeconds, Time};
-mod fmt_buffer;
-pub use fmt_buffer::{FmtBuffer, str_to_cstr};
-mod bme680;
-pub use bme680::BME680;
-mod bhi160;
-pub use bhi160::{
-    Accelerometer, Error as BHI160Error, Gyroscope, Orientation, Sensor as BHI160,
-    SensorData as BHI160Data,
-};
-pub mod fs;
diff --git a/l0dable/src/vibra.rs b/l0dable/src/vibra.rs
deleted file mode 100644
index 963634cb36b3bb01286836fd20ff25f070818c67..0000000000000000000000000000000000000000
--- a/l0dable/src/vibra.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use super::bindings::*;
-
-pub fn set(status: bool) {
-    unsafe { epic_vibra_set(status.into()); }
-}
-
-pub fn vibrate(millis: i32) {
-    unsafe { epic_vibra_vibrate(millis); }
-}
diff --git a/rkanoid/Cargo.toml b/rkanoid/Cargo.toml
index a7467193c332339c4316344e062414a6417aa0a1..e85651882303b63514cf1ef20ede50bcdc4f9d36 100644
--- a/rkanoid/Cargo.toml
+++ b/rkanoid/Cargo.toml
@@ -5,7 +5,7 @@ version = "0.0.0"
 authors = ["Astro <astro@spaceboyz.net>"]
 
 [dependencies]
-card10-l0dable = { path = "../l0dable" }
+card10-l0dable = { path = "../card10-l0dable" }
 
 [build-dependencies]
 cc = "1.0"