[chirp_devel] Baofeng UV-B5 Wide Splits and Cross-Band Programming

Hi All,
This weekend I accidentally discovered that the UV-B5/B6 radios can be programmed with any frequency split across the band and not just the 69.995 MHz maximum offset when programming from the keypad. In addition to that, the radio can also be successfully programmed for cross-band operation.
The following code currently limits CHIRP to programming these radios with maximun offset of 69.995 MHz in a single band with no checking to make sure that the offset doesn't put the TX frequency out of the working band of the radio.
def validate_memory(self, mem): msgs = chirp_common.CloneModeRadio.validate_memory(self, mem)
if (mem.duplex == "split" and abs(mem.freq - mem.offset) > 69995000) \ or (mem.duplex in ["+", "-"] and mem.offset > 69995000): msgs.append(chirp_common.ValidationError( "Max split is 69.995MHz")) return msgs
What I propose to do is change the code to something like the following. It allows programming any split within the VHF or UHF band and any cross-band pair of frequencies. If the user programs an Offset or Split frequency that puts the TX frequency outside of the band limits, an error is displayed.
def validate_memory(self, mem): msgs = chirp_common.CloneModeRadio.validate_memory(self, mem)
valid = False for lo, hi in VALID_BANDS: if mem.duplex == "split": freq=chirp_common.format_freq(mem.offset) _msg = "Offset %s is out of supported range" % freq if lo <= mem.offset < hi: valid = True break elif mem.duplex == "-": freq=chirp_common.format_freq(mem.offset) _msg = "Offset %s is out of supported range" % freq if lo <= mem.freq - mem.offset < hi: valid = True break elif mem.duplex == "+": freq=chirp_common.format_freq(mem.offset) _msg = "Offset %s is out of supported range" % freq if lo <= mem.freq + mem.offset < hi: valid = True break elif not mem.duplex in ["+", "-", "split"]: _msg = " " if lo <= mem.freq < hi: valid = True break if not valid: msgs.append(chirp_common.ValidationError(_msg)) return msgs
My question is...
Is there a more tidy way to code this or should I go ahead and submit something like this?
Thanks, Jim KC9HI

Hi Jim
I would write the code this way (WARNING untested code)
def validate_memory(self, mem): msgs = chirp_common.CloneModeRadio.validate_memory(self, mem)
if mem.duplex == "split": freq = mem.offset elif mem.duplex == "-": freq = mem.freq - mem.offset elif mem.duplex == "+": freq = mem.freq + mem.offset else: msgs.append(chirp_common.ValidationError(" ")) return msgs
valid = False for lo, hi in VALID_BANDS: if lo <= freq < hi: valid = True break
if not valid: _msg = _("Tx freq %s is out of supported range") % chirp_common.format_freq(freq) msgs.append(chirp_common.ValidationError(_msg))
return msgs
We can also think to add this to RadioFeatures.validate_memory as I suppose it's a valid check to be done for any radio that support split.
73 de IZ3GME Marco
On 27/04/2015 00:00, Jim Unroe wrote:
Hi All,
This weekend I accidentally discovered that the UV-B5/B6 radios can be programmed with any frequency split across the band and not just the 69.995 MHz maximum offset when programming from the keypad. In addition to that, the radio can also be successfully programmed for cross-band operation.
The following code currently limits CHIRP to programming these radios with maximun offset of 69.995 MHz in a single band with no checking to make sure that the offset doesn't put the TX frequency out of the working band of the radio.
def validate_memory(self, mem): msgs = chirp_common.CloneModeRadio.validate_memory(self, mem) if (mem.duplex == "split" and abs(mem.freq - mem.offset) > 69995000) \ or (mem.duplex in ["+", "-"] and mem.offset > 69995000): msgs.append(chirp_common.ValidationError( "Max split is 69.995MHz")) return msgs
What I propose to do is change the code to something like the following. It allows programming any split within the VHF or UHF band and any cross-band pair of frequencies. If the user programs an Offset or Split frequency that puts the TX frequency outside of the band limits, an error is displayed.
def validate_memory(self, mem): msgs = chirp_common.CloneModeRadio.validate_memory(self, mem) valid = False for lo, hi in VALID_BANDS: if mem.duplex == "split": freq=chirp_common.format_freq(mem.offset) _msg = "Offset %s is out of supported range" % freq if lo <= mem.offset < hi: valid = True break elif mem.duplex == "-": freq=chirp_common.format_freq(mem.offset) _msg = "Offset %s is out of supported range" % freq if lo <= mem.freq - mem.offset < hi: valid = True break elif mem.duplex == "+": freq=chirp_common.format_freq(mem.offset) _msg = "Offset %s is out of supported range" % freq if lo <= mem.freq + mem.offset < hi: valid = True break elif not mem.duplex in ["+", "-", "split"]: _msg = " " if lo <= mem.freq < hi: valid = True break if not valid: msgs.append(chirp_common.ValidationError(_msg)) return msgs
My question is...
Is there a more tidy way to code this or should I go ahead and submit something like this?
Thanks, Jim KC9HI _______________________________________________ chirp_devel mailing list chirp_devel@intrepid.danplanet.com http://intrepid.danplanet.com/mailman/listinfo/chirp_devel Developer docs: http://chirp.danplanet.com/projects/chirp/wiki/Developers

