~hmatuschek/+junk/qdmr-package

« back to all changes in this revision

Viewing changes to lib/uv390_codeplug.cc

  • Committer: Hannes Matuschek
  • Date: 2020-07-07 14:49:41 UTC
  • mfrom: (1.1.4)
  • Revision ID: hmatuschek@gmail.com-20200707144941-niwxz5phhmi0kt1w
* Finalized implementation of MD5R.
* Fixed RD-5R upload.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
#include "utils.hh"
4
4
#include "channel.hh"
5
5
#include "gpssystem.hh"
 
6
#include "userdatabase.hh"
6
7
#include "config.h"
7
8
#include <QTimeZone>
8
9
 
9
10
 
10
 
#define NCHAN           3000
11
 
#define NCONTACTS       10000
12
 
#define NZONES          250
13
 
#define NGLISTS         250
14
 
#define NSCANL          250
15
 
#define NMESSAGES       50
16
 
#define NGPSSYSTEMS     16
17
 
 
18
 
// ---- first segment ---- additional offset 0x000800
19
 
#define OFFSET_TIMESTMP 0x002800
20
 
#define OFFSET_SETTINGS 0x002840
21
 
#define OFFSET_MSG      0x002980
22
 
#define OFFSET_GLISTS   0x00f420
23
 
#define OFFSET_ZONES    0x0151e0
24
 
#define OFFSET_SCANL    0x019060
25
 
#define OFFSET_ZONEXT   0x031800
26
 
#define OFFSET_GPS_SYS  0x03f40e
27
 
// ---- second segment ---- additional offset 0x110800
28
 
#define OFFSET_CHANNELS 0x110800
29
 
#define OFFSET_CONTACTS 0x140800
30
 
 
31
 
#define CALLSIGN_START  0x00200000  // Start of callsign database
32
 
#define CALLSIGN_FINISH 0x01000000  // End of callsign database
33
 
#define CALLSIGN_OFFSET 0x4003
34
 
 
35
 
#define VALID_TEXT(txt)     (*(txt) != 0 && *(txt) != 0xffff)
36
 
#define VALID_CHANNEL(ch)   VALID_TEXT((ch)->name)
37
 
#define VALID_ZONE(z)       VALID_TEXT((z)->name)
38
 
#define VALID_SCANLIST(sl)  VALID_TEXT((sl)->name)
39
 
#define VALID_GROUPLIST(gl) VALID_TEXT((gl)->name)
40
 
#define VALID_CONTACT(ct)   ((ct)->type != 0 && VALID_TEXT((ct)->name))
 
11
#define NCHAN            3000
 
12
#define NCONTACTS        10000
 
13
#define NZONES           250
 
14
#define NEMERGENCY       32
 
15
#define NGLISTS          250
 
16
#define NSCANL           250
 
17
#define NMESSAGES        50
 
18
#define NGPSSYSTEMS      16
 
19
 
 
20
// ---- first segment ----
 
21
#define OFFSET_TIMESTMP  0x002800
 
22
#define OFFSET_SETTINGS  0x002840
 
23
#define OFFSET_MENU      0x0028f0
 
24
#define OFFSET_BUTTONS   0x002900
 
25
#define OFFSET_MSG       0x002980
 
26
#define OFFSET_PRIVACY   0x0061c0
 
27
#define OFFSET_EMERGENCY 0x006250
 
28
#define OFFSET_GLISTS    0x00f420
 
29
#define OFFSET_ZONES     0x0151e0
 
30
#define OFFSET_SCANL     0x019060
 
31
#define OFFSET_VFO_A     0x02f700
 
32
#define OFFSET_VFO_B     0x02f740
 
33
#define OFFSET_ZONEXT    0x031800
 
34
#define OFFSET_GPS_SYS   0x03f440
 
35
// ---- second segment ----
 
36
#define OFFSET_CHANNELS  0x110800
 
37
#define OFFSET_CONTACTS  0x140800
 
38
// ---- thrid segement ----
 
39
#define CALLSIGN_START   0x00200000  // Start of callsign database
 
40
#define CALLSIGN_END     0x01000000  // End of callsign database
 
41
#define CALLSIGN_OFFSET  0x00204003  // Start of callsign entries
41
42
 
42
43
 
