diff --git a/Cargo.lock b/Cargo.lock
index 972f6fc8d5197e803981565ec33307d9413ec819..364d4f00966ef05fed858c4df98aef895d89802b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -198,7 +198,6 @@ dependencies = [
  "core2",
  "cortex-m",
  "cortex-m-rt",
- "nb 1.1.0",
  "panic-semihosting",
  "rf4463",
  "ringbuf",
diff --git a/Cargo.toml b/Cargo.toml
index 0fc719683bfa4fc22d5cc18246bb2e402051b27e..ecf56b3e378fce7236ceb3c1eef6970cfde259a6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,6 @@ cortex-m = "0.7"
 cortex-m-rt = "0.7"
 # cortex-m-semihosting = "0.5"
 panic-semihosting = "0.6"
-nb = "1.0.0"
 core2 = { version = "0.3", default_features = false }
 rf4463 = { path = "../rf4463" }
 ringbuf = { version = "0.3", default_features = false }
diff --git a/src/main.rs b/src/main.rs
index 59590c4c62bef0c1e875960488715861d2c92667..f86ce79b09588b0628e5869c8f0df89aec026ea7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,28 +4,24 @@
 extern crate cortex_m;
 #[macro_use(entry, exception)]
 extern crate cortex_m_rt as rt;
-#[macro_use(block)]
-extern crate nb;
 extern crate panic_semihosting;
 
 extern crate stm32f4xx_hal as hal;
 // #[macro_use(block)]
 // extern crate nb;
 
-use core::borrow::BorrowMut;
 use core::cell::RefCell;
 
-use core2::io::{Cursor, Write};
 use cortex_m::interrupt::{free, Mutex};
 use cortex_m::peripheral::NVIC;
-use hal::gpio::{self, Alternate, Pin, Pull, PushPull};
+use hal::gpio::Pull;
 use hal::pac::{self, SPI2};
 use hal::spi::{Event, Mode, Phase, Polarity, Spi, SpiSlave};
 use rf4463::config::RADIO_CONFIG_500_2;
 use rf4463::Rf4463;
 use ringbuf::{Rb, StaticRb};
 
-use crate::hal::{interrupt, prelude::*, serial::Serial};
+use crate::hal::{interrupt, prelude::*};
 use crate::rt::ExceptionFrame;
 
 enum SlaveCmd {
@@ -61,15 +57,17 @@ const MODE: Mode = Mode {
     phase: Phase::CaptureOnFirstTransition,
 };
 
+const PACKET_LEN: usize = 256 + 2 + 65;
+
 #[entry]
 fn main() -> ! {
     let cp = cortex_m::Peripherals::take().unwrap();
     let dp = pac::Peripherals::take().unwrap();
 
-    let mut rcc = dp.RCC.constrain();
+    let rcc = dp.RCC.constrain();
 
-    let mut gpioa = dp.GPIOA.split();
-    let mut gpiob = dp.GPIOB.split();
+    let gpioa = dp.GPIOA.split();
+    let gpiob = dp.GPIOB.split();
 
     // setup clocks
     let clocks = rcc.cfgr.use_hse(25.MHz()).sysclk(48.MHz()).freeze();
@@ -96,10 +94,8 @@ fn main() -> ! {
 
     let mut spi2 = dp.SPI2.spi_slave((sck2, miso2, mosi2, Some(nss)), MODE);
 
-    // fill up the tx buffer
-    while spi2.is_tx_empty() {
-        spi2.write(&[0x00]);
-    }
+    // need something in the outgoing buffer for when the master toggles the clock
+    spi2.write(&[0x00]).unwrap();
 
     spi2.listen(Event::Rxne);
 
@@ -113,12 +109,11 @@ fn main() -> ! {
         NVIC::unmask(interrupt::SPI2);
     }
 
-    const LEN: usize = 256 + 2 + 65;
-    let mut data = [0; LEN];
+    let mut data = [0; PACKET_LEN];
     let mut i = 0;
 
     loop {
-        if i == LEN {
+        if i == PACKET_LEN {
             radio.tx(&data).unwrap();
             i = 0;
             continue;
@@ -149,20 +144,59 @@ unsafe fn HardFault(ef: &ExceptionFrame) -> ! {
 #[interrupt]
 fn SPI2() {
     free(|cs| {
+        let mut state = SLAVE_STATE.borrow(cs).borrow_mut();
+
         let mut spi = SPI_SLAVE.borrow(cs).borrow_mut();
         let spi = spi.as_mut().unwrap();
 
-        let x = [0];
-        spi.read(&mut x).unwrap();
-        spi.write(&[0x00]).unwrap();
-
         let mut buf = BUF.borrow(cs).borrow_mut();
         let buf = buf.as_mut().unwrap();
 
-        buf.push(x).unwrap();
+        let mut x = [0];
+        spi.read(&mut x).unwrap();
 
-        if buf.free_len() == 400 {
-            block!(us.write(b'F')).unwrap();
-        }
+        let out = match *state {
+            SlaveState::Idle => {
+                if let Some(cmd) = SlaveCmd::from_u8(x[0]) {
+                    match cmd {
+                        SlaveCmd::BufferStatus => {
+                            *state = SlaveState::BufferStatus;
+
+                            if buf.free_len() < PACKET_LEN {
+                                0x01 // not enough space for a new packet
+                            } else {
+                                0x02 // safe to send a packet
+                            }
+                        }
+
+                        SlaveCmd::SendPacket => {
+                            *state = SlaveState::RecvPacket(PACKET_LEN - 1);
+
+                            0x00
+                        }
+                    }
+                } else {
+                    0x00
+                }
+            }
+            SlaveState::BufferStatus => {
+                *state = SlaveState::Idle;
+
+                0x00
+            }
+            SlaveState::RecvPacket(i) => {
+                *state = if i == 0 {
+                    SlaveState::Idle
+                } else {
+                    SlaveState::RecvPacket(i - 1)
+                };
+
+                buf.push(x[0]).unwrap();
+
+                0x00
+            }
+        };
+
+        spi.write(&[out]).unwrap();
     });
 }