Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for GA510v2 #1074

Merged
merged 4 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions chirp/drivers/baofeng_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ def _rawrecv(radio, amount):
raise errors.RadioError(msg)

if len(data) != amount:
LOG.debug('Wanted %i, got %i: %s',
amount, len(data), util.hexprint(data))
msg = "Error reading data from radio: not the amount of data we want."
raise errors.RadioError(msg)

Expand Down
98 changes: 56 additions & 42 deletions chirp/drivers/baofeng_uv17.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ def _get_memory_size(radio):
def _get_memory_map(radio):
# Get memory map
memory_map = []
mem_size = _get_memory_size(radio)
if radio._magic_memsize:
mem_size = _get_memory_size(radio)
else:
mem_size = radio._radio_memsize
if mem_size != radio._radio_memsize:
raise errors.RadioError("Incorrect radio model or model not supported "
"(memory size doesn't match)")
Expand All @@ -60,7 +63,9 @@ def _get_memory_map(radio):

def _download(radio):
"""Get the memory map"""
baofeng_uv17Pro._do_ident(radio)
if not radio._DETECTED_BY:
# The GA510v2 (at least) is detected, and thus has already done ident
baofeng_uv17Pro._do_ident(radio)
data = b""
memory_map = _get_memory_map(radio)

Expand All @@ -73,6 +78,8 @@ def _download(radio):
for block_number in radio.BLOCK_ORDER:
if block_number not in memory_map:
# Memory block not found.
LOG.error('Block %i (0x%x) not in memory map: %s',
block_number, block_number, memory_map)
raise errors.RadioError('Radio memory is corrupted. ' +
'Fix this by uploading a backup image ' +
'to the radio.')
Expand Down Expand Up @@ -189,8 +196,7 @@ class UV17(baofeng_uv17Pro.UV17Pro):
LIST_MODE = ["Name", "Frequency"]
CHANNELS = 999

MEM_FORMAT = """
#seekto 0x0030;
MEM_DEFS = """
struct channel {
lbcd rxfreq[4];
lbcd txfreq[4];
Expand All @@ -209,28 +215,10 @@ class UV17(baofeng_uv17Pro.UV17Pro):
scan:1;
u8 unknown4;
};

struct {
struct channel mem[252];
} mem1;

#seek 0x10;
struct {
struct channel mem[255];
} mem2;

#seek 0x10;
struct {
struct channel mem[255];
} mem3;

#seek 0x10;
struct {
struct channel mem[237];
} mem4;

#seekto 0x7000;
struct {
struct channelname {
char name[11];
};
struct settings {
u8 powerondistype;
u8 unknown0[15];
char boottext1[10];
Expand Down Expand Up @@ -261,7 +249,39 @@ class UV17(baofeng_uv17Pro.UV17Pro):
u8 unknown9:6,
chbdistype:1,
chadistype:1;
} settings;
};
struct ani {
u8 unknown[5];
u8 code[5];
};
struct pttid {
u8 code[5];
};
"""

MEM_LAYOUT = """
#seekto 0x0030;
struct {
struct channel mem[252];
} mem1;

#seek 0x10;
struct {
struct channel mem[255];
} mem2;

#seek 0x10;
struct {
struct channel mem[255];
} mem3;

#seek 0x10;
struct {
struct channel mem[237];
} mem4;

#seekto 0x7000;
struct settings settings;

struct vfo {
lbcd rxfreq[4];
Expand Down Expand Up @@ -289,27 +309,18 @@ class UV17(baofeng_uv17Pro.UV17Pro):
} vfo;

#seekto 0x4000;
struct channelname {
char name[11];
};

struct channelname names1[372];
#seek 0x4;
struct channelname names2[372];
#seek 0x4;
struct channelname names3[255];

#seekto 0x8000;
struct {
u8 code[5];
} pttid[15];

struct {
u8 unknown[5];
u8 code[5];
} ani;
struct pttid pttid[15];