43
44
/* ******************************************************************************************** *
276
277
    const DigitalChannel *dchan = chan->as<const DigitalChannel>();
277
278
    channel_mode = MODE_DIGITAL;
278
279
    switch (dchan->admit()) {
279
 
    case DigitalChannel::AdmitNone: admit_criteria = ADMIT_ALWAYS;
280
 
    case DigitalChannel::AdmitFree: admit_criteria = ADMIT_CH_FREE;
281
 
    case DigitalChannel::AdmitColorCode: admit_criteria = ADMIT_COLOR;
 
280
    case DigitalChannel::AdmitNone: admit_criteria = ADMIT_ALWAYS; break;
 
281
    case DigitalChannel::AdmitFree: admit_criteria = ADMIT_CH_FREE; break;
 
282
    case DigitalChannel::AdmitColorCode: admit_criteria = ADMIT_COLOR; break;
282
283
    }
283
284
    color_code = dchan->colorCode();
284
285
    time_slot = (DigitalChannel::TimeSlot1 == dchan->timeslot()) ? 1 : 2;
285
286
    group_list_index = conf->rxGroupLists()->indexOf(dchan->rxGroupList()) + 1;
286
287
    contact_name_index = conf->contacts()->indexOfDigital(dchan->txContact()) + 1;
 
288
    squelch = 0;
 
289
    bandwidth = BW_12_5_KHZ;
 
290
    ctcss_dcs_receive = 0xffff;
 
291
    ctcss_dcs_transmit = 0xffff;
287
292
    if (dchan->gpsSystem()) {
288
293
      gps_system = conf->gpsSystems()->indexOf(dchan->gpsSystem())+1;
289
294
      send_gps_info = 0;
295
300
    bandwidth = ((AnalogChannel::BWNarrow == achan->bandwidth()) ? BW_12_5_KHZ : BW_25_KHZ);
296
301
    squelch = achan->squelch();
297
302
    switch (achan->admit()) {
298
 
    case AnalogChannel::AdmitNone: admit_criteria = ADMIT_ALWAYS;
299
 
    case AnalogChannel::AdmitFree: admit_criteria = ADMIT_CH_FREE;
300
 
    case AnalogChannel::AdmitTone: admit_criteria = ADMIT_TONE;
 
303
    case AnalogChannel::AdmitNone: admit_criteria = ADMIT_ALWAYS; break;
 
304
    case AnalogChannel::AdmitFree: admit_criteria = ADMIT_CH_FREE; break;
 
305
    case AnalogChannel::AdmitTone: admit_criteria = ADMIT_TONE; break;
301
306
    }
302
307
    ctcss_dcs_receive = encode_ctcss_tone_table(achan->rxTone());
303
308
    ctcss_dcs_transmit = encode_ctcss_tone_table(achan->txTone());
 
309
    group_list_index = 0;
 
310
    contact_name_index = 0;
304
311
  }
305
312
}
306
313
 
712
719
  mic_level = 0;
713
720
  edit_radio_id = 0;
714
721
  _unused_160_7 = 1;
 
722
 
 
723
  memset(_reserved_161, 0xff, sizeof(_reserved_161));
715
724
}
716
725
 
717
726
QTimeZone
805
814
 
806
815
void
807
816
UV390Codeplug::general_settings_t::fromConfigObj(const Config *conf) {
 
817
  // Set only those elements configured, preserve the rest as already configured in the radio.
808
818
  setName(conf->name());
809
819
  setRadioId(conf->id());
810
820
  setIntroLine1(conf->introLine1());
811
821
  setIntroLine2(conf->introLine2());
812
822
  setTimeZone();
813
 
  mic_level = conf->micLevel()/2;
 
823
  mic_level = (conf->micLevel()-1)/2;
814
824
  channel_voice_announce = (conf->speech() ? 1 : 0);
815
825
}
816
826
 
957
967
  setRepeatInterval(l->period());
958
968
}
959
969
 
 
970
 
 
971
/* ******************************************************************************************** *
 
972
 * Implementation of UV390Codeplug::buttons_t
 
973
 * ******************************************************************************************** */
 
974
UV390Codeplug::buttons_t::buttons_t()
 
975
{
 
976
  clear();
 
977
}
 
978
 
 
979
void
 
