Project

General

Profile

New Model #9131 » vxf20ab.py

Mathieu Therrien, 06/14/2021 02:02 PM

 
#!/usr/bin/env python3
'''
[rx_status, rx_frequence, tx_status, tx_frequence, rx_dcs, tx_dcs]
status bits :
0: Rig ON(0)/OFF(1)
1: DCS ON(0)/OFF(1)
2: ARTS ON(0)/OFF(1)
rxs rx frequence txs tx frequence rx dcx tx dcs
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111
111 0111110100000 110 0111110100000 11111111 11111111

Weather channels
1111111111111111
1111111111111111
1111111111111111
1111111111111111
1111111111111111
1111111111111111
1111111111111111
1111111111111111
1111111111111111
1111111111111111

* Voici une representation de la matrice initiale.
* Le premier octet est toujours 0x01 et l'avant dernier est 0x0. Les dernier est un checksum.
* 00000001 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11101111 10100000 11001111 10100000 11111111
* 11111111 11111111 11111111 11111111 11111111 11111111
* 11111111 11111111 11111111 11111111 11111111 11111111
* 11111111 11111111 11111111 11111111 11111111 11111111
* 11111111 11111111 11111111 00000000 11111111
*
* Exemple d'un fichier CSV valide
Channel,RX on,RX DCS on,RX ARTS on,RX Frequency,RX DCS,TX on,TX DCS on,TX ARTS on,TX Frequency,TX DCS
1,True,True,True,462.5625,23,True,True,True,462.5625,23
2,True,True,True,462.5875,23,True,True,True,462.5875,23
3,True,True,True,462.6125,23,True,True,True,462.6125,23
4,True,True,True,462.6375,23,True,True,True,462.6375,23
5,True,True,True,462.6625,23,True,True,True,462.6625,23
6,True,True,True,462.6875,23,True,True,True,462.6875,23
7,True,True,True,462.7125,23,True,True,True,462.7125,23
8,True,True,True,467.5625,23,True,True,True,467.5625,23
9,True,True,True,467.5875,23,True,True,True,467.5875,23
10,True,True,True,467.6125,23,True,True,True,467.6125,23
11,True,True,True,467.6375,23,True,True,True,467.6375,23
12,True,True,True,467.6625,23,True,True,True,467.6625,23
13,True,True,True,467.6875,23,True,True,True,467.6875,23
14,True,True,True,467.7125,23,True,True,True,467.7125,23
Weather Frequency
162.4
162.425
162.45
162.475
162.5
162.525
162.55
""
""
""

'''

import serial
import csv

class vxf20(object):
def __init__(self):
self.channels = dict()
self.ch_weather = list()
def decode_pgmbytes(self, pgmbytes):
for ch in range(0, 14):
i = ch * 6 + 1
channel = dict()
rx = dict()
tx = dict()
rx['status'] = self.get_status(pgmbytes[i] >> 5)
rx['frequency'] = self.get_frequency( (pgmbytes[i] & 0x1f) << 8 | pgmbytes[i+1] )

tx['status'] = self.get_status(pgmbytes[i+2] >> 5)
tx['frequency'] = self.get_frequency( (pgmbytes[i+2] & 0x1f) << 8 | pgmbytes[i+3] )

rx['dcs'] = self.get_dcs(pgmbytes[i+4])
tx['dcs'] = self.get_dcs(pgmbytes[i+5])
channel['rx'] = rx
channel['tx'] = tx
self.channels[ch + 1] = channel

for wch in range(0, 10):
i = wch * 2 + 85
ch_weather = self.get_weather_frequency(pgmbytes[i] << 8 | pgmbytes[i+1])
self.ch_weather.append(ch_weather)
def encode_pgmbytes(self):
pgmlist = [1]
for ch in self.channels:
rx = (self.set_status(self.channels[ch]['rx']['status']) << 5+8) | self.set_frequency(self.channels[ch]['rx']['frequency'])
rxHIGH = (rx & 0xff00) >> 8
rxLOW = rx & 0xff

tx = (self.set_status(self.channels[ch]['tx']['status']) << 5+8) | self.set_frequency(self.channels[ch]['tx']['frequency'])
txHIGH = (tx & 0xff00) >> 8
txLOW = tx & 0xff

