Operation Of Original PM-6668 Counter

In this chapter I'm going to explain the operation of the original PM-6668 counter, the way it was before the face lift. I'm going to use the original circuit diagram which was supplied with the counter as reference during this description.

The original counter was controlled by a 8048 micro controller. This controller is equipped with the astonishing amount of 1kB of program ROM and the even more amazing 64 bytes of data RAM. Furthermore the controller is equipped with an 8 bit counter which is used as a pulse counter in this application.

With a little trick it is possible to read the contents of the ROM in the 8048. For this purpose I've designed the 8049 SPY which will read the contents of practically every 8048 or 8049 processor. After disassembling the original program I knew every detail about reciprocal frequency counting which enabled me to transport the same principles to the new brains of the counter.

Reciprocal Frequency Counting

The PM-6668 uses an unconventional counting technique called reciprocal Frequency counting. Reciprocal frequency counting broke through when micro controllers became affordable. Nowadays it is not that unique anymore but it sure was when the counter was first released back in the late seventies.
Strangely enough you can still buy "normal" counters, even though reciprocal frequency counting is ever so much superior.

A normal counter uses an accurate fixed gate time and simply counts the number of pulses that are presented on the input. Needless to say that you can only count 50 pulses if a 50Hz frequency is applied to an acceptable gate time of 1 second. If you want to measure this low frequency with a 3 digit resolution you will have to increase the gate time to 10s. And on top of this very low resolution there is also a ±1 counting error because the gate is not synchronized to the input frequency. This error is particularly a big problem with these low frequencies. In the case of a 50Hz signal it means an additional error of 2% !
Reciprocal frequency counting works in a totally different way on the PM-6668 resulting in a constant resolution of 7 digits with a 1 second gate time regardless of how high or how low the input frequency really is. There is still a ±1 digit error but that is not such a big problem on a 7 digit result any more.

The gate time is not timed very accurately with reciprocal frequency counting as opposed to normal frequency counting principles where the precision of the gate time determines the final precision of the instrument. In the PM6668 the gate is even timed by a software loop which results in a far from accurate gate time, let alone a constant gate time. However this inaccuracy doesn't affect the meter's accuracy in any way.
The starting of the gate time is synchronized with the incoming frequency. This means that the real gate time is only started on the falling edge of the input signal. At the same time the software gate timer is started. Once this software timer times out we wait again for the last falling edge of the input signal before we finally end the gate time. Synchronizing the gate time with the incoming frequency eliminates the traditional ±1 count error.
All incoming pulses are counted during the gate time. At the same time a second counter counts the number of pulses originating from the counter's 10MHz reference oscillator. We can't synchronize to this reference signal too like we did with the input signal. This will introduce a ±1 error again, but this time this error is only ±1 out of 10,000,000 pulses when a 1 second long gate time is used. Because the counter has only 7 visible digits on it's display this error will never be noticed.

The 10MHz reference frequency can be generated in 3 different ways. On the cheaper models it is generated by a fairly simple crystal oscillator. Better results can be expected from the more expensive model with a temperature stabilized TCXO oscillator.
Finally the reference signal may be applied to the external reference input at the back panel of the instrument.

After counting the number of input and reference pulses during the gate time we can calculate the actual input frequency. Below you see the formula we use to calculate the frequency.

finp  =        event counter      x 107
reference counter

The 107 factor in the formula is of course the frequency of the reference oscillator. Given a gate time of 1 second and a reference oscillator of 10MHz this will result in a constant 7 digit resolution.

Like I've said before the exact duration of the gate time is not very important. As long as it is longer than 1 second we can be sure that the counter will have a resolution of 7 significant digits.
The gate time can be shortened to 0.2 seconds in the fast mode. It is inevitably that the counter's resolution degrades to 20% of its original 7 digits now. This means that values of up to 20% of the full scale still have a 7 digit resolution. While values above 20% of the full scale value will have a 6 digit resolution.
That's why the counter will switch back to a 6 digit value if the mantissa of the frequency exceeds 2000000. A hysteresis is included to avoid nervous switching between 6 and 7 digit resolution when the input frequency happens to fluctuate around the tripping point. The counter will switch from 7 to 6 digits when the frequency exceeds 22% of the full scale. It will switch back from 6 to 7 digits when the frequency drops below 20% of the full scale again.