980
UV390Codeplug::buttons_t::clear() {
 
981
  _reserved_0 = 0x0000;
 
982
  side_button_1 = Disabled;
 
983
  side_button_1_long = Tone1750Hz;
 
984
  side_button_2 = MonitorToggle;
 
985
  side_button_2_long = Disabled;
 
986
  memset(_unused_6, 0x00, sizeof(_unused_6));
 
987
  _unknown_16 = 0x01;
 
988
  long_press_dur = 0x04;
 
989
  _unused_18 = 0xffff;
 
990
  for (int i=0; i<6; i++)
 
991
    one_touch[i].clear();
 
992
  memset(_unused_42, 0x00, sizeof(_unused_42));
 
993
}
 
994
 
 
995
 
 
996
/* ******************************************************************************************** *
 
997
 * Implementation of UV390Codeplug::emergency_t
 
998
 * ******************************************************************************************** */
 
999
UV390Codeplug::emergency_t::emergency_t() {
 
1000
  clear();
 
1001
}
 
1002
 
 
1003
void
 
1004
UV390Codeplug::emergency_t::clear() {
 
1005
  radio_dis_dec = 1;
 
1006
  remote_mon_decode = 0;
 
1007
  em_remote_mon_decode = 1;
 
1008
  _unknown_0_3 = 0b11111;
 
1009
 
 
1010
  remote_mon_dur = 1;
 
1011
  tx_sync_wakeup_tot = 5;
 
1012
  tx_wakeup_msg_limit = 2;
 
1013
  memset(_unused_4, 0xff, sizeof(_unused_4));
 
1014
 
 
1015
  for (int i=0; i<32; i++)
 
1016
    systems[i].clear();
 
1017
}
 
1018
 
 
1019
/* ******************************************************************************************** *
 
1020
 * Implementation of UV390Codeplug::emergency_t::system_t
 
1021
 * ******************************************************************************************** */
 
1022
UV390Codeplug::emergency_t::system_t::system_t() {
 
1023
  clear();
 
1024
}
 
1025
 
 
1026
void
 
1027
UV390Codeplug::emergency_t::system_t::clear() {
 
1028
  memset(name, 0x00, sizeof(name));
 
1029
  alarm_type = DISABLED;
 
1030
  _unknown_32_2 = 0b11;
 
1031
  alarm_mode = ALARM;
 
1032
  _unknown_32_6 = 0b01;
 
1033
  impolite_retires = 15;
 
1034
  polite_retries = 5;
 
1035
  hot_mic_dur = 10;
 
1036
  revert_channel = 0x0000;
 
1037
  _unused_37 = 0xffff;
 
1038
}
 
1039
 
 
1040
bool
 
1041
UV390Codeplug::emergency_t::system_t::isValid() const {
 
1042
  return 0x0000 != revert_channel;
 
1043
}
 
1044
 
 
1045
 
 
1046
/* ******************************************************************************************** *
 
1047
 * Implementation of UV390Codeplug::privacy_t
 
1048
 * ******************************************************************************************** */
 
1049
UV390Codeplug::privacy_t::privacy_t() {
 
1050
  clear();
 
1051
}
 
1052
 
 
1053
void
 
1054
UV390Codeplug::privacy_t::clear() {
 
1055
  memset(enhanced_keys, 0xff, sizeof(enhanced_keys));
 
1056
  memset(_reserved, 0xff, sizeof(_reserved));
 
1057
  memset(basic_keys, 0xff, sizeof(basic_keys));
 
1058
}
 
1059
 
 
1060
 
 
1061
/* ******************************************************************************************** *
 
1062
 * Implementation of UV390Codeplug::buttons_t::one_touch_t
 
1063
 * ******************************************************************************************** */
 
1064
void
 
1065
UV390Codeplug::buttons_t::one_touch_t::clear() {
 
1066
  action        = CALL;
 
1067
  type          = Disabled;
 
1068
  _reserved_0_6 = 0b11;
 
1069
  message       = 0;
 
1070
  contact       = 0;
 
1071
}
 
1072
 
 
1073
 
 
1074
/* ******************************************************************************************** *
 
1075
 * Implementation of UV390Codeplug::menu_t
 
1076
 * ******************************************************************************************** */
 
1077
UV390Codeplug::menu_t::menu_t() {
 
1078
  clear();
 
1079
}
 