Hi Marco,
This is exactly what I was looking for. I only had a limited amount of time to test his before work. I had to add a "" to the end of the first line below. And I'm not sure if the "_" prior to the "(" is intentional or a typo.
_msg = _("Tx freq %s is out of supported range") % chirp_common.format_freq(freq)
The one thing I noticed, and I may be overlooking something, is that when invoking " def validate_memory(self, mem):" locally, it seems to replace the "common" one. That's why I had code to check the Rx frequency as well. This seems to let me enter any Rx frequency.
Jim KC9HI

Hi Jim
And I'm not sure if the "_" prior to the "(" is intentional or a typo.
It's intentional: it invokes the translation funtion for the string, IMHO all strings visible to users should be passed to _
_msg = _("Tx freq %s is out of supported range") % chirp_common.format_freq(freq)
The one thing I noticed, and I may be overlooking something, is that when invoking " def validate_memory(self, mem):" locally, it seems to replace the "common" one. That's why I had code to check the Rx frequency as well. This seems to let me enter any Rx frequency.
That's strange: in your validate_memory you call chirp_common.CloneModeRadio.validate_memory which should check for the rx freq to be withing ranges.
But there's a bug in the code I sent: else: msgs.append(chirp_common.ValidationError(" ")) return msgs
should be elif mem.duplex != "": msgs.append(chirp_common.ValidationError( _("Invalid duplex %s") % mem.duplex)) return msgs
73 de IZ3GME Marco

I didn't get to this until late (too late) last night. I should have waited until today after work because I can tell that I will pay for it at work today. ;-)
And I'm not sure if the "_" prior to the "(" is intentional or a typo.
It's intentional: it invokes the translation funtion for the string, IMHO all strings visible to users should be passed to _
I will check into this more to hopefully understand how this works. I just thought the _ was a convention and didn't realize it was being passed to anything. Thanks for the heads up.
The one thing I noticed, and I may be overlooking something, is that when invoking " def validate_memory(self, mem):" locally, it seems to replace the "common" one. That's why I had code to check the Rx frequency as well. This seems to let me enter any Rx frequency.
That's strange: in your validate_memory you call chirp_common.CloneModeRadio.validate_memory which should check for the rx freq to be withing ranges.
Yes. If I key in 600. which is out of range, there is no error to the user. The row is greyed out an unusable, but no error.
In the command window there is this error: "UnboundLocalError: local variable 'freq' referenced before assignment"
I will repeat the current code below...
def validate_memory(self, mem): msgs = chirp_common.CloneModeRadio.validate_memory(self, mem)
if mem.duplex == "split": freq = mem.offset elif mem.duplex == "-": freq = mem.freq - mem.offset elif mem.duplex == "+": freq = mem.freq + mem.offset elif mem.duplex != "": msgs.append(chirp_common.ValidationError( _("Invalid duplex %s") % mem.duplex)) return msgs
valid = False for lo, hi in VALID_BANDS: if lo <= freq < hi: valid = True break
if not valid: _msg = ("Tx freq %s is out of supported range") % \ chirp_common.format_freq(freq) msgs.append(chirp_common.ValidationError(_msg))
return msgs
I believe that none of the initial if/elif statements are matched so when the code reaches " if lo <= freq < hi:", the variable "freq" hasn't been referenced.
There is also nothing to deal with when Duplex is set to "off"
I don't know if I will have time to look into this further after work tonight, but I will try.
Thanks for you input and ideas with this Marco. I like where it is going.
Jim KC9HI