The PM6668 has 2 prescalers which divide the frequency applied on the inputs before the signal reaches the actual counter. The PM6667 version has only one prescaler because it lacks the HF input.

The LF prescaler divides the input frequency on the LF input by 10. This divide by 10 prescaler serves two purposes. First of all it lowers the input frequency to a maximum of 12MHz to be processed by the rest of the counter.
It will also average the input frequency which will result in a more stable display of low frequencies. The software simply multiplies the measured frequency by 10 to compensate for the effect of this prescaler. Please note that this does not affect the counter's resolution in any way!

The HF prescaler divides the frequency present on the HF input by 256. Again the software compensates this by multiplying the measured frequency by 256 again. This prescaler is included to extend the frequency range of the counter up to 1GHz.
Please note that the PM6667 isn't equipped with an HF input and therefore must lack the HF prescaler altogether.

There must be a way for the PM6668 to select between the two inputs because the counter is completely auto ranging. This is done by an RF detector on the HF input PCB. The output level of this detector indicates the presence or absence of an HF frequency of at least 70MHz.
With this detector signal the software can then decide whether to use the LF or HF input.

Synchronizing The Gate To The Input Signal

Like I've said, the gate is carefully synchronized to the incoming pulses. This will eliminate the traditional ±1 counting error because we always count an exact multiple of the incoming frequency.
The bottom half of IC105 plays the main roll in synchronizing the gate time. It is a D-type flip-flop. On its D input it receives the gate signal from the main processor on P2.5. This signal is high when the gate is closed. The output Q of the flip-flop remains low, which can also be enforced by the Reset line from the main processor P2.6, effectively keeping the gate closed.
As soon as the processor is ready to start a new measurement it makes the D-input of the flip-flop low. The first falling edge of the input signal will now trigger the flip-flop making its Q output high which opens the gates. Both counters now start counting. The reference counter counts the number of reference pulses coming from the 10MHz oscillator. And the event counter counts the input pulses coming from one of the 2 prescalers. The processor won't start the software timing loop until the gate is opened by the first falling edge of the input signal.
Once the gate time is over the processor makes the D-input of the flip-flop high again. This will close the gate at the next falling edge of the input signal and no sooner than that. Until the gates are closed the counting of reference pulses still continues.

The counter will not wait indefinitely for the first input pulse to arrive. This would freeze the last reading in the display far too long in case the input signal is removed. Therefore the processor will restart the process after about 350ms while clearing the display to 0000000.

Similarly it is also possible that the last pulse never arrives if the input signal is removed during the measurement. This time a software timer is started to wait about 1.5 seconds before we know for certain that no pulses of very low frequencies have arrived anymore. When this happens the processor will display 0000000 again and will start a new measurement.

The Event Counter

The purpose of the event counter is to count all incoming pulses originating from one of the two prescalers during the gate time. It must be large enough to count the maximum frequency (i.e. 12MHz) during the longest gate time without overflowing. Thus it should be capable of counting up to at least 12,000,000.
The event counter consists of 2 initial flip-flops and an 8 decade counter array. The task of both flip-flops is to reduce the maximum frequency presented to decade counter.

The top half of IC105 gets the highest input frequency and divides it by 2. This signal is then applied to the left half of IC110, which again will divide the frequency by 2. Then the remaining signal is applied to the decade counter array IC107 and IC108.

It's the task of the software to compose a normal BCD value out of the results of these counters once the gate time is over. Therefore the result of the 8 decade counter array is multiplied by 4 and the outputs of both flip-flops is added to that result. This produces a counter that can count up to 399,999,999, which is more dan adequate for our purpose.

Now the software must correct the effects of the selected prescaler to get the real event count. For the LF input we need to multiply the counter's result by 10 to get the actual number of events. This is fairly easy, we only have to increment the decimal exponent value once to achieve that.
For the RF input we need to multiply the counter's result by 256 to get the actual number of events. This is also quite easy, we simply double the value 8 times to achieve this.
Internal resolution of the event counter is 12 digits which is far more than we really need. Therefore it's safe to say that counter overflows will never occur.

The Reference Counter