1080
 
 
1081
void
 
1082
UV390Codeplug::menu_t::clear() {
 
1083
  hangtime           = 0;
 
1084
 
 
1085
  text_message       = 1;
 
1086
  call_alert         = 1;
 
1087
  contacts_edit      = 1;
 
1088
  manual_dial        = 1;
 
1089
  radio_check        = 0;
 
1090
  remote_monitor     = 0;
 
1091
  radio_disable      = 0;
 
1092
  radio_enable       = 0;
 
1093
 
 
1094
  _reserved_2_0      = 1;
 
1095
  scan               = 1;
 
1096
  edit_scan_list     = 1;
 
1097
  calllog_missed     = 1;
 
1098
  calllog_answered   = 1;
 
1099
  calllog_outgoing   = 1;
 
1100
  talkaround         = 0;
 
1101
  tone_or_alert      = 1;
 
1102
 
 
1103
  power              = 1;
 
1104
  backlight          = 1;
 
1105
  intro_screen       = 1;
 
1106
  keypad_lock        = 1;
 
1107
  led_indicator      = 1;
 
1108
  squelch            = 1;
 
1109
  _unknown_3_6       = 0;
 
1110
  vox                = 1;
 
1111
 
 
1112
  password           = 0;
 
1113
  display_mode       = 1;
 
1114
  hide_prog_radio    = 0;
 
1115
  _unknown_4_3       = 1;
 
1116
  hide_gps           = 0;
 
1117
  record_switch      = 1;
 
1118
  _unknown_4_6       = 0b11;
 
1119
 
 
1120
  _unknown_5_0       = 0b11;
 
1121
  group_call_match   = 1;
 
1122
  private_call_match = 1;
 
1123
  menu_hangtime      = 1;
 
1124
  tx_mode            = 1;
 
1125
  zone               = 1;
 
1126
  new_zone           = 1;
 
1127
 
 
1128
  edit_zone          = 1;
 
1129
  new_scan_list      = 1;
 
1130
  _unknown_6_2       = 0b111111;
 
1131
 
 
1132
  memset(_reserved_7, 0xff, sizeof(_reserved_7));
 
1133
}
 
1134
 
 
1135
/* ******************************************************************************************** *
 
1136
 * Implementation of UV390Codeplug::callsign_db_t
 
1137
 * ******************************************************************************************** */
 
1138
UV390Codeplug::callsign_db_t::entry_t::entry_t() {
 
1139
  clear();
 
1140
}
 
1141
 
 
1142
void
 
1143
UV390Codeplug::callsign_db_t::entry_t::clear() {
 
1144
  id_high = 0xfff;
 
1145
  index   = 0xfffff;
 
1146
}
 
1147
 
 
1148
bool
 
1149
UV390Codeplug::callsign_db_t::entry_t::isValid() const {
 
1150
  return (0xfff != id_high) && (0xfffff != index);
 
1151
}
 
1152
 
 
1153
UV390Codeplug::callsign_db_t::callsign_t::callsign_t() {
 
1154
  clear();
 
1155
}
 
1156
 
 
1157
void
 
1158
UV390Codeplug::callsign_db_t::callsign_t::clear() {
 
1159
  memset(dmrid, 0xff, sizeof(dmrid));
 
1160
  _unused = 0xff;
 
1161
  memset(callsign, 0xff, sizeof(callsign));
 
1162
  memset(name, 0xff, sizeof(name));
 
1163
}
 
1164
 
 
1165
bool
 
1166
UV390Codeplug::callsign_db_t::callsign_t::isValid() const {
 
1167
  return (0xff != dmrid[0]) && (0xff != dmrid[1]) && (0xff != dmrid[2]);
 
1168
}
 
1169
 
 
1170
void
 
1171
UV390Codeplug::callsign_db_t::callsign_t::setID(uint32_t dmrid) {
 
1172
  encode_dmr_id_bcd(this->dmrid, dmrid);
 
1173
}
 
1174
 
 
1175
void
 
1176
UV390Codeplug::callsign_db_t::callsign_t::setCall(const QString &call) {
 
1177
  memset(callsign, 0xff, sizeof(callsign));
 
1178
  strncpy(callsign, call.toStdString().c_str(), sizeof(callsign));
 
1179
}
 
