Browse code

bug fixes

gandolf authored on 08/25/2022 22:02:58
Showing 4 changed files
1 1
deleted file mode 100644
... ...
@@ -1,6 +0,0 @@
1
-Memory Ch,VFO_A,VFO_B,RepeaterShift,Mode,Tag,Encoding,Tone,DCS,Clarifier,RxClar,TxClar,PreAmp,RfAttn,NB,IFshift,IFwidthIndex,ContourState,ContourFreq,APFstate,APFfreq,DNRstate,DNRalgorithm,DNFstate,NBFstate,NotchState,NotchFreq
2
-1,146.52,,OFF,FM,VHF Call,OFF,100.0 Hz,23,0,OFF,OFF,IPO,NA,OFF,NA,NA,NA,NA,NA,NA,NA,1,NA,WIDE,ON,150
3
-2,145.29,,-RPT,FM,WA7ABU,OFF,118.8 Hz,23,0,OFF,OFF,IPO,NA,OFF,NA,NA,NA,NA,NA,NA,NA,1,NA,WIDE,ON,150
4
-3,162.55,,OFF,FM,WX PDX,OFF,100.0 Hz,23,0,OFF,OFF,IPO,NA,OFF,NA,NA,NA,NA,NA,NA,NA,1,NA,WIDE,ON,150
5
-4,122.725,,OFF,AM,ALB CTAF,OFF,100.0 Hz,23,0,OFF,OFF,IPO,NA,OFF,NA,NA,NA,NA,NA,NA,OFF,1,OFF,WIDE,OFF,150
6
-5,14.25,,OFF,USB,20 Meters,OFF,67.0 Hz,23,0,OFF,OFF,AMP 2,ON,ON,20,14,0,300,0,25,OFF,1,OFF,WIDE,OFF,150
7 0
new file mode 100644
... ...
@@ -0,0 +1,6 @@
1
+Memory Ch,VFO_A,RepeaterShift,Mode,Tag,Encoding,Tone,DCS,Clarifier,RxClar,TxClar,PreAmp,RfAttn,NB,IFshift,IFwidthIndex,ContourState,ContourFreq,APFstate,APFfreq,DNRstate,DNRalgorithm,DNFstate,NBFstate,NotchState,NotchFreq
2
+1,146.52,OFF,FM,VHF Call,OFF,100.0 Hz,23,0,OFF,OFF,IPO,NA,OFF,NA,2,1,300,0,25,NA,1,NA,WIDE,ON,150
3
+2,145.29,-RPT,FM-N,WA7ABU,TONE ENC,100.0 Hz,23,0,OFF,OFF,IPO,NA,OFF,NA,1,1,300,0,25,NA,1,NA,NARROW,ON,150
4
+3,162.55,OFF,FM,WX PDX,OFF,100.0 Hz,23,0,OFF,OFF,IPO,NA,OFF,NA,2,1,300,0,25,NA,1,NA,WIDE,ON,150
5
+4,122.725,OFF,AM,ALB CTAF,OFF,100.0 Hz,23,0,OFF,OFF,IPO,NA,OFF,NA,4,0,300,0,25,OFF,1,OFF,WIDE,OFF,150
6
+5,14.25,OFF,USB,20 Meters,OFF,67.0 Hz,23,0,OFF,OFF,AMP 2,ON,ON,20,14,0,300,0,25,OFF,1,OFF,WIDE,OFF,150
... ...
@@ -31,12 +31,9 @@
31 31
 #
32 32
 # Revision History
33 33
 #   * v10 24 Nov 2019 by J L Owrey; first release
34
-#   * v11 03 Oct 2020 by J L owrey; upgraded to Python 3
34
+#   * v11 03 Oct 2020 by J L Owrey; upgraded to Python 3
35
+#   * v12 24 Aug 2022 by J L Owrey; added methods to get and set APF
35 36
 #
36
-# This script has been tested with the following
37
-#
38
-#     Python 3.8.10 (default, Mar 15 2022, 12:22:08) 
39
-#     [GCC 9.4.0] on linux
40 37
 #2345678901234567890123456789012345678901234567890123456789012345678901234567890
41 38
 
42 39
 import sys, serial, time
... ...
@@ -173,6 +170,8 @@ def getCTCSS():
173 170
     """
174 171
     # Get result CTCSS tone
175 172
     sResult = sendCommand('CN00;')
173
+    if sResult == '?;':
174
+        return 'NA'
176 175
     tone = sResult[4:7]
177 176
     return list(dTones.keys())[list(dTones.values()).index(tone)]
178 177
 ## end def
... ...
@@ -185,6 +184,8 @@ def getDCS():
185 184
     """
