diff --git a/Cargo.lock b/Cargo.lock
index 3d13b31af886ac8bcf7362dd91a3483930447c51..339bd57f1dace448212aae4175c943e70ce27ba6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -345,6 +345,7 @@ dependencies = [
  "embedded-hal 0.2.7",
  "embedded-hal 1.0.0-alpha.10",
  "embedded-hal-async",
+ "esp-println",
  "esp32s3-hal",
  "heapless",
  "serial-line-ip",
@@ -698,6 +699,7 @@ dependencies = [
  "port-expander",
  "shared-bus",
  "smart-leds",
+ "smoltcp",
  "static_cell",
  "tinybmp",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index bd10eabbab5164fe63fce54a7cfe7acaa0c85fae..72876148168092e3eaca959dcee778889bbc2dc8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -32,5 +32,6 @@ heapless = "0.7.16"
 port-expander = "0.4.0"
 shared-bus = { version = "0.3.0", features = ["xtensa"] }
 smart-leds = "0.3.0"
+smoltcp = { version = "0.10.0", default-features = false }
 static_cell = "1.2.0"
 tinybmp = "0.5.0"
diff --git a/embassy-net-badgelink/Cargo.toml b/embassy-net-badgelink/Cargo.toml
index fabc26ff1de22c5bfc8b296ffed398ab195e8e05..ab412ce829b90de476fe877eccc9537777467671 100644
--- a/embassy-net-badgelink/Cargo.toml
+++ b/embassy-net-badgelink/Cargo.toml
@@ -16,3 +16,4 @@ embedded-hal-async = "0.2.0-alpha.1"
 serial-line-ip = "0.5.0"
 heapless = "0.7.16"
 esp32s3-hal = { version = "0.10.0", features = ["embedded-hal-async", "async"] }
+esp-println = { version = "0.5.0", features = ["esp32s3"] }
diff --git a/embassy-net-badgelink/src/lib.rs b/embassy-net-badgelink/src/lib.rs
index 58f788cb5c5dca8aeb93351b7bd242b567dfa7a7..3a409921be1ee27e88748dfcc8240ef433bee4dc 100644
--- a/embassy-net-badgelink/src/lib.rs
+++ b/embassy-net-badgelink/src/lib.rs
@@ -2,13 +2,14 @@
 
 use ch::driver::LinkState;
 use embassy_futures::join::join;
-use embassy_futures::select::{Either, select};
+use embassy_futures::select::{select, Either};
 use embassy_net_driver_channel as ch;
 use embedded_hal_async::serial::Write;
-use esp32s3_hal::Uart;
 use esp32s3_hal::uart::Instance;
-use serial_line_ip::{Decoder, Encoder};
+use esp32s3_hal::Uart;
+use esp_println::println;
 use heapless::Vec;
+use serial_line_ip::{Decoder, Encoder};
 
 const MTU: usize = 1500;
 
@@ -31,7 +32,7 @@ pub struct Runner<'d, UART> {
     uart: UART,
     ch: ch::Runner<'d, MTU>,
     decoder: Decoder,
-} 
+}
 
 impl<'d, UART> Runner<'d, Uart<'static, UART>>
 where