1180
 
 
1181
void
 
1182
UV390Codeplug::callsign_db_t::callsign_t::setName(const QString &name) {
 
1183
  memset(this->name, 0xff, sizeof(this->name));
 
1184
  strncpy(this->name, name.toStdString().c_str(), sizeof(this->name));
 
1185
}
 
1186
 
 
1187
void
 
1188
UV390Codeplug::callsign_db_t::callsign_t::fromUser(const UserDatabase::User &user) {
 
1189
  setID(user.id);
 
1190
  setCall(user.call);
 
1191
  QString name = user.name;
 
1192
  if (! user.surname.isEmpty())
 
1193
    name += " " + user.surname;
 
1194
  if (! user.country.isEmpty())
 
1195
    name += ", " + user.country;
 
1196
  setName(name);
 
1197
}
 
1198
 
 
1199
UV390Codeplug::callsign_db_t::callsign_db_t() {
 
1200
  clear();
 
1201
}
 
1202
 
 
1203
void
 
1204
UV390Codeplug::callsign_db_t::clear() {
 
1205
  n = 0;
 
1206
  for (int i=0; i<4096; i++)
 
1207
    index[i].clear();
 
1208
  for (int i=0; i<122197; i++)
 
1209
    db[i].clear();
 
1210
}
 
1211
 
 
1212
void
 
1213
UV390Codeplug::callsign_db_t::fromUserDB(const UserDatabase *db) {
 
1214
  // Clear database and index
 
1215
  clear();
 
1216
  // Limit users to 122197 entries
 
1217
  n = std::min(122197ll, db->count());
 
1218
  // If there are no users -> done.
 
1219
  if (0 == n)
 
1220
    return;
 
1221
 
 
1222
  // Select n users and sort them in ascending order of their IDs
 
1223
  QVector<UserDatabase::User> users;
 
1224
  for (int i=0; i<n; i++)
 
1225
    users.append(db->user(i));
 
1226
  std::sort(users.begin(), users.end(),
 
1227
            [](const UserDatabase::User &a, const UserDatabase::User &b) { return a.id < b.id; });
 
1228
 
 
1229
  // First index entry
 
1230
  int  j = 0;
 
1231
  uint cidh = (users[0].id >> 12);
 
1232
  this->index[j].id_high = cidh;
 
1233
  this->index[j].index = 1;
 
1234
  j++;
 
1235
 
 
1236
  // Store users and update index
 
1237
  for (int i=0; i<n; i++) {
 
1238
    this->db[i].fromUser(users[i]);
 
1239
    uint idh = (users[i].id >> 12);
 
1240
    if (idh != cidh) {
 
1241
      this->index[j].id_high = idh;
 
1242
      this->index[j].index = i+1;
 
1243
      cidh = idh; j++;
 
1244
    }
 
1245
  }
 
1246
}
 
1247
 
 
1248
 
960
1249
/* ******************************************************************************************** *
961
1250
 * Implementation of UV390Codeplug
962
1251
 * ******************************************************************************************** */
966
1255
  addImage("TYT MD-UV390 Codeplug");
967
1256
  image(0).addElement(0x002800, 0x3e000);
968
1257
  image(0).addElement(0x110800, 0x90000);
969
 
 
970
1258
  // Clear entire codeplug
 
1259
  clear();
 
1260
}
 
1261
 
 
1262
void
 
1263
UV390Codeplug::clear()
 