struct ani ani;
"""
MEM_FORMAT = MEM_DEFS + MEM_LAYOUT

def _make_frame(self, cmd, addr, length, data=""):
"""Pack the info in the header format"""
Expand Down Expand Up @@ -395,7 +406,7 @@ def decode_tone(self, val):

return mode, xval, pol

def get_raw_memory(self, number):
def _get_raw_memory(self, number):
# The flash memory contains page_numbers
# This is probably to do wear leveling on the memory
# These numbers are needed, but make the channel memory
Expand All @@ -413,6 +424,9 @@ def get_raw_memory(self, number):
_mem = self._memobj.mem1.mem[number]
return _mem

def get_raw_memory(self, number):
return repr(self._get_raw_memory(number))

def get_channel_name(self, number):
number = number - 1
if number >= 744:
Expand All @@ -425,7 +439,7 @@ def get_channel_name(self, number):
return _name

def get_memory(self, number):
_mem = self.get_raw_memory(number)
_mem = self._get_raw_memory(number)
_nam = self.get_channel_name(number)

mem = chirp_common.Memory()
Expand Down Expand Up @@ -456,7 +470,7 @@ def encode_tone(self, memtone, mode, tone, pol):
memtone.set_value(memtone + 0x4000)

def set_memory(self, mem):
_mem = self.get_raw_memory(mem.number)
_mem = self._get_raw_memory(mem.number)
_nam = self.get_channel_name(mem.number)

if mem.empty:
Expand Down
11 changes: 7 additions & 4 deletions chirp/drivers/baofeng_uv17Pro.py
Original file line number Diff line number Diff line change
Expand Up @@ -1191,11 +1191,14 @@ def get_memory_common(self, _mem, name, mem):

mem.name = str(name).replace('\xFF', ' ').replace('\x00', ' ').rstrip()

def get_raw_memory(self, number):
def _get_raw_memory(self, number):
return self._memobj.memory[number - 1]

def get_raw_memory(self, number):
return repr(self._get_raw_memory(number))

def get_memory(self, number):
_mem = self.get_raw_memory(number)
_mem = self._get_raw_memory(number)

mem = chirp_common.Memory()
mem.number = number
Expand All @@ -1205,7 +1208,7 @@ def get_memory(self, number):
return mem

def unsplit_txfreq(self, mem):
_mem = self.get_raw_memory(mem.number)
_mem = self._get_raw_memory(mem.number)
if mem.duplex == "off":
for i in range(0, 4):
_mem.txfreq[i].set_raw(b"\xFF")
Expand Down Expand Up @@ -1251,7 +1254,7 @@ def set_memory_common(self, mem, _mem):
_mem.scode = self._scode_offset

def set_memory(self, mem):
_mem = self.get_raw_memory(mem.number)
_mem = self._get_raw_memory(mem.number)

_mem.set_raw(b"\x00"*16 + b"\xff" * 16)

Expand Down
90 changes: 88 additions & 2 deletions chirp/drivers/ga510.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2011 Dan Smith <dsmith@danplanet.com>
# Copyright 2024 Dan Smith <dsmith@danplanet.com>
# Portions copyright 2023 Dave Liske <dave@micuisine.com>
# Portions copyright 2020 by Jiauxn Yang <jiaxun.yang@flygoat.com>
#
Expand All @@ -21,6 +21,8 @@
from chirp import bitwise
from chirp import chirp_common
from chirp import directory
from chirp.drivers import baofeng_uv17
from chirp.drivers import baofeng_uv17Pro
from chirp import errors
from chirp import memmap
from chirp.settings import RadioSetting, RadioSettingGroup, RadioSettings
Expand Down Expand Up @@ -60,7 +62,7 @@ def start_program(radio):


def do_download(radio):
ident = start_program(radio)
# No start_program() here because it was done in detect_from_serial()

s = chirp_common.Status()
s.msg = 'Downloading'
Expand Down Expand Up @@ -355,6 +357,24 @@ class RadioddityGA510Radio(chirp_common.CloneModeRadio):

_gmrs = False

@classmethod
def detect_from_serial(cls, pipe):
for rcls in reversed(cls.detected_models()):
pipe.baudrate = rcls.BAUD_RATE
radio = rcls(pipe)
try:
if isinstance(radio, baofeng_uv17Pro.UV17Pro):
ident = baofeng_uv17Pro._do_ident(radio)
else:
ident = start_program(radio)
except errors.RadioError:
LOG.debug('No response from radio with %s', rcls)
pipe.read(256)
continue
if ident:
return rcls
raise errors.RadioError('No response from radio')

def sync_in(self):
try:
data = do_download(self)
Expand Down Expand Up @@ -1074,3 +1094,69 @@ def _set_mem(self, num):

def _set_nam(self, number):
return self._memobj.names[number - 1]


@directory.register
@directory.detected_by(RadioddityGA510Radio)
class RadioddityGA510v2(baofeng_uv17.UV17):
"""Baofeng UV-17"""
VENDOR = "Radioddity"
MODEL = "GA-510"
VARIANT = "V2"

MODES = ["FM", "NFM"]
BLOCK_ORDER = [2, 4, 6, 16, 24]
MEM_TOTAL = 0x6000
WRITE_MEM_TOTAL = 0x6000
BLOCK_SIZE = 0x40
BAUD_RATE = 57600

_magic = b"PSEARCH"
_magic_response_length = 8
_magics = [(b"PASSSTA", 3), (b"SYSINFO", 1),
(b"\x56\x00\x00\x0A\x0D", 13), (b"\x06", 1),
(b"\x56\x00\x10\x0A\x0D", 13), (b"\x06", 1),
(b"\x56\x00\x20\x0A\x0D", 13), (b"\x06", 1),
(b"\x56\x00\x00\x00\x0A", 11), (b"\x06", 1),
(b"\xFF\xFF\xFF\xFF\x0C\x44\x4d\x52\x31\x37\x30\x32", 1),
(b"\02", 8), (b"\x06", 1)]
_magic_memsize = []
_radio_memsize = 0x10000
_magics2 = []
_fingerprint = b"\x06DMR1702"
_scode_offset = 1

_tri_band = False
POWER_LEVELS = [chirp_common.PowerLevel("Low", watts=1.00),
chirp_common.PowerLevel("Medium", watts=5.00),
chirp_common.PowerLevel("High", watts=10.00)]

LENGTH_NAME = 11
SCODE_LIST = ["%s" % x for x in range(1, 16)]
SQUELCH_LIST = ["Off"] + list("123456789")
LIST_POWERON_DISPLAY_TYPE = ["Full", "Message", "Voltage"]
LIST_TIMEOUT = ["Off"] + ["%s sec" % x for x in range(15, 615, 15)]
LIST_VOICE = ["Chinese", "English"]
LIST_BACKLIGHT_TIMER = ["Always On"] + ["%s sec" % x for x in range(1, 11)]
LIST_MODE = ["Name", "Frequency"]
CHANNELS = 128

MEM_LAYOUT = """
#seekto 0x1000;
struct settings settings;