Hi Jim in attach you can find a patch that add the check directly to chirp_common, this way the check will be used by all radios. Obviously the local validate_memory in uv5r driver is not needed anymore. I also had to refine the bruteforce test which was using an invalid tx freq.
The patch is working and passes the automatic tests but I suggest you to deeply test it.
73 de IZ3GME Marco
On 29/04/2015 12:33, Jim Unroe wrote:
I didn't get to this until late (too late) last night. I should have waited until today after work because I can tell that I will pay for it at work today. ;-)
And I'm not sure if the "_" prior to the "(" is intentional or a typo.
It's intentional: it invokes the translation funtion for the string, IMHO all strings visible to users should be passed to _
I will check into this more to hopefully understand how this works. I just thought the _ was a convention and didn't realize it was being passed to anything. Thanks for the heads up.
The one thing I noticed, and I may be overlooking something, is that when invoking " def validate_memory(self, mem):" locally, it seems to replace the "common" one. That's why I had code to check the Rx frequency as well. This seems to let me enter any Rx frequency.
That's strange: in your validate_memory you call chirp_common.CloneModeRadio.validate_memory which should check for the rx freq to be withing ranges.
Yes. If I key in 600. which is out of range, there is no error to the user. The row is greyed out an unusable, but no error.
In the command window there is this error: "UnboundLocalError: local variable 'freq' referenced before assignment"
I will repeat the current code below...
def validate_memory(self, mem): msgs = chirp_common.CloneModeRadio.validate_memory(self, mem) if mem.duplex == "split": freq = mem.offset elif mem.duplex == "-": freq = mem.freq - mem.offset elif mem.duplex == "+": freq = mem.freq + mem.offset elif mem.duplex != "": msgs.append(chirp_common.ValidationError( _("Invalid duplex %s") % mem.duplex)) return msgs valid = False for lo, hi in VALID_BANDS: if lo <= freq < hi: valid = True break if not valid: _msg = ("Tx freq %s is out of supported range") % \ chirp_common.format_freq(freq) msgs.append(chirp_common.ValidationError(_msg)) return msgs
I believe that none of the initial if/elif statements are matched so when the code reaches " if lo <= freq < hi:", the variable "freq" hasn't been referenced.
There is also nothing to deal with when Duplex is set to "off"
I don't know if I will have time to look into this further after work tonight, but I will try.
Thanks for you input and ideas with this Marco. I like where it is going.
Jim KC9HI _______________________________________________ chirp_devel mailing list chirp_devel@intrepid.danplanet.com http://intrepid.danplanet.com/mailman/listinfo/chirp_devel Developer docs: http://chirp.danplanet.com/projects/chirp/wiki/Developers

On Thu, Apr 30, 2015 at 6:46 AM, Marco Filippi IZ3GME iz3gme.marco@gmail.com wrote:
Hi Jim in attach you can find a patch that add the check directly to chirp_common, this way the check will be used by all radios. Obviously the local validate_memory in uv5r driver is not needed anymore. I also had to refine the bruteforce test which was using an invalid tx freq.
The patch is working and passes the automatic tests but I suggest you to deeply test it.
73 de IZ3GME Marco
Marco,
I just got home and imported this patch. From the testing that I have done with the uvb5.py driver (with the local validate_memory disabled) and the anytone_ht.py driver, this appears to work perfectly.
If you would submit this, I will take care of getting the validate_memory being removed from the uvb5.py driver.
Thank you for you collaboration with this. The result is much better than I had hoped for.
Jim KC9HI

Hey,
Just curious,
I didn't know this was able to be done on the uv5b
Any chance the uv5r can do this...
Bret

On Thu, Apr 30, 2015 at 5:43 PM, Bret Hedrington Bret.Hedrington@brethedrington.com wrote:
Hey,
Just curious,
I didn't know this was able to be done on the uv5b
Any chance the uv5r can do this...
Bret
Bret, I've always known that the UV-B5/B6 radio was capable of being programmed with a 2.5 KHz resolution even though the OEM software was limited to 5 KHz resolution.
It has always been thought (at least by me) that the UV-B5 was limited to a maximum split of 69.95 MHz and that no cross band operation was possible. Last weekend I accidentally discovered that the odd-split can be software programmed across the whole width of either band and cross-band operation was also programmable anywhere within the two bands.
The UV-5R (and its many variants) have always (since early 2012) has been capable of operating with any split and cross-band within its operating ranges. And CHIRP has supported programming it since UV-5R support was added in the summer of 2012.
Jim KC9HI

Great!
Thanks for you years of time!
Mucho Garacias!
On Apr 30, 2015, at 6:17 PM, "Jim Unroe" rock.unroe@gmail.com wrote:
On Thu, Apr 30, 2015 at 5:43 PM, Bret Hedrington Bret.Hedrington@brethedrington.com wrote:
Hey,
Just curious,
I didn't know this was able to be done on the uv5b
Any chance the uv5r can do this...
Bret
Bret, I've always known that the UV-B5/B6 radio was capable of being programmed with a 2.5 KHz resolution even though the OEM software was limited to 5 KHz resolution.
It has always been thought (at least by me) that the UV-B5 was limited to a maximum split of 69.95 MHz and that no cross band operation was possible. Last weekend I accidentally discovered that the odd-split can be software programmed across the whole width of either band and cross-band operation was also programmable anywhere within the two bands.
The UV-5R (and its many variants) have always (since early 2012) has been capable of operating with any split and cross-band within its operating ranges. And CHIRP has supported programming it since UV-5R support was added in the summer of 2012.
Jim KC9HI _______________________________________________ chirp_devel mailing list chirp_devel@intrepid.danplanet.com http://intrepid.danplanet.com/mailman/listinfo/chirp_devel Developer docs: http://chirp.danplanet.com/projects/chirp/wiki/Developers
participants (3)
-
Bret Hedrington
-
Jim Unroe
-
Marco Filippi IZ3GME