Over Complicating Hello World

I came accross this TikTok video recently, where the presenter shows how to make an “Object Oriented” Hello World program. It made me laugh so much, I thought I would try my own hello world program.

This is my solution, which uses the Python ast module to inspect the script looking for functions to use in the hello world message.

#!/usr/bin/env python3

import ast

def Hello():
    ...

def World():
    ...

class Visitor(ast.NodeVisitor):
    def __init__(self):
        self.functions: list[str] = []

    def visit_FunctionDef(self, node: ast.AST):
        if '_' not in node.name and node.name[0].isupper():
            self.functions.append(node.name)
        self.generic_visit(node)

def _say_hi():
    with open(__file__, 'r') as fd:
        code = fd.read()
    node = ast.parse(code)
    visitor = Visitor()
    visitor.visit(node)
    print(' '.join(visitor.functions))

if __name__ == '__main__':
    _say_hi()

     

Solving Problem 1 Using Windows Batch files

As crazy a it sounds, it turns out it is possible to solve Project Euler problem 1 using Windows Batch files! It is possible because modern versions for cmd support delayed expansion of variables, and arithmetic expressions using “SET /A”.

Delayed expansion means that variables are expanded at runtime, rather than parse time. Normally %VARIABLE% will be expanded once with whatever value it contains before the script is run, however with delayed expansion we can use !VARIABLE!. This variable is expanded whenever that line is executed, which with a for loop could be multiple times.

@echo off
setlocal enabledelayedexpansion

set /a sum = 0
FOR /L %%L IN (1, 1, 999) DO (
    set /a mod = %%L %% 3
    IF NOT !mod! EQU 0 set /a mod = %%L %% 5
    IF !mod! EQU 0 set /a sum = sum + %%L
)

echo %sum%
endlocal
       

Extracting Audio From MP4 Videos

Iā€™ve been asked to help someone create a device that can play steam train whistle sounds when a button is pressed. I was given a load of MP4 video files with recordings of the whistles.

FirstĀ I wanted to rename them because they all had a ā€œPrj ā€ prefix on them. The code snippet below is what I used to remove the prefix from the file names.

for file in *.mp4 ;
do
    mv "$file" $(echo "$file" | sed 's/Prj //')
done

The next thing to do is extract the audio from all the videos. FFMPEG is perfect for this. The Bash code below will extract the audio fromĀ all of the MP4 files in a directory.

for file in *.mp4 ;
do
    ffmpeg -i $file -map 0:1 -acodec pcm_s16le -ac 2 ${file/.mp4/.wav}
done

Now that Iā€™ve got the audio files I need to open them in Audacity and edit them, that is something I canā€™t automate unfortunatelyĀ šŸ˜¢

         

An Analogue Clock in Processing

I came across some code I wrote in Processing a while ago so I thought Iā€™d post bits of it here. I made a really simple analogue clock. Below is s screenshot of what I came up with.

I wrote a small function that handles drawing a hand of the clock. This function is called for each hand of the code by the draw loop.

void draw_hand(long count, long modulo, long len)
{
    float nx, ny;
    a = (2*PI/modulo) * count - (2*PI/4);
    nx = (width/2) + (Clock_Size/2-len) * cos(a);
    ny = (height/2) + (Clock_Size/2-len) * sin(a);
    strokeWeight(7);
    line(width/2, height/2, nx, ny);
}

Then all we need to do in the draw loop is call the function for each of the hands of the clock. Here is an example of drawing the hours hand.

To put the ticks around the outside of the clock I used the code below.

  fill(0,0,0);
  for( int i = 0; i < 12; i ++ ) {
    float angle = radians(i*30) - (2*PI/4);
    nx = (width/2) + (Clock_Size/2-35) * cos(angle);
    ny = (height/2) + (Clock_Size/2-35) * sin(angle);
    text(i == 0 ? 12 : i, nx, ny);
  }

Processing.js Version

I have got this code working fine using Processing.js. See it here

     

