01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
crc32(data, len)
>> 0x00FF: ACK
schedule(task, interval)
lock.acquire()
>> SYNC COMPLETE
release(ptr)
0x00 0x00 0x00 0x01
watchdog.reset()
>> LINK ESTABLISHED
fn poll(&mut self) -> Poll
waker.wake_by_ref()
cx.waker().clone()
01101001 01101110
fn init() -> Result<()>
for x in 0..buf.len()
load(addr, 0xFF)
sys.run(0x4A, flags)
if val > 0 { dispatch() }
>> 0x00: READY
loop { poll(); yield; }
stream.flush()
0xDEAD :: 0xBEEF
bind(sock, &addr, len)
pub fn connect(host: &str)
match state {
State::Init => boot(),
State::Run => tick(),
_ => halt(),
}
reg[0x3] = 0b11001010
clk.tick()
assert!(val != null)
>> SIGNAL RECEIVED
buf[i] ^= key[i % klen]
let n = read(fd, buf, 64)
while !done { step(); }
push(stack, frame)
0x7F :: OK
type Handler = fn(Ctx)
emit(Event::Data, payload)
select! { rx => handle(rx) }
spawn(async move { run() })
>> 0x01: PROCESSING
map.insert(k, v)
drain().collect::<Vec<_>>()
let _ = tx.send(msg)
timeout(Duration::ms(100))
>> CHECKSUM PASS
fn encode(src: &[u8]) -> Vec
pipe.write_all(&frame)
← JOURNAL
PUBLIC6 min read

Where It Started

personalphilosophydirection

Injex Performance from above — where it all clicked into place

Twelve years ago I took apart a Saitek X36 flight stick.

Not because it was broken. Because I wanted to understand it. I wanted to rip out the original electronics, wire every input to an Arduino Leonardo, and build something that worked exactly the way I needed it to. Custom USB descriptors, remappable controls, switchable modes — the kind of thing that didn't exist off the shelf.

I was playing flight sims. KSP, Elite, Star Citizen, ARMA. I needed control interfaces that could keep up with what was happening on screen. So I built them.

I put the project on Hackaday.io. Called it the Aerospace Control Interface. Two build logs, some janky photos, a write-up about USB HID descriptors that I was genuinely proud of at the time. Nine and a half thousand people looked at it. Seventy-eight followed it. That mattered to me more than I let on.

The desk, 2014 — dual monitors, Saitek X36 throttle and stick, Arduino on a breadboard, wires everywhere

When Everything Was Possible

That project came from one of the best times of my life. I'd just met Hollie. We were on cloud nine. Everything felt like it was falling into place.

Around the same time I was introduced to Rick at Injex Performance, and suddenly I was surrounded by cars, computers, planes, research and development — everything I cared about, all in one place. It fit. All of it fit. The Hackaday project wasn't built by someone grinding through hardship. It was built by someone who felt like the world was opening up.

That energy — that feeling that anything was possible — that's what you see in those photos. A messy desk, wires everywhere, a joystick in pieces, and someone who couldn't wait to see what came next.

What Came Next

Life kept moving. Injex became real work — ECU tuning, running the file service, managing the workshop. I was learning every day. Cars on the ramp, laptops on the bench, remote tuning sessions with customers across the country. It was hands-on, it was technical, it was exactly where I was supposed to be.

Hollie and I had our daughter. Named her Indigo.

And then I lost Hollie.

I'm not going to write the details here. I've written about it before and I'll write about it again. But the version of me who posted that Hackaday project — the one grinning at a breadboard with his whole life ahead of him — he had no idea what was coming.

The Gap

The project sat on Hackaday.io, untouched, for over a decade. I didn't stop building entirely — you never really do, not when it's in you — but I stopped sharing. I stopped believing anyone would care. I was surviving, raising my daughter, trying to figure out who I was without the person who made everything make sense.

But the instinct never went away. That need to take something apart and understand it. To make something better than it was. To solve a problem not because someone asked, but because it was there and it bothered me.

Coming Back

When I started indigo-nx, I didn't have a grand plan. I had a need. I needed to build again. I needed to show my daughter that you don't stop. That when things break — including you — you learn why, and you fix what you can, and you keep going.

So I started. ViewShift came from needing to switch my three monitors between work and gaming without Windows fighting me every time. IRNode came from wanting to turn my TV on with a single command instead of hunting for a remote. The Workshop Bus came from wanting all of it to talk to each other. Vessel came from wanting to talk to my desk.

None of it was planned. All of it was needed.

What Changed

Looking back at that Hackaday project, I see someone who had the right instincts but didn't know what to do with them yet. Someone who could build the thing but couldn't see the bigger picture. The joystick worked. The USB descriptors were correct. But it was one project, in isolation, with no thread connecting it to anything else.

Neovin Heavy Industries 1.0 — the LCD splash screen on an Arduino Mega, before indigo-nx had a name

That's what's different now. Everything connects. The voice assistant talks to the message bus. The message bus talks to the display manager. The display manager talks to the IR blaster. One voice command and my entire workspace reconfigures. Not because I set out to build a smart home — because I kept solving individual problems and eventually they found each other.

That Saitek X36 was the first time I looked at a piece of hardware and thought: I can do better than what they gave me. I didn't know it then, but that was the thread. That's been the thread through everything I've built since.

The switch panel — gutted from the X36 throttle, every toggle wired to its own input

The Uncomfortable Truth

I'm not where I want to be yet. I'm building tools in my living room come workshop while my daughter sleeps. I don't have a workshop. I don't have funding. I don't have a team. Some days I wonder if any of this matters.

But then I look at what I've actually built. Working software. Real hardware integrations. A blog with people reading it. A store taking shape. Twelve years ago I had an Arduino and a gutted joystick. Now I've got an architecture.

I'm not saying that to boast. I'm saying it because I need to hear it sometimes. And maybe you do too.

To Earlier Me

If I could talk to the version of me who posted that Hackaday project in 2014, I wouldn't tell him to do anything differently. I wouldn't warn him about what's coming. I'd just tell him to hold on to that feeling — that cloud nine, everything-is-possible feeling — because it was real. And it still is, even after everything.

The instinct — the one that says take it apart, understand it, make it better — that's the thing. That's always been the thing.

Don't lose it.


The Aerospace Control Interface is still up on Hackaday.io. Nine and a half thousand views, seventy-eight followers, and a version of me who was just getting started.

He had no idea.

// FEEDBACK

LEAVE A COMMENT

← BACK TO JOURNAL