Tuesday, February 22, 2011

WX-1 baud rate fix

On Thursday I wrote about how my WX-1 APRS weather station was not being received by my TH-D72 and the PIC TNC because the baud rate was slightly fast, and of my unsuccessful attempt to fix it. Glenn W9IQ offered to take a look at the PIC source code and see if there was an easy fix. I sent him a link to the code and a day later I got a reply back. Glenn's suggestion solved the problem perfectly. But he didn't just tell me what to change, he explained what the code did and how it worked. I thought that his explanation would be of interest to anyone trying to understand how packet tones are generated using a PIC, so with his permission I am copying it here.

"The baud rate is determined by an interrupt service routine. The interrupt is driven by Timer 0 (TMR0) that is configured to use the instruction clock as its input (frequency of Y1 divided by 4). The input of TMR0 is also initialized to have a divide by 32 prescaler (the code comment says 16 but that is wrong). So at this point the timer is being driven by the frequency of Y1 divided by 128 or (20 MHz / 128) =  156.25 kHZ or a period of 6.4 uS.

Now the math and routines get a little more complicated. The interrupt is serviced by the code in the "packet" file. This code sets the TMR0 count to start at a value of 127. This TMR0 count will tick up one count every 6.2 uS (the clock from the output of the prescaler). When the timer count rolls over from 255 to 0, the interrupt is triggered.

At first glance, it would appear that this would generate an interrupt every 129 counts or 825.6 uS (6.4 uS * 129). That would seem to put the interrupt at roughly 1211 Hertz ( 1/825.6 uS). But this is not correct due to the way the author wrote the interrupt routine plus a small nuance of how a PIC handles the reset of the prescaled interrupt timer.

The interrupt service routine in "packet" executes 6 instructions before resetting the interrupt timer to a value of 127. Each instruction takes 4 clock cycles so this adds another 1.2 uS to the time between interrupts. In addition, when the prescaled interrupt timer register is written, there are another 4 instruction cycles of delay before the timer starts to run again. This is another 0.8 uS added to the interrupt time. So we now have an interrupt cycle of 825.6 uS + 1.2 uS + 0.8 uS totaling 827.6 uS or 1208 Hz. I believe this is what you measured as the current baud rate from your board.

Improving this is fairly straight forward. The interrupt goal is 1200 Hz or 833.3 uS. If we change the TMR0 count to 126 instead of 127, this will add another 6.4 uS to the interrupt period. This would give us 827.6 uS + 6.4 uS = 834 uS. Then if we eliminate one instruction in the interrupt routine, we eliminate a 0.2 uS delay for a total interrupt time of 834 uS - 0.2 uS = 833.8 uS or 1199.3 Hz.

This change is effected in the code located in the "packet" file. Look for the following code fragment:

        movlw        0x80        ; 128 decimal
        sublw        0xFF        ; subtract 128 from 255 to get TMR0
        movwf        TMR0        ; move it to the TMR0 register

Change this code fragment to read like this:

        movlw        0x7E        ; 126 decimal
        movwf        TMR0        ; move it into the TMR0 register

Recompile everything and reload the processor and you should see the baud rate drop as described."

When I ran the modified code the baud rate dropped from 1207/8 baud to 1198/9 baud which is pretty much just as Glenn predicted. The weather station is now being received by the Kenwood TH-D72 as well as my other APRS radios. It can also now be received using the PIC TNC though the level of the receiver audio is critical and unfortunately not the same as that needed to decode the VX-8R. I think that is because the maximum deviation I can get out of the Radiometrix transmitter module is a bit on the low side.

I had an anxious couple of minutes when I found that although the D72 was decoding the packets it was rejecting them as invalid. This turned out to be because the position co-ordinates had a lower case n for North and w for west: In my haste to see what effect the changed code had I had entered the settings carelessly, though the other radios didn't seem to mind. That was soon fixed.

The WX-1 weather station is now back in position beaconing the temperature, humidity and pressure as G4ILO-5. I would like once again to express my thanks to Glenn W9IQ for acting in the finest spirit of ham radio and helping me out with this.

1 comment:

Lynn (D) said...

"32 prescaler (the code comment says 16 but that is wrong)".

A friend of mine is fond of stating that "I've never seen a comment execute yet". And some managers still insist on useless English descriptions of what any good programmer needs to read in the code because that's the only "real" thing about the program.

You might want to post the upper/lower-case n/w and the D72 not liking the packets to the aprssig. Bob is fond of thinking that those two bits are "available" for flagging various things. It'd be quite the rub for him to see that his favorite brand is picky about the case of the coordinates.