rxDCS = self.set_dcs(self.channels[ch]['rx']['dcs'])
txDCS = self.set_dcs(self.channels[ch]['rx']['dcs'])
pgmlist += [rxHIGH, rxLOW, txHIGH, txLOW, rxDCS, txDCS]
for wch in self.ch_weather:
fr = self.set_weather_frequency(wch)
frHIGH = (fr & 0xff00) >> 8
frLOW = fr & 0xff
pgmlist += [frHIGH, frLOW]

pgmlist += [0x00, self.set_checksum(bytes(pgmlist))]
pgmbytes = bytes(pgmlist)
print(pgmbytes)
return pgmbytes

def read(self, com = '/dev/ttyUSB0'):
with serial.Serial(com, 2400, timeout=5) as rig:
print('Press PTT...')
pgmbytes = rig.read(107)
print(pgmbytes)
self.decode_pgmbytes(pgmbytes)
def write(self, com = '/dev/ttyUSB0'):
pgmbytes = self.encode_pgmbytes()
with serial.Serial(com, 2400, timeout=5) as rig:
rig.write(pgmbytes)
checkback = rig.read(107)
pgmlist = list(pgmbytes)
#pgmlist += [0xff]
if bytes(pgmlist) == checkback:
#rig.write(bytes([0x06]))
print('done')

def get_frequency(self, fr):
return (125 * fr + 4000000) / 10000

def set_frequency(self, fr):
return int((10000 * fr - 4000000) / 125)

def get_weather_frequency(self, wfr):
if wfr < 0xffff:
return (6.25 * wfr + 130025) / 1000
else:
return None

def set_weather_frequency(self, wfr):
if wfr is None:
return 0xffff
else:
return int((1000 * wfr - 130025) / 6.25)

def get_status(self, status):
s = dict()
s['rig'] = bool(~status & 0b100)
s['dcs'] = bool(~status & 0b010)
s['arts'] = bool(~status & 0b001)
return s

def set_status(self, status):
rig = int((not status['rig']) << 2)
dcs = int((not status['dcs']) << 1)
arts = int(not status['arts'])
return (rig | dcs | arts)

def get_dcs(self, dcs):
if dcs == 0:
return 23
elif dcs == 1:
return 25
elif dcs == 2:
return 26
elif dcs == 3:
return 31
elif dcs == 4:
return 32
elif dcs == 5:
return 36
elif dcs == 6:
return 43
elif dcs == 7:
return 47
elif dcs == 8:
return 51
elif dcs == 9:
return 53
elif dcs == 10:
return 54
elif dcs == 11:
return 65
elif dcs == 12:
return 71
elif dcs ==13:
return 72
elif dcs == 14:
return 73
elif dcs == 15:
return 74
elif dcs == 16:
return 114
elif dcs == 17:
return 115
elif dcs == 18:
return 116
elif dcs == 19:
return 122
elif dcs == 20:
return 125
elif dcs == 21:
return 131
elif dcs == 22:
return 132
elif dcs == 23:
return 134
elif dcs == 24:
return 143
elif dcs == 25:
return 145
elif dcs == 26:
return 152
elif dcs == 27:
return 155
elif dcs == 28:
return 156
elif dcs == 29:
return 162
elif dcs == 30:
return 165
elif dcs == 31:
return 172
elif dcs == 32:
return 174
elif dcs == 33:
return 205
elif dcs == 34:
return 212
elif dcs == 35:
return 223
elif dcs == 36:
return 225
elif dcs == 37:
return 226
elif dcs == 38:
return 243
elif dcs == 39:
return 244
elif dcs == 40:
return 245
elif dcs == 41:
return 246
elif dcs == 42:
return 251
elif dcs == 43:
return 252
elif dcs == 44:
return 255
elif dcs == 45:
return 261
elif dcs == 46:
return 263
elif dcs == 47:
return 265
elif dcs == 48:
return 266
elif dcs == 49:
return 271
elif dcs == 50:
return 274
elif dcs == 51:
return 306
elif dcs == 52:
return 311
elif dcs == 53:
return 315
elif dcs == 54:
return 325
elif dcs == 55:
return 331
elif dcs == 56:
return 332
elif dcs == 57:
return 343
elif dcs == 58:
return 346
elif dcs == 59:
return 351
elif dcs == 60:
return 356
elif dcs == 61:
return 364
elif dcs == 62:
return 365
elif dcs == 63:
return 371
elif dcs == 64:
return 411
elif dcs == 65:
return 412
elif dcs == 66:
return 413
elif dcs == 67:
return 423
elif dcs == 68:
return 431
elif dcs == 69:
return 432
elif dcs == 70:
return 445
elif dcs == 71:
return 446
elif dcs == 72:
return 452
elif dcs == 73:
return 454
elif dcs == 74:
return 455
elif dcs == 75:
return 462
elif dcs == 76:
return 464
elif dcs == 77:
return 465
elif dcs == 78:
return 466
elif dcs == 79:
return 503
elif dcs == 80:
return 506
elif dcs == 81:
return 513
elif dcs == 82:
return 523
elif dcs == 83:
return 526
elif dcs == 84:
return 532
elif dcs == 85:
return 546
elif dcs == 86:
return 565
elif dcs == 87:
return 606
elif dcs == 88:
return 612
elif dcs == 89:
return 624
elif dcs == 90:
return 627
elif dcs == 91:
return 631
elif dcs == 92:
return 632
elif dcs == 93:
return 654
elif dcs == 94:
return 662
elif dcs == 95:
return 664
elif dcs == 96:
return 703
elif dcs == 97:
return 712
elif dcs == 98:
return 723
elif dcs == 99:
return 731
elif dcs == 100:
return 732
elif dcs == 101:
return 734
elif dcs == 102:
return 743
elif dcs == 103:
return 754
else:
return 0