The purpose of the reference counter is to count the number of pulses originating from the 10MHz reference oscillator during the gate time. It must be capable of counting up to 10,000,000 during normal gate times of 1 second.
The implementation of the event counter is a bit more complicated than with the event counter. IC106 is the first 8-bit binary stage of the counter which is triggered by the full 10MHz of the reference signal. The carry output from this 8-bit binary counter (typically @ 40kHz) is connected to the timer input of the micro controller which is programmed to act as an 8-bit binary counter. Every time this internal timer overflows (typically every 6.5ms) it triggers an interrupt routine which increments a 4 digit decimal counter in software.

It may be obvious that it takes a bit more effort for the software to compose a normal decimal value from this counter. First of all the internal 4 digit counter is multiplied by 256 * 256 = 65,536. This is simply done by doubling the counted value 16 times.
Then both 8-bit binary counters (IC106 and internal timer/counter) must be converted to a decimal number which is then added to the temporary result of the 4 most significant digits.

This mechanism produces a counter that can count up to 9999 * 65,536 + 65,535 = 655,359,999. We only need to be able to count up to approximately 10,000,0000, so the resolution of the reference counter is also large enough to assure that no overflows will ever occur.

Calculating The Result

Up until here we've got 2 BCD values, the event counter and the reference counter. Now we have to calculate the result. This is not a very easy task for an 8048 processor which only knows how to add two 8 bit numbers together. Calculating the result requires a floating point division.
At Philips they managed to implement this floating point calculation routine in the 8048, even though they used some very peculiar detours. I'll explain the detour story later, first we're going to divide two BCD numbers.

Before we can divide the event counter by the reference counter we must normalize both values. Normalizing is a procedure where both mantissas are left justified to enable us to subtract both numbers from each other.
First we start with setting the exponent of the event counter to 107 because we have to multiply the end result with this value anyway (see formula above). In case of the LF prescaler this exponent value is incremented once to compensate for the divide by 10 ratio of this prescaler.
Once the exponent for the event counter is set we can start normalizing. We multiply the mantissa by 10 until the 11th digit becomes non-zero. Every time we multiply the mantissa by 10 we have to decrement the exponent to ensure that the actual value doesn't change. Remember that the mantissa was 12 digits wide but we deliberately don't normalize all the way to the 12th digit.
In a similar way we normalize the reference counter value to the 11th digit. But this time we increment the exponent each time we have to multiply the mantissa by 10. Please note that the exponent is already the exponent of the end result, which is now effectively the event exponent minus the reference component.
After normalizing both values this way we compare them. If the event counter happens to be less than the reference counter we multiply the event mantissa by 10 once more and decrement its exponent one last time. This ensures that we actually can subtract at least once later on. This explains why we only normalized until the 11th digit before.

Now it's time for the actual division. This is done by subtracting the reference counter from the event counter as often as we can. We count the number of times it was possible to subtract without getting a negative result. The result of this is the most significant mantissa digit of the result.
Then we multiply the remaining event counter value by 10 again and repeat this procedure for the next digits. This procedure is repeated until we have a result of 7 digits.


With long gate times all 7 digits are relevant and may be displayed without restriction. But with short gate times the relevant resolution is less, in our case 20% of the normal resolution.
One might expect that we simply display 7 digits if the value is below 20% of the full scale and 6 digits if the value is above 20%. Real life is a bit more complicated than that. With an input frequency close to 20% of the full scale we can expect a very nervous display if it switches back and forth between 6 and 7 digit resolution 5 times per second. This is simply solved by building a 10% hysteresis around the tripping point. We won't switch from 7 to 6 digits until the value is above 22% of full scale. Switching back from 6 to 7 digits is not done until the value drops below 20% of full scale again.

6 digit results are displayed right justified, leaving the left most digit blank. The decimal point is placed in such a way that it will not have to shift back and forth if we have to change resolution.

Floating Point

At last we know the result The only thing left to be done is to present the value on the display. The mantissa is easy, we only have to copy that to the display remembering that 6 digit values have to be right justified. Placing the decimal point and showing the right unit annunciator (Hz, kHz, MHz) is a bit more difficult.