Notes on Implementing a Timer

Iā€™m currently working on a project at work that includes a timer that will turn relays on during certain time periods and off outside them. The timer wasnā€™t nearly as easy as I thought it would be so I decided to prototype the code on the PC as itā€™s a lot easier to debug than on a tiny little PIC18F. All of the code in this post will be in C# which I what I used to prototype with.

The weird thing about this timer is that the day is assumed change at 3am and not midnight. So a day starts at 3am and ends at 2:59am, this is apparently so that the relay can be on across midnight. This caused massive confusion and I struggled to implement it.

The idea is that the timer will store and work with an internal representation of time and then convert to hours/minutes only when displaying settings to the user and when getting the time from the RTC. This internal representation is a single integer number of minutes from midnight offset in such a way that times less than 03:00am are offset by a day. This means that 03:00am is 180 minutes as you would expect but 02:55 is actually 1615 minutes. Using this representation means that comparing time is really easy and that makes the whole timer and user interface much easier to implement. Below are some constants

const int MinutesPerDay = 1440;
const int MinInternalTime = 180;
const int MaxInternalTime = 1619;

Below is a function that converts hours and minutes to the internal representation. If the time is less than the minimum internal time then itā€™ll add a whole day to the time.

int TimeToInternal(int hrs, int min)
{
    int time = hrs*60 + min;
    if( time < MinInternalTime) {
        time += MinutesPerDay;
    }
    return time;
}

Next I needed a function to convert the internal representation to actual time, in hours and minutes. Here the time is returned as a tuple of two integers, in the C version I used two pointer parameters instead.

Tuple<int, int> InternalToTime(int time)
{
    if( time > MinutesPerDay ) {
        time -= MinutesPerDay;
    }
    return new Tuple<int, int>(time/60, time%60);
}

I have also implemented a similar timer elsewhere in the project, but it was much simpler and the day changed at midnight as you would expect. This is the code I used to implement the timer that turns on a feature during a time period, then turns off. This period can span across midnight. The time is really simple, just multiply hours by 100 then add the minutes so 11:32 is 1132.

bool IsInPeriod(int time, Period period)
{
    if( period.Start < period.Stop ) {
        return (time >= period.Start) && (time <= period.Stop);
    } else if ( period.Start > period.Stop ) {
        return (time >= period.Start) || (time <= period.Stop);
    } else {
        return false;
    }
}

Here is the Period class as I implemented it, nothing special or interesting here

public class Period {
    public Period() {
    }
     
    public Period(int start, int stop) {
        this.Start = start;
        this.Stop = stop;
    }
     
    public static int HrsMinToInt(int hrs, int min) {
        return hrs*100 + min;
    }
     
    public int Start { get; set; }
    public int Stop { get; set; }
}

Sorry if none of this make any sense, this post has mostly just been a brain dump so that if in the future I work on this again, or something similar I can remind myself of all this.

       

A Switch Debouncing Method

There are a lot of different methods used to debounce switch inputs and this post is just about one method that I read about recently and used a couple of times now. So far it seems pretty good and does the job.

The C code for this method is just below, I defined it as a macro so I can use it for multiple switch inputs. All you need to do is execute this code at a fixed sample rate and it will do the rest.

if( input == OFF ) {
    if( integrator > 0 ) {
        integrator--;
    }
} else if( integrator < PERIOD ) {
    integrator++;
}
 
if( integrator == 0 ) {
    output = OFF;
} else if( integrator >= PERIOD ) {
    output = ON;
    integrator = PERIOD;
}

What this basically does is average samples. When the input is high the ā€œintegratorā€ counts up until it reaches the PERIOD constant. Then it sets the output high and also saturates the integrator to the value of PERIOD. When the input is low the integrator counts down until it reaches 0 when it sets the output low.

I cant remember where I found this method, I believe the link is somewhere on Jack Ganssleā€™s website. He also has a good tutorial on switch debouncing.

       

C# Bit Manipulation

