Search

Saturday, July 4, 2020

Playing Audio Music (Big Ben Westminster Clock Chime) on Internal PC Speaker Connected to Motherboard Southbridge 8253 / 8254 PIT chip (Not Sound Card)

Supratim Sanyal's Blog: PC internal speaker buzzer beeper (beep speaker)
Motherboard with connected internal speaker

I have always built my own internet routers to serve as gateways to ISPs for my home and family. The last one - a Pentium-D based build - was getting challenged with 200 mbps uplinks to Verizon FiOS and Comcast xfinity. So I recently built a new router using a ASRock J4105B-ITX Mini ITX motherboard with Intel Gemini Lake Celeron J4105 quad-core processor,  8 GB of DDR4 SODIMM memory,  a four-port IBM Netxtreme gigabit ethernet adapter (removed for the picture above to show the piezo buzzer clearly),  a 120 GB SSD for storage and a InWin Mini-ITX case with power supply unit. The router works great, easily supporting two WAN gateways in failover / redundant mode and two gigabit private LAN subnets. The power requirements at just 10 watts TDP for the CPU and five more watts for the quad-port Netxtreme gigabit Ethernet adapter are a fraction of the Pentium-D build with 95 watts TDP just for the processor.

PC Motherboard Internal BIOS Alarm Speaker Buzzer - Piezo Beeper
PC internal Piezoelectric speaker »
Whenever I build a computer I make it a point to install a motherboard-connected speaker or a beeper. Unfortunately a lot of recent computer cases do not include this simple and cheap part, thus depriving builders of a basic tool for troubleshooting when the computer does not boot far enough to get to the BIOS screen. The mini-ITX case I bought for the router was also missing the speaker / buzzer, so I obtained and installed a piezo buzzer as you can see in the picture at the top of this post.

The ASRock motherboard has a header for the speaker (as do all motherboards I have come across, including ASUS and Dell motherboards over the last thirty years). Strangely, ASRock's BIOS had the internal speaker turned off by default. I turned it on manually, and was happy to hear the familiar single short beep at boot time: all systems go. Perhaps some people do not want their PCs to signal all is good when they boot or reboot their computer.

The router runs Ubuntu 20.04 LTS (Focal Fossa) operating system which serves as the virtualization hypervisor for a Sophos UTM 9 Home virtual machine that performs actual routing, firewall, IDS and IPS functions (the four physical ethernet ports on the Netxtreme are bridged into the virtual machine).

Of relevance to this post, Ubuntu provides a nifty PC Speaker device driver kernel module that allows command-line and shell script access to the internal speaker.  This module was was automatically included during installation, but was not being loaded by default during Focal Fossa boot. I added a simple "modprobe pcspkr" line in /etc/rc.local (and made it executable) to load it at boot-time. The driver provides access to the case speaker via a /dev/input/by-path/platform-pcspkr-event-spkr device which in my case is a link to "../event6".  It then becomes possible to write to it this device to play tones of specific frequencies and duration. Armed with a frequency lookup table for musical notes, entire tunes can then be played on the chassis / case speaker.  This method does not require writing to the processor's I/O ports that are connected to the Intel 8253 / 8254 Programmable Interval Timer (PIT) to which the case speaker is connected via an AND gate on Counter 2.

With the PC speaker kernel module loaded, we can use the convenient beep utility from beep package to play notes on the internal buzzer. "beep" needs to be invoked from the native root account (it does not work with sudo).

I wrote a cron-invoked bash shell script that plays the famous Westminster Chimes (Westminster Quarters) melody at each quarter, half, three-quarters and top of the hour.  The Westminster Chimes consists of four sequences of four notes each rendered by a bell in the bell tower. The first, second and third of the four sequences are played at fifteen minutes, thirty minutes and forty-five minutes past the hour.  All four sequences are played at the top of the hour, followed by all four bells ringing to count the hour.

Piezoelectric beepers are reported to work best at audio frequencies in the 1 to 5 KHz range. Mapping the Westminster Quarters notes to frequencies just around 1 KHz, here is the piezo buzzer playing at the top of the hour:



Here are root's crontab entries:

