PROJECTS



Projects

Here I have compiled some examples of projects I've worked on. Not every one is finished, but they are for the most part.


xFrog3D

This is something I made for a class I took at university. It's supposed to be a 3D version of the arcade game Frogger. It is written in C++ and uses OpenGL immediate mode as well as FreeGLUT and also SOIL (for loading textures). You can see a video of it to the right. Admittedly it needs a bit of work :).


Chunked

This is an asset creation/editing tool I created for an Ncurses based side-scroller I have been working on. It is for creating background chunks and rules chunks (it is essentially a simple drawing program albeit with some features that would be out of place in a normal drawing program.) See my article on it for a bit more info.

NESEmu

Currently very much incomplete this program is intended to be an NES emulator. However it is currently just a mostly functional 6502 emulator. It will pass almost all of the tests in 6502_functional_test.asm. I think that the only thing currently stopping it from working is a flag being incorrectly set by some of the adc and sbc instructions. I plan to do more work on this in the future. Hopefully one day it will be able to play an NES game.


Binary Clock

Binary clock breadboard. 3D render of binary clock. Binary clock circuit.

A clock with binary digit's for hours minutes and seconds (note that it is not a BCD clock.) The time is read from left to right with the left most column representing hours. It uses an ATmega16 to do most of the work. The output of a 1MHz crystal oscillator is fed into a CD74HCT390E which is set up in a duel bi-quinary configuration. In this way it will divide the signal by 100. Then this chip is hooked up to an identical chip setup in the same configuration and this next chip is again hooked up to one the same as it and in the same configuration. Thus we end up with the 1MHz signal being divided by 1,000,000. This is then fed into the micro controller in such a way as to cause an interrupt and the chip updates it's seconds counter (and the minutes and hours counters if need be.) The chip was programmed in assembly language. It has 40 pins and so there is no need to multiplex the output and we can directly drive each LED individually. I first built the circuit on a few breadboards and then wrote the code that the micro controller runs. Finally I designed a PCB using KiCad and had it manufactured. There is a small bodge on the board as I originally had the oscillator powered by a voltage regulator. However I made a mistake when translating what I had on the bread board to the KiCad schematic. Anyway it turns out that the oscillator runs fine off of 5V (the data sheet was a bit confusing.) Not having much electronics knowledge I feel this was a good project and I learnt a bit (even if most of the time I spent on it was programming the micro.)

Menger Sponge

Nothing special just a simple menger sponge. It's written in C++ and OpenGL.

SOLP

SOLP warning message. SOLP sleep countdown timer.

#!/bin/sh


################################################################################
################################################################################
###									     ###
###	Program Name:			Sleep On Low Power		     ###
###	File:				solp				     ###
###	Author:				Samual G Brown			     ###
###	Date of Creation:		31/10/2020			     ###
###	Late Modified:			31/10/2020			     ###
###	Purpos:				To warn the user when the machines   ###
###					battery level is below some certain  ###
###					percentage and to put the machine    ###
###					to sleep if the machines battery     ###
###					level is below some certain	     ###
###					percentage independent of the	     ###
###					previously mentioned percentage.     ###
###					This script should be run after X11  ###
###					has been started.		     ###
###									     ###
################################################################################
################################################################################


################################# Program paths ################################
################################################################################
SYSCTL_PROG="/sbin/sysctl"
ZENITY_PROG="/usr/local/bin/zenity"
ECHO_PROG="/bin/echo"
BC_PROG="/usr/bin/bc"
SLEEP_PROG="/bin/sleep"
TOUCH_PROG="/usr/bin/touch"
RM_PROG="/bin/rm"
MPV_PROG="/usr/local/bin/mpv"


################################### Constants ##################################
################################################################################
TRUE="1"
FALSE="0"
WARNING_THRESHOLD="15"
SLEEP_THRESHOLD="8"
CARGING_OFF="0"			# 1 if machine is charging 0 if not.
UPDATE_RATE="30"		# Check status every $UPDATE_RATE seconds
CURRENT_CHARGING_STATUS=$($SYSCTL_PROG -n hw.acpi.acline)
BATTERY_LEVEL=$($SYSCTL_PROG -n hw.acpi.battery.life)



