Room3327, Inc.

Embedded software development

NXP Support —

Room3327 provides software and hardware development for NXP devices, including the LPC1549 and K66F.  We leverage our years of embedded experience to help with the development of embedded devices and systems from design to implementation.

  • NXP hardware interfaces
    • SPI
      • SPI Flash, Accelerometer, A/D, D/A, Rheostat, Motor controller
    • I2C
      • Both via on-chip hardware and bit-banging
      • Video processing chips, pH and EC sensors
    • High precision hardware timers
      • Precise measurement of time deltas between hall sensor readings.
    • Serial port data processing
      • Cell modem module support
    • GPIO
      • Interrupts to take action, inputs to read system state and outputs to change configuration
      • Interlock switch for mechanical device
    • USB
      • Serial Port
  • C/C++
  • NXP software stacks 
    • LPCOpen
    • freeRTOS
    • EtherCAT Slave Stack Code (SSC)

EtherCAT Support —

Room3327 provides software and hardware development for EtherCAT master and slave devices. We leverage our years of embedded experience to help with the development of embedded devices and systems from design to implementation. 

We can cover: 

  • Proof of concept development 
  • System Specification and Design, including Hardware Selection
  • Master Software Development
  • Slave Hardware and Software Development

Specifically, we have experience with:

  • EtherCAT Slave Device development
    • EtherCAT Slave Stack Code (SSC) support
      • Object Dictionary Development
      • Hardware Abstraction Implementation
    • Bootloader Development
    • In-System Programming
    • EtherCAT Slave Device hardware design
  • TwinCAT 3 PLC Development
    • Structured Text
    • Visualization Development (Integrated, PLC HMI, and PLC HMI Web)
    • Device Integration
      • Motors, Solenoids, Pressure Sensors, EC, pH, A/D, and more
      • Beckhoff Fieldbus devices (ELM3148, EL1104, EL6021, EL2004)
  • OPC-UA Server
    • TwinCAT 3 Integration
    • Installation and configuration

We’re EtherCAT software consultants! —

Room3327 is excited to announce our membership in the EtherCAT Technology Group. We bring our years of embedded development expertise and hardware partnerships to help you develop and integrate EtherCAT devices.

If you’re interested in working together, contact us or checkout our EtherCAT Support page.

Maybe; try Optionals —

Maybe; try Optionals.

Optionals, what are they? They are being added almost uniformly to newer languages (Rust, Swift) and to older languages in heavy use (C++ 17, Java 8). They can help you write clearer, cleaner code when used correctly. Let’s see what they are about.

Optionals (or Option types or Nullable types) are types that are allowed to have a valid state (Some) and an invalid state (None). They help to clarify that a piece of data is not yet initialized and so its value is not valid. This helps particularly with types that have a default value that could be used but it’s not clear if it is actually set.

For example, an integer or boolean type, all the values in the range could be used. How can you state something is actually initialized without blindly assuming 0 for integers means invalid, or false for booleans means it’s not initialized? Use Optionals.

When explaining optionals, it’s a good idea to start with what they are at their core: Variants.


Variants or Tagged Unions, or Sum Types, are a simple concept. They are a type that can hold other fixed types. You can think of it as a C union, except that they explicitly keep track of what Type they contain. You can’t mix the types inside the variant. It is one and only one of the things it holds at any point in time.

What do Optionals look like?

In a hypothetical language that supports them, they go like this:

