File: opengd77base_codeplug.hh

package info (click to toggle)
qdmr 0.13.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 22,236 kB
  • sloc: cpp: 93,672; xml: 10,526; python: 1,108; makefile: 78; sh: 10
file content (1480 lines) | stat: -rw-r--r-- 53,681 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
#ifndef OPENGD77BASE_CODEPLUG_HH
#define OPENGD77BASE_CODEPLUG_HH

#include "channel.hh"
#include "codeplug.hh"
#include "gpssystem.hh"
#include "contact.hh"
#include "zone.hh"
#include "satellitedatabase.hh"

#include <QGeoCoordinate>

/** Base codeplug for all OpenGD77 based firmware variants.
 * @ingroup ogd77 */
class OpenGD77BaseCodeplug : public Codeplug
{
  Q_OBJECT

public:
  /** Possible image types. */
  enum ImageType { EEPROM = 0, FLASH = 1 };

public:
  /** Encodes an angle used to store locations. */
  static uint32_t encodeAngle(double degee);
  /** Decodes an angle used to store locations. */
  static double decodeAngle(uint32_t code);

  /** Encodes a selective call (tx/rx tone). */
  static uint16_t encodeSelectiveCall(const SelectiveCall &call);
  /** Decodes a selective call (tx/rx tone). */
  static SelectiveCall decodeSelectiveCall(uint16_t code);

public:
  /** Implements the base for all OpenGD77 channel encodings. */
  class ChannelElement: public Codeplug::Element
  {
  public:
    /** Possible channel types. */
    enum Mode {
      MODE_ANALOG = 0,   ///< Analog channel, aka FM.
      MODE_DIGITAL = 1   ///< Digital channel, aka DMR.
    };

    /** Alias to transmit. */
    enum class Alias {
      None = 0, APRS = 1, Text = 2, Both = 3
    };

    /** Possible squelch modes. */
    enum class SquelchMode {
      Global, Open, Normal, Closed
    };

  protected:
    /** Constructs a channel from the given memory. */
    ChannelElement(uint8_t *ptr, size_t size);

  public:
    /** Constructs a channel from the given memory. */
    explicit ChannelElement(uint8_t *ptr);
    /** Destructor. */
    virtual ~ChannelElement();

    /** The size of the channel. */
    static constexpr unsigned int size() { return 0x0038; }

    /** Resets the channel. */
    virtual void clear();

    /** Returns the name of the channel. */
    virtual QString name() const;
    /** Sets the name of the channel. */
    virtual void setName(const QString &n);

    /** Returns the RX frequency of the channel. */
    virtual Frequency rxFrequency() const;
    /** Sets the RX frequency of the channel. */
    virtual void setRXFrequency(const Frequency &freq);
    /** Returns the TX frequency of the channel. */
    virtual Frequency txFrequency() const;
    /** Sets the TX frequency of the channel. */
    virtual void setTXFrequency(const Frequency &freq);

    /** Returns the channel mode. */
    virtual Mode mode() const;
    /** Sets the channel mode. */
    virtual void setMode(Mode mode);

    /** Returns @c true if the power-setting is global. */
    virtual bool globalPower() const;
    /** Returns the power setting of the channel. */
    virtual Channel::Power power() const;
    /** Sets the power setting of the channel. */
    virtual void setPower(Channel::Power pwr);
    /** Clears the power setting. The global power setting is used. */
    virtual void clearPower();

    /** Returns the transmit timeout.
     * An invalid interval indicates an infinite timeout. */
    virtual Interval transmitTimeout() const;
    /** Sets a transmit timeout.
     * To disable the timeout, set an invalid interval. */
    virtual void setTransmitTimeout(const Interval &interval);

    /** Returns @c true, if a fixed position is set for the channel. */
    virtual bool hasFixedPosition() const;
    /** Returns the fixed position. */
    virtual QGeoCoordinate fixedPosition() const;
    /** Sets the fixed position for this channel. */
    virtual void setFixedPosition(const QGeoCoordinate &coordinate);
    /** Resets the fixed position. */
    virtual void clearFixedPosition();

    /** Returns the RX subtone. */
    virtual SelectiveCall rxTone() const;
    /** Sets the RX subtone. */
    virtual void setRXTone(const SelectiveCall &code);
    /** Returns the TX subtone. */
    virtual SelectiveCall txTone() const;
    /** Sets the TX subtone. */
    virtual void setTXTone(const SelectiveCall &code);

    /** Returns @c true if the channel is set to simplex. */
    virtual bool isSimplex() const;
    /** Sets the channel to simplex. */
    virtual void enableSimplex(bool enable);

    /** Returns @c true, if the power-save feature is enabled. */
    virtual bool powerSave() const;
    /** Enables/disables power-save. */
    virtual void enablePowerSave(bool enable);

    /** Returns @c true, if the "beep" is enabled. */
    virtual bool beep() const;
    /** Enables/disables "the beep". */
    virtual void enableBeep(bool enable);

    /** Returns @c true if the global DMR ID is overridden. */
    virtual bool hasDMRId() const;
    /** Retruns the DMR ID for this channel. */
    virtual unsigned int dmrId() const;
    /** Sets the DMR ID for this channel. */
    virtual void setDMRId(unsigned int id);
    /** Resets the DMR ID for this channel to the global one. */
    virtual void clearDMRId();

    /** Returns @c true if a group list is set. */
    virtual bool hasGroupList() const;
    /** Returns the group-list index. */
    virtual unsigned groupListIndex() const;
    /** Sets the group-list index. */
    virtual void setGroupListIndex(unsigned index);
    /** Clears the group list index. */
    virtual void clearGroupListIndex();

    /** Returns the color code. */
    virtual unsigned colorCode() const;
    /** Sets thecolor code. */
    virtual void setColorCode(unsigned cc);

    /** Returns @c true, if the APRS system index is set. */
    virtual bool hasAPRSIndex() const;
    /** Returns the APRS system index. */
    virtual unsigned int aprsIndex() const;
    /** Sets the APRS system index. */
    virtual void setAPRSIndex(unsigned int index);
    /** Resets the APRS system index. */
    virtual void clearAPRSIndex();

    /** Returns @c true, if the TX contact is set. */
    virtual bool hasTXContact() const;
    /** Returns the TX contact index. */
    virtual unsigned int txContactIndex() const;
    /** Sets the TX contact index. */
    virtual void setTXContactIndex(unsigned int index);
    /** Clears the TX contact index. */
    virtual void clearTXContact();