This post is a collection of C# method extensions that I have written recentlyĀ to help me do bit manipulations on unsigned integers. These methods allow you to set, clear, toggle, and write bits. Iā€™ve also added a read method for testing bits.

public static UInt32 SetBit(this UInt32 Value, byte bit)
{
    if (bit >= 32) {
        throw new ArgumentException("bit must be between 0 and 31");
    }
 
    Value |= (UInt32)(1U << bit);
    return Value;
}
 
public static UInt32 ClearBit(this UInt32 Value, byte bit)
{
    if (bit >= 32) {
        throw new ArgumentException("bit must be between 0 and 31");
    }
 
    Value &= ~(UInt32)(1U << bit);
    return Value;
}
 
public static UInt32 WriteBit(this UInt32 Value, byte bit, bool state)
{
    if (bit >= 32) {
        throw new ArgumentException("bit must be between 0 and 31");
    }
 
    if (state) {
        Value |= (UInt32)(1U << bit);
    } else {
        Value &= ~(UInt32)(1U << bit);
    }
 
    return Value;
}
 
public static UInt32 ToggleBit(this UInt32 Value, byte bit)
{
    if (bit >= 32) {
        throw new ArgumentException("bit must be between 0 and 31");
    }
 
    if ((Value & (1 << bit)) == (1 << bit)) {
        Value &= ~(UInt32)(1U << bit);
    } else {
        Value |= (UInt32)(1U << bit);
    }
 
    return Value;
}
 
public static bool ReadBit(this UInt32 Value, byte bit)
{
    if (bit >= 32) {
        throw new ArgumentException("bit must be between 0 and 31");
    }
 
    return ((Value & (1 << bit)) == (1 << bit));
}

I also added wrappers so these methods are avaliable UInt16 and Byte types.

   

Converting a String to a Double (with SI prefixes)

Engineers and scientists will often use SI prefixes to make writing down very large, and very small, numbers easier. Writing down 3 GV is much better than 3000000000 V :). Iā€™m currently working on a couple of software projects, both at home and work, where Iā€™d like the ability to enter numbers with SI prefixes for convenience.

First I decided to write down the different styles of input my code will have to support, below is the list of styles I came up with.

  • +2.2, or -2.2 => I want to be able to specify the sign of a number explicitly
  • .33333 => Iā€™d like to omit the starting zero
  • 2.2k => Have SI prefixes
  • 2k2 => This style is commonly found in the electronics industry.

Now I know what I want the code to do I can start writing it. I created a dictionary containing the prefixe character and the associated multiplier. I am writing this code in C# by the way, and used LINQPad to try it all out. Once I had it working I put into the class library I was working on.

private readonly Dictionary Prefixes = new Dictionary(){
    {'P', 1e15},
    {'T', 1e12},
    {'G', 1e9},
    {'M', 1e6},
    {'k', 1e3},
    {'h', 1e2},
    {'d', 1e-1},
    {'c', 1e-2},
    {'m', 1e-3},
    {'u', 1e-6},
    {'n', 1e-9},
    {'p', 1e-12},
    {'f', 1e-15},
};

Then I wrote a method that will take in the input string and convert it to a double. The first thing the method does is check to see if it is a plain number that Double.Parse() can take care of, it does this check using a regex. If the Regex matched then it simply calls the Double.Parse() method and returns the result.

If the regex fails then it check using two more regexes if the number looks like it contains SI prefixes. If it does then we find out what prefix is used then remove the prefix and convert the number.

I am not very good with regular expressions so there may be better ways of writing them than this. I have tested this code quite a bit with different types of input and it seems pretty solid. It will throw a FormatException if anything goes wrong.

// These are the regexes used by the method. These are initialised in a constructor.
Regex plain_number_regex = new Regex(@"^[+-]?(?=[\.\d])\d*(\.\d+)?$"); // For .2222, 0.222, 2.32
Regex si_number_a_regex = new Regex(@"^[+-]?[\d]+[PTGMkcmunpf]?[\d]*$"); // for 2k, 2k2
Regex si_number_b_regex = new Regex(@"^[+-]?[\d]+(\.\d+)?[PTGMkcmunpf]?$"); // For 1.2k
 