1264
{
 
1265
  // Clear entire images
 
1266
  memset(data(0x002800), 0xff, 0x3e000);
 
1267
  memset(data(0x110800), 0xff, 0x90000);
971
1268
 
972
1269
  // Clear timestamp
973
1270
  ((timestamp_t *)(data(OFFSET_TIMESTMP)))->set();
974
 
  // Clear some unused memory sections
975
 
  memset(data(0x00280c),0xff,52);
 
1271
 
976
1272
  // Clear general config
977
1273
  ((general_settings_t *)(data(OFFSET_SETTINGS)))->clear();
978
 
  // Clear contacts
979
 
  for (int i=0; i<NCONTACTS; i++)
980
 
    ((contact_t *)(data(OFFSET_CONTACTS+i*sizeof(contact_t))))->clear();
 
1274
 
 
1275
  // Clear menu settings
 
1276
  ((menu_t *)(data(OFFSET_MENU)))->clear();
 
1277
 
 
1278
  // Clear button settings
 
1279
  ((buttons_t *)(data(OFFSET_BUTTONS)))->clear();
 
1280
 
 
1281
  // Clear text messages
 
1282
  for (int i=0; i<NMESSAGES; i++)
 
1283
    ((message_t *)(data(OFFSET_MSG+i*sizeof(message_t))))->clear();
 
1284
 
 
1285
  // Clear privacy keys
 
1286
  ((privacy_t *)(data(OFFSET_PRIVACY)))->clear();
 
1287
 
 
1288
  // Clear emergency systems
 
1289
  ((emergency_t *)(data(OFFSET_EMERGENCY)))->clear();
 
1290
 
981
1291
  // Clear RX group lists
982
1292
  for (int i=0; i<NGLISTS; i++)
983
1293
    ((grouplist_t *)(data(OFFSET_GLISTS+i*sizeof(grouplist_t))))->clear();
984
 
  // Clear channels
985
 
  for (int i=0; i<NCHAN; i++)
986
 
    ((channel_t *)(data(OFFSET_CHANNELS+i*sizeof(channel_t))))->clear();
987
 
  // Clear zones
 
1294
 
 
1295
  // Clear zones & zone extensions
988
1296
  for (int i=0; i<NZONES; i++) {
989
1297
    ((zone_t *)(data(OFFSET_ZONES+i*sizeof(zone_t))))->clear();
990
1298
    ((zone_ext_t*)(data(OFFSET_ZONEXT+i*sizeof(zone_ext_t))))->clear();
991
1299
  }
 
1300
 
992
1301
  // Clear scan lists
993
1302
  for (int i=0; i<NSCANL; i++)
994
1303
    ((scanlist_t *)(data(OFFSET_SCANL+i*sizeof(scanlist_t))))->clear();
 
1304
 
 
1305
  // Clear VFO A & B settings.
 
1306
  ((channel_t *)(data(OFFSET_VFO_A)))->clear();
 
1307
  ((channel_t *)(data(OFFSET_VFO_B)))->clear();
 
1308
 
 
1309
  // Clear GPS systems
 
1310
  for (int i=0; i<NGPSSYSTEMS; i++)
 
1311
    ((gpssystem_t *)(data(OFFSET_GPS_SYS+i*sizeof(gpssystem_t))))->clear();
 
1312
 
 
1313
  // Clear channels
 
1314
  for (int i=0; i<NCHAN; i++)
 
1315
    ((channel_t *)(data(OFFSET_CHANNELS+i*sizeof(channel_t))))->clear();
 
1316
 
 
1317
  // Clear contacts
 
1318
  for (int i=0; i<NCONTACTS; i++)
 
1319
    ((contact_t *)(data(OFFSET_CONTACTS+i*sizeof(contact_t))))->clear();
995
1320
}
996
1321
 
997
1322
bool
998
1323
UV390Codeplug::encode(Config *config) {
999
 
  // Some unused memory sections
1000
 
  memset(data(0x00280c),0xff,52);
1001
 
 
1002
1324
  // Set timestamp
1003
1325
  ((timestamp_t *)(data(OFFSET_TIMESTMP)))->set();
1004
1326
 
1064
1386
      gps->clear();
1065
1387
  }
1066
1388
 
 
1389
  // Define User DataBase (ContactCSV)
 
1390
  // If userdatabase is given and not defined yet -> allocate user DB
 
1391
  if (config->uploadUserDB() && config->hasUserDB() && (2 == this->image(0).numElements()))
 
1392
    this->image(0).addElement(CALLSIGN_START, CALLSIGN_END-CALLSIGN_START);
 
1393
  // If user database is given and defined -> reset and fill user DB.
 
1394
  if (config->uploadUserDB() && config->hasUserDB() && (3 == this->image(0).numElements())) {
 
1395
    // clear DB memory
 
1396
    memset(data(CALLSIGN_START), 0xff, CALLSIGN_END-CALLSIGN_START);
 
1397
    ((callsign_db_t *)data(CALLSIGN_START))->fromUserDB(config->userDB());
 
1398
  }
1067
1399
 
1068
1400
  return true;
1069
1401
}