    /** Returns the alias transmitted on time slot 1. */
    virtual OpenGD77ChannelExtension::TalkerAlias aliasTimeSlot1() const;
    /** Sets the alias transmitted on time slot 1. */
    virtual void setAliasTimeSlot1(OpenGD77ChannelExtension::TalkerAlias alias);
    /** Returns the alias transmitted on time slot 2. */
    virtual OpenGD77ChannelExtension::TalkerAlias aliasTimeSlot2() const;
    /** Sets the alias transmitted on time slot 2. */
    virtual void setAliasTimeSlot2(OpenGD77ChannelExtension::TalkerAlias alias);

    /** Returns the time slot of the channel. */
    virtual DMRChannel::TimeSlot timeSlot() const;
    /** Sets the time slot of the channel. */
    virtual void setTimeSlot(DMRChannel::TimeSlot ts);

    /** Returns the bandwidth. */
    virtual FMChannel::Bandwidth bandwidth() const;
    /** Sets the bandwidth. */
    virtual void setBandwidth(FMChannel::Bandwidth bw);

    /** Returns @c true if RX only is enabled. */
    virtual bool rxOnly() const;
    /** Enables/disables RX only. */
    virtual void enableRXOnly(bool enable);

    /** Returns @c true if channel is skipped in a scan. */
    virtual bool skipScan() const;
    /** Enables/disables skipping in scan. */
    virtual void enableSkipScan(bool enable);
    /** Returns @c true if channel is skipped in zone scan. */
    virtual bool skipZoneScan() const;
    /** Enables/disables skipping in zone scan. */
    virtual void enableSkipZoneScan(bool enable);

    /** Returns @c true if VOX is enabled. */
    virtual bool vox() const;
    /** Enables/disables VOX. */
    virtual void enableVOX(bool enable);

    /** Returns the squelch mode*/
    virtual SquelchMode squelchMode() const;
    /** Retunrs the squelch level. */
    virtual unsigned int squelchLevel() const;
    /** Set the squelch level and mode. Level is ignored, if mode is not normal.*/
    virtual void setSquelch(SquelchMode mode, unsigned int level);

    /** Constructs a generic @c Channel object from the codeplug channel. */
    virtual Channel *decode(Context &ctx, const ErrorStack &err=ErrorStack()) const;
    /** Links a previously constructed channel to the rest of the configuration. */
    virtual bool link(Channel *c, Context &ctx, const ErrorStack &err=ErrorStack()) const;
    /** Initializes this codeplug channel from the given generic configuration. */
    virtual bool encode(const Channel *c, Context &ctx, const ErrorStack &err=ErrorStack());

  public:
    /** Some limits for this element. */
    struct Limit {
      /** The maximum length of the name. */
      static constexpr unsigned int nameLength() { return 16; }
    };