186 185
     # Get result of CN01 command
187 186
     sResult = sendCommand('CN01;')
187
+    if sResult == '?;':
188
+        return 'NA'
188 189
     dcs = sResult[4:7]
189 190
     return list(dDcs.keys())[list(dDcs.values()).index(dcs)]
190 191
 ## end def
... ...
@@ -198,6 +199,8 @@ def getRxClarifier():
198 199
     # An exception will automatically be raised if incorrect data is
199 200
     # supplied - most likely a "key not found" error.
200 201
     sResult = sendCommand('RT;')
202
+    if sResult == '?;':
203
+        return 'NA'
201 204
     state = sResult[2]
202 205
     return list(bState.keys())[list(bState.values()).index(state)]
203 206
 ## end def
... ...
@@ -211,6 +214,8 @@ def getTxClarifier():
211 214
     # An exception will automatically be raised if incorrect data is
212 215
     # supplied - most likely a "key not found" error.
213 216
     sResult = sendCommand('XT;')
217
+    if sResult == '?;':
218
+        return 'NA'
214 219
     state = sResult[2]
215 220
     return list(bState.keys())[list(bState.values()).index(state)]
216 221
 ## end def
... ...
@@ -222,17 +227,22 @@ def getPower():
222 227
     Returns: string containing the power in Watts
223 228
     """
224 229
     sResult = sendCommand('PC;')
230
+    if sResult == '?;':
231
+        return 'NA'
225 232
     return sResult[2:5]
226 233
 ##end def
227 234
 
228 235
 def getPreamp():
229 236
     """
230
-    Description:  Gets the state of the Rx preamplifier.
237
+    Description:  Gets the state of the Rx preamplifier.  The state of
238
+    the preamplifier is the same as the IPO state.
231 239
     Parameters: none
232 240
     Returns: string containing the state of the preamplifier.
233 241
     """
234 242
     # Get result of PA0 command
235 243
     sResult = sendCommand('PA0;')
244
+    if sResult == '?;':
245
+        return 'NA'
236 246
     ipo = sResult[3:4]
237 247
     return list(dPreamp.keys())[list(dPreamp.values()).index(ipo)]
238 248
 ## end def
... ...
@@ -257,6 +267,8 @@ def getNoiseBlanker():
257 267
     Returns: string containing the state of the noise blanker.
258 268
     """
259 269
     sResult = sendCommand('NB0;')
270
+    if sResult == '?;':
271
+        return 'NA'
260 272
     nb = sResult[3:4]
261 273
     return list(bState.keys())[list(bState.values()).index(nb)]
262 274
 ## end def
... ...
@@ -267,8 +279,6 @@ def getIFshift():
267 279
     Parameters: none
268 280
     Returns: string containing the amount of shift.
269 281
     """
270
-    if getRfAttn() == 'NA':
271
-        return 'NA'
272 282
     sResult = sendCommand('IS0;')
273 283
     if sResult == '?;':
274 284
         return 'NA'
... ...
@@ -284,9 +294,9 @@ def getIFwidth():
284 294
     Parameters: none
285 295
     Returns: string containing the amount index number.
286 296
     """
287
-    if getRfAttn() == 'NA':
288
-        return 'NA'
289 297
     sResult = sendCommand('SH0;')
298
+    if sResult == '?;':
299
+        return 'NA'
290 300
     width = int(sResult[3:5])
291 301
     return width
292 302
 ## end def
... ...
@@ -297,22 +307,42 @@ def getContour():
297 307
     Parameters: none
298 308
     Returns: list object containing the four parameters.
299 309
     """
300
-    if getRfAttn() == 'NA':
301
-        return [ 'NA', 'NA', 'NA', 'NA' ]
310
+    #if getRfAttn() == 'NA':
311
+    #    return [ 'NA', 'NA', 'NA', 'NA' ]
302 312
     lContour = []
303 313
 
304 314
     sResult = sendCommand('CO00;')
315
+    if sResult == '?;':
316
+        return 'NA'
305 317
     lContour.append(int(sResult[4:8]))
306 318
 
307 319
     sResult = sendCommand('CO01;')
320
+    if sResult == '?;':
321
+        return 'NA'
308 322
     lContour.append(int(sResult[4:8]))
309 323
 
324
+    return lContour
325
+## end def
326
+
327
+def getAPF():
328
+    """
329
+    Description:  Gets the audio peak filter parameters.
330
+    Parameters: none
331
+    Returns: list object containing the four parameters.
332
+    """
333
+    lapf = []
334
+
310 335
     sResult = sendCommand('CO02;')
311
-    lContour.append(int(sResult[4:8]))
336
+    if sResult == '?;':
337
+        return 'NA'
338
+    lapf.append(int(sResult[4:8]))
312 339
 
313 340
     sResult = sendCommand('CO03;')
314
-    lContour.append(int(sResult[4:8]))
315
-    return lContour
341
+    if sResult == '?;':
342
+        return 'NA'
343
+    lapf.append(int(sResult[4:8]))
344
+
345
+    return lapf
316 346
 ## end def
317 347
 
318 348
 def getDNRstate():
... ...
@@ -335,6 +365,8 @@ def getDNRalgorithm():
335 365
     Returns: a number between 1 and 16 inclusive
336 366
     """
