Mitchell K

About Me

Welcome to my tech blog, where we explore the exciting world of technology and its impact on our lives. Join me as I share engaging content, personal insights, and the latest trends in the ever-evolving tech landscape.

The Subjective Nature of "Good" Code

Exploring What Defines Code Quality

Read on Medium

In a recent Medium post, I explored the nuanced world of defining what constitutes "good" code. While there are certainly universal fundamentals like code functionality, syntax adherence, and coherent structure, the specific implementations and areas of emphasis around factors like readability, maintainability, security, and performance can vary significantly across development teams.

The article argues that rather than seeking an objectively "correct" way to code, teams should focus on aligning around their own collective beliefs and priorities for how software should be built. By doing so, they can prevent conflicting notions of quality and ensure productive technical discussions.

The post provides examples of how different types of organizations approach code quality through their own distinct lenses based on their unique requirements and philosophies. It emphasizes the importance of establishing a shared vision and documenting heavily opinionated, hard-lined rules to serve as a technical roadmap and cultural foundation for all contributors to uphold.

Ultimately, the article concludes that top engineering organizations intentionally cultivate their own unique coding philosophies and progressively iterate on them to form their distinct flavor of "good" code. Regular retrospectives and process reviews allow teams to adapt their priorities as technologies and requirements evolve over an application's lifecycle.

DIY Emissions Checker

Getting started with vehicle programming can be an exciting journey, and one of the best ways to begin is by using an ELM327 device. This versatile tool allows you to communicate with a wide range of vehicles manufactured from 1998 onwards. Once you've mastered the basics of ELM327, you can explore more advanced methods of vehicle communication, such as Controller Area Network (CAN). These devices enable you to extract a wealth of information from any compatible car. In this tutorial, I'll guide you through the process of developing a simple scan tool using an ELM327 microcontroller. Our goal is to check if our car will pass emissions testing, saving us a potentially wasted trip to the testing facility. For this project, we'll be using C# and .NET, as they provide a great balance between abstraction and hardware device handling. To get started, you'll need a wired ELM327 device, which can be easily purchased from online marketplaces like Amazon. While it's possible to adapt the code to work with Bluetooth, it's important to consider your target platform, as Bluetooth code is often not compatible across different systems. Most of the code will remain the same, but you'll need to make some modifications to accommodate Bluetooth functionality. This can be more challenging than it initially appears, which is why we've chosen to focus on the wired version in this tutorial.

Step 1: Creating the ICommunicator Interface

To ensure flexibility and adaptability in our code, we'll start by creating an interface named ICommunicator. This interface defines the common methods and properties required for communicating with our physical device.

By defining this interface, we can create different implementations of communication protocols while maintaining a consistent interface for interacting with the device. This promotes code reusability and allows for easy substitution of communication methods in the future.


public interface ICommunicator : IDisposable
{
  Task ConnectAsync();
  void Disconnect();
  bool IsConnected { get; }
  void Write(string command);
  string ReadString();
}
          

Step 2: Implementing the SerialCommunicator Class

To establish a connection with the ELM327 device, we need to create an RS232 serial connection using the SerialPort class provided by C#. We will encapsulate this functionality within a class called SerialCommunicator, which implements the ICommunicator interface.

This class provides methods for connecting, disconnecting, writing, and reading data from the serial port. It also handles proper disposal of resources when the connection is no longer needed.


public class SerialCommunicator : ICommunicator
{
  public SerialPort Port { get; private set; }

  public SerialCommunicator(string portName, int baudRate, Parity parity, int dataBits)
  {
    Port = new SerialPort(portName, baudRate, parity, dataBits);
  }

  public async Task ConnectAsync()
  {
    try
    {
      if (!Port.IsOpen)
      {
        await Task.Run(() => Port.Open());
      }
    }
    catch (Exception ex)
    {
      Console.WriteLine("Error: Unable to establish a connection with serial port.");
      Console.WriteLine(ex.Message);
    }
  }

  public void Disconnect()
  {
    if (Port.IsOpen)
    {
      Port.Close();
    }
  }

  public void Write(string message)
  {
    Port.DiscardInBuffer();
    Port.DiscardOutBuffer();
    Port.Write(message);
  }

  public string ReadString()
  {
    return Port.ReadExisting();
  }

  public bool IsConnected
  {
    get
    {
      return Port.IsOpen;
    }
  }

  public void Dispose()
  {
    if (Port.IsOpen)
    {
      Port.Close();
      Port.Dispose();
    }
  }

