# Copyright 2013 Ben Weiss # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . from chirp import chirp_common, directory, memmap from chirp import bitwise import time MEM_FORMAT = """ struct { u8 unknown1; u8 unknown2; u8 batterysaver:1, unknownbits1:4, mute_pll_unlock:1, unknownbits2:2; u8 unknown4; u8 unknown5; u8 unknown6; u8 batterysaverdelay; u8 unknown8; u8 unknown9; u8 unknown10; u8 unknown11; u8 unknown12; u8 unknown13; u8 unknown14; u8 unknown15; u8 unknown16; u8 unknown17; u8 unknown18; u8 unknown19; u8 unknown20; u8 pqc_all_call:1, unknownbits3:3, qc_decode_output:1, trunking_interface:1, unknonwnbits4:1, priority_from_scan:1; u8 unknown22; u8 tx_timeout_time; u8 unknown24; u8 qc_tone_reversal_default:1, unknownbits5:7; u8 turn_off_time_qc; u8 turn_off_time_dqc; u8 unknown28; u8 unknown29; u8 unknown30; u8 unknown31; u8 unknown32; u8 priority_scan_look_time; u8 scan_resume_delay; u8 tx_busy_inhibit_override_time; u8 unknown36; u8 unknown37; u8 unknown38; u8 unknown39; u8 unknown40; u8 unknown41; u8 unknown42; u8 unknown43; u8 unknown44; u8 unknown45; u8 unknown46; u8 unknown47; u8 unknown48; u8 unknown49; u8 unknown50; u8 unknown51; u8 special_qc_code; u16 pqc_443_tone_1; u16 pqc_443_tone_2; u8 unknownbits7:4, monitor_button_type:1, unknownbits8:3; u8 unknown58; u8 unknown59; u8 unknown60; u8 unknown61; u8 unknown62; u8 number_of_channels; } radiosettings; #seekto 0x004b; struct{ bbcd rx_freq[3]; bbcd tx_freq[3]; bbcd qc_tone; bbcd dqc_tone; u8 tone_type; u8 sq_tightener_factor; u8 chan_readout_allowed:1, chan_mon_lockout:1, time_out_timer:1, tx_inhibit:1, pqc_respond:1, scan_resume_delay:1, high_power:1, special_mode_output:1; } channeldata[11]; #seekto 0x00f0; struct{ bbcd serial_number[3]; u24 factory_date; u16 field_code; u16 field_date; u32 customer_id_number; u8 unknown255; u8 unknown256; bbcd pattern[1]; } radiodata; """ def do_download(radio): """This is your download function""" serial = radio.pipe serial.setTimeout(1) for _x in range(15): serial.write("?") time.sleep(.05) serial.write("G") # Our radio is just a simple download of 257 bytes # from the serial port. Do that one byte at a time and # store them in the memory map data = "" for _i in range(0, 257): data += serial.read(1) _do_status(radio, _i) return memmap.MemoryMap(data) def do_upload(radio): """This is your upload function""" # NOTE: Remove this in your real implementation! raise Exception("This template driver does not really work!") # Get the serial port connection serial = radio.pipe # Our radio is just a simple upload of 257 bytes # to the serial port. Do that one byte at a time, reading # from our memory map for i in range(0, 257): serial.write(radio.get_mmap()[i]) def _do_status(radio, block): status = chirp_common.Status() status.msg = "Cloning" status.cur = block status.max = radio.get_memsize() radio.status_fn(status) # Uncomment this to actually register this radio in CHIRP @directory.register class RTX450(chirp_common.CloneModeRadio): """Ritron Patriot RTX-450""" VENDOR = "Ritron" MODEL = "RTX-450" BAUD_RATE = 1200 #TODO: 8N2 setting, how?? Radio seems happy with 8N1 _memsize = 257 # Return information about this radio's features, including # how many memories it has, what bands it supports, etc def get_features(self): rf = chirp_common.RadioFeatures() rf.has_bank = False rf.memory_bounds = (0, 11) rf.valid_bands = [(420000000, 512000000)]# It'll program anywhere, whether the VCO is tuned for the desired range is another issue..... rf.has_settings = True rf.has_dtcs_polarity = True rf.has_mode = False rf.has_offset = False rf.has_name = False rf.has_tuning_step = False rf.has_cross = True rf.can_odd_split = True return rf # Do a download of the radio from the serial port def sync_in(self): self._mmap = do_download(self) self._memobj = bitwise.parse(MEM_FORMAT, self._mmap) # Do an upload of the radio to the serial port def sync_out(self): do_upload(self) # Return a raw representation of the memory object, which # is very helpful for development def get_raw_memory(self, number): return repr(self._memobj.memory[number]) # Extract a high-level memory object from the low-level memory map # This is called to populate a memory in the UI def get_memory(self, number): # Get a low-level memory object mapped to the image _mem = self._memobj.memory[number] # Create a high-level memory object to return to the UI mem = chirp_common.Memory() mem.number = number # Set the memory number mem.freq = int(_mem.freq) # Convert your low-level frequency # to Hertz mem.name = str(_mem.name).rstrip() # Set the alpha tag # We'll consider any blank (i.e. 0MHz frequency) to be empty if mem.freq == 0: mem.empty = True return mem # Store details about a high-level memory to the memory map # This is called when a user edits a memory in the UI def set_memory(self, mem): # Get a low-level memory object mapped to the image _mem = self._memobj.memory[mem.number] _mem.freq = mem.freq # Convert to low-level frequency # representation _mem.name = mem.name.ljust(8)[:8] # Store the alpha tag