Wireless Keyboard Mystery

Sometimes, a background in Embedded Systems can be useful in IT work.

Recently, a Logitech wireless keyboard at work was acting strangely. Before being moved to a new computer, it had worked flawlessly, but now was only responding intermittently (perhaps registering one keystroke in twenty — but always correctly.)

Since the wireless adapter plugged in to the laptop via USB and had been detected readily by Windows 7, it wasn’t likely to be a driver issue. (Keyboards usually don’t cause many driver problems in Win7.) The batteries had been recently changed, so that didn’t seem to be the problem. It was a classic case of gremlins.

The next step in troubleshooting was to narrow the problem down to what had changed. The computer had been changed, so that was one possible suspect — although an unlikely one, since the only connection to this computer was as a USB keyboard. The power connection to the wireless base was still plugged in securely and the base was getting power.

The only other change was that the PS/2 mouse connection, which had been connected but not in use on the older computer’s docking station, had been left unplugged on the new machine (which didn’t have any PS/2 ports.) Hmmm.

Plugging the PS/2 mouse connection back in to the old docking station (while leaving the USB keyboard connector plugged in to the new machine) made the problems go away: the keyboard started working perfectly. My guess, as an Embedded Systems geek, is that the processor in the wireless base was getting stuck in the “wait-for-PS/2-mouse-response” routine, and not processing the keyboard input. In Muggle terms, it realized that it no longer had a mouse port to talk to, and had gone off to sulk.

It works for now — while the old docking station is still there — but keeping an entire legacy docking station on a desk just to keep a wireless keyboard working properly is rather inefficient. Something tells me that there’s a PIC project to emulate a PS/2 mouse port in my immediate future. That should rank right up there on my list of weird projects.

Posted in Digital, System Administration | Leave a comment

Making Music With Microcontrollers

Often, in embedded systems design, it is useful to be able to produce musical notes. A device which uses a brief, pleasant melody to announce an end-of-cycle condition, for example, can be perceived as more sophisticated — and therefore, more desirable — than one which simply beeps.

Musical notes can be produced by even the simplest microcontrollers, given a basic understanding of elementary music theory. Notes are distinguished by three qualities: frequency, amplitude, and timbre. Frequency is simply how many cycles per second are present — the “pitch” of the note. Amplitude is the loudness or energy present in the note. Finally, timbre is the quality of note (its shape, as seen on an oscilloscope). Sine waves are pure tones of a single frequency. Notes with other timbres have other, higher frequencies as additional components of their waveform.

Frequency is what makes a particular note, for example, a “C#” or an “E.” Higher-pitched notes are higher in frequency — and the notes are related by a specific formula. “Concert pitch A” (A4 in musical notation) is defined as 440Hz, or 440 cycles per second. Other notes, using the equal-tempered scale common in Western music, are defined from A440 using a specific formula.