337 367
     sResult = sendCommand('RL0;')
368
+    if sResult == '?;':
369
+        return 'NA'
338 370
     algorithm = int(sResult[3:5])
339 371
     return algorithm
340 372
 ## end def
... ...
@@ -651,7 +683,23 @@ def setContour(lParams):
651 683
     if lParams[0] == 'NA':
652 684
         return
653 685
 
654
-    for inx in range(4):
686
+    for inx in range(2):
687
+        sCmd = 'CO0%d%04d' % (inx, int(lParams[inx]))
688
+        sResult = sendCommand(sCmd)
689
+        if sResult == '?;':
690
+            raise Exception('setContour error')
691
+## end def
692
+
693
+def setAPF(lParams):
694
+    """
695
+    Description:  Sends a formatted CO command that sets contour parameters
696
+    Parameters: lParams - list object containing the parameters
697
+    Returns: nothing
698
+    """
699
+    if lParams[0] == 'NA':
700
+        return
701
+
702
+    for inx in range(2,4):
655 703
         sCmd = 'CO0%d%04d' % (inx, int(lParams[inx]))
656 704
         sResult = sendCommand(sCmd)
657 705
         if sResult == '?;':
... ...
@@ -755,28 +803,28 @@ def parseCsvData(sline):
755 803
     # Store the parsed items with the appropriate key in the dictionary object.
756 804
     dChan['memloc'] = lchan[0]
757 805
     dChan['vfoa'] = lchan[1]
758
-    dChan['vfob'] = lchan[2]
759
-    dChan['rpoffset'] = lchan[3]
760
-    dChan['mode'] = lchan[4]
761
-    dChan['tag'] = lchan[5]
762
-    dChan['encode'] = lchan[6]
763
-    dChan['tone'] = lchan[7]
764
-    dChan['dcs'] = lchan[8]
765
-    dChan['clarfreq'] = lchan[9]
766
-    dChan['rxclar'] = lchan[10]
767
-    dChan['txclar'] = lchan[11]
768
-    dChan['preamp'] = lchan[12]
769
-    dChan['rfattn'] = lchan[13]
770
-    dChan['nblkr']  = lchan[14]
771
-    dChan['shift'] = lchan[15]
772
-    dChan['width'] = lchan[16]
773
-    dChan['contour'] = [ lchan[17], lchan[18], lchan[19], lchan[20] ]
774
-    dChan['dnrstate'] = lchan[21]
775
-    dChan['dnralgorithm'] = lchan[22]
776
-    dChan['dnfstate'] = lchan[23]
777
-    dChan['narstate'] = lchan[24]
778
-    dChan['notchstate'] = lchan[25]
779
-    dChan['notchfreq'] = lchan[26]
806
+    dChan['rpoffset'] = lchan[2]
807
+    dChan['mode'] = lchan[3]
808
+    dChan['tag'] = lchan[4]
809
+    dChan['encode'] = lchan[5]
810
+    dChan['tone'] = lchan[6]
811
+    dChan['dcs'] = lchan[7]
812
+    dChan['clarfreq'] = lchan[8]
813
+    dChan['rxclar'] = lchan[9]
814
+    dChan['txclar'] = lchan[10]
815
+    dChan['preamp'] = lchan[11]
816
+    dChan['rfattn'] = lchan[12]
817
+    dChan['nblkr']  = lchan[13]
818
+    dChan['shift'] = lchan[14]
819
+    dChan['width'] = lchan[15]
820
+    dChan['contour'] = [ lchan[16], lchan[17] ]
821
+    dChan['afp'] = [ lchan[18], lchan[19] ]
822
+    dChan['dnrstate'] = lchan[20]
823
+    dChan['dnralgorithm'] = lchan[21]
824
+    dChan['dnfstate'] = lchan[22]
825
+    dChan['narstate'] = lchan[23]
826
+    dChan['notchstate'] = lchan[24]
827
+    dChan['notchfreq'] = lchan[25]
780 828
     return dChan # return the dictionary object