  public Task ReadDesiredStringResponse(Func desiredResultFunc, int timeoutDuration)
  {
    throw new NotImplementedException();
  }
}
          

Step 3: Creating the ELM327Controller Class

To facilitate communication with the ELM327 device, we will create a dedicated class called ELM327Controller. This class will handle sending commands to the device and receiving responses from it.

It utilizes regular expressions to clean up and process the responses received from the ELM device, ensuring a consistent and reliable format for the data we work with. The ELM327Controller also includes a DebugMode flag for debugging and troubleshooting purposes.


using System.Text.RegularExpressions;

public static class ELM327Controller
{
  public static bool DebugMode { get; set; } = false;

  public static void Write(ICommunicator communication, string message)
  {
    if (DebugMode)
      Console.WriteLine("Sent: " + message);

    try
    {
      communication.Write(message + "\r");
    }
    catch (Exception e)
    {
      Console.WriteLine("Exception occurred during write: " + e.ToString());
    }
  }

  public static string ReadString(ICommunicator communication)
  {
    string response = communication.ReadString().Trim();
    response = Regex.Replace(response, ">", "");
    response = Regex.Replace(response, "\r", "");

    if (DebugMode && !string.IsNullOrEmpty(response))
      Console.WriteLine("Received: " + response);

    return response;
  }

  public static async Task ReadDesiredStringResponse(ICommunicator communication, Func desiredResultFunc, int timeoutDuration)
  {
    string response = "";
    int timeout = timeoutDuration;
    while (!desiredResultFunc(response) && timeout > 0)
    {
      response = ELM327Controller.ReadString(communication);
      timeout -= 10;
      await Task.Delay(10);
    }

    if (DebugMode && timeout <= 0)
      Console.WriteLine("Timeout reached before desired response was received.");

    if (timeout <= 0)
      throw new TimeoutException("Desired response not received within the specified timeout.");

    return response;
  }
}
          

Step 4: Defining the ICommand Interface and Command Class

To send commands to our ELM327 controller, we'll define an interface called ICommand and a class named Command that implements this interface. The ICommand interface defines the basic structure of a command, including the command identifier and the Execute method.

The Command class provides the implementation for executing commands, handling response validation, and timeout management.


public interface ICommand
{
  string pid { get; }
  Task Execute(ICommunicator communication);
}

public class Command : ICommand
{
  public string pid { get; }
  private readonly Func validator;
  private readonly int timeout;

  public Command(string pid, Func validator, int timeout)
  {
    this.pid = pid;
    this.validator = validator;
    this.timeout = timeout;
  }

  public async Task Execute(ICommunicator communication)
  {
    return await SendCommand(communication, pid, validator);
  }

  private async Task SendCommand(ICommunicator communication, string pid, Func responseValidator)
  {
    ELM327Controller.Write(communication, pid);
    string response = "";
    try
    {
      response = await ELM327Controller.ReadDesiredStringResponse(communication, responseValidator, timeout);

      if (!responseValidator(response))
      {
        throw new Exception("Failed to retrieve data.");
      }
    }
    catch (Exception e)
    {
      Console.WriteLine("Error: " + e.Message);
      throw;
    }

    return response;
  }
}
          

Step 5: Creating Specific Commands

With the Command class in place, we can now create specific commands for interacting with the ELM327 device. In this example, we create two commands: one for setting the vehicle's protocol and another for retrieving emission codes.

These commands are implemented as static methods that return instances of the Command class with the appropriate parameters.


public static Command CreateSetProtocolToAutoCommand()
{
    return new Command("ATSP0", response => response == "ATSP0OK", 10000);
}
public static Command CreateImReadinessCommand()
{
  return new Command("0101", response => response.StartsWith("41 01") && response.Length >= 17, 10000);
}
          

Step 6: Interpreting Emission Codes

After receiving the emission codes from the ELM327 device, we need a way to interpret the data. We create an Emissions class that provides a method called RetrieveEmissionReadinessData.

This method takes the response from the ELM device, decodes the relevant bytes, and returns a dictionary containing the emission test results for each component, indicating whether they are supported and complete.