public double ParseInputStringSI(string input)
{
    // Test to see if it is a plain number with no SI prefixes
    if (plain_number_regex.IsMatch(input)) {
        return Double.Parse(input);
    }
 
    // Test to see if it is a number with an SI prefix.
    if(si_number_a_regex.IsMatch(input) || si_number_b_regex.IsMatch(input) ) {
        // Find where in the string the prefix is and what
        // kind of prefix it is.
        var input_prefix = from p in Prefixes.Keys
                           where input.IndexOf(p) > 0
                           select input[input.IndexOf(p)];
 
        // Make sure the above query worked. There should be
        // no reason for it to fail because the Regex checks
        // the prefix characters.
        if (input_prefix.Count() == 0) {
            throw new FormatException("Invalid Input");
        }
 
        // Get the multiplier for the prefix
        var multiplier = Prefixes[input_prefix.First()];
 
        // Ether replace the prefix with a decimal point or
    // remove it entierly. Depends on the format of the
    // input.
    string inputp;
    if( si_number_a_regex.IsMatch(input) ) {
            inputp = Regex.Replace(input, @"[PTGMkhdcmunpf]", ".");
    } else {
        inputp = Regex.Replace(input, @"[PTGMkhdcmunpf]", "");
    }
 
        // Attempt the conversion, multiply it then return it.
        var tmp = Double.Parse(inputp);
        return tmp * multiplier;
    } else {
        throw new FormatException("Input String is Invalid");
    }
}
     

Getting a List of the Available COM Ports in C#

Itā€™s really nice to show the user a list of the COM ports they actually have on their machines. All too often I have seen software that makes you type in the COM port name. Even worse are the applications that force you to select from a list of COM ports, usually COM1 to COM5, without the option of typing in a different one!

Below is some really simple code that generates a list of the available COM ports and inserts the list into a drop-down selection control in a WinForms application.

string[] ports = SerialPort.GetPortNames();
if (ports.Length > 0) {
    Array.Sort(ports);
    COMPort.Items.AddRange(ports);
    COMPort.Text = ports[0];
} else {
    COMPort.Text = "Unable to Detect COM ports";
}
     

Creating an IO Assignment Header File

When developing embedded firmware I like to define macros that provide aliases for the IO port registers that I need. The name of each of the macros will correspond to the net name on the schematic to make it easy to check for errors. I put all of these macros into a single header file that I can include, I have sometimes seen these called board support packages. They can sometime be entire libraries that abstract details of the hardware. In my case they are just simple header files as that is all I need for now.

Recently I decided to automate some of the work of creating these files as it can be very time consuming. This is the Awk script I ended up with.

#!/usr/bin/awk -f
{
    if ($0 == "") next;
 
    if ($2 == "PORTA") { port = "A"; }
    if ($2 == "PORTB") { port = "B"; }
    if ($2 == "PORTC") { port = "C"; }
    if ($2 == "PORTD") { port = "D"; }
    if ($2 == "PORTE") { port = "E"; }
    if ($2 == "PORTF") { port = "F"; }
    if ($2 == "PORTG") { port = "G"; }
 
    print "#define " $1 "_PIN " $3;
    print "#define " $1 "_TRIS TRIS" port "bits.TRIS" port $3;
    print "#define " $1 "_LAT LAT" port "bits.LAT" port $3;
    print "#define " $1 "_PORT PORT" port "bits.R" port $3;
    print "";
}

All I need to do is write a space separated file in which each line contains the name I want, the port it is on and the number of the pin that it is attached to. Then this simple script generates the C code. This was for a PIC24F series micro, I have a slightly different script for a project involving a PIC32 which I may post later.

This makes creating BSP header files really easy, especially if you need to modify the pin assignments!

       
1 2