Don't like ads? PRO users don't see any ads ;-)
Guest

icf3.py rev02

By: a guest on Sep 7th, 2012  |  syntax: Python  |  size: 5.37 KB  |  hits: 15  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
This paste has a previous version, view the difference. Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. # Copyright 2011 Dan Smith <dsmith@danplanet.com>
  2. #
  3. # This program is free software: you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation, either version 3 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program.  If not, see <http://www.gnu.org/licenses/>.
  15.  
  16. from chirp import chirp_common, icf, util, directory
  17. from chirp import bitwise
  18.  
  19. MEM_FORMAT = """
  20. #seekto 0x%x;
  21. struct {
  22.  bbcd freq[3];
  23.  bbcd offset[3];
  24.  u8 ctone;
  25.  u8 rtone;
  26.  char name[8];
  27. } memory[111];
  28.  
  29. #seekto 0x%x;
  30. struct {
  31.  u8 empty:1,
  32.     skip:1,
  33.     tmode:2,
  34.     duplex:2,
  35.     unk3:1,
  36.     am:1;
  37. } flag[111];
  38.  
  39. #seekto 0x0E9C;
  40. struct {
  41.  u8 unknown1:7,
  42.     right_scan_direction:1;
  43.  u8 right_scanning:1,
  44.     unknown2:7;
  45.  u8 unknown3:7,
  46.     left_scan_direction:1;
  47.  u8 left_scanning:1,
  48.     unknown4:7;
  49. } state[1];
  50.  
  51. #seekto 0x0F20;
  52. struct {
  53.  bbcd freq[3];
  54.  bbcd offset[3];
  55.  u8 ctone;
  56.  u8 rtone;
  57. } callchans[2];
  58.  
  59. """
  60.  
  61. DUPLEX = ["", "", "-", "+"]
  62. TONE = ["", "", "Tone", "TSQL"]
  63.  
  64. def _get_special():
  65.     special = {}
  66.     for i in range(0, 5):
  67.         special["M%iA" % (i+1)] = 100 + i*2
  68.         special["M%iB" % (i+1)] = 100 + i*2 + 1
  69.     return special            
  70.  
  71. @directory.register
  72. class ICF3Radio(icf.IcomCloneModeRadio):
  73.     """Icom IC-F3-2"""
  74.     VENDOR = "Icom"
  75.     MODEL = "IC-F3-2"
  76.  
  77.     _model = "\x19\x02\x03\x02"
  78.     _memsize = 4064
  79.     _endframe = "Icom Inc.\xFD"
  80.  
  81.     _ranges = [(0x0000, 0x0FE0, 16)]
  82.  
  83.     _limits = (0, 0)
  84.     _mem_positions = (0, 1)
  85.  
  86.     def get_features(self):
  87.         rf = chirp_common.RadioFeatures()
  88.         rf.memory_bounds = (0, 99)
  89.         rf.valid_bands = [self._limits]
  90.         if int(self._limits[0] / 100) == 1:
  91.             rf.valid_modes = ["FM"]
  92.         else:
  93.             rf.valid_modes = ["FM"]
  94.         rf.valid_tmodes = ["", "Tone", "TSQL"]
  95.         rf.valid_name_length = 8
  96.         rf.valid_special_chans = sorted(_get_special().keys())
  97.    
  98.         rf.has_sub_devices = self.VARIANT == ""
  99.         rf.has_ctone = True
  100.         rf.has_dtcs = False
  101.         rf.has_dtcs_polarity = False
  102.         rf.has_mode = "AM" in rf.valid_modes
  103.         rf.has_tuning_step = False
  104.         rf.has_bank = False
  105.  
  106.         return rf
  107.  
  108.     def process_mmap(self):
  109.         fmt = MEM_FORMAT % self._mem_positions
  110.         self._memobj = bitwise.parse(fmt, self._mmap)
  111.  
  112.     def get_raw_memory(self, number):
  113.         return repr(self._memobj.memory[number])
  114.  
  115.     def get_memory(self, number):
  116.         if isinstance(number, str):
  117.             number = _get_special()[number]
  118.  
  119.         _mem = self._memobj.memory[number]
  120.         _flg = self._memobj.flag[number]
  121.  
  122.         mem = chirp_common.Memory()
  123.         mem.number = number
  124.  
  125.         if number < 100:
  126.             # Normal memories
  127.             mem.skip = _flg.skip and "S" or ""
  128.         else:
  129.             # Special memories
  130.             mem.extd_number = util.get_dict_rev(_get_special(), number)
  131.  
  132.         if _flg.empty:
  133.             mem.empty = True
  134.             return mem
  135.  
  136.         mem.freq = chirp_common.fix_rounded_step(int(_mem.freq) * 1000)
  137.         mem.offset = int(_mem.offset) * 100
  138.         if str(_mem.name)[0] != chr(0xFF):
  139.             mem.name = str(_mem.name).rstrip()
  140.         mem.rtone = chirp_common.TONES[_mem.rtone]
  141.         mem.ctone = chirp_common.TONES[_mem.ctone]
  142.  
  143.         mem.mode = _flg.am and "AM" or "FM"
  144.         mem.duplex = DUPLEX[_flg.duplex]
  145.         mem.tmode = TONE[_flg.tmode]
  146.  
  147.         if number > 100:
  148.             mem.immutable = ["number", "skip", "extd_number", "name"]
  149.  
  150.         return mem
  151.  
  152.     def set_memory(self, mem):
  153.         _mem = self._memobj.memory[mem.number]
  154.         _flg = self._memobj.flag[mem.number]
  155.  
  156.         _flg.empty = mem.empty
  157.         if mem.empty:
  158.             return
  159.  
  160.         _mem.freq = mem.freq / 1000
  161.         _mem.offset = mem.offset / 100
  162.         if mem.name:
  163.             _mem.name = mem.name.ljust(8)[:8]
  164.         else:
  165.             _mem.name = "".join(["\xFF" * 8])
  166.         _mem.rtone = chirp_common.TONES.index(mem.rtone)
  167.         _mem.ctone = chirp_common.TONES.index(mem.ctone)
  168.  
  169.         _flg.duplex = DUPLEX.index(mem.duplex)
  170.         _flg.tmode = TONE.index(mem.tmode)
  171.         _flg.skip = mem.skip == "S"
  172.         _flg.am = mem.mode == "AM"
  173.  
  174.         if self._memobj.state.left_scanning:
  175.             print "Canceling scan on left VFO"
  176.             self._memobj.state.left_scanning = 0
  177.         if self._memobj.state.right_scanning:
  178.             print "Canceling scan on right VFO"
  179.             self._memobj.state.right_scanning = 0
  180.  
  181.     def get_sub_devices(self):
  182.         return [ICW32ARadioVHF(self._mmap), ICW32ARadioUHF(self._mmap)]
  183.  
  184.     @classmethod
  185.     def match_model(cls, filedata, filename):
  186.         if not len(filedata) == cls._memsize:
  187.             return False
  188.         return filedata[-16:] == "IcomCloneFormat3"
  189.  
  190. class ICF3RadioVHF(ICF3Radio):
  191.     """ICF3 VHF subdevice"""
  192.     VARIANT = "VHF"
  193.     _limits = (136000000, 174000000)
  194.     _mem_positions = (0x0000, 0x0DC0)