public static class Emissions
{
    public static Dictionary RetrieveEmissionReadinessData(string response)
    {
        string[] parts = response.Split(' ');

        byte thirdByte = Convert.ToByte(parts[3], 16);
        byte fourthByte = Convert.ToByte(parts[4], 16);
        byte fifthByte = Convert.ToByte(parts[5], 16);

        int bitValue = (thirdByte >> 2) & 1;

        var engineType = bitValue == 1 ? "Spark-ignited" : "Compression-ignited";

        var readinessDict = new Dictionary();
        string[] emissionTestsSpark = new string[] { "Catalyst", "Heated Catalyst", "Evaporative System", "Secondary Air System",
            "Gasoline Particulate Filter", "Oxygen Sensor", "Oxygen Sensor Heater", "EGR and/or VVT System" };
        string[] emissionTestsDiesel = new string[] { "NMHC Catalyst", "NOx/SCR Monitor", "Reserved", "Boost Pressure", "Reserved",
            "Exhaust Gas Sensor", "PM filter monitoring", "EGR and/or VVT System" };

        if (engineType == "Spark-ignited")
        {
            for (int i = 0; i < 8; i++)
            {
                var testAbility = ((fourthByte >> i) & 1) == 1 ? "Supported" : "Not supported";
                var testCompleteness = ((fifthByte >> i) & 1) == 1 ? "Complete" : "Not complete";
                readinessDict.Add(emissionTestsSpark[i], $"{testAbility}, {testCompleteness}");
            }
        }
        else if (engineType == "Compression-ignited")
        {
            for (int i = 0; i < 8; i++)
            {
                var testAbility = ((fourthByte >> i) & 1) == 1 ? "Supported" : "Not supported";
                var testCompleteness = ((fifthByte >> i) & 1) == 1 ? "Complete" : "Not complete";
                readinessDict.Add(emissionTestsDiesel[i], $"{testAbility}, {testCompleteness}");
            }
        }
        return readinessDict;
    }
}           
          

Step 7: Putting It All Together

Finally, we write the driving code that executes everything we have written. We create an instance of the SerialCommunicator, connect to the ELM327 device, execute the specific commands, retrieve the emission readiness data, and display the results.

After this, you have a fully functional emission scan tool for your car. Feel free to play around more and challenge yourself with real-world problems, such as reading vehicle fault codes and creating a system for looking up their names and descriptions. Hint: You can use the same Command to get the Engine DTC codes Command("0101", response => response.StartsWith("41 01") && response.Length >= 17, 10000);


using (var serial = new SerialCommunicator("/dev/tty.usbserial-113010763101", 115200, Parity.None, 8))
{
    await serial.ConnectAsync();

    ELM327Controller.DebugMode = true;

    ICommand setProtocol = CreateSetProtocolToAutoCommand();
    await setProtocol.Execute(serial);

    ICommand ImReadinessCommand = CreateFaultsAndImReadinessCommand();
    string data = await ImReadinessCommand.Execute(serial);

    var readinessData = Emissions.RetrieveEmissionReadinessData(data);
    foreach (var pair in readinessData)
    {
        Console.WriteLine($"Monitor: {pair.Key}, Ready: {pair.Value}");
    }
    
    serial.Disconnect();
}    
          

Enjoy!

How To Build A Renderer from Scratch. Well sort of ...

Phong Lighting On Range Rover Model

Introduction

My fascination with computers began with video games during my childhood, right when 3D graphics acceleration was in its infancy. I was captivated by the way virtual worlds could be brought to life on screen, allowing for interactive experiences. Since then, the industry has evolved tremendously, with countless innovations. For this project, I set out to challenge myself by learning how 3D graphics work at a low level, not realizing the ambitious nature of this undertaking.

Linear Algebra Review

Before diving into the project, I needed to refresh my knowledge of linear algebra concepts that I hadn't used in over a decade. This included vectors, matrices, and trigonometry. Although it was mostly a review, I made sure to gain a thorough understanding of these concepts, as they would be directly applied in my rendering system. Taking the time to solidify my linear algebra foundation was crucial for the success of the project.

Choosing a Graphics API

One of the key decisions I had to make was choosing a graphics API. Graphics APIs provide a way for programmers to design a graphics pipeline, which can be thought of as an assembly line that takes raw data and transforms it into a frame displayed on the screen. There are numerous graphics APIs available, each with its own intricacies and workflows. After careful consideration, I chose DirectX due to its widespread popularity and Microsoft's comprehensive documentation. However, it's worth noting that DirectX has fewer tutorials and code samples compared to alternatives like OpenGL. For beginners, I would recommend starting with OpenGL unless they have a specific reason to learn DirectX.

OBJ Model File 3D Graphics Pipeline Diagram
Wireframe Render of GTR

Code Modularization

As I progressed with the project, I quickly realized the importance of modularizing my codebase. 3D rendering codebases can grow very large, very quickly. To manage this complexity, I had to structure my code in a way that was organized, reusable, and maintainable. This involved creating separate modules for different components of the rendering pipeline, such as shader management, model loading, and scene graph handling. By keeping the codebase modular, I could more easily debug issues, add new features, and optimize performance.