  protected:
    /** Some internal offsets within the channel element. */
    struct Offset: public Element::Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int name() { return 0x0000; }
      static constexpr unsigned int rxFrequency() { return 0x0010; }
      static constexpr unsigned int txFrequency() { return 0x0014; }
      static constexpr unsigned int mode() { return 0x0018; }
      static constexpr unsigned int power() { return 0x0019; }
      static constexpr unsigned int latitude0() { return 0x001a; }
      static constexpr unsigned int txTimeout() { return 0x001b; }
      static constexpr unsigned int latitude1() { return 0x001c; }
      static constexpr unsigned int latitude2() { return 0x001d; }
      static constexpr unsigned int longitude0() { return 0x001e; }
      static constexpr unsigned int longitude1() { return 0x001f; }
      static constexpr unsigned int rxTone() { return 0x0020; }
      static constexpr unsigned int txTone() { return 0x0022; }
      static constexpr unsigned int longitude2() { return 0x0024; }
      static constexpr Bit simplex() { return {0x0026, 2}; }
      static constexpr Bit useFixedLocation() { return {0x0026, 3}; }
      static constexpr Bit disablePowerSave() { return {0x0026, 5}; }
      static constexpr Bit disableBeep() { return {0x0026, 6}; }
      static constexpr Bit overrideDMRID() { return {0x0026, 7}; }
      static constexpr unsigned int dmrId() { return 0x0027; }
      static constexpr unsigned int groupList() { return 0x002b; }
      static constexpr unsigned int colorCode() { return 0x002c; }
      static constexpr unsigned int aprsIndex() { return 0x002d; }
      static constexpr unsigned int txContact() { return 0x002e; }
      static constexpr Bit aliasTimeSlot2() { return { 0x030, 2}; }
      static constexpr Bit aliasTimeSlot1() { return { 0x030, 0}; }
      static constexpr Bit timeSlot() { return {0x0031, 6}; }
      static constexpr Bit bandwidth() { return {0x0033, 1}; }
      static constexpr Bit rxOnly() { return {0x0033, 2}; }
      static constexpr Bit skipScan() { return {0x0033, 4}; }
      static constexpr Bit skipZoneScan() { return {0x0033, 5}; }
      static constexpr Bit vox() { return {0x0033, 6}; }
      static constexpr unsigned int squelch() { return 0x0037; }
      /// @endcond
    };
  };


  /** Implements the base for channel banks in Radioddity codeplugs.
   *
   * Memory layout of a channel bank:
   * @verbinclude radioddity_channelbank.txt */
  class ChannelBankElement: public Element
  {
  protected:
    /** Hidden constructor. */
    ChannelBankElement(uint8_t *ptr, unsigned size);

  public:
    /** Constructor. */
    explicit ChannelBankElement(uint8_t *ptr);
    /** Destructor. */
    virtual ~ChannelBankElement();

    /** The size of the channel bank. */
    static constexpr unsigned int size() { return 0x1c10; }

    /** Clears the bank. */
    void clear();

    /** Returns @c true if the channel is enabled. */
    virtual bool isEnabled(unsigned idx) const ;
    /** Enable/disable a channel in the bank. */
    virtual void enable(unsigned idx, bool enabled);
    /** Returns a pointer to the channel at the given index. */
    virtual uint8_t *get(unsigned idx) const;
    /** Retunrs the n-th channel. */
    ChannelElement channel(unsigned int n);

  public:
    /** Some limits for the channel bank. */
    struct Limit {
      /** The maximum number of channels. */
      static constexpr unsigned int channelCount() { return 128; }
    };

  protected:
    /** Some internal offset within the element. */
    struct Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int bitmask() { return 0x0000; }
      static constexpr unsigned int channels() { return 0x0010; }
      /// @endcond
    };
  };


  /** VFO Channel representation within the binary codeplug.
   *
   * Each channel requires 0x38b:
   * @verbinclude radioddity_vfochannel.txt */
  class VFOChannelElement: public ChannelElement
  {
  public:
    /** Possible offset frequency modes. */
    enum class OffsetMode {
      Off = 0,       ///< Disables transmit frequency offset.
      Positive = 1,  ///< Transmit offset frequency is positive (TX above RX).
      Negative = 2   ///< Transmit offset frequency is negative (TX below RX).
    };

    /** Possible tuning step sizes. */
    enum class StepSize {
      SS2_5kHz = 0,  ///< 2.5kHz
      SS5kHz = 1,    ///< 5kHz
      SS6_25kHz = 2, ///< 6.25kHz
      SS10kHz = 3,   ///< 10kHz
      SS12_5kHz = 4, ///< 12.5kHz
      SS20kHz = 5,   ///< 20kHz
      SS30kHz = 6,   ///< 30kHz
      SS50kHz = 7    ///< 50kHz
    };

  protected:
    /** Hidden constructor. */
    VFOChannelElement(uint8_t *ptr, unsigned size);

  public:
    /** Constructor. */
    explicit VFOChannelElement(uint8_t *ptr);

    void clear();

    /** The VFO channel has no name. */
    QString name() const;
    /** The VFO channel has no name. */
    void setName(const QString &name);

    /** Returns the tuning step-size in kHz. */
    virtual double stepSize() const;
    /** Sets the tuning step-size in kHz. */
    virtual void setStepSize(double kHz);

    /** Returns the transmit frequency offset mode. */
    virtual OffsetMode offsetMode() const;
    /** Returns the transmit frequency offset. */
    virtual double txOffset() const;
    /** Sets the transmit frequency offset in MHz. */
    virtual void setTXOffset(double f);
    /** Sets the transmit frequency offset mode. */
    virtual void setOffsetMode(OffsetMode mode);

  protected:
    /// @cond DO_NOT_DOCUMENT
    struct Offset: public ChannelElement::Offset {
      static constexpr Bit stepSize()                         { return {0x0036, 4} ; }
      static constexpr Bit offsetMode()                       { return {0x0036, 2} ; }
      static constexpr unsigned int txOffset()                { return 0x0034; }
    };
    /// @endcond
  };


  /** Encodes the settings element for all OpenGD77 codeplugs. */
  class GeneralSettingsElement: public Element
  {
  protected:
    /** Hidden constructor. */
    GeneralSettingsElement(uint8_t *ptr, size_t size);

  public:
    /** Constructor. */
    GeneralSettingsElement(uint8_t *ptr);

    /** Returns the size of the element. */
    static constexpr unsigned int size() { return 0x0090; }

    void clear();

    /** Returns the UHF minimum frequency. */
    virtual Frequency uhfMinFrequency() const;
    /** Sets the UHF minimum frequency. */
    virtual void setUHFMinFrequency(const Frequency &f);
    /** Returns the UHF maximum frequency. */
    virtual Frequency uhfMaxFrequency() const;
    /** Sets the UHF maximum frequency. */
    virtual void setUHFMaxFrequency(const Frequency &f);

    /** Returns the VHF minimum frequency. */
    virtual Frequency vhfMinFrequency() const;
    /** Sets the VHF minimum frequency. */
    virtual void setVHFMinFrequency(const Frequency &f);
    /** Returns the VHF maximum frequency. */
    virtual Frequency vhfMaxFrequency() const;
    /** Sets the VHF maximum frequency. */
    virtual void setVHFMaxFrequency(const Frequency &f);

    /** Returns the radio callsign. */
    virtual QString call() const;
    /** Sets the radio callsign. */
    virtual void setCall(const QString &call);

    /** Returns the DMR ID. */
    virtual unsigned int radioId() const;
    /** Sets the DMR ID. */
    virtual void setRadioId(unsigned int id);

    /** Encodes the settings. */
    virtual bool encode(const Context &ctx, const ErrorStack &err = ErrorStack());
    /** Decodes the settings. */
    virtual bool decode(const Context &ctx, const ErrorStack &err = ErrorStack());

  public:
    /** Some limits. */
    struct Limit: public Element::Limit {
      /** The maximum call length. */
      static constexpr unsigned int callLength() { return 8; }
    };

  protected:
    /** Some internal offset within the element. */
    struct Offset: public Element::Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int uhfMinFrequency() { return 0x0000; }
      static constexpr unsigned int uhfMaxFrequency() { return 0x0002; }
      static constexpr unsigned int vhfMinFrequency() { return 0x0004; }
      static constexpr unsigned int vhfMaxFrequency() { return 0x0006; }
      static constexpr unsigned int call()            { return 0x0060; }
      static constexpr unsigned int dmrId()           { return 0x0068; }
      /// @endcond
    };
  };


  /** APRS system for OpenGD77 devices. */
  class APRSSettingsElement: public Element
  {
  public:
    /** Possible APRS baud rates. */
    enum class BaudRate {
      Baud300 = 1, Baud1200 = 0
    };

    /** Possible position precisions. */
    enum class PositionPrecision {
      Max = 0,
      Mask1_8sec = 1,
      Mask3_6sec = 2,
      Mask18sec = 3,
      Mask36sec = 4,
      Mask3min = 5,
      Mask6min = 6,
      Mask30min = 7
    };

  public:
    /** Constructor from pointer. */
    explicit APRSSettingsElement(uint8_t *ptr);

  protected:
    /** Hidden constructor. */
    APRSSettingsElement(uint8_t *ptr, size_t size);

  public:
    /** The size of the channel bank. */
    static constexpr unsigned int size() { return 0x40; }

    /** Clears the bank. */
    void clear();

    /** Returns @c true, if the system is valid. */
    virtual bool isValid() const;

    /** Returns the name of the system. */
    virtual QString name() const;
    /** Sets the name of the system. */
    virtual void setName(const QString &name);

    /** Returns the source SSID. */
    virtual unsigned int sourceSSID() const;
    /** Sets the source SSID. */
    virtual void setSourceSSID(unsigned int ssid);

    /** Returns @c true, if a fixed position is send. */
    virtual bool hasFixedPosition() const;
    /** Returns the fixed position. */
    virtual QGeoCoordinate fixedPosition() const;
    /** Sets the fixed position. */
    virtual void setFixedPosition(const QGeoCoordinate &coor);
    /** Resets the fixed position. */
    virtual void clearFixedPosition();

    /** Retunrs the posiiton reporting precision. */
    virtual PositionPrecision positionPrecision() const;
    /** Sets the position reporting precision in degrees. */
    virtual void setPositionPrecision(PositionPrecision prec);

    /** Returns @c true, if the first via node is set. */
    virtual bool hasVia1() const;
    /** Returns the first via node call. */
    virtual QString via1Call() const;
    /** Returns the first via node ssid. */
    virtual unsigned int via1SSID() const;
    /** Sets the first via node. */
    virtual void setVia1(const QString &call, unsigned int ssid);
    /** Clears the first via node. */
    virtual void clearVia1();

    /** Returns @c true, if the second via node is set. */
    virtual bool hasVia2() const;
    /** Returns the second via node call. */
    virtual QString via2Call() const;
    /** Returns the second via node ssid. */
    virtual unsigned int via2SSID() const;
    /** Sets the second via node. */
    virtual void setVia2(const QString &call, unsigned int ssid);
    /** Clears the second via node. */
    virtual void clearVia2();

    /** Retunrs the icon. */
    virtual APRSSystem::Icon icon() const;
    /** Sets the icon. */
    virtual void setIcon(APRSSystem::Icon icon);

    /** Retunrs the comment text. */
    virtual QString comment() const;
    /** Sets the comment text. */
    virtual void setComment(const QString &text);

    /** Retunrs the baud-rate. */
    virtual BaudRate baudRate() const;
    /** Sets the baud rate. */
    virtual void setBaudRate(BaudRate rate);

    Frequency fmFrequency() const;
    void setFMFrequency(Frequency f);

    /** Encodes the APRS settings. */
    virtual bool encode(const APRSSystem *system, const Context &ctx, const ErrorStack &err=ErrorStack());
    /** Decodes some APRS settings. */
    virtual APRSSystem *decode(const Context &ctx, const ErrorStack &err=ErrorStack()) const;
    /** Links the ARPS settings. */
    virtual bool link(APRSSystem *system, const Context &ctx, const ErrorStack &err=ErrorStack());

  public:
    /** Some limits. */
    struct Limit: public Element::Limit {
      /** The maximum name length in chars. */
      static constexpr unsigned int nameLength() { return 8; }
      /** The maximum comment length in chars. */
      static constexpr unsigned int commentLength() { return 23; }
    };

  protected:
    /** Some internal offsets within the element. */
    struct Offset: public Element::Offset
    {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int name() { return 0x0000; }
      static constexpr unsigned int sourceSSID() { return 0x0008; }
      static constexpr unsigned int latitude() { return 0x0009; }
      static constexpr unsigned int longitude() { return 0x000c; }
      static constexpr unsigned int via1Call() { return 0x000f; }
      static constexpr unsigned int via1SSID() { return 0x0015; }
      static constexpr unsigned int via2Call() { return 0x0016; }
      static constexpr unsigned int via2SSID() { return 0x001c; }
      static constexpr unsigned int iconTable() { return 0x001d; }
      static constexpr unsigned int iconIndex() { return 0x001e; }
      static constexpr unsigned int comment() { return 0x001f; }
      static constexpr unsigned int fmFrequency() { return 0x0037; }
      static constexpr Bit positionPrecision() { return { 0x003d, 4}; }
      static constexpr Bit useFixedPosition() { return { 0x003d, 1}; }
      static constexpr Bit baudRate() { return { 0x003d, 0}; }
      static constexpr unsigned int unknownBytes() { return 0x003e; }
      /// @endcond
    };
  };


  /** APRS System bank. */
  class APRSSettingsBankElement: public Element
  {
  public:
    /** Constructor from pointer. */
    explicit APRSSettingsBankElement(uint8_t *ptr);

  protected:
    /** Hidden constructor. */
    APRSSettingsBankElement(uint8_t *ptr, size_t size);

  public:
    /** The size of the channel bank. */
    static constexpr unsigned int size() { return 0x40; }

    /** Clears the bank. */
    void clear();

    /** Retunrs the n-th APRS system. */
    APRSSettingsElement system(unsigned int idx) const;

    /** Encodes all FM APRS systems. */
    virtual bool encode(Context &ctx, const ErrorStack &err=ErrorStack());
    /** Decodes all FM APRS systems. */
    virtual bool decode(Context &ctx, const ErrorStack &err=ErrorStack());
    /** Links all FM APRS systems. */
    virtual bool link(Context &ctx, const ErrorStack &err=ErrorStack());

  public:
    /** Some limits for the bank. */
    struct Limit: public Element::Limit {
      /** The total number of APRS systems. */
      static constexpr unsigned int systems() { return 8; }
    };

  public:
    /// @cond DO_NOT_DOCUMENT
    struct Offset: public Element::Offset {
      static constexpr unsigned int systems() { return 0x0000; }
      static constexpr unsigned int betweenSystems() { return APRSSettingsElement::size(); }
    };
    /// @endcond
  };


  /** DTMF contact element.
   * Just a name and DTMF number. */
  class DTMFContactElement: public Element
  {
  protected:
    /** Hidden constructor. */
    DTMFContactElement(uint8_t *ptr, size_t size);

  public:
    /** Constructor. */
    explicit DTMFContactElement(uint8_t *ptr);

    /** Returns the size of the element. */
    static constexpr unsigned int size() { return 0x0020; }

    void clear();
    bool isValid() const;

    /** Returns the name. */
    virtual QString name() const;
    /** Sets the name. */
    virtual void setName(const QString &name);

    /** Returns the DTMF number. */
    virtual QString number() const;
    /** Sets the DTMF number. */
    virtual void setNumber(const QString &number);

    /** Encodes a number. */
    virtual bool encode(const DTMFContact *contact, const Context &ctx, const ErrorStack &err=ErrorStack());
    /** Decodes a number. */
    virtual DTMFContact *decode(const Context &ctx, const ErrorStack &err=ErrorStack());

  public:
    /** Some limits. Ü*/
    struct Limit: public Element::Limit {
      /** The maximum name length. */
      static constexpr unsigned int nameLength() { return 16; }
      /** The maximum length of the number. */
      static constexpr unsigned int numberLength() { return 16; }
    };

  protected:
    /// @cond DO_NOT_DOCUMENT
    struct Offset: public Element::Offset {
      static constexpr unsigned int name() { return 0x0000; }
      static constexpr unsigned int number() { return 0x0010; }
    };
    /// @endcond
  };


  /** DTMF contact bank. */
  class DTMFContactBankElement: public Element
  {
  protected:
    /** Hidden constructor. */
    DTMFContactBankElement(uint8_t *ptr, size_t size);

  public:
    /** Constructor. */
    DTMFContactBankElement(uint8_t *ptr);

    /** Returns the size of the element. */
    static constexpr unsigned int size() { return Limit::contacts()*DTMFContactElement::size(); }

    void clear();

    /** Returns the n-th DTMF contact. */
    DTMFContactElement contact(unsigned int n) const;

    /** Encodes all DTMF contacts. */
    virtual bool encode(Context &ctx, const ErrorStack &err=ErrorStack());
    /** Decodes all DTMF contacts. */
    virtual bool decode(Context &ctx, const ErrorStack &err=ErrorStack());

  public:
    /** Some limits for the bank. */
    struct Limit: public Element::Limit {
      /** The total number of contacts. */
      static constexpr unsigned int contacts() { return 64; }
    };

  public:
    /// @cond DO_NOT_DOCUMENT
    struct Offset: public Element::Offset {
      static constexpr unsigned int contacts() { return 0x0000; }
      static constexpr unsigned int betweenContacts() { return DTMFContactElement::size(); }
    };
    /// @endcond
  };


  /** Implements the base class of boot settings for all OpenGD77 codeplugs. */
  class BootSettingsElement: public Element
  {
  protected:
    /** Hidden constructor. */
    BootSettingsElement(uint8_t *ptr, unsigned size);

  public:
    /** Constructor. */
    explicit BootSettingsElement(uint8_t *ptr);
    /** Destructor. */
    virtual ~BootSettingsElement();

    /** Resets the settings. */
    void clear();

    /** Returns @c true if the text is shown on boot, other wise an image is shown. */
    virtual bool bootText() const;
    /** Enables/disables boot text. */
    virtual void enableBootText(bool enable);

    /** Returns @c true if the boot password is enabled. */
    virtual bool bootPasswordEnabled() const;
    /** Returns the boot password (6 digit). */
    virtual unsigned bootPassword() const;
    /** Sets the boot password (6 digit). */
    virtual void setBootPassword(unsigned passwd);
    /** Clear boot password. */
    virtual void clearBootPassword();

    /** Returns the first line. */
    virtual QString line1() const;
    /** Sets the first line. */
    virtual void setLine1(const QString &text);
    /** Returns the Second line. */
    virtual QString line2() const;
    /** Sets the second line. */
    virtual void setLine2(const QString &text);

    /** Encodes boot text settings from configuration. */
    virtual bool encode(const Context &ctx, const ErrorStack &err = ErrorStack());
    /** Updates the configuration with the boot text settings. */
    virtual bool decode(Context &ctx, const ErrorStack &err = ErrorStack());

  public:
    /** Some limits for the settings. */
    struct Limit: public Element::Limit {
      /** The total number of contacts. */
      static constexpr unsigned int lineLength() { return 16; }
    };

  public:
    /// @cond DO_NOT_DOCUMENT
    struct Offset: public Element::Offset {
      static constexpr unsigned int bootText() { return 0x0000; }
      static constexpr unsigned int bootPasswdEnable() { return 0x0001; }
      static constexpr unsigned int bootPasswd() { return 0x000c; }
      static constexpr unsigned int line1() { return 0x0028; }
      static constexpr unsigned int line2() { return 0x0038; }
    };
    /// @endcond
  };


  /** Represents a zone within OpenGD77 codeplugs. */
  class ZoneElement: public Element
  {
  protected:
    /** Hidden constructor. */
    ZoneElement(uint8_t *ptr, unsigned size);

  public:
    /** Constructor. */
    explicit ZoneElement(uint8_t *ptr);
    virtual ~ZoneElement();

    /** The size of the zone element. */
    static constexpr unsigned int size() { return 0x00b0; }

    /** Resets the zone. */
    void clear();
    /** Returns @c true if the zone is valid. */
    bool isValid() const;

    /** Returns the name of the zone. */
    virtual QString name() const;
    /** Sets the name of the zone. */
    virtual void setName(const QString &name);

    /** Returns @c true if a member is stored at the given index. */
    virtual bool hasMember(unsigned n) const;
    /** Returns the n-th member index. */
    virtual unsigned member(unsigned n) const;
    /** Sets the n-th member index. */
    virtual void setMember(unsigned n, unsigned idx);
    /** Clears the n-th member index. */
    virtual void clearMember(unsigned n);

    /** Resets this codeplug zone representation from the given generic @c Zone object. */
    virtual bool encode(const Zone *zone, Context &ctx, const ErrorStack &err=ErrorStack());
    /** Constructs a generic @c Zone object from this codeplug zone. */
    virtual Zone *decode(const Context &ctx, const ErrorStack &err=ErrorStack()) const;
    /** Links a previously constructed @c Zone object to the rest of the configuration. That is
     * linking to the referred channels. */
    virtual bool link(Zone *zone, Context &ctx, const ErrorStack &err=ErrorStack()) const;

  public:
    /** Some limits for zone elements. */
    struct Limit: public Element::Limit {
      /** The maximum length of the zone name. */
      static constexpr unsigned int nameLength() { return 16; }
      /** The maximum number of members. */
      static constexpr unsigned int memberCount() { return 80; }
    };

  protected:
    /** Some internal offsets within the element. */
    struct Offset: public Element::Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int name()  { return 0x0000; }
      static constexpr unsigned int channels() { return 0x0010; }
      static constexpr unsigned int betweenChannels() { return 0x0002; }
      /// @endcond
    };
  };


  /** Implements the base class for all zone banks of OpenGD77 codeplugs. */
  class ZoneBankElement: public Element
  {
  protected:
    /** Hidden constructor. */
    ZoneBankElement(uint8_t *ptr, unsigned size);

  public:
    /** Constructor. */
    explicit ZoneBankElement(uint8_t *ptr);
    /** Destructor. */
    ~ZoneBankElement();

    /** The size of the zone element. */
    static constexpr unsigned int size() {
      return 0x0020 + Limit::zoneCount()*ZoneElement::size();
    }

    /** Resets the bank. */
    void clear();

    /** Returns @c true if the zone is enabled. */
    virtual bool isEnabled(unsigned idx) const ;
    /** Enable/disable a zone in the bank. */
    virtual void enable(unsigned idx, bool enabled);

    /** Retunrs the n-th zone. */
    ZoneElement zone(unsigned int n);

    /** Encodes all zones. */
    virtual bool encode(Context &ctx, const ErrorStack &err=ErrorStack());
    /** Decodes all zones. */
    virtual bool decode(Context &ctx, const ErrorStack &err=ErrorStack());
    /** Links all zones. */
    virtual bool link(Context &ctx, const ErrorStack &err=ErrorStack());

  public:
    /** Some limits for the zone bank. */
    struct Limit: public Element::Limit {
      /** The maximum number of zones in this bank. */
      static constexpr unsigned int zoneCount() { return 68; }
    };

  protected:
    /** Some internal offsets within the element. */
    struct Offset: public Element::Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int bitmap() { return 0x0000; }
      static constexpr unsigned int zones()  { return 0x0020; }
      static constexpr unsigned int betweenZones() { return ZoneElement::size(); }
      /// @endcond
    };
  };


  /** Implements digital contacts in OpenGD77 codeplugs. */
  class ContactElement: public Element
  {
  public:
    /** Possible values for the time-slot override option.
     * Encoded values are correct for firmware 2022-02-28 (0118581D) to 2025-03-23 (1bd23ea). */
    enum class TimeSlotOverride {
      None = 0x01,                  ///< Do not override time-slot of channel.
      TS1  = 0x00,                  ///< Force time-slot to TS1.
      TS2  = 0x02                   ///< Force time-slot to TS2.
    };

  protected:
    /** Hidden constructor. */
    ContactElement(uint8_t *ptr, unsigned size);

  public:
    /** Constructor. */
    explicit ContactElement(uint8_t *ptr);
    /** Destructor. */
    virtual ~ContactElement();

    /** The size of the contact element. */
    static constexpr unsigned int size() { return 0x0018; }

    /** Resets the contact. */
    void clear();

    /** Returns @c true if the contact is valid. */
    bool isValid() const;

    /** Returns the name of the contact. */
    virtual QString name() const;
    /** Sets the name of the contact. */
    virtual void setName(const QString name);

    /** Returns the DMR number of the contact. */
    virtual unsigned number() const;
    /** Sets the DMR number of the contact. */
    virtual void setNumber(unsigned id);

    /** Returns the call type. */
    virtual DMRContact::Type type() const;
    /** Sets the call type. */
    virtual void setType(DMRContact::Type type);

    /** Returns the time slot override of the contact. */
    virtual TimeSlotOverride timeSlotOverride() const;
    /** Sets the time slot override. */
    virtual void setTimeSlotOverride(TimeSlotOverride ts);

    /** Constructs a @c DigitalContact instance from this codeplug contact. */
    virtual DMRContact *decode(Context &ctx, const ErrorStack &err=ErrorStack()) const;
    /** Resets this codeplug contact from the given @c DigitalContact. */
    virtual bool encode(const DMRContact *obj, Context &ctx, const ErrorStack &err=ErrorStack());

  public:
    /** Some limits for the contact. */
    struct Limit {
      /** Maximum name length. */
      static constexpr unsigned int nameLength() { return 16; }
    };

  protected:
    /** Some internal offsets within the element. */
    struct Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int name() { return 0x0000; }
      static constexpr unsigned int number() { return 0x0010; }
      static constexpr unsigned int type() { return 0x0014; }
      static constexpr unsigned int timeSlotOverride() { return 0x0017; }
      /// @endcond
    };
  };


  /** Encodes the contact bank. */
  class ContactBankElement: public Element
  {
  protected:
    /** Hidden constructor. */
    ContactBankElement(uint8_t *ptr, size_t size);

  public:
    /** Constructor. */
    ContactBankElement(uint8_t *ptr);

    /** The size of the element. */
    static constexpr unsigned int size() {
      return Limit::contactCount() * ContactElement::size();
    }

    /** Resets the contact. */
    void clear();

    /** Returns the i-th contact element. */
    ContactElement contact(unsigned int idx) const;

    /** Encodes all DMR contacts. */
    virtual bool encode(Context &ctx, const ErrorStack &err = ErrorStack());
    /** Decodes all DMR contacts. */
    virtual bool decode(Context &ctx, const ErrorStack &err = ErrorStack());

  public:
    /** Some limits for the element. */
    struct Limit {
      /** Maximum number of contacts. */
      static constexpr unsigned int contactCount() { return 1024; }
    };

  protected:
    /** Some internal offsets within the element. */
    struct Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int contacts() { return 0x0000; }
      static constexpr unsigned int betweenContacts() { return ContactElement::size(); }
      // @endcond
    };
  };


  /** Encodes a group list for all OpenGD77 codeplugs. */
  class GroupListElement: public Element
  {
  protected:
    /** Hidden constructor. */
    GroupListElement(uint8_t *ptr, size_t size);

  public:
    /** Constructor. */
    GroupListElement(uint8_t *ptr);

    /** Returns the size of the element. */
    static constexpr unsigned int size() { return 0x0050; }

    /** Clears the group list. */
    void clear();

    /** Returns the name of the group list. */
    virtual QString name() const;
    /** Sets the name of the group list. */
    virtual void setName(const QString &name);

    /** Returns @c true, if the i-th contact is set. */
    virtual bool hasContactIndex(unsigned int i) const;
    /** Returns the i-th contact index. */
    virtual unsigned int contactIndex(unsigned int i) const;
    /** Sets the i-th contact index. */
    virtual void setContactIndex(unsigned int i, unsigned int contactIdx);
    /** Clears the i-th contact index. */
    virtual void clearContactIndex(unsigned int i);

    /** Encodes group list element. */
    virtual bool encode(RXGroupList *lst, Context &ctx, const ErrorStack &err=ErrorStack());
    /** Decodes group list element. */
    virtual RXGroupList *decode(Context &ctx, const ErrorStack &err=ErrorStack()) const;
    /** Links the group list element. */
    virtual bool link(RXGroupList *lst, Context &ctx, const ErrorStack &err=ErrorStack()) const;

  public:
    /** Some limits for the element. */
    struct Limit {
      /** Maximum name length. */
      static constexpr unsigned int nameLength() { return 15; }
      /** Maximum number of contacts. */
      static constexpr unsigned int contactCount() { return 32; }
    };

  protected:
    /** Some internal offsets within the element. */
    struct Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int name() { return 0x0000; }
      static constexpr unsigned int contacts() { return 0x0010; }
      static constexpr unsigned int betweenContacts() { return 0x0002; }
      // @endcond
    };
  };


  /** Encodes a group list bank for all OpenGD77 codeplugs. */
  class GroupListBankElement: public Element
  {
  protected:
    /** Hidden constructor. */
    GroupListBankElement(uint8_t *ptr, size_t size);

  public:
    /** Constructor. */
    GroupListBankElement(uint8_t *ptr);

    /** Returns the size of the element. */
    static constexpr unsigned int size() { return 0x1840; }

    /** Clears the group list bank. */
    void clear();

    /** Returns @c true, if the i-th group list is encoded. */
    virtual bool hasGroupList(unsigned int i) const;
    /** Returns the number of contacts in the given group list. */
    virtual unsigned int groupListContactCount(unsigned int i) const;
    /** Sets the number of contacts in the given group list. */
    virtual void setGroupListContactCount(unsigned int i, unsigned int count);
    /** Returns the i-th group list. */
    virtual GroupListElement groupList(unsigned int i) const;
    /** Clears the i-th group list. */
    virtual void clearGroupList(unsigned int i);

    /** Encodes all group lists. */
    virtual bool encode(Context &ctx, const ErrorStack &err = ErrorStack());
    /** Decodes all group lists. */
    virtual bool decode(Context &ctx, const ErrorStack &err = ErrorStack());
    /** Links all group lists. */
    virtual bool link(Context &ctx, const ErrorStack &err = ErrorStack());

  public:
    /** Some limits for the element. */
    struct Limit {
      /** Maximum number of group lists. */
      static constexpr unsigned int groupListCount() { return 76; }
    };

  protected:
    /** Some internal offsets within the element. */
    struct Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int length() { return 0x0000; }
      static constexpr unsigned int groupLists() { return 0x0080; }
      static constexpr unsigned int betweenGroupLists() { return GroupListElement::size(); }
      // @endcond
    };
  };

  /** Encodes a satellite for the  OpenGD77 devices.
   * That is a set of orbital elements and transponder information. */
  class SatelliteElement: public Codeplug::Element
  {
  protected:
    /** Hidden constructor. */
    SatelliteElement(uint8_t *ptr, size_t size);

  public:
    /** Constructor. */
    SatelliteElement(uint8_t *ptr);

    /** The size of the element. */
    static constexpr unsigned int size() { return 0x0064; }

    void clear();

    /** Sets the name of the element. */
    virtual void setName(const QString &name);

    /** Sets the epoch. */
    virtual void setEpoch(const ::OrbitalElement::Epoch &epoch);
    /** Sets the first derivative of mean motion. */
    virtual void setMeanMotion(double mm);
    /** Sets the first derivative of mean motion. */
    virtual void setMeanMotionDerivative(double dmm);
    /** Sets the inclination. */
    virtual void setInclination(double incl);
    /** Right ascension of the ascending node. */
    virtual void setAscension(double asc);
    /** Sets eccentricity. */
    virtual void setEccentricity(double ecc);
    /** Sets argument of perigee. */
    virtual void setPerigee(double arg);
    /** Set the mean anomaly. */
    virtual void setMeanAnomaly(double ma);
    /** Sets the revolution number at epoch. */
    virtual void setRevolutionNumber(unsigned int num);

    /** Sets the downlink frequency. */
    void setFMDownlink(const Frequency &f);
    /** Sets the uplink frequency. */
    void setFMUplink(const Frequency &f);
    /** Sets the CTCSS tone. */
    void setCTCSS(const SelectiveCall &call);
    /** Sets the APRS downlink frequency. */
    void setAPRSDownlink(const Frequency &f);
    /** Sets the APRS uplink frequency. */
    void setAPRSUplink(const Frequency &f);

    /** Sets the beacon frequency. */
    void setBeacon(const Frequency &f);

    /** Sets the APRS path. */
    void setAPRSPath(const QString &path);

    /** Encodes a satellite. */
    virtual bool encode(const Satellite &sat, const ErrorStack &err = ErrorStack());

  protected:
    /** Writes a fixed point value as a BCD number. Using 0-9 as digits, ah as decimal dot and bh
     * as blank.
     * @param offset Specifies, where to write the fixed point value.
     * @param value The value to write.
     * @param sign If @c true, a sign is written.
     * @param dec The number of digits in the integer part.
     * @param frac The number of digits in the fractional part.
     */
    void writeFixedPoint(const Offset::Bit &offset, double value, bool sign, unsigned int dec, unsigned int frac);
    /** Writes a fixed point value as a BCD number. Using 0-9 as digits and bh as blank. In contrast
     * to @c writeFixedPoint, this function expects no integer part.
     * @param offset Specifies, where to write the fixed point value.
     * @param value The value to write.
     * @param sign If @c true, a sign is written.
     * @param frac The number of digits in the fractional part.
     */
    void writeFractional(const Offset::Bit &offset, double value, bool sign, unsigned int frac);
    /** Write a fixed digit integer value. */
    void writeInteger(const Offset::Bit &offset, int value, bool sign, unsigned dec);
    /** Writes a single digit at the given offset. */
    void writeDigit(const Offset::Bit &offset, uint8_t digit);

  public:
    /** Some limits for the zone bank. */
    struct Limit: public Element::Limit {
      /** The maximum name length. */
      static constexpr unsigned int nameLength() { return 8; }
      /** Maximum length of the APRS path. */
      static constexpr unsigned int pathLength() { return 24; }
    };

  protected:
    /** Some internal offsets within the element. */
    struct Offset: public Element::Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int name()         { return 0x0000; }
      static constexpr Bit epochYear()             { return {0x0008, 4}; }
      static constexpr Bit epochJulienDay()        { return {0x0009, 4}; }
      static constexpr Bit meanMotionDerivative()  { return {0x000f, 4}; }
      static constexpr Bit inclination()           { return {0x0014, 4}; }
      static constexpr Bit ascension()             { return {0x0018, 4}; }
      static constexpr Bit eccentricity()          { return {0x001c, 4}; }
      static constexpr Bit perigee()               { return {0x001f, 0}; }
      static constexpr Bit meanAnomaly()           { return {0x0023, 0}; }
      static constexpr Bit meanMotion()            { return {0x0027, 0}; }
      static constexpr Bit revolutionNumber()      { return {0x002d, 4}; }
      static constexpr unsigned int fmDownlink()   { return 0x0030; }
      static constexpr unsigned int fmUplink()     { return 0x0034; }
      static constexpr unsigned int ctcss()        { return 0x0038; }
      static constexpr unsigned int aprsDownlink() { return 0x003c; }
      static constexpr unsigned int aprsUplink()   { return 0x0040; }
      static constexpr unsigned int beacon()       { return 0x0044; }
      static constexpr unsigned int aprsPath()     { return 0x004c; }
      /// @endcond
    };
  };


  /** Implements the satellite config bank. Holding all satellites to track. */
  class SatelliteBankElement: Codeplug::Element
  {
  protected:
    /** Hidden constructor. */
    SatelliteBankElement(uint8_t *ptr, size_t size);

  public:
    /** Constructor. */
    SatelliteBankElement(uint8_t *ptr);

    /** The size of the element. */
    static constexpr unsigned int size() { return 0x09e0; }

    void clear();

    /** Returns the i-th satellite. */
    SatelliteElement satellite(unsigned int idx);
    /** Encodes the given satellite database. */
    bool encode(SatelliteDatabase *db, const ErrorStack &err=ErrorStack());

  public:
    /** Some limits for the satellite config. */
    struct Limit {
      /** The maximum number of satellites. */
      static constexpr unsigned int satellites() { return 25; }
    };

  protected:
    /** Some internal offsets. */
    struct Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int blockId()           { return 0x0000; }
      static constexpr unsigned int segmentSize()       { return 0x0004; }
      static constexpr unsigned int satellites()        { return 0x0008; }
      static constexpr unsigned int betweenSatellites() { return SatelliteElement::size(); }
      /// @endcond
    };
  };



  /** Encodes some additional settings for OpenGD77 based radios. These
   * settings include boot image, boot melody, satellite orbital elements and themes, if the radio
   * supports it. */
  class AdditionalSettingsElement: public Element
  {
  public:
    enum Settings {
      BootImage         = 1,
      BootMelody        = 2,
      SatelliteOrbitals = 3,
      LightTheme        = 4,
      DarkTheme         = 5
    };

  protected:
    /** Hidden constructor. */
    AdditionalSettingsElement(uint8_t *ptr, size_t size);

  public:
    /** Constructor. */
    AdditionalSettingsElement(uint8_t *ptr);

    /** Returns the size of the element. */
    static constexpr unsigned int size() { return 0x11a0; }

    bool isValid() const;
    void clear();

    /** Returns the magic string. */
    virtual QString magic() const;
    /** Returns the version number. */
    virtual unsigned int version() const;

    /** Returns @c true, if the given settings is stored. */
    virtual bool hasSettings(Settings set) const;
    /** Returns statellite settings bank, if present. If not, a new empty setting is returned. */
    virtual SatelliteBankElement satellites() const;

  public:
    /** Some limits for the element. */
    struct Limit {
      /** Size of magic string. */
      static constexpr unsigned int magicStringLength() { return 8; }
    };

  protected:
    /** Some internal offsets within the element. */
    struct Offset {
      /// @cond DO_NOT_DOCUMENT
      static constexpr unsigned int magicString()    { return 0x0000; }
      static constexpr unsigned int versionNumber()  { return 0x0008; }
      static constexpr unsigned int blocks()         { return 0x000c; }
      // @endcond
    };
  };