The decimal point is always placed to the right of the 6th, 5th, or 4th digit (counting from the right). This ensures that the decimal point will remain in the same location in both 6 digit and 7 digit resolution which makes it easier to interpret the result.
In the rare event that the frequency drops below 10Hz the decimal point is placed to the right of the 7th digit. Remember that the counter isn't really supposed to count frequencies below 10Hz, but you may be lucky and find that it counts a few counts lower than 10Hz anyway. Please note that with these extremely low frequencies it is no problem to display 7 digits anyway because the gate time is automatically increased for these low frequencies due to the gate synchronizing mechanism (a 10Hz signal produces only 1 pulse per second after the first prescaler).

Positioning the decimal point and range annunciators is done in a very complicated way with a long range of comparisons. It would have been far easier and faster if a simple lookup table was used with just 10 entries telling it where the decimal point should go and what range it is in.

Below you'll find this table showing you where the decimal points are for the different ranges in both resolutions.

-1x.xxxxxx Hz 
 x.xxxxx Hz 
7 digits
6 digits
0 xx.xxxxx Hz 
 xx.xxxx Hz 
7 digits
6 digits
1 xxx.xxxx Hz 
 xxx.xxx Hz 
7 digits
6 digits
2 xxxx.xxx Hz 
 x.xxxxx kHz
7 digits
6 digits
3 xx.xxxxx kHz
 xx.xxxx kHz
7 digits
6 digits
4 xxx.xxxx kHz
 xxx.xxx kHz
7 digits
6 digits
5 xxxx.xxx kHz
 x.xxxxx MHz
7 digits
6 digits
6 xx.xxxxx MHz
 xx.xxxx MHz
7 digits
6 digits
7 xxx.xxxx MHz
 xxx.xxx MHz
7 digits
6 digits
8 xxxx.xxx MHz
 xxxx.xx MHz
7 digits
6 digits

The Detours

I already mentioned that the Philips engineers made some peculiar detours in the software for the PM-6668. Here's how they manage to double a BCD number for instance:

Assume that the initial number is held in buffer A. Buffer B is cleared first, then buffer A is added to buffer B to get an exact copy. Then buffer A is added to buffer B once more, effectively doubling the value. But now the result is in the wrong buffer so we have to move the result back to buffer A again.
Wouldn't it have been easier to make the source and destination point to the same buffer and add that buffer to itself? This would only require one addition routine, whereas they use 2, an erase buffer routine and a move buffer routine to achieve the same thing.
Remember that this weird programming practice is repeated several times in the entire program!

I've already mentioned the strange and complicated way to place the decimal point and the way they determined what range annunciator to show.

Apart from these peculiarities there are still some more strange things in the program, but those are not really worth mentioning here.

Self Test

A few self tests are implemented in the system software. They are particularly useful to fill the entire ROM space for I can't think of another purpose for most of the tests.

The most obvious self test is the segment test that you can see for a few seconds when the counter is switched on. All segments and annunciators are, or at least should be, on.

In the mean time we perform some functionality tests. We'll start by checking the program ROM. For this purpose there are 4 routines which calculate a CRC value of each of the four 256 byte memory banks in ROM. Please note that the 8048 can only read data from the current bank, so that explains why there are 4 routines involved. ERROR 1 will be displayed if the CRC should fail. If you ask me, a simple checksum could have done the trick too, a CRC is a bit heavy for this purpose.

Next comes the RAM test. First the registers R0 and R1 are tested because we're going to use them as variables. Then a loop is started to test all remaining 62 bytes of RAM Memory. This test is fairly useless if you ask me. If the RAM did fail the software would probably not have passed the previous CRC test anyway. And if we do find a faulty RAM location we're not even sure if we can actually display it because ERROR 1 is put in RAM first before it is copied to the display.

Finally some counters are tested. We only test to see if they read 0 and remain 0. No tests are made to assure that the counters can really count or that the internal counter in the micro controller is operational. Or to find out that the internal counter can generate interrupts. These tests are equally important to assure a proper operation of the total instrument.
If a faulty timer is found it will be indicated by an error (ERROR 2 ... ERROR 6).


Philips managed to squeeze a complete reciprocal frequency counter in just 1kB of program memory. A remarkable result, considering the wild detours they took and the useless tests they've made. If one would clean up the code a little and omit the useless tests it should even be possible to achieve the same result in just 3/4 kB of ROM.

Despite the remarks on the software, I think that the PM-6668 is a very nice little counter with good accuracy which can be put to good use in every day service and I'm very glad to own one.