Learning Resources

While online resources can be helpful, I found that books were invaluable for learning DirectX and 3D graphics concepts. Two books that I highly recommend are "3D Game Programming" by Frank Luna and "Real-Time 3D Rendering with DirectX 11" by Paul Varcholik. These books provide in-depth explanations of core concepts and offer practical examples to reinforce understanding. They helped me grasp the intricacies of DirectX and guided me through the process of building a rendering pipeline from the ground up.

Rendering Pipeline

Building the rendering pipeline was an incremental process. I started by creating a simple pipeline that rendered a solid red screen, just to ensure that the basic setup was working correctly. From there, I progressively added more complexity, moving on to rendering a basic triangle, then a cube, and so on. Each step brought new challenges and learning opportunities. When it came to handling 3D models, I discovered that it often requires using a library to parse common model file formats. However, I still needed to structure the model data hierarchically, breaking it down into components like Model, Meshes, and Materials.

Red Screen Render Simple Triangle Simple Cube Range Rover Render Windmill Render

Virtual Camera

One of the most satisfying milestones in the project was creating a movable virtual camera. This was the moment when I could finally navigate through the virtual 3D space I had created. The core concept behind a virtual camera is relatively simple. Each vertex of a triangle is multiplied against a ModelViewProjection matrix, which yields the 2D screen coordinates for that vertex. The matrix needs to be regenerated each frame or whenever the camera moves. I created vectors representing the camera's position and orientation, and as those values changed, the matrix was updated to transform the vertices accordingly. Implementing the virtual camera gave me a sense of presence within the 3D scene and opened up new possibilities for exploration and interaction.

WVP

Lighting

Implementing lighting was another gratifying challenge. To achieve realistic lighting, I researched various lighting models and decided to implement the popular Phong reflection model. This model takes into account ambient, diffuse, and specular lighting components to calculate the final color of each pixel. By carefully tuning the parameters of the Phong model, I was able to achieve a range of lighting effects, from soft and subtle to bright and dramatic. Seeing the 3D scene come to life with proper lighting was a rewarding experience and added a new level of depth and realism to the rendering.

Phong Lighting On Range Rover Model Phong Lighting On Range Rover Model

VR Integration

Integrating VR support for my Oculus Quest 2 headset was an exciting venture that took the project to new heights. I used Valve's OpenVR SDK to handle the VR integration. Rendering for a VR headset is similar to rendering to a monitor, with the main difference being that you have two render targets, one for each eye. OpenVR provides the necessary ModelViewProjection matrices based on the headset's position and orientation, allowing for accurate stereoscopic rendering. Although implementing VR support was not the most straightforward task, it was certainly achievable with persistence and careful study of the OpenVR documentation. The ability to walk around the virtual scene in true 1:1 scale, as if I were physically present, was an awe-inspiring experience that made all the effort worthwhile.

VR Wireframe Render

Conclusion

Undertaking the challenge of building my own 3D renderer was an incredibly fun and rewarding experience, despite the significant time investment and occasional feelings of slow progress. It's important to recognize that creating a full-featured renderer from scratch is a monumental task, and established engines like Unreal, Unity, and Blender have massive codebases developed by large teams of experts.

However, the benefits of building your own basic renderer are immense. It provides a deep understanding and appreciation of the underlying principles and techniques used in 3D graphics. This knowledge empowers you to modify and optimize existing engines more effectively. For example, learning HLSL allowed me to write custom shaders that completely transformed the visual style of an existing renderer.

To anyone who is curious and willing to embark on a challenging but rewarding project, I wholeheartedly recommend building your own 3D renderer. The knowledge and skills you acquire along the way are invaluable and will serve you well in various aspects of computer graphics and software development.

Remember, the journey may be long and sometimes frustrating, but the satisfaction of seeing your virtual world come to life makes it all worthwhile. Embrace the challenge, stay curious, and never stop learning. The world of 3D graphics is vast and ever-evolving, and building your own renderer is just the beginning of an exciting adventure.

Source Code

Prompts

Project 3 Screenshot

Prompts is a Flutter UI control designed to guide users through a series of prompts and collect their responses.

Prompts works on IOS, Andorid, Web & wherver else flutter runs!

Github Link

Pixelated

Pixelated App

Pixelated is a user-friendly tool that simplifies the process of flashing images on Pixel devices. With just a few clicks, users can easily install stock or custom images on their supported Pixel devices. This repository and all branches are experimental for now.

Github Link