dialogueDisplayed()
{	# The following arguments should be passed
    # "dialogue displayed info dir", where dialogue displayed info dir is the
    # directory of the sentinal file that will indicate wheather or not a
    # dialogue box should possibly be displayed.
    if [ -f "${1}" ]
    then
	RET=$TRUE
    else
	RET=$FALSE
    fi
    $ECHO_PROG $RET
}


playSound()
{
    $MPV_PROG --volume=90 -audio-display=no --profile=low-latency "${1}" > \
	      /dev/null &
}


cowntdown()
{	# The following arguments should be passed "sleep interval",
    # "sleep message" and "window title" their order should be as seen here.
    # Where sleep interval is the time spent sleeping between status bar updates
    # (for example if sleep interval was 0.6 then the status bar would take one
    # minute to complete as 0.6*100 = 60).
    STATUS_BAR_MIN="0"
    STATUS_BAR_MAX="100"
    
    (for iter in $(seq $STATUS_BAR_MIN $STATUS_BAR_MAX)
     do
	 timeLeft=$($ECHO_PROG "( ${STATUS_BAR_MAX} - ${iter} ) * \
${1}" | $BC_PROG);

	 # Check charging status and return if charging.
	 if [ "$("${SYSCTL_PROG}" -n hw.acpi.acline)" -ne $CARGING_OFF ]
	 then			# We are now charging
	     break
	 fi
	 
	 $ECHO_PROG "${2}${timeLeft}s"
	 $ECHO_PROG "${iter}"
	 $SLEEP_PROG "${1}"
     done) | zenity --progress --title "${3}" --auto-close --no-cancel \
		    --display=:0.0

    # Reset CURRENT_CHARGING_STATUS as it may have changed. This should be
    # checked for after this function is run.
    CURRENT_CHARGING_STATUS=$(${SYSCTL_PROG} -n hw.acpi.acline)
}


zzzSleep()
{	# Lock the computer and put it to sleep.
    "${HOME}"/.config/i3/configdir/lock.sh
}


displayWarningMessage()
{	# The following arguments should be passed "window title" and
    # "warning message"
    $ZENITY_PROG --warning --title "${1}" --width 300 --text \
		 "${2}" --display=:0.0 &
}


setDialogueDisplayed()
{	# The following arguments should be passed
    # "dialogue displayed info dir" and "dialogue threshold", where dialogue
    # displayed info dir is the directory of the sentinal file that will
    # indicate wheather or not a dialogue box should possibly be displayed, and
    # dialogue threshold is the battery level at which the dialouge should be
    # displayed.
    if [ "${BATTERY_LEVEL}" -le "${2}" ]
    then			# If the battery level is less than.
	if [ \( ! -f "${1}" \) ] && [ \( "${CURRENT_CHARGING_STATUS}" -eq \
					 "${CARGING_OFF}" \) ]
	then			# If the file doesn't exist and we are not
	    $TOUCH_PROG "$1"
	fi
    else			# If the battery level is greater than.
	if [ \( -f "${1}" \) ] && [ \( "${CURRENT_CHARGING_STATUS}" -ne \
				       "${CARGING_OFF}" \) ]
	then			# If it exists and we are charging remove it.
	    $RM_PROG "${1}"
	fi
    fi
}