#seekto 0x2000;
struct pttid pttid[15];
struct ani ani;

#seekto 0x3040;
struct {
struct channel mem[128];
} mem1;

#seekto 0x400B;
struct channelname names1[128];
"""
MEM_FORMAT = baofeng_uv17.UV17.MEM_DEFS + MEM_LAYOUT

_has_workmode_support = False
7 changes: 4 additions & 3 deletions tests/Python3_Driver_Testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@
| <a name="Radioddity_DB25-G"></a> Radioddity_DB25-G | [@KC9HI](https://github.com/KC9HI) | 11-Nov-2022 | Yes | 0.17% |
| <a name="Radioddity_GA-2S"></a> Radioddity_GA-2S | [@KC9HI](https://github.com/KC9HI) | 4-Dec-2022 | Yes | 0.19% |
| <a name="Radioddity_GA-510"></a> Radioddity_GA-510 | [@kk7ds](https://github.com/kk7ds) | 21-Oct-2022 | Yes | 0.42% |
| <a name="Radioddity_GA-510_V2"></a> Radioddity_GA-510_V2 | | | Yes | |
| <a name="Radioddity_GS-5B"></a> Radioddity_GS-5B | [@lunapiercook](https://github.com/lunapiercook) | 5-Mar-2023 | Yes | |
| <a name="Radioddity_R2"></a> Radioddity_R2 | [@KC9HI](https://github.com/KC9HI) | 17-Dec-2022 | Yes | 0.04% |
| <a name="Radioddity_UV-5G"></a> Radioddity_UV-5G | [@KC9HI](https://github.com/KC9HI) | 18-Nov-2022 | Yes | 0.47% |
Expand Down Expand Up @@ -466,11 +467,11 @@
| <a name="Zastone_ZT-X6"></a> Zastone_ZT-X6 | [Implied by Retevis_RT22](#user-content-Retevis_RT22) | 9-Dec-2022 | Yes | 0.11% |
## Stats

**Drivers:** 463
**Drivers:** 464

**Tested:** 87% (406/57) (93% of usage stats)
**Tested:** 87% (406/58) (93% of usage stats)

**Byte clean:** 91% (424/39)
**Byte clean:** 91% (425/39)

## Meaning of this testing

Expand Down
Binary file added tests/images/Radioddity_GA-510_V2.img
Binary file not shown.
Loading