781 829
 ## end def
782 830
 
... ...
@@ -873,8 +921,9 @@ def receiveSerial(termchar=';'):
873 921
         try:
874 922
             # Form a string from the received characters.
875 923
             answer += c.decode('utf_8')
924
+            #xpass
876 925
         except Exception as e:
877
-            print('serial rx error: %s' % e)
926
+            print('serial rx error: %s  chr=%s' % (e, c))
878 927
         #answer += str(c) # Form a string from the received characters.
879 928
         charCount += 1 # Increment character count.
880 929
         # If a semicolon has arrived then the FT991 has completed
... ...
@@ -26,19 +26,20 @@
26 26
 #
27 27
 # Revision History
28 28
 #   * v10 24 Nov 2019 by J L Owrey; first release
29
-#   * v11 03 Oct 2020 by J L owrey; upgraded to Python 3
29
+#   * v11 03 Oct 2020 by J L Owrey; upgraded to Python 3
30
+#   * v12 24 Aug 2022 by J L Owrey; fixed error occurring when setting
31
+#     the FT991 IF filter width for unsupported modulation modes; added
32
+#     command line parameter to set the CAT baud rate; fixed error that
33
+#     occurs when the restore menu settings tries to restore the CAT baud
34
+#     rate setting
30 35
 #
31
-# This script has been tested with the following
32
-#
33
-#     Python 3.8.10 (default, Mar 15 2022, 12:22:08) 
34
-#     [GCC 9.4.0] on linux
35 36
 #2345678901234567890123456789012345678901234567890123456789012345678901234567890
36 37
 
37 38
 # Environment Setup
38 39
 
39 40
 _WINDOWS_COM_PORT = 'COM5'
40 41
 _LINUX_COM_PORT = '/dev/ttyUSB0'
41
-_FT991_BAUD_RATE = 4800
42
+_DEFAULT_FT991_BAUD_RATE = 4800
42 43
 
43 44
 import os, sys, serial, time
44 45
 import ft991 # module should be in same directory as this utility
... ...
@@ -56,6 +57,7 @@ _DEBUG = False
56 57
 menuBackupFile = _DEFAULT_MENU_SETTINGS_FILE
57 58
 memoryBackupFile = _DEFAULT_MEMORY_SETTINGS_FILE
58 59
 commandLineOption = ''
60
+baudRate = _DEFAULT_FT991_BAUD_RATE
59 61
 
60 62
 # Command processing functions
61 63
 
... ...
@@ -270,7 +272,7 @@ def readMemorySettings():
270 272
              contained in the list.