protected:
  /** Default hidden constructor. */
  explicit OpenGD77BaseCodeplug(QObject *parent = nullptr);

public:
  /** Clears and resets the complete codeplug to some default values. */
  virtual void clear();

  bool index(Config *config, Context &ctx, const ErrorStack &err=ErrorStack()) const;

  bool decode(Config *config, const ErrorStack &err=ErrorStack());
  bool postprocess(Config *config, const ErrorStack &err=ErrorStack()) const;

  Config *preprocess(Config *config, const ErrorStack &err=ErrorStack()) const;
  bool encode(Config *config, const Flags &flags = Flags(), const ErrorStack &err=ErrorStack());

public:
  /** Decodes the binary codeplug and stores its content in the given generic configuration using
   * the given context. */
  virtual bool decodeElements(Context &ctx, const ErrorStack &err=ErrorStack());
  /** Encodes the given generic configuration as a binary codeplug using the given context. */
  virtual bool encodeElements(const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack());

  /** Clears the general settings in the codeplug. */
  virtual void clearGeneralSettings() = 0;
  /** Updates the general settings from the given configuration. */
  virtual bool encodeGeneralSettings(const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Updates the given configuration from the general settings. */
  virtual bool decodeGeneralSettings(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;

  /** Clears the DTMF settings. */
  virtual void clearDTMFSettings() = 0;
  /** Encodes DTMF settings. */
  virtual bool encodeDTMFSettings(const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Decodes the DTMF settings. */
  virtual bool decodeDTMFSettings(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;

  /** Clears the APRS settings. */
  virtual void clearAPRSSettings() = 0;
  /** Encodes APRS settings. */
  virtual bool encodeAPRSSettings(const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Decodes the APRS settings. */
  virtual bool decodeAPRSSettings(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Links the APRS settings. */
  virtual bool linkAPRSSettings(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;

  /** Clears all DTMF contacts in the codeplug. */
  virtual void clearDTMFContacts() = 0;
  /** Encodes all DTMF contacts. */
  virtual bool encodeDTMFContacts(const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Adds all DTMF contacts to the configuration. */
  virtual bool createDTMFContacts(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;

  /** Clear all channels. */
  virtual void clearChannels() = 0;
  /** Encode all channels. */
  virtual bool encodeChannels(const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Adds all defined channels to the configuration. */
  virtual bool createChannels(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Links all channels. */
  virtual bool linkChannels(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;

  /** Clear boot settings. */
  virtual void clearBootSettings() = 0;
  /** Encodes boot settings. */
  virtual bool encodeBootSettings(const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Decodes the boot settings. */
  virtual bool decodeBootSettings(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;

  /** Clears the VFO settings. */
  virtual void clearVFOSettings() = 0;

  /** Clears all zones. */
  virtual void clearZones() = 0;
  /** Encodes zones. */
  virtual bool encodeZones(const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Adds zones to the configuration. */
  virtual bool createZones(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Links all zones within the configuration. */
  virtual bool linkZones(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;

  /** Clears all contacts in the codeplug. */
  virtual void clearContacts() = 0;
  /** Encodes all digital contacts in the configuration into the codeplug. */
  virtual bool encodeContacts(const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Adds a digital contact to the configuration for each one in the codeplug. */
  virtual bool createContacts(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;

  /** Clears all group lists. */
  virtual void clearGroupLists() = 0;
  /** Encodes all group lists. */
  virtual bool encodeGroupLists(const Flags &flags, Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Creates all group lists. */
  virtual bool createGroupLists(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
  /** Links all group lists. */
  virtual bool linkGroupLists(Context &ctx, const ErrorStack &err=ErrorStack()) = 0;
};

#endif // OPENGD77BASE_CODEPLUG_HH