@@ -39,29 +40,38 @@ where
 {
     pub async fn run(mut self) -> ! {
         let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
-        let mut read_buf = [0u8;64];
+        let mut read_buf = [0u8; 4096];
         state_chan.set_link_state(LinkState::Up);
         loop {
             match select(
-                join(
-                    self.uart.read(&mut read_buf),
-                    rx_chan.rx_buf()
-                ),
+                join(self.uart.read(&mut read_buf), rx_chan.rx_buf()),
                 tx_chan.tx_buf(),
-            ).await {
-                Either::First((_,p)) => {
-                    if let Ok((num_bytes, _, end_of_packet)) = self.decoder.decode(&read_buf, p) {
-                        if end_of_packet {
-                            rx_chan.rx_done(num_bytes);
+            )
+            .await
+            {
+                Either::First((r, p)) => {
+                    let read_bytes = r.unwrap();
+                    println!("reading from uart {}", read_bytes);
+                    match self.decoder.decode(&read_buf, p) {
+                        Ok((num_bytes, _, end_of_packet)) => {
+                            println!("decoded packet");
+                            if end_of_packet {
+                                println!("end of packet");
+                                rx_chan.rx_done(num_bytes);
+                            }
                         }
+                        Err(error) => println!("Error: {}", error),
                     }
                 }
                 Either::Second(p) => {
-                    let mut enc: Vec<u8, 1500> = Vec::new();
+                    println!("sending packet");
+                    //println!("packet len {}", p.len());
+                    let mut enc = [0u8; 1500];
                     let mut encoder = Encoder::new();
-                    encoder.encode(p, &mut enc).ok();
+                    encoder.encode(p, &mut enc).unwrap();
                     let num_bytes = encoder.finish(&mut enc).unwrap();
-                    self.uart.write(&enc[0..num_bytes.written]).await.ok();
+                    self.uart.write(&enc[0..num_bytes.written]).await.unwrap();
+                    //println!("packet written to uart");
                     tx_chan.tx_done();
                 }
             }
@@ -84,4 +94,4 @@ pub fn new<'a, const N_RX: usize, const N_TX: usize, UART>(
             decoder: Decoder::new(),
         },
     )
-}
\ No newline at end of file
+}
diff --git a/src/demo_tasks.rs b/src/demo_tasks.rs
index ab643fa4f60f82d9f31e39574960f0a5c04d35cd..98a399d5c690599f9e8e0fc91aeb3db229e2ad1c 100644
--- a/src/demo_tasks.rs
+++ b/src/demo_tasks.rs
@@ -1,5 +1,8 @@
-use crate::flow3r::{captouch::CaptouchHandler, display::Display, imu::ImuHandler};
+use crate::flow3r::{captouch::CaptouchHandler, display::Display, imu::ImuHandler, badgelink::{BadgeLink, badgenet::{BadgenetUartLeft, BadgenetUartRight, start_badgenet_left, start_badgenet_right}}};
+use embassy_executor::Spawner;
 use embassy_futures::select::{select, select3, Either, Either3};
+use embassy_net::{udp::{UdpSocket, PacketMetadata}, Ipv6Address, Stack, StaticConfigV6, Config, Ipv6Cidr};
+use embassy_net_badgelink::Device;
 use embassy_time::{Duration, Timer};
 use embedded_graphics::{
     image::Image,
@@ -11,6 +14,9 @@ use embedded_graphics::{
 };
 use esp_backtrace as _;
 use esp_println::println;
+use hal::{Rng, uart};
+use heapless::Vec;
+use smoltcp::wire::IpEndpoint;
 use tinybmp::Bmp;
 
 use smart_leds::SmartLedsWrite;
@@ -270,3 +276,117 @@ pub async fn captouch_demo(display: &mut Display) {
         }
     }
 }
+
+pub async fn badgelink_demo(badgelink: &mut BadgeLink, uart0: BadgenetUartLeft, uart1: BadgenetUartRight, rng: &'static mut Rng<'static>) -> (&'static mut BadgenetUartLeft, &'static mut BadgenetUartRight,  &'static mut Rng<'static>) {
+    badgelink.left_badgelink().unwrap();
+    badgelink.right_badgelink().unwrap();
+
+    let addr_left = Ipv6Address::new(0xfe80, 0x00, 0x00, 0x00, 0x5686, 0x8cff, 0xfe5c, 0x278d);
+    let addr_right = Ipv6Address::new(0xfe80, 0x00, 0x00, 0x00, 0x5686, 0x8cfa, 0xfe5c, 0x278d);
+
+    let config_left = Config::ipv6_static(StaticConfigV6 {
+        address: Ipv6Cidr::new(addr_left, 10),
+        gateway: None,
+        dns_servers: Vec::new(),
+    });
+
+    let config_right = Config::ipv6_static(StaticConfigV6 {
+        address: Ipv6Cidr::new(addr_right, 10),
+        gateway: None,
+        dns_servers: Vec::new(),
+    });
+
+
+    let network_stack_left = start_badgenet_left(uart0, rng.random().into(), config_left).await;
+    let network_stack_right = start_badgenet_right(uart1, rng.random().into(), config_right).await;
+
+    Timer::after(Duration::from_millis(10)).await;
+
+    let spawner = Spawner::for_current_executor().await;
+    spawner.spawn(listen_task(network_stack_left)).unwrap();
+    spawner.spawn(send_task(network_stack_right, addr_left)).unwrap();
+
+    loop {
+        Timer::after(Duration::from_secs(10)).await;
+    }
+}
+
+/* 
+#[embassy_executor::task]
+async fn listen_task(mut uart: BadgenetUartLeft) {
+    let mut data = [0u8;10];
+    println!("ready to recv");
+    loop {
+        uart.read(&mut data).await.unwrap();
+        println!("recvd");
+    }
+}
+
+#[embassy_executor::task]
+async fn send_task(mut uart: BadgenetUartRight) {
+    let data = [0,1,2,3,4];
+    loop {
+        uart.write_bytes(&data).unwrap();
+        println!("sent");
+        Timer::after(Duration::from_secs(1)).await;
+    }
+}*/
+
+#[embassy_executor::task]
+async fn listen_task(network_stack: &'static Stack<Device<'static>>) {
+    let mut rx_buffer_left = [0; 4096];
+    let mut tx_buffer_left = [0; 4096];
+    let mut rx_meta_left = [PacketMetadata::EMPTY; 16];
+    let mut tx_meta_left = [PacketMetadata::EMPTY; 16];
+    let mut buf_left = [0; 4096];
+
+    let mut socket_left = UdpSocket::new(
+        network_stack,
+        &mut rx_meta_left,
+        &mut rx_buffer_left,
+        &mut tx_meta_left,
+        &mut tx_buffer_left,
+    );
+
+    let config_left = network_stack.config_v6().unwrap();
+    println!("config: {:?}", config_left.address);
+
+    socket_left.bind(1234).unwrap();
+
+    loop {
+        socket_left.recv_from(&mut buf_left).await.unwrap();
+        println!("data recieved");
+    }
+}
+
+#[embassy_executor::task]
+async fn send_task(network_stack: &'static Stack<Device<'static>>, addr_left: Ipv6Address) {
+    let mut rx_buffer_right = [0; 4096];
+    let mut tx_buffer_right = [0; 4096];
+    let mut rx_meta_right = [PacketMetadata::EMPTY; 16];
+    let mut tx_meta_right = [PacketMetadata::EMPTY; 16];
+
+    let mut socket_right = UdpSocket::new(
+        network_stack,
+        &mut rx_meta_right,
+        &mut rx_buffer_right,
+        &mut tx_meta_right,
+        &mut tx_buffer_right,
+    );
+
+    let config_right = network_stack.config_v6().unwrap();
+    println!("config: {:?}", config_right.address);
+
+    socket_right.bind(2345).unwrap();
+
+    let endpoint = IpEndpoint::new(addr_left.into_address(), 1234);
+    let send_data = [1,2,3,4,5];
+
+    loop {
+        socket_right.send_to(&send_data, endpoint).await.unwrap();
+        println!("data sent");
+
+        Timer::after(Duration::from_secs(1)).await;
+    }
+
+}
\ No newline at end of file
diff --git a/src/flow3r/badgelink/badgelink.rs b/src/flow3r/badgelink/badgelink.rs
deleted file mode 100644
index ecf93f782ef7f84f8f09e7e948a819b7618dc07e..0000000000000000000000000000000000000000
--- a/src/flow3r/badgelink/badgelink.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-
-pub fn init_badgelink_io(i2c: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>) {
-    let mut pe1 = port_expander::Max7321::new(shared_i2c.acquire_i2c(), true, true, true, false);
-
-    let mut pe1_io = pe1.split();
-    pe1_io.p1.set_high().unwrap();
-    let _in_r_sw = pe1_io.p3;
-    let _in_t_sw = pe1_io.p4;
-    let _out_r_sw = pe1_io.p5;
-    let _out_t_sw = pe1_io.p6;
-}
\ No newline at end of file
diff --git a/src/flow3r/badgelink/badgenet.rs b/src/flow3r/badgelink/badgenet.rs
index 66262b3e8ee59d25a5158040dd3018e1a4ad355c..42c2fe117f41e3521e550931d69cd80c7928fb3d 100644
--- a/src/flow3r/badgelink/badgenet.rs
+++ b/src/flow3r/badgelink/badgenet.rs
@@ -1,69 +1,85 @@
 use embassy_executor::Spawner;
 use embassy_net::{Config, Ipv6Address, Ipv6Cidr, Stack, StackResources, StaticConfigV6};
 use embassy_net_badgelink::{Device, Runner, State};
+use esp_println::println;
 use hal::{
     efuse::Efuse,
-    peripherals::{UART0, UART1},
+    peripherals::{UART0, UART1, UART2},
     Rng, Uart,
 };
 use heapless::Vec;
 use static_cell::StaticCell;
 
-static STATE: StaticCell<State<8, 8>> = StaticCell::new();
-static STACK: StaticCell<Stack<Device<'static>>> = StaticCell::new();
-static STACK_RESOURCES: StaticCell<StackResources<2>> = StaticCell::new();
+static STATE_LEFT: StaticCell<State<8, 8>> = StaticCell::new();
+static STACK_LEFT: StaticCell<Stack<Device<'static>>> = StaticCell::new();
+static STACK_RESOURCES_LEFT: StaticCell<StackResources<2>> = StaticCell::new();
+static STATE_RIGHT: StaticCell<State<8, 8>> = StaticCell::new();
+static STACK_RIGHT: StaticCell<Stack<Device<'static>>> = StaticCell::new();
+static STACK_RESOURCES_RIGHT: StaticCell<StackResources<2>> = StaticCell::new();
 
-pub async fn start_badgenet_left(uart: Uart<'static, UART0>, rng: &'static mut Rng<'static>) {
+pub type BadgenetUartLeft = Uart<'static, UART1>;
+pub type BadgenetUartRight = Uart<'static, UART2>;
+
+pub async fn start_badgenet_left(uart: BadgenetUartLeft, seed: u64, config: Config ) -> &'static Stack<Device<'static>> {
     let mac_addr = Efuse::get_mac_address();
-    let state = STATE.init(State::<8, 8>::new());
+    let state = STATE_LEFT.init(State::<8, 8>::new());
     let (device, runner) = embassy_net_badgelink::new(mac_addr, state, uart);
-    let stack = STACK.init(Stack::new(
+    let stack = STACK_LEFT.init(Stack::new(
         device,
-        Config::ipv6_static(StaticConfigV6 {
-            address: Ipv6Cidr::new(Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 0), 128),
-            gateway: None,
-            dns_servers: Vec::new(),
-        }),
-        STACK_RESOURCES.init(StackResources::new()),
-        rng.random().into(),
+        config,
+        STACK_RESOURCES_LEFT.init(StackResources::new()),
+        seed,
     ));
 
     let spawner = Spawner::for_current_executor().await;
     spawner.spawn(runner_0_task(runner)).ok();
-    spawner.spawn(stack_task(stack)).ok();
+    spawner.spawn(stack_task_0(stack)).ok();
+
+    println!("started left badgenet");
+
+    stack
 }
 
-pub async fn start_badgenet_right(uart: Uart<'static, UART1>, rng: &'static mut Rng<'static>) {
+pub async fn start_badgenet_right(uart: BadgenetUartRight, seed: u64, config: Config) -> &'static Stack<Device<'static>> {
     let mac_addr = Efuse::get_mac_address();
-    let state = STATE.init(State::<8, 8>::new());
+    let state = STATE_RIGHT.init(State::<8, 8>::new());
     let (device, runner) = embassy_net_badgelink::new(mac_addr, state, uart);
-    let stack = STACK.init(Stack::new(
+    let stack = STACK_RIGHT.init(Stack::new(
         device,
-        Config::ipv6_static(StaticConfigV6 {
-            address: Ipv6Cidr::new(Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 0), 128),
-            gateway: None,
-            dns_servers: Vec::new(),
-        }),
-        STACK_RESOURCES.init(StackResources::new()),
-        rng.random().into(),
+        config,
+        STACK_RESOURCES_RIGHT.init(StackResources::new()),
+        seed,
     ));
 
     let spawner = Spawner::for_current_executor().await;
     spawner.spawn(runner_1_task(runner)).ok();
-    spawner.spawn(stack_task(stack)).ok();
+    spawner.spawn(stack_task_1(stack)).ok();
+
+    println!("started right badgenet");
+
+    stack
 }
 
 #[embassy_executor::task]
-pub async fn runner_0_task(runner: Runner<'static, Uart<'static, UART0>>) -> ! {
+pub async fn runner_0_task(runner: Runner<'static, BadgenetUartLeft>) -> ! {
+    println!("left badgenet runner started");
     runner.run().await
 }
 
 #[embassy_executor::task]
-pub async fn runner_1_task(runner: Runner<'static, Uart<'static, UART1>>) -> ! {
+pub async fn runner_1_task(runner: Runner<'static, BadgenetUartRight>) -> ! {
+    println!("right badgenet runner started");
     runner.run().await
 }
 
-#[embassy_executor::task(pool_size = 2)]
-pub async fn stack_task(stack: &'static mut Stack<Device<'static>>) -> ! {
+#[embassy_executor::task]
+pub async fn stack_task_0(stack: &'static Stack<Device<'static>>) -> ! {
+    println!("left badgenet stack started");
+    stack.run().await
+}
+
+#[embassy_executor::task]
+pub async fn stack_task_1(stack: &'static Stack<Device<'static>>) -> ! {
+    println!("right badgenet stack started");
     stack.run().await
 }
diff --git a/src/flow3r/badgelink/mod.rs b/src/flow3r/badgelink/mod.rs
index eb46d3e0df6ebcde8425daae69c8922414e0da26..ab584afb9d7dd671bfdab5bbf4a72a5502cf44fb 100644
--- a/src/flow3r/badgelink/mod.rs
+++ b/src/flow3r/badgelink/mod.rs
@@ -1,4 +1,4 @@
-use hal::{i2c::I2C, peripherals::I2C0};
+use hal::{i2c::I2C, peripherals::{I2C0, UART0, UART1}, Uart, Rng};
 use port_expander::{dev::max7321::Driver, Max7321};
 use shared_bus::{I2cProxy, NullMutex, XtensaMutex};
 
@@ -11,7 +11,7 @@ pub struct BadgeLink {
 impl BadgeLink {
     pub fn new(i2c: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>) -> Self {
         let port_expander = port_expander::Max7321::new(i2c, true, true, true, false);
-        Self { port_expander }
+        Self { port_expander}
     }
 
     pub fn left_audio(&mut self) -> Result<(), hal::i2c::Error> {
@@ -37,4 +37,4 @@ impl BadgeLink {
         pes.p5.set_high()?;
         pes.p6.set_high()
     }
-}
+}
\ No newline at end of file
diff --git a/src/flow3r/imu.rs b/src/flow3r/imu.rs
index f61ed7e0897b1220f991b5532079f89d30a678a8..c6b012d816a634377ca70f3710ac9e62fd3a1182 100644
--- a/src/flow3r/imu.rs
+++ b/src/flow3r/imu.rs
@@ -11,6 +11,7 @@ impl ImuHandler {
     pub fn new(i2c: I2cProxy<'static, XtensaMutex<I2C<'static, I2C0>>>) -> Self {
         let mut bmi270 = Bmi270::new_i2c(i2c, bmi270::I2cAddr::Default, bmi270::Burst::Max);
 
+        /*
         if let Some(chip_id) = bmi270.get_chip_id().ok() {
             println!("imu chip id: {}", chip_id);
         }
@@ -23,7 +24,7 @@ impl ImuHandler {
             acc_en: true,
             temp_en: false,
         };
-        bmi270.set_pwr_ctrl(pwr_ctrl).ok();
+        bmi270.set_pwr_ctrl(pwr_ctrl).ok();*/
         Self { imu: bmi270 }
     }
 
diff --git a/src/flow3r/mod.rs b/src/flow3r/mod.rs
index a2f881955f8ecf30f077a1dd8e3cd1becb1b96bc..89cc941d3eee34d3578625e7cf4619face8b89bd 100644
--- a/src/flow3r/mod.rs
+++ b/src/flow3r/mod.rs
@@ -1,4 +1,8 @@
+use hal::{Uart, Rng};
+use hal::peripherals::{UART0, UART1};
+
 use self::badgelink::BadgeLink;
+use self::badgelink::badgenet::{BadgenetUartLeft, BadgenetUartRight};
 use self::captouch::CaptouchHandler;
 use self::display::Display;
 use self::imu::ImuHandler;
@@ -21,6 +25,9 @@ pub struct Flow3r {
     pub imu: ImuHandler,
     pub inputs: InputHandler,
     pub leds: Leds,
+    pub uart0: BadgenetUartLeft,
+    pub uart1: BadgenetUartRight,
+    pub rng: &'static mut Rng<'static>,
 }
 
 impl Flow3r {
@@ -31,6 +38,9 @@ impl Flow3r {
         imu: ImuHandler,
         inputs: InputHandler,
         leds: Leds,
+        uart0: BadgenetUartLeft,
+        uart1: BadgenetUartRight,
+        rng: &'static mut Rng<'static>,
     ) -> Self {
         Self {
             badgelink,
@@ -39,6 +49,9 @@ impl Flow3r {
             imu,
             inputs,
             leds,
+            uart0,
+            uart1,
+            rng
         }
     }
 }
diff --git a/src/flow3r/ui/main_menu.rs b/src/flow3r/ui/main_menu.rs
index 9440c0cd5c4baa6153c4b99784682ef3e1a1e3b4..436588c6f01cb17a65bd242540461ad74fc90841 100644
--- a/src/flow3r/ui/main_menu.rs
+++ b/src/flow3r/ui/main_menu.rs
@@ -6,16 +6,24 @@ use embedded_graphics::{
     prelude::*,
     text::Text,
 };
+use hal::Rng;
+use static_cell::StaticCell;
 
 use crate::{
-    demo_tasks::{display_demo, imu_demo, captouch_demo},
-    flow3r::{display::Display, input::InputHandler, imu::ImuHandler},
+    demo_tasks::{display_demo, imu_demo, captouch_demo, badgelink_demo},
+    flow3r::{display::Display, input::InputHandler, imu::ImuHandler, badgelink::{badgenet::{BadgenetUartLeft, BadgenetUartRight}, BadgeLink}},
 };
 
-pub async fn main_menu(mut display: Display, inputs: InputHandler, mut imu: ImuHandler) -> ! {
+static UART_LEFT: StaticCell<BadgenetUartLeft> = StaticCell::new();
+static UART_RIGHT: StaticCell<BadgenetUartRight> = StaticCell::new();
+
+pub async fn main_menu(mut display: Display, inputs: InputHandler, mut imu: ImuHandler, mut badgelink: BadgeLink, uart0: BadgenetUartLeft, uart1: BadgenetUartRight, mut rng: &'static mut Rng<'static>) -> ! {
     let mut inputs = inputs.split();
 
-    let apps = ["input_test", "imu_test", "captouch_test"];
+    let mut uart0 = UART_LEFT.init(uart0);
+    let mut uart1 = UART_RIGHT.init(uart1);
+
+    let apps = ["input_test", "imu_test", "captouch_test", "badgenet_test"];
     let mut selected = 0usize;
 
     display
@@ -39,7 +47,7 @@ pub async fn main_menu(mut display: Display, inputs: InputHandler, mut imu: ImuH
         .await
         {
             Either3::First(_) => {
-                start_current_app(apps[selected], &mut display, &mut imu).await;
+                (uart0, uart1, rng) = start_current_app(apps[selected], &mut display, &mut imu, &mut badgelink, uart0, uart1, rng).await;
                 display
                     .fill_solid(&display.bounding_box(), Rgb565::BLACK)
                     .unwrap();
@@ -103,11 +111,12 @@ async fn play_transition_animation<'a>(
     }
 }
 
-async fn start_current_app(app: &str, display: &mut Display, imu: &mut ImuHandler) {
+async fn start_current_app(app: &str, display: &mut Display, imu: &mut ImuHandler, badgelink: &mut BadgeLink,  uart0: &'static mut BadgenetUartLeft, uart1: &'static mut BadgenetUartRight, rng: &'static mut Rng<'static>) -> (&'static mut BadgenetUartLeft, &'static mut BadgenetUartRight,  &'static mut Rng<'static>) {
     match app {
-        "input_test" => display_demo(display).await,
-        "imu_test" => imu_demo(display, imu).await,
-        "captouch_test" => captouch_demo(display).await,
-        _ => (),
+        "input_test" => {display_demo(display).await; (uart0, uart1, rng)}
+        "imu_test" =>{imu_demo(display, imu).await; (uart0, uart1, rng)}
+        "captouch_test" => {captouch_demo(display).await; (uart0, uart1, rng)}
+        //"badgenet_test" => badgelink_demo(badgelink, uart0, uart1, rng).await,
+        _ => (uart0, uart1, rng),
     }
 }
diff --git a/src/main.rs b/src/main.rs
index 9e3ddf291f989e622d5bb1da9ab0a23748b0bc7c..82b4d3a03f27dea41c18b81668639d8b6668bf1f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,7 +8,7 @@ mod demo_tasks;
 mod flow3r;
 mod runtime;
 
-use demo_tasks::draw_start_screen;
+use demo_tasks::{draw_start_screen, badgelink_demo};
 use embassy_executor::Spawner;
 use embassy_time::{Duration, Timer};
 
@@ -30,7 +30,11 @@ async fn main(mut flow3r: Flow3r) -> ! {
     let spawner = Spawner::for_current_executor().await;
     spawner.spawn(demo_tasks::leds_fade(flow3r.leds)).ok();
 
-    Timer::after(Duration::from_secs(3)).await;
+    //Timer::after(Duration::from_secs(3)).await;
 
-    main_menu(flow3r.display, flow3r.inputs, flow3r.imu).await
+    badgelink_demo(&mut flow3r.badgelink, flow3r.uart0, flow3r.uart1, flow3r.rng).await;
+
+    loop {}
+
+    //main_menu(flow3r.display, flow3r.inputs, flow3r.imu, flow3r.badgelink, flow3r.uart0, flow3r.uart1, flow3r.rng).await
 }
diff --git a/src/runtime.rs b/src/runtime.rs
index 2228e93e777c8db3b631c5e81026a54b3b211c05..d6e2ba89e8155390642530a3eb78d12dbbd95ebc 100644
--- a/src/runtime.rs
+++ b/src/runtime.rs
@@ -1,5 +1,6 @@
 use embassy_executor::{Executor, Spawner};
 use embassy_time::{Duration, Timer};
+use esp_println::println;
 use hal::{
     clock::{ClockControl, Clocks},
     cpu_control::CpuControl,
@@ -12,7 +13,7 @@ use hal::{
     pulse_control::ClockSource,
     systimer::SystemTimer,
     timer::TimerGroup,
-    PulseControl, Rng, Rtc, Spi, Uart, IO,
+    PulseControl, Rng, Rtc, Spi, Uart, IO, uart::{self, TxRxPins}, gpio::{Gpio6, Unknown, Gpio4, Gpio7, Gpio5},
 };
 use static_cell::StaticCell;
 
@@ -162,26 +163,49 @@ async fn init_runtime() {
 
     // Init uart
 
-    let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
+    let uart0_config = uart::config::Config {
+        baudrate: 9600, //115200,
+        data_bits: uart::config::DataBits::DataBits8,
+        parity: uart::config::Parity::ParityNone,
+        stop_bits: uart::config::StopBits::STOP1
+    };
+    let uart0_pins = TxRxPins::new_tx_rx(io.pins.gpio7.into_push_pull_output(), io.pins.gpio6.into_floating_input());
+    let mut uart0 = Uart::new_with_config(peripherals.UART1, Some(uart0_config), Some(uart0_pins), &clocks, &mut system.peripheral_clock_control);
     uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
 
     hal::interrupt::enable(
-        hal::peripherals::Interrupt::UART0,
+        hal::peripherals::Interrupt::UART1,
+        hal::interrupt::Priority::Priority2,
+    )
+    .unwrap();
+
+    let uart1_config = uart::config::Config {
+        baudrate: 9600, //115200,
+        data_bits: uart::config::DataBits::DataBits8,
+        parity: uart::config::Parity::ParityNone,
+        stop_bits: uart::config::StopBits::STOP1
+    };
+    let uart1_pins = TxRxPins::new_tx_rx(io.pins.gpio5.into_push_pull_output(), io.pins.gpio4.into_floating_input());
+    let mut uart1 = Uart::new_with_config(peripherals.UART2, Some(uart1_config),Some(uart1_pins), &clocks, &mut system.peripheral_clock_control);
+    uart1.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
+
+    hal::interrupt::enable(
+        hal::peripherals::Interrupt::UART2,
         hal::interrupt::Priority::Priority2,
     )
     .unwrap();
 
-    let _rng = RNG.init(Rng::new(peripherals.RNG));
+    let rng = RNG.init(Rng::new(peripherals.RNG));
 
     // Init Flow3r components
 
-    let badgelink = BadgeLink::new(i2c_busmanager.acquire_i2c());
+    let mut badgelink = BadgeLink::new(i2c_busmanager.acquire_i2c());
     let imu = ImuHandler::new(i2c_busmanager.acquire_i2c());
     let inputs = InputHandler;
     let captouch = CaptouchHandler;
     let leds = init_leds(pulse.channel0, io.pins.gpio14);
 
-    let flow3r = Flow3r::new(badgelink, captouch, display, imu, inputs, leds);
+    let flow3r = Flow3r::new(badgelink, captouch, display, imu, inputs, leds, uart0, uart1, rng);
 
     // Spawn background tasks
 
@@ -205,4 +229,54 @@ async fn init_runtime() {
 
     // Hand over to main task
     spawner.spawn(main(flow3r)).ok();
+    /*spawner.spawn(test_pins_a(io.pins.gpio5)).unwrap();
+    spawner.spawn(test_pins_b(io.pins.gpio6)).unwrap();
+    spawner.spawn(test_pins_c(io.pins.gpio4)).unwrap();
+    spawner.spawn(test_pins_d(io.pins.gpio7)).unwrap();*/
+}
+
+/*
+#[embassy_executor::task]
+async fn test_pins_a(pin: Gpio5<Unknown>) -> ! {
+    let mut pin = pin.into_push_pull_output();
+    println!("toggle task running");
+    loop {
+        pin.set_high().unwrap();
+        Timer::after(Duration::from_secs(1)).await;
+        pin.set_low().unwrap();
+        Timer::after(Duration::from_secs(1)).await;
+    }
+}
+
+
+#[embassy_executor::task]
+async fn test_pins_d(pin: Gpio7<Unknown>) -> ! {
+    let mut pin = pin.into_push_pull_output();
+    println!("toggle task running");
+    loop {
+        pin.set_high().unwrap();
+        Timer::after(Duration::from_secs(1)).await;
+        pin.set_low().unwrap();
+        Timer::after(Duration::from_secs(1)).await;
+    }
+}
+
+#[embassy_executor::task]
+async fn test_pins_b(pin: Gpio6<Unknown>) -> ! {
+    let mut pin = pin.into_floating_input();
+    println!("wait task running");
+    loop {
+        pin.wait_for_any_edge().await.unwrap();
+        println!("pin 5 changed, is now {}", pin.is_high().unwrap());
+    }
 }
+
+#[embassy_executor::task]
+async fn test_pins_c(pin: Gpio4<Unknown>) -> ! {
+    let mut pin = pin.into_floating_input();
+    println!("wait task running");
+    loop {
+        pin.wait_for_any_edge().await.unwrap();
+        println!("pin 4 changed, is now {}", pin.is_high().unwrap());
+    }
+} */
\ No newline at end of file