This formula involves counting the number of musical half-steps (A to A#, A# to B, B to C, etc) between A440 and the note in question. The frequency of the new note is then defined by the following formula:

F = 440 * 2^(N/12)

…where N is the number of half-steps (positive or negative) between A440 and the new note. For example, A220 (one octave lower) is twelve half-steps down. Therefore:

F_A3  =  440 * 2^(-12/12)
= 440 * 2^(-1)
= 440 * 1/2
= 220Hz

This provides a good check of the formula, since each octave higher corresponds exactly to a doubling of frequency. (That’s why, musically, each note sounds similar to the same letter note one octave higher or lower.)

Once you have determined the frequency for a certain note, this is converted into a time period between half-cycles. For example, the 220Hz note in the example above would correspond to 1/220th of a second for a whole cycle, and 1/440th of a second for each half cycle. Doing the division results in a delay of 2.273 milliseconds for each half cycle. So, to produce a 220Hz “A,” a microcontroller program could do the following:

  • Drive the output pin high
  • Wait for 2.273 milliseconds
  • Drive the output pin low
  • Wait for another 2.273 milliseconds
  • Repeat as desired until the tone should no longer sound.

One important consideration when producing musical notes is frequency accuracy. For a note to sound correct, its frequency should be within roughly ten “cents” of the correct tone (where 100 “cents” is equal to the frequency ratio of one musical half-step.) For an ideal note frequency of 220Hz (corresponding to A3), this means the actual frequency of the note must be between 218.73Hz and 221.27Hz. The delay for each half-cycle, therefore, must be between roughly 2.260ms and 2.286ms. (A delay of 2.273ms would be nearly ideal.)

Here is a list of the ideal frequencies for each note in the range from C3 (one octave below Middle C) to C5 (one octave above Middle C), along with the minimum and maximum acceptable frequencies and the corresponding minimum and maximum half-cycle delay times, assuming an allowed tolerance of ten cents. For higher octaves, double the frequencies and divide the delay times by two. For lower octaves, divide the frequencies by two and double the delay times.

A chart of minimum and maximum frequencies and half-cycle delay times. (Click for larger.)

(Here is the original Excel file, with formulas.)


Posted in Analog, Assembly, Audio, Coding, Digital, Math, Music, Science | 2 Comments

Isochronous Assembly Code

Assembly language is great for writing really fast, efficient routines where hard-realtime timing constraints have to be met. Making a tachometer using a microcontroller running from a TTL oscillator is one example: if coded correctly, the microcontroller can be relied on to measure timing with great accuracy.

In order to do this, it is often necessary to write check-and-count routines in such a way as to make the loop execute in a fixed number of clock cycles, no matter what the current state of the count happens to be. Implementing carry logic takes extra processor cycles, so this must be compensated if the loop is to run isochronously.

On low-end to midrange 8-bit PIC microcontrollers such as the 16F88, the only available native data type is an 8-bit integer. These can be combined to produce 32-bit integers, if the next-higher byte is incremented each time the lower byte rolls back to 0x00. Done properly, the loop will always execute in the same amount of time, no matter how many of the registers roll over for a given count.

Here is the relevant portion of the code for a tachometer project I’m working on. It uses a 32-bit counter, allowing up to over four billion counts before resetting. This provides much greater accuracy than would be possible with a single 8-bit counter. The extra accuracy is worth the extra coding effort, in this case…

CycleCount:
   goto $+1

Loop1:
   goto $+1

Loop2:
   goto $+1

Loop3:
   btfss PORTA, 0 ;If A.0 is low, then
   goto HandleEvent ;skip out

   incfsz Count0, f ;Increment the low byte.
   goto CycleCount ;Low byte isn't zero. Go back to beginning.

   incfsz Count1, f ;Increment the 2nd byte.
   goto Loop1 ;2nd byte isn't zero. Go back -- two cycles later.

   incfsz Count2, f ;Increment the 3rd byte.
   goto Loop2 ;3rd byte isn't zero. Go back four cycles later.

   incf Count3, f ;Increment the high byte.
   goto Loop3 ;Go back six cycles later.

Except for the last cycle where it jumps to the HandleEvent routine, this code will always execute in 44 clock cycles. Instructions on a PIC16 always take four clock cycles (eight, if the program counter register is modified.) If Count0 is incremented to a nonzero number, execution will then pass to the top of the routine — the CycleCount: label. If Count0 rolls over but Count1 does not, execution passes to the Loop1: label, saving the two instruction cycles that were used to increment Count1. Likewise, if Count2 is incremented, control passes to Loop2: — unless Count3 is also incremented.

Since the code is constructed this way, execution will always take 44 clock cycles per loop. If the count shows one million, exactly 44 million cycles (less two cycles) will have passed since the loop started timing. This allows the system accuracy to be readily calculated — and often makes the system clock (a 50PPM, 20MHz TTL oscillator, in this case) the limiting factor in accuracy.

At 20MHz (or 5 MIPS), this code allows timing of events to within 8.8 microseconds (give or take 50PPM). Not half bad for a chip costing $1.83 or less.

Now for the hard part: implementing 32-bit integer division with a processor that doesn’t even natively do multiplication…!

Posted in Assembly, Coding, Digital, Electronics, PIC Microcontrollers | Leave a comment

Minecraft Scientific Calculator

You may have heard that Minecraft, with its various Redstone-based constructs, is Turing-complete — meaning that it can, in theory, emulate any digital computer. (The size of the Minecraft world, in fact, would make quite a few interesting designs possible.)

It’s another thing entirely, however, to see this put into practice. By combining hundreds (thousands?) of building blocks such as BCD adders and subtracters, “MaxSGB” has created an in-world Minecraft scientific/graphing calculator. Because Minecraft’s discrete 1m x 1m x 1m block system doesn’t lend itself very well to miniaturization, the resulting construct is immense — taking up millions of cubic meters of space. It gets the job done, though — just check out the video!

I’m still waiting for the ultimate Minecraft emulator, though — a computer capable of running Minecraft, inside Minecraft.

Posted in Digital, Games, Internet, Minecraft | Leave a comment