def set_dcs(self, dcs):
if dcs == 23:
return 0
elif dcs == 25:
return 1;
elif dcs == 26:
return 2;
elif dcs == 31:
return 3;
elif dcs == 32:
return 4;
elif dcs == 36:
return 5;
elif dcs == 43:
return 6;
elif dcs == 47:
return 7;
elif dcs == 51:
return 8;
elif dcs == 53:
return 9;
elif dcs == 54:
return 10;
elif dcs == 65:
return 11;
elif dcs == 71:
return 12;
elif dcs == 72:
return 13;
elif dcs == 73:
return 14;
elif dcs == 74:
return 15;
elif dcs == 114:
return 16;
elif dcs == 115:
return 16;
elif dcs == 116:
return 18;
elif dcs == 122:
return 19;
elif dcs == 125:
return 20;
elif dcs == 131:
return 21;
elif dcs == 132:
return 22;
elif dcs == 134:
return 23;
elif dcs == 143:
return 24;
elif dcs == 145:
return 25;
elif dcs == 152:
return 26;
elif dcs == 155:
return 27;
elif dcs == 156:
return 28;
elif dcs == 162:
return 29;
elif dcs == 165:
return 30;
elif dcs == 172:
return 31;
elif dcs == 174:
return 32;
elif dcs == 205:
return 33;
elif dcs == 212:
return 34;
elif dcs == 223:
return 35;
elif dcs == 225:
return 36;
elif dcs == 226:
return 37;
elif dcs == 243:
return 38;
elif dcs == 244:
return 39;
elif dcs == 245:
return 40;
elif dcs == 246:
return 41;
elif dcs == 251:
return 42;
elif dcs == 252:
return 43;
elif dcs == 255:
return 44;
elif dcs == 261:
return 45;
elif dcs == 263:
return 46;
elif dcs == 265:
return 47;
elif dcs == 266:
return 48;
elif dcs == 271:
return 49;
elif dcs == 274:
return 50;
elif dcs == 306:
return 51;
elif dcs == 311:
return 52;
elif dcs == 315:
return 53;
elif dcs == 325:
return 54;
elif dcs == 331:
return 55;
elif dcs == 332:
return 56;
elif dcs == 343:
return 57;
elif dcs == 346:
return 58;
elif dcs == 351:
return 59;
elif dcs == 356:
return 60;
elif dcs == 364:
return 61;
elif dcs == 365:
return 62;
elif dcs == 371:
return 63;
elif dcs == 411:
return 64;
elif dcs ==412:
return 65;
elif dcs == 413:
return 66;
elif dcs == 423:
return 67;
elif dcs == 431:
return 68;
elif dcs == 432:
return 69;
elif dcs == 445:
return 70;
elif dcs == 446:
return 71;
elif dcs == 452:
return 72;
elif dcs == 454:
return 73;
elif dcs == 455:
return 74;
elif dcs == 462:
return 75;
elif dcs == 464:
return 76;
elif dcs == 465:
return 77;
elif dcs == 466:
return 78;
elif dcs == 503:
return 79;
elif dcs == 506:
return 80;
elif dcs == 513:
return 81;
elif dcs == 523:
return 82;
elif dcs == 526:
return 83;
elif dcs == 532:
return 84;
elif dcs == 546:
return 85;
elif dcs == 565:
return 86;
elif dcs == 606:
return 87;
elif dcs == 612:
return 88;
elif dcs == 624:
return 89;
elif dcs == 627:
return 90;
elif dcs == 631:
return 91;
elif dcs == 632:
return 92;
elif dcs == 654:
return 93;
elif dcs == 662:
return 94;
elif dcs == 664:
return 95;
elif dcs == 703:
return 96;
elif dcs == 712:
return 97;
elif dcs == 723:
return 98;
elif dcs == 731:
return 99;
elif dcs == 732:
return 100;
elif dcs == 734:
return 101;
elif dcs == 743:
return 102;
elif dcs == 754:
return 103;
else:
return 0xff;