main()
{ 
    SLEEP_DIALOGUE_DISPLAYED_INFO_DIR="/tmp/sleepDialogueDisplayed"
    WARNING_DIALOGUE_DISPLAYED_INFO_DIR="/tmp/sleepWarningDialogueDisplayed"

    while [ $TRUE ]
    do
	CURRENT_CHARGING_STATUS=$(${SYSCTL_PROG} -n hw.acpi.acline)
	BATTERY_LEVEL=$(${SYSCTL_PROG} -n hw.acpi.battery.life)

	
	if [ "${CURRENT_CHARGING_STATUS}" -eq "${CARGING_OFF}" ]
	then			# We are on battery power.
	    # UI alert sound dirs (one is light harted and two is ominous!).
	    ALERT_SOUND_ONE="${HOME}/.uiSoundResources/541560__sieuamthanh__\
chuong-6e.wav"
	    ALERT_SOUND_TWO="${HOME}/.uiSoundResources/541605__erokia__msfxp9\
-49-one-shot.wav"
	    
	    if [ \( "${BATTERY_LEVEL}" -le "${SLEEP_THRESHOLD}" \) ] && \
		   [ \( "$(dialogueDisplayed \
"${SLEEP_DIALOGUE_DISPLAYED_INFO_DIR}")" -eq $FALSE \) ]
	    then	# The battery level is below $SLEEP_THRESHOLD.
		SLEEP_INTERVAL="0.6"
		SLEEP_MESSAGE="# Battery at or below (${BATTERY_LEVEL}%). \
Computer will sleep in "
		WINDOW_TITLE="WARNING LOW BATTERY (${BATTERY_LEVEL}%)"

		playSound "${ALERT_SOUND_ONE}"
		playSound "${ALERT_SOUND_TWO}"
		cowntdown "${SLEEP_INTERVAL}" "${SLEEP_MESSAGE}" \
			  "${WINDOW_TITLE}"
		if [ "${CURRENT_CHARGING_STATUS}" -eq "${CARGING_OFF}" ]
		then		# We are still not charging.
		    zzzSleep
		fi
	    else
		if [ \( "${BATTERY_LEVEL}" -le "${WARNING_THRESHOLD}" \) ] && \
		       [ \( "$(dialogueDisplayed \
"${WARNING_DIALOGUE_DISPLAYED_INFO_DIR}")" -eq $FALSE \) ]
		then		# The battery level is above $SLEEP_THRESHOLD
		    # but below $WARNING_THRESHOLD.
		    WINDOW_TITLE="Warning Low Battery (${BATTERY_LEVEL}%)"
		    WARNING_MESSAGE="It has been detected that your machines \
batterry level is ${BATTERY_LEVEL}% which is at or below ${WARNING_THRESHOLD}%!\
 The machine will automatically be put to sleep when it is detected that the \
battery level is at or below ${SLEEP_THRESHOLD}%!"


		    playSound "${ALERT_SOUND_ONE}"
	    	    displayWarningMessage "${WINDOW_TITLE}" "${WARNING_MESSAGE}"
		fi
	    fi
	fi

	# Recorde whether or not dialogues have already been displayed since
	# entering the relevant battery percentages.
	setDialogueDisplayed $SLEEP_DIALOGUE_DISPLAYED_INFO_DIR $SLEEP_THRESHOLD
	setDialogueDisplayed $WARNING_DIALOGUE_DISPLAYED_INFO_DIR \
			     $WARNING_THRESHOLD

	$SLEEP_PROG "${UPDATE_RATE}"
    done
}


main	
	    

Sleep FreeBSD On Low Power is a small shell script I've written to check for low battery on my laptop. When the battery get's below a certain percentage it will play a sound and generate a dialogue box to warn of the situation as it stands. Then if things get worse and the battery get's too low it will play a more ominous sound and display a dialogue box with a count down timer. When the timer is up the script will put the computer to sleep.
The script should be started when X11 starts because it generates the aforementioned dialogue boxes. I practically always start X when I boot up my laptop so this isn't a problem. It wakes up every few seconds to check the battery level. This of course isn't optimal. I may modify the script so that it can be used in such a way that FreeBSD would call it when some event related to low battery is generated. However I haven't yet looked into how this would be done.

F62 Model F Keyboard Solenoid Holder

A photo from the top of a solenoid holder for the Model
		      F62 reproduction keyboard. A photo from an angle of a solenoid holder for the Model
		      F62 reproduction keyboard.

You can buy a solenoid and solenoid driver along with your new re-production Model F64. That is if you get one (which is recommended). However there is no standard way to mound it. So I designed and 3D printed a mount for it (the solenoid that is) along with the solenoid driver using FreeCAD.

Laptop Stand

Laptop stand from front with laptop. Laptop stand from front. Laptop stand upside down. Part of the design for the laptop stand in FreeCAD.

A laptop stand I designed using FreeCAD. This took quite a long time to design as it is not just a relatively complex shape it also has over 20 parts, since my printer only has so much print volume. The legs are detachable and although the height is not adjustable I've used it on a couple of desks of different heights and it works quite well. It is designed so that a relatively small keyboard can fit under it and thus you don't have to have your keyboard too close to you or your laptop too far away when your using it.


Date: 02/12/2023