# Westminster chimes
0 * * * * /root/beep/westminster-pcspkr.sh -00 > /dev/null 2>&1
15 * * * * /root/beep/westminster-pcspkr.sh -15 > /dev/null 2>&1
30 * * * * /root/beep/westminster-pcspkr.sh -30 > /dev/null 2>&1
45 * * * * /root/beep/westminster-pcspkr.sh -45 > /dev/null 2>&1

and here is the shell script "/root/beep/westminster-pcspkr.sh":

#!/bin/bash
# ----------
# westminster-pcspkr.sh
#
# Plays the three parts of the Westminster chime at 15, 30 and 45 minutes and
# the whole thing followed by gongs couting the hour at 00 minutes.
#
# Uses the pcspkr kernel module and "beep" utility to play on the internal
# PC speaker / beeper (the one connected to the motherboard and uses the
# 8253/8254 PIT chip to generate audio tones)
#
# Pass one of -00, -15, -30 or -45 on the command line for the corresponding
# chime. -00 takes the hour from system time to count the number of strikes
# after playing the full chime.
#
# Distributed under beerware license revision 42:
# Supratim Sanyal (http://tuklusan.decsystem.org) wrote this file. As long
# as you retain this notice you can do whatever you want with this stuff.
# If we meet some day, and you think this stuff is worth it, you can buy me
# a beer in return.
# ----------
# Westminster Chime
# 15 mins: FAGC
# 30 mins: CGAF
# 45 mins: AGFC
# 00 mins: FAGC CGAF AGFC CGAF <#gongs for hour - all four bells>
# Frequencies in hertz
#CNOTE="523.25"
#FNOTE="698.46"
#GNOTE="783.99"
#ANOTE="880.00"
CNOTE="1046.50"
FNOTE="1396.91"
GNOTE="1567.98"
ANOTE="1760.00"
GONG_20MS="-f ${FNOTE} -l 5 -n -f ${ANOTE} -l 5 -n -f ${GNOTE} -l 5 -n -f ${CNOTE} -l 5"
usage ()
{
echo "usage: $0 {-00|-15|-30|-45}"
echo "example: $0 -45"
echo "Plays Westminster chime at 00, 15, 30, 45 minutes using"
echo "beep command to drive internal PC speaker"
echo "Kernel module pcspkr must be available (modprobe pcspkr)"
echo "Obviously motherboard speaker header must have a speaker!"
echo "MUST RUN AS full root, not even as sudo"
sync;sync;sync
exit 1
}
quarter ()
{
beep -f ${FNOTE} -l 1000 -D 500 \
-n -f ${ANOTE} -l 1000 -D 500 \
-n -f ${GNOTE} -l 1000 -D 500 \
-n -f ${CNOTE} -l 1000 -D 1000
}
half ()
{
beep -f ${CNOTE} -l 1000 -D 500 \
-n -f ${GNOTE} -l 1000 -D 500 \
-n -f ${ANOTE} -l 1000 -D 500 \
-n -f ${FNOTE} -l 1000 -D 1000
}
threequarters ()
{
beep -f ${ANOTE} -l 1000 -D 500 \
-n -f ${GNOTE} -l 1000 -D 500 \
-n -f ${FNOTE} -l 1000 -D 500 \
-n -f ${CNOTE} -l 1000 -D 1000
}
full ()
{
quarter
half
threequarters
half
# and now hit all four bells to signal the hour
# create a 1-second gong beep string alternating four bells 5 msec each
# do this only on the top of the hour, not every time script is invoked
GONG="${GONG_20MS}"
for ii in {1..49}
do
GONG="${GONG} -n ${GONG_20MS}"
done
GONG="${GONG} -D 1000"
HOUR=`date +%l|tr -d '[:space:]'`
for ii in $(eval echo "{1..${HOUR}}")
do
# echo "[$ii] HOUR [${HOUR}]"
beep ${GONG}
done
}
# --- main ---
if [ "$#" -ne 1 ]; then
usage
fi
case $1 in
-15)
quarter
;;
-30)
half
;;
-45)
threequarters
;;
-00)
full
;;
*)
usage
;;
esac
sync;sync;sync
exit 0







No comments:

Post a Comment

"SEO" link builders: move on, your spam link will not get posted.

Note: Only a member of this blog may post a comment.

Recommended Products from Amazon