def write_csv(self, filename = 'vxf20ab.csv'):
with open(filename, 'w') as f:
headers = ['Channel', 'RX on', 'RX DCS on', 'RX ARTS on', 'RX Frequency', 'RX DCS', 'TX on', 'TX DCS on', 'TX ARTS on', 'TX Frequency', 'TX DCS']
writer = csv.writer(f)

writer.writerow(headers)
for ch in self.channels:
writer.writerow([ch,
self.channels[ch]['rx']['status']['rig'],
self.channels[ch]['rx']['status']['dcs'],
self.channels[ch]['rx']['status']['arts'],
self.channels[ch]['rx']['frequency'],
self.channels[ch]['rx']['dcs'],
self.channels[ch]['tx']['status']['rig'],
self.channels[ch]['tx']['status']['dcs'],
self.channels[ch]['tx']['status']['arts'],
self.channels[ch]['tx']['frequency'],
self.channels[ch]['tx']['dcs']])
writer.writerow(['Weather Frequency'])
for wch in self.ch_weather:
writer.writerow([wch])
def read_csv(self, filename = 'vxf20ab.csv'):
wch = False
with open(filename, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
if(not wch):
if(row['Channel'] != 'Weather Frequency'):
channel = dict()
rx = dict()
tx = dict()
rx_status = dict()
tx_status = dict()
ch = int(row['Channel'])
rx_status['rig'] = bool(row['RX on'])
rx_status['dcs'] = bool(row['RX DCS on'])
rx_status['arts'] = bool(row['RX ARTS on'])
rx['status'] = rx_status
rx['frequency'] = float(row['RX Frequency'])
rx['dcs'] = int(row['RX DCS'])
tx_status['rig'] = bool(row['TX on'])
tx_status['dcs'] = bool(row['TX DCS on'])
tx_status['arts'] = bool(row['TX ARTS on'])
tx['status'] = tx_status
tx['frequency'] = float(row['TX Frequency'])
tx['dcs'] = int(row['TX DCS'])
channel['rx'] = rx
channel['tx'] = tx
self.channels[ch] = channel
else:
wch = True
else:
if row['Channel'] != '':
self.ch_weather.append(float(row['Channel']))
else:
self.ch_weather.append(None)
def get_checksum(self, pgmbytes):
cs = 0
for i in pgmbytes:
cs+=i
first = pgmbytes[0]
last = pgmbytes[-1]
cs = cs - first - last
if cs % 256 == last:
return last
else:
return False
def set_checksum(self, pgmbytes):
cs = 0
for i in pgmbytes:
cs+=i
cs = (cs - 1) % 256
print(hex(cs))
return cs
def main():
myrig = vxf20()
myrig.read_csv()
myrig.write()
myrig.read()
print(myrig.channels)

if __name__ == '__main__':
main()
(1-1/3)