diff --git a/chirp/drivers/uv5r.py b/chirp/drivers/uv5r.py index 28e052541..8e6b1c2a0 100644 --- a/chirp/drivers/uv5r.py +++ b/chirp/drivers/uv5r.py @@ -193,8 +193,10 @@ txpower3:2; } vfob; -#seekto 0x0F56; -u16 fm_presets; +#seekto 0x0F48; // some new radios do not support this feature +char bcstfmlo[14]; // broadcast FM 65-75 MHz band +u16 fm_presets; // broadcast FM frequency +char bcstfmhi[14]; // broadcast FM 75-108 MHz band #seekto 0x1008; struct { @@ -473,7 +475,10 @@ def _get_radio_firmware_version(radio): else: block1 = _read_block(radio, 0x1E80, 0x40, True) block2 = _read_block(radio, 0x1EC0, 0x40, False) + block3 = _read_block(radio, 0x0F40, 0x40, False) version = block2[48:62] + brdcstfm = block3[0:30] + return version, brdcstfm return version @@ -517,7 +522,10 @@ def _ident_radio(radio): def _do_download(radio): data = _ident_radio(radio) - radio_version = _get_radio_firmware_version(radio) + if radio.MODEL == "BJ-UV55": + radio_version = _get_radio_firmware_version(radio) + else: + radio_version, radio_fm = _get_radio_firmware_version(radio) LOG.info("Radio Version is %s" % repr(radio_version)) if b"HN5RV" in radio_version: @@ -591,10 +599,16 @@ def _do_upload(radio): raise errors.RadioError("Image not supported by radio") image_version = _firmware_version_from_image(radio) - radio_version = _get_radio_firmware_version(radio) + if radio.MODEL == "BJ-UV55": + radio_version = _get_radio_firmware_version(radio) + else: + radio_version, radio_fm = _get_radio_firmware_version(radio) LOG.info("Image Version is %s" % repr(image_version)) LOG.info("Radio Version is %s" % repr(radio_version)) + imagev_matched_radiov = image_version == radio_version + _skip_aux_block = False + # default ranges _ranges_main_default = [ (0x0008, 0x0CF8), @@ -602,44 +616,54 @@ def _do_upload(radio): (0x0E08, 0x1808) ] _ranges_aux_default = [ - (0x1EC0, 0x1EF0), + (0x1EC0, 0x1EF0) # 6 key power-on & welcome messages + ] + + # skip broadcast fm range + _ranges_main_no_fm = [ + (0x0008, 0x0CF8), + (0x0D08, 0x0DF8), + (0x0E08, 0x0F48), + (0x0F68, 0x1808) ] # extra aux ranges _ranges_aux_extra = [ - (0x1F60, 0x1F70), - (0x1F80, 0x1F90), - (0x1FC0, 0x1FE0) + (0x1F60, 0x1F70), # squelch thresholds - vhf + (0x1F80, 0x1F90), # squelch thresholds - uhf + (0x1FC0, 0x1FE0) # band limits ] - if b"HN5RV" in radio_version: - # not safe to upload 'aux block', skip it. + # set default ranges + ranges_main = _ranges_main_default + ranges_aux = _ranges_aux_default + + # check destinaton radio for invalid bcst FM data + if b"\xFF" in radio_fm: + # 0x0F48-0x0F65 contains invalid data + # This radio is likely to 'break' the Aux block if it is changed. + # The safest thing to do is to skip uploading of the Aux block. + ranges_main = _ranges_main_no_fm _skip_aux_block = True - else: - _skip_aux_block = False + # check source image for invalid bcst FM data + elif "\xFF" in str(radio._memobj.bcstfmlo) or \ + "\xFF" in str(radio._memobj.bcstfmhi): + # 0x0F48-0x0F65 contains invalid data + # This image appears to be from a radio that was likely to 'break' + # the Aux block if it is changed (and could be broken). + # The safest thing to do is to skip uploading of the Aux block. + ranges_main = _ranges_main_no_fm + _skip_aux_block = True + # check if radio and image firmware versions match + elif imagev_matched_radiov: + # matched - allow all safe Aux block ranges + ranges_aux = _ranges_aux_default + _ranges_aux_extra if radio._all_range_flag: _skip_aux_block = False - image_matched_radio = True ranges_main = radio._ranges_main ranges_aux = radio._ranges_aux LOG.warning('Sending all ranges to radio as instructed') - elif image_version == radio_version: - image_matched_radio = True - ranges_main = _ranges_main_default - ranges_aux = _ranges_aux_default + _ranges_aux_extra - elif any(type in radio_version for type in radio._basetype): - image_matched_radio = False - ranges_main = _ranges_main_default - ranges_aux = _ranges_aux_default - else: - msg = ("The upload was stopped because the firmware " - "version of the image (%s) does not match that " - "of the radio (%s).") - raise errors.RadioError(msg % (image_version, radio_version)) - - if not radio._aux_block: - image_matched_radio = True # Main block mmap = radio.get_mmap().get_byte_compatible() @@ -663,13 +687,6 @@ def _do_upload(radio): addr = 0x1808 + (i - 0x1EC0) _send_block(radio, i, mmap[addr:addr + 0x10]) - if not image_matched_radio: - msg = ("Upload finished, but the 'Other Settings' " - "could not be sent because the firmware " - "version of the image (%s) does not match " - "that of the radio (%s).") - raise errors.RadioError(msg % (image_version, radio_version)) - if radio._all_range_flag: radio._all_range_flag = False LOG.warning('Sending all ranges to radio has completed') @@ -677,6 +694,14 @@ def _do_upload(radio): "This is NOT an error.\n" "The upload has finished successfully.\n" "Please restart CHIRP.") + return + + if radio._aux_block and not imagev_matched_radiov: + msg = ("This is NOT an error. The upload finished successfully.\n" + "The 'Other Settings' and 'Service Settings' were skipped " + "because the firmware version of the image (%s) does not " + "match that of the radio (%s).") + raise errors.RadioError(msg % (image_version, radio_version)) UV5R_POWER_LEVELS = [chirp_common.PowerLevel("High", watts=4.00), @@ -1104,6 +1129,7 @@ def _my_upper_band(self): return band_tag def _get_settings(self): + _mem = self._memobj _ani = self._memobj.ani _fm_presets = self._memobj.fm_presets _settings = self._memobj.settings @@ -1111,7 +1137,9 @@ def _get_settings(self): _vfoa = self._memobj.vfoa _vfob = self._memobj.vfob _wmchannel = self._memobj.wmchannel - HN5RV = "HN5RV" in str(self._memobj.firmware_msg.line1) + _has_fmradio = (str(_mem.bcstfmlo) == " FM 65-75M" and + str(_mem.bcstfmhi) == " FM 76-108M") + basic = RadioSettingGroup("basic", "Basic Settings") advanced = RadioSettingGroup("advanced", "Advanced Settings") @@ -1431,7 +1459,7 @@ def _filter(name): 'to them. Please see bug #10505 on the CHIRP ' 'issue tracker for more details.') for setting in aux_settings: - if HN5RV: + if not _has_fmradio: setting.set_warning(hn5rv_warn) other.append(setting) @@ -1608,29 +1636,30 @@ def apply_offset(setting, obj): STEP_LIST, STEP_LIST[_vfob.step])) workmode.append(rs) - fm_preset = RadioSettingGroup("fm_preset", "FM Radio Preset") - group.append(fm_preset) - - # broadcast FM settings - value = self._memobj.fm_presets - value_shifted = ((value & 0x00FF) << 8) | ((value & 0xFF00) >> 8) - if value_shifted >= 65.0 * 10 and value_shifted <= 108.0 * 10: - # storage method 3 (discovered 2022) - self._bw_shift = True - preset = value_shifted / 10.0 - elif value >= 65.0 * 10 and value <= 108.0 * 10: - # storage method 2 - preset = value / 10.0 - elif value <= 108.0 * 10 - 650: - # original storage method (2012) - preset = value / 10.0 + 65 - else: - # unknown (undiscovered method or no FM chip?) - preset = False - if preset: - rs = RadioSettingValueFloat(65, 108.0, preset, 0.1, 1) - rset = RadioSetting("fm_presets", "FM Preset(MHz)", rs) - fm_preset.append(rset) + if _has_fmradio: + fm_preset = RadioSettingGroup("fm_preset", "FM Radio Preset") + group.append(fm_preset) + + # broadcast FM settings + value = self._memobj.fm_presets + value_shifted = ((value & 0x00FF) << 8) | ((value & 0xFF00) >> 8) + if value_shifted >= 65.0 * 10 and value_shifted <= 108.0 * 10: + # storage method 3 (discovered 2022) + self._bw_shift = True + preset = value_shifted / 10.0 + elif value >= 65.0 * 10 and value <= 108.0 * 10: + # storage method 2 + preset = value / 10.0 + elif value <= 108.0 * 10 - 650: + # original storage method (2012) + preset = value / 10.0 + 65 + else: + # unknown (undiscovered method or no FM chip?) + preset = False + if preset: + rs = RadioSettingValueFloat(65, 108.0, preset, 0.1, 1) + rset = RadioSetting("fm_presets", "FM Preset(MHz)", rs) + fm_preset.append(rset) dtmf = RadioSettingGroup("dtmf", "DTMF Settings") group.append(dtmf) @@ -1743,7 +1772,7 @@ def apply_code(setting, obj): RadioSettingValueInteger( 0, 123, getattr(_obj, "sql%i" % (index)))) - if HN5RV: + if not _has_fmradio: rs.set_warning(hn5rv_warn) service.append(rs)