Optional of T {
None, //There is nothing here. Empty. Nada.
Some(T) //We have an item T
let myOption = Some(5); // Some(int32)
let myOption = Some("Rodents of unusual size. I don't believe they exist"); // Some(String)
let myOption = None; // We got nothing.

view raw

hosted with ❤ by GitHub

So when you have a bit of data that holds an Optional, it either contains a T or None.

You can really think about it like a present. When you unwrap the present and has a toy in it, you have Some(Toy). But when you unwrap your present and there is nothing there, you have None. It’s not more complicated than that.

So why would I even use this?

It seems easier to just pass an int32 * or a struct *Widget to a function and follow the convention that if it’s not nullptr, it’s safe. Everyone knows that an integer with the value -1 is not ready to be used. So we won’t have any issues…

It’s about clarity

Writing a function that receives or takes an optional as a parameter should give you pause. Instead of thinking about just handling an integer or struct you should now be thinking about how to handle this value and what you should do if it’s None.

Without getting all monadic about it, this is Haskell’s Maybe Type. But you don’t need to know type theory to use it. You only need to be thinking about handling both cases and what is the right thing to do each possiblity comes along. Types that imply branching. Neat.

Passing optionals suggests you will have a branch when you go to unwrap them because you need to unwrap them to access their values. This makes it clearer in your code that you are about to use a value you were given, and that you know that the value was initialized before you try to use it.

It’s about safety

Using optional types bakes in the idea of default type construction. But constructing a type that has no initial value means that your variant has nothing in it at all. So uninitialized Optionals default to None.

You don’t have to go back to your function and think what the initial value of present is, it’s None. You also don’t have to try to create a bogus initial value that you are “sure” is safe and everyone understands. It’s coded right into the type itself.

Unwrapping Optionals

The process of inspecting what is inside the optional is called unwrapping. Think of it like a present. You unwrap the optional and you got Some(present) or the box was empty and you got None. In the None case, since you haven’t got a type, you can’t pretend it’s a null pointer to an int32 and try to access it. There isn’t anything there to access.

Example in Java

Java 8 has some nice ways of dealing with optional values.

public class Magician {
public Magician(){}
public Magician(String name){ = name;
public String getName() {
return name;
String name;
Magician magician = new Magician("Miracle Max");
Optional<Magician> optMagician = Optional.ofNullable(magician);
if (optMagician.isPresent())
return optMagician.get(); //returns a Miracle Max Magician
System.out.println("Miracle Max isn't home.");

The Optional.ofNullable() method takes a type and wraps it up in an optional. You can then see if the optional is set (isPresent()) and pull out the Magician value with the Optional.get() method. If it’s not present then you will just see that “Miracle Max isn’t home”

Example in Rust

Here’s a way to use some optionals in Rust:

let waiting = Some("I'm Waiting for Vizzini.");
//Rust's match statement lets you figure out if you got Some or None
match waiting {
Some(c) => println!("{}", c),
None => println!("You got None"),
Prints "I'm Waiting for Vizzini."

view raw

hosted with ❤ by GitHub


A neat little helper for cleanly unwrapping optionals inline in Rust works like this:

assert_eq!(Some("Andre").unwrap_or("Giant"), "Andre"); // "Andre"
assert_eq!(None.unwrap_or("Vizzini"), "Vizzini"); // "Vizzini"
//from above
assert_eq!(waiting.unwrap_or("Nope"), "I'm Waiting for Vizzini."); // I'm Waiting for Vizzini.

view raw

hosted with ❤ by GitHub

assert_eq()! just lets you confirm that the item on the left is the same as the item on the right. The interesting part here is chaining the optionals with unwrap_or() to give a default to an optional you are expecting to be in one state or another.

Wrap up

Optionals are useful in making your intentions clearer and safer to use, reducing confusion and simple programming errors. Give them a try on your next project. You might find it easier to reason about your program and spend less time debugging it.

Brant Rosenberger


Welcome to year 4 —

So it’s been four years, and our first post seems as fresh as ever… or maybe not.

Things have changed in the four years. Our team has grown to 5 full-time employees. We’ve extended our team with great contractors like Max Tower and Eric Montellese. We’ve added a partners for hardware design: Warlowe LLC and mechanical design: Integral Concepts.

During this time we’ve worked on fun projects from set-top boxes, Android embedded devices, medical devices and even LIDAR applications.

It’s been a fun ride. The only thing that hasn’t seemed to change has been our blog. With that being said, this post is going to be the end of that. Going forward, we’ll be posting about things we’ve done, found out and discovered while we work on our projects. Hopefully you’ll enjoy following along with us, and to quote Fat Albert, “Maybe you’ll learn something.” I know we have.