def set_memory(self, memory): if memory.number < 0 or memory.number > self._upper: raise errors.InvalidMemoryLocation( "Number must be between 0 and %i" % self._upper) spec = self._make_mem_spec(memory) spec = "".join(spec) r1 = command(self.pipe, *self._cmd_set_memory(memory.number, spec)) if not iserr(r1): memory.name = memory.name.rstrip() self._memcache[memory.number] = memory # if we're tuned to the channel, reload it r1 = command(self.pipe, *self._cmd_cur_memory(memory.number)) if not iserr(r1): pattern = re.compile("MC([0-9]{3})") match = pattern.search(r1) if match is not None: cur_mem = int(match.group(1)) if cur_mem == memory.number: cur_mem = \ command(self.pipe, *self._cmd_recall_memory(memory.number)) else: raise errors.InvalidDataError("Radio refused %i" % memory.number) # FIXME if memory.duplex == "split" and self._kenwood_split: spec = "".join(self._make_split_spec(memory)) result = command(self.pipe, *self._cmd_set_split(memory.number, spec)) if iserr(result): raise errors.InvalidDataError("Radio refused %i" % memory.number)
def set_memory(self, memory): if memory.number < 0 or memory.number > self._upper: raise errors.InvalidMemoryLocation( "Number must be between 0 and %i" % self._upper) spec = self._make_mem_spec(memory) spec = ",".join(spec) r1 = command(self.pipe, *self._cmd_set_memory(memory.number, spec)) if not iserr(r1): time.sleep(0.5) r2 = command( self.pipe, *self._cmd_set_memory_name(memory.number, memory.name)) if not iserr(r2): memory.name = memory.name.rstrip() self._memcache[memory.number] = memory else: raise errors.InvalidDataError( "Radio refused name %i: %s" % (memory.number, repr(memory.name))) else: raise errors.InvalidDataError("Radio refused %i" % memory.number) if memory.duplex == "split" and self._kenwood_split: spec = ",".join(self._make_split_spec(memory)) result = command(self.pipe, *self._cmd_set_split(memory.number, spec)) if iserr(result): raise errors.InvalidDataError("Radio refused %i" % memory.number)
def set_call_indices(_map, mmap, urcall, r1call, r2call): ulist = [] for i in range(0, 6): ulist.append(get_urcall(_map, i)) rlist = [] for i in range(0, 6): rlist.append(get_rptcall(_map, i)) try: if not urcall: uindex = 0 else: uindex = ulist.index(urcall) except ValueError: raise errors.InvalidDataError("Call `%s' not in URCALL list" % urcall) try: if not r1call: r1index = 0 else: r1index = rlist.index(r1call) except ValueError: raise errors.InvalidDataError("Call `%s' not in RCALL list" % r1call) try: if not r2call: r2index = 0 else: r2index = rlist.index(r2call) except ValueError: raise errors.InvalidDataError("Call `%s' not in RCALL list" % r2call) mmap[18] = (ord(mmap[18]) & 0xF0) | uindex mmap[19] = (r1index << 4) | r2index
def send_magic(pipe): """Send the magic incantation to wake up an ic9x radio""" if pipe.getBaudrate() == 38400: resp = _send_magic_38400(pipe) if resp: return print "Switching from 38400 to 4800" pipe.setBaudrate(4800) resp = _send_magic_4800(pipe) pipe.setBaudrate(38400) if resp: return raise errors.RadioError("Radio not responding") elif pipe.getBaudrate() == 4800: resp = _send_magic_4800(pipe) if resp: return print "Switching from 4800 to 38400" pipe.setBaudrate(38400) resp = _send_magic_38400(pipe) if resp: return pipe.setBaudrate(4800) raise errors.RadioError("Radio not responding") else: raise errors.InvalidDataError("Radio in unknown state (%i)" % \ pipe.getBaudrate())
def send(self, pipe, verbose=False): rframes = ic9x_send(pipe, self.get_raw()) if len(rframes) == 0: raise errors.InvalidDataError("No response from radio") return rframes
def fix_rounded_step(freq): """Some radios imply the last bit of 12.5kHz and 6.25kHz step frequencies. Take the base @freq and return the corrected one""" try: required_step(freq) return freq except errors.InvalidDataError: pass try: required_step(freq + 500) return freq + 500 except errors.InvalidDataError: pass try: required_step(freq + 250) return freq + 250 except errors.InvalidDataError: pass try: required_step(freq + 750) return float(freq + 750) except errors.InvalidDataError: pass raise errors.InvalidDataError("Unable to correct rounded frequency " + format_freq(freq))
def set_skip(self, number, skip): if skip == "S": self.memobj.tv_channel_skip[number] = 2 elif skip == "": self.memobj.tv_channel_skip[number] = 0 else: raise errors.InvalidDataError("skip '%s' not supported" % skip)
def send_magic(pipe): """Send the magic incantation to wake up an ic9x radio""" if pipe.baudrate == 38400: resp = _send_magic_38400(pipe) if resp: return LOG.info("Switching from 38400 to 4800") pipe.baudrate = 4800 resp = _send_magic_4800(pipe) pipe.baudrate = 38400 if resp: return raise errors.RadioError("Radio not responding") elif pipe.baudrate == 4800: resp = _send_magic_4800(pipe) if resp: return LOG.info("Switching from 4800 to 38400") pipe.baudrate = 38400 resp = _send_magic_38400(pipe) if resp: return pipe.baudrate = 4800 raise errors.RadioError("Radio not responding") else: raise errors.InvalidDataError("Radio in unknown state (%i)" % pipe.baudrate)
def _ic9x_set_banks(self, banks): if len(banks) != len(self.__bankcache.keys()): raise errors.InvalidDataError( "Invalid bank list length (%i:%i)" % (len(banks), len(self.__bankcache.keys()))) cached_names = [ str(self.__bankcache[x]) for x in sorted(self.__bankcache.keys()) ] need_update = False for i in range(0, 26): if banks[i] != cached_names[i]: need_update = True self.__bankcache[i] = banks[i] LOG.dbeug("Updating %s: %s -> %s" % (chr(i + ord("A")), cached_names[i], banks[i])) if need_update: self._lock.acquire() try: self._maybe_send_magic() ic9x_ll.set_banks(self.pipe, self.vfo, banks) except: self._lock.release() raise self._lock.release()
def _process_frames(self): if not self.data.startswith("\xFE\xFE"): raise errors.InvalidDataError("Out of sync with radio") elif len(self.data) < 5: return [] # Not enough data for a full frame frames = [] while self.data: try: cmd = ord(self.data[4]) except IndexError: break # Out of data try: frame, rest = parse_frame_generic(self.data) if not frame: break elif frame.src == 0xEE and frame.dst == 0xEF: # PC echo, ignore pass else: frames.append(frame) self.data = rest except errors.InvalidDataError, e: LOG.error("Failed to parse frame (cmd=%i): %s" % (cmd, e)) return []
def get_mycall(mmap, index): if index > 5: raise errors.InvalidDataError("MYCALL index %i must be <= 5" % index) start = call_location(POS_MYCALL, index) return mmap[start:start + 8].rstrip()
def _encode_tone(self, memtone, meminv, mode, tone, pol): """Parse the tone data to encode from UI to mem""" if mode == '' or mode is None: memtone.set_value(0) meminv.set_value(0) elif mode == 'Tone': # caching errors for analog tones. try: memtone.set_value(TONES.index(tone) + 1) meminv.set_value(0) except: msg = "TCSS Tone '%d' is not supported" % tone LOG.error(msg) raise errors.RadioError(msg) elif mode == 'DTCS': # caching errors for digital tones. try: memtone.set_value(DTCS.index(tone) + 51) if pol == "R": meminv.set_value(True) else: meminv.set_value(False) except: msg = "Digital Tone '%d' is not supported" % tone LOG.error(msg) raise errors.RadioError(msg) else: msg = "Internal error: invalid mode '%s'" % mode LOG.error(msg) raise errors.InvalidDataError(msg)
def erase_memory(pipe, vfo, number): """Erase memory @number on @vfo via @pipe""" frame = IC92MemClearFrame(number) frame.set_vfo(vfo) rframe = frame.send(pipe) if rframe.get_raw()[2] != "\xfb": raise errors.InvalidDataError("Radio reported error")
def set_mycall(mmap, index, call): if index > 5: raise errors.InvalidDataError("MYCALL index %i must be <= 5" % index) start = call_location(POS_MYCALL, index) mmap[start] = call.ljust(12) return mmap
def load(self, filename=None): if filename is None and self._filename is None: raise errors.RadioError("Need a location to load from") if filename: self._filename = filename self._blank() f = open(self._filename, "r") for line in f: if line.strip() == "// Memory Channels": break reader = csv.reader(f, delimiter=chirp_common.SEPCHAR, quotechar='"') good = 0 lineno = 0 for line in reader: lineno += 1 if lineno == 1: header = line continue if len(header) > len(line): LOG.debug("Line %i has %i columns, expected %i" % (lineno, len(line), len(header))) self.errors.append("Column number mismatch on line %i" % lineno) continue # hmk stores Tx Freq. in its own field, but Chirp expects the Tx # Freq. for odd-split channels to be in the Offset field. # If channel is odd-split, copy Tx Freq. field to Offset field. if line[header.index('Shift/Split')] == "S": line[header.index('Offset')] = line[header.index('Tx Freq.')] # fix EU decimal line = [i.replace(',', '.') for i in line] try: mem = self._parse_csv_data_line(header, line) if mem.number is None: raise Exception("Invalid Location field" % lineno) except Exception as e: LOG.error("Line %i: %s" % (lineno, e)) self.errors.append("Line %i: %s" % (lineno, e)) continue self._grow(mem.number) self.memories[mem.number] = mem good += 1 if not good: for e in errors: LOG.error("kenwood_hmk: %s", e) raise errors.InvalidDataError("No channels found")
def set_memory(self, mem): _mem = self._memobj.memory[mem.number - 1] _flg = self._memobj.flags[mem.number - 1] _flg.empty = mem.empty if mem.empty: self._set_bank(mem.number, None) return mult = chirp_common.is_fractional_step(mem.freq) and 6250 or 5000 _mem.mult_flag = mult == 6250 _mem.freq = mem.freq / mult _mem.offset = mem.offset / 5000 _mem.duplex = DUPLEX.index(mem.duplex) _mem.mode = MODES.index(mem.mode) _mem.tmode = TMODES.index(mem.tmode) _mem.rtone = chirp_common.TONES.index(mem.rtone) _mem.ctone = chirp_common.TONES.index(mem.ctone) _mem.dtcs = chirp_common.DTCS_CODES.index(mem.dtcs) _mem.dtcs_polarity = DTCS_POL.index(mem.dtcs_polarity) _mem.tuning_step = STEPS.index(mem.tuning_step) set_name(_mem, mem.name) _flg.pskip = mem.skip == "P" _flg.skip = mem.skip == "S" if mem.mode == "DV": urcalls = self.get_urcall_list() rptcalls = self.get_repeater_call_list() if not isinstance(mem, chirp_common.DVMemory): raise errors.InvalidDataError("DV mode is not a DVMemory!") try: err = mem.dv_urcall _mem.urcall = urcalls.index(mem.dv_urcall) err = mem.dv_rpt1call _mem.rpt1call = rptcalls.index(mem.dv_rpt1call) err = mem.dv_rpt2call _mem.rpt2call = rptcalls.index(mem.dv_rpt2call) except IndexError: raise errors.InvalidDataError("DV Call %s not in list" % err) else: _mem.urcall = 0 _mem.rpt1call = 0 _mem.rpt2call = 0
def set_skip(mmap, number, skip): if skip == "P": raise errors.InvalidDataError("PSKIP not supported by this model") val = struct.unpack("B", mmap[POS_FLAGS_START + number])[0] & 0xEF if skip == "S": val |= 0x10 mmap[POS_FLAGS_START + number] = val
def load(self, filename=None): if filename is None and self._filename is None: raise errors.RadioError("Need a location to load from") if filename: self._filename = filename self._blank() f = file(self._filename, "r") for line in f: if line.strip() == "// Conventional Data": break reader = csv.reader(f, delimiter=chirp_common.SEPCHAR, quotechar='"') good = 0 lineno = 0 for line in reader: lineno += 1 if lineno == 1: header = line continue if len(line) == 0: # End of channel data break if len(header) > len(line): LOG.error("Line %i has %i columns, expected %i" % (lineno, len(line), len(header))) self.errors.append("Column number mismatch on line %i" % lineno) continue # fix EU decimal line = [i.replace(',', '.') for i in line] try: mem = self._parse_csv_data_line(header, line) if mem.number is None: raise Exception("Invalid Location field" % lineno) except Exception as e: LOG.error("Line %i: %s" % (lineno, e)) self.errors.append("Line %i: %s" % (lineno, e)) continue self._grow(mem.number) self.memories[mem.number] = mem good += 1 if not good: for e in errors: LOG.error("kenwood_itm: %s", e) raise errors.InvalidDataError("No channels found")
def send(self, pipe, verbose=False): """Send the frame to the radio via @pipe""" if verbose: print "Sending:\n%s" % util.hexprint(self.get_raw()) response = ic9x_send(pipe, self.get_raw()) if len(response) == 0: raise errors.InvalidDataError("No response from radio") return response[0]
def set_banks(pipe, vfo, banks): """Set banks for @vfo via @pipe""" for i in range(0, 26): bframe = IC92BankFrame() bframe.set_vfo(vfo) bframe.set_identifier(chr(i + ord("A"))) bframe.set_name(banks[i]) rframe = bframe.send(pipe) if rframe.get_payload() != "\xfb": raise errors.InvalidDataError("Radio reported error")
def get_tune_step(mmap): tsidx = struct.unpack("B", mmap[POS_TUNE_STEP])[0] & 0xF0 tsidx >>= 4 icx8x_ts = list(chirp_common.TUNING_STEPS) del icx8x_ts[1] try: return icx8x_ts[tsidx] except IndexError: raise errors.InvalidDataError("TS index %i out of range (%i)" % (tsidx, len(icx8x_ts)))
def set_bank(mmap, number, bank): if bank is not None and bank > 9: raise errors.InvalidDataError("Invalid bank number %i" % bank) if bank is None: index = 0x0A else: index = bank val = ord(mmap[POS_FLAGS_START + number]) & 0xF0 val |= index mmap[POS_FLAGS_START + number] = val
def set_skip(self, number, skip): bank_item = self.memobj.banks[number] if skip == "P": bank_item.prog_skip = 1 bank_item.mem_skip = 1 elif skip == "S": bank_item.prog_skip = 0 bank_item.mem_skip = 1 elif skip == "": bank_item.prog_skip = 0 bank_item.mem_skip = 0 else: raise errors.InvalidDataError("skip '%s' not supported" % skip)
def map_dtmf_chirp2icom(self, item): item = str(item).upper() if item == "*": item = "E" elif item == "#": item = "F" elif item == " ": return 0xff try: ret = int(item, 16) except ValueError: raise errors.InvalidDataError("invalid DTMF number '%s'" % item) return ret
def set_memory(self, memory): if memory.number < 0 or memory.number > self._upper: raise errors.InvalidMemoryLocation( "Number must be between 0 and %i" % self._upper) if memory.number > 90: if memory.duplex == TS850_DUPLEX[0]: memory.duplex = TS850_DUPLEX[1] memory.offset = memory.freq else: if memory.freq > memory.offset: temp = memory.freq memory.freq = memory.offset memory.offset = temp # Clear out memory contents to prevent errors spec = self._make_base_spec(memory, 0) spec = "".join(spec) result = command(self.pipe, *self._cmd_set_memory(memory.number, spec)) if iserr(result): raise errors.InvalidDataError("Radio refused %i" % memory.number) # If we have a split set the transmit frequency first. if memory.duplex == TS850_DUPLEX[1]: spec = "".join(self._make_split_spec(memory)) result = command(self.pipe, *self._cmd_set_split(memory.number, spec)) if iserr(result): raise errors.InvalidDataError("Radio refused %i" % memory.number) spec = self._make_mem_spec(memory) spec = "".join(spec) result = command(self.pipe, *self._cmd_set_memory(memory.number, spec)) if iserr(result): raise errors.InvalidDataError("Radio refused %i" % memory.number)
def set_freq(pipe, freq): """Set the frequency of the radio on @pipe to @freq""" freqbcd = util.bcd_encode(freq, bigendian=False, width=9) buf = "\x01\x7f\x05" + freqbcd drain(pipe) send_magic(pipe) resp = send(pipe, buf) for frame in resp: if len(frame) == 6: if frame[4] == "\xfb": return True raise errors.InvalidDataError("Repeater reported error")
def set_memory(pipe, vfo, memory): """Set memory @memory on @vfo via @pipe""" frame = IC92MemoryFrame() frame.set_memory(memory) frame.set_vfo(vfo) #print "Sending (%i):" % (len(frame.get_raw())) #print util.hexprint(frame.get_raw()) rframe = frame.send(pipe) if rframe.get_raw()[2] != "\xfb": raise errors.InvalidDataError("Radio reported error:\n%s" %\ util.hexprint(rframe.get_payload()))
def required_step(freq): """Returns the simplest tuning step that is required to reach @freq""" if is_5_0(freq): return 5.0 elif is_12_5(freq): return 12.5 elif is_6_25(freq): return 6.25 elif is_2_5(freq): return 2.5 else: raise errors.InvalidDataError("Unable to calculate the required " + "tuning step for %i.%5i" % (freq / 1000000, freq % 1000000))
def unescape_raw_bytes(escaped_data): """Unescapes raw bytes from the radio.""" data = b"" i = 0 while i < len(escaped_data): byte = escaped_data[i] if byte == 0xff: if i + 1 >= len(escaped_data): raise errors.InvalidDataError( "Unexpected escape character at end of data") i += 1 byte = 0xf0 | escaped_data[i] data += bytes([byte]) i += 1 return data
def unescape_raw_bytes(escaped_data): """Unescapes raw bytes from the radio.""" data = "" i = 0 while i < len(escaped_data): byte = escaped_data[i] if byte == '\xff': if i + 1 >= len(escaped_data): raise errors.InvalidDataError( "Unexpected escape character at end of data") i += 1 byte = chr(0xf0 | ord(escaped_data[i])) data += byte i += 1 return data