271 273
     """
272 274
     # Define the column headers as the first item in the list.
273
-    lSettings = [ 'Memory Ch,VFO_A,VFO_B,' \
275
+    lSettings = [ 'Memory Ch,VFO_A,' \
274 276
                   'RepeaterShift,Mode,Tag,Encoding,Tone,DCS,' \
275 277
                   'Clarifier,RxClar,TxClar,PreAmp,RfAttn,NB,IFshift,' \
276 278
                   'IFwidthIndex,ContourState,ContourFreq,' \
... ...
@@ -297,6 +299,7 @@ def readMemorySettings():
297 299
         shift = ft991.getIFshift()
298 300
         width = ft991.getIFwidth()
299 301
         lContour = ft991.getContour()
302
+        lAFP = ft991.getAPF()
300 303
         dnrstate = ft991.getDNRstate()
301 304
         dnralgorithm = ft991.getDNRalgorithm()
302 305
         dnfstate = ft991.getDNFstate()
... ...
@@ -305,14 +308,14 @@ def readMemorySettings():
305 308
         # getMemory, above, stores data in a dictionary object.  Format
306 309
         # the data in this object, as well as, the DCS code and CTCSS
307 310
         # tone into a comma-delimited string.
308
-        sCsvFormat = '%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,' \
311
+        sCsvFormat = '%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,' \
309 312
                      '%s,%s,%s,%s,%s,%s,%s,%s,%s,%s' % \
310 313
                (
311
-                 dMem['memloc'], dMem['vfoa'], '', \
314
+                 dMem['memloc'], dMem['vfoa'], \
312 315
                  dMem['rpoffset'], dMem['mode'], dMem['tag'], dMem['encode'], \
313 316
                  tone, dcs, dMem['clarfreq'], dMem['rxclar'], \
314 317
                  dMem['txclar'], preamp, rfattn, nblkr, shift, width, \
315
-                 lContour[0], lContour[1], lContour[2], lContour[3], \
318
+                 lContour[0], lContour[1], lAFP[0], lAFP[1], \
316 319
                  dnrstate, dnralgorithm, dnfstate, narstate, notch[0],
317 320
                  notch[1]
318 321
                )
... ...
@@ -358,12 +361,19 @@ def writeMemorySettings(lSettings):
358 361
             ft991.setRfAttn(dItem['rfattn'])
359 362
             # Set Noise Blanker state
360 363
             ft991.setNoiseBlanker(dItem['nblkr'])
361
-            # Set IF shift amount
362
-            ft991.setIFshift(dItem['shift'])
363
-            # Set IF width index
364
-            ft991.setIFwidth(dItem['width'])
365
-            # Set Contour parameters
364
+            # v12 24 Aug 2022 by J L Owrey; fixed error occurring when setting
365
+            # the FT991 IF filter width for unsupported modulation modes
366
+            if dItem['mode'] in ['LSB', 'USB', 'CW', 'RTTY-LSB',
367
+                                 'RTTY-USB', 'DATA-LSB', 'DATA-USB']:
368
+                # Set IF width index
369
+                ft991.setIFwidth(dItem['width'])
370
+                # Set IF shift amount
371
+                ft991.setIFshift(dItem['shift'])
372
+            # Set Contour parameters; also sets audio peak filter (APF)
366 373
             ft991.setContour(dItem['contour'])
374
+            if dItem['mode'] in ['CW']:
375
+                # Set audio peak filter (APF)
376
+                ft991.setAPF(dItem['apf'])
367 377
             # Set DNR state and algorithm
368 378
             ft991.setDNRstate(dItem['dnrstate'])
369 379
             ft991.setDNRalgorithm(dItem['dnralgorithm'])
... ...
@@ -415,6 +425,13 @@ def writeMenuSettings(lSettings):
415 425
         # setting is the "Radio ID" setting.
416 426
         if item.find('EX087') > -1:
417 427
             continue;
428
+        # Do not change the CAT baud rate while restoring menu
429
+        # items as this could result in failure to restore menu
430
+        # items after item #31.  This situation might happen if
431
+        # the FT991 CAT baud rate gets changed some time after
432
+        # the menu settings have been backed up. 
433
+        if item.find('EX031') > -1:
434
+            continue;
418 435
         # Send the pre-formatted menu setting to the FT991.
419 436
         sResult = ft991.sendCommand(item)
420 437
         if sResult.find('?;') > -1:
... ...
@@ -504,18 +521,20 @@ def getCLarguments():
504 521
         Parameters: none
505 522
         Returns: nothing
506 523
     """
524
+    global baudRate
507 525
     index = 1
508 526
     fileName = ''
509 527
     backupOption = ''
510 528
 
511 529
     # Define a splash to help the user enter command line arguments.
512
-    usage =  "Usage: %s [-v] [OPTION] [-f file]\n"  \
530
+    usage =  "Usage: %s [-v] [OPTION] [-f file] [-u baud rate]\n"  \
513 531
              "  -b: backup memory\n"                \
514 532
              "  -r: restore memory\n"               \
515 533
              "  -m: backup menu\n"                  \
516 534
              "  -s: restore menu\n"                 \
517 535
              "  -f: backup/restore file name\n"     \
518 536
              "  -v: verbose mode\n"                 \
537
+             "  -u: baud rate\n"                    \
519 538
              % sys.argv[0].split('/')[-1]
520 539
 
521 540
     # Process all command line arguments until done.  Note that the last
... ...
@@ -541,6 +560,16 @@ def getCLarguments():
541 560
             ft991.verbose = True
542 561
         elif sys.argv[index] == '-d': # set debug mode 'ON'
543 562
             ft991.debug = True
563
+        elif sys.argv[index] == '-u': # set the baud rate
564
+            # v12 24 Aug 2022 by J L Owrey; added command line parameter
565
+            # for setting the CAT baud rate
566
+            # Get the backup file name.
567
+            baudRate = sys.argv[index + 1]
568
+            if not baudRate in ['4800', '9600', '19200', '38400']:
569
+                print("invalid baud rate")
570
+                exit(1)
571
+            baudRate = int(baudRate)
572
+            index += 1
544 573
         else:
545 574
             print(usage)
546 575
             exit(-1)
... ...
@@ -569,7 +598,7 @@ def main():
569 598
     else:
570 599
         port = _LINUX_COM_PORT
571 600
 
572
-    ft991.begin(port, _FT991_BAUD_RATE) # open com port session to FT991
601
+    ft991.begin(port, baudRate) # open com port session to FT991
573 602
 
574 603
     # Process command line options (if any).
575 604
     if commandLineOption != '':