-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathmainwindow_tab_radio.cpp
More file actions
1394 lines (1292 loc) · 74.4 KB
/
mainwindow_tab_radio.cpp
File metadata and controls
1394 lines (1292 loc) · 74.4 KB
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
#include "mainwindow.h"
#include "ui_mainwindow.h"
//------------------------------------------------------------------------------------------------------------------------>>
// FORM CONTROLS - RADIO TAB - SETUP
//------------------------------------------------------------------------------------------------------------------------>>
void MainWindow::SetupControls_RadioTab(void)
{
// Initialize these to false
Flag_StartRadioStream = false;
Flag_SaveCenterValues = false;
Flag_SaveMinMaxValues = false;
Flag_RadioValuesChanged = false;
// Here we create an array of ChannelSettings struct that point to the individual variables
// Later this will let us update these channel settings quickly by stepping through the array
ChannelSettings[0].channelNum = &DeviceData.Sticks.Throttle.Settings.channelNum;
ChannelSettings[1].channelNum = &DeviceData.Sticks.Turn.Settings.channelNum;
ChannelSettings[2].channelNum = &DeviceData.Sticks.Elevation.Settings.channelNum;
ChannelSettings[3].channelNum = &DeviceData.Sticks.Azimuth.Settings.channelNum;
ChannelSettings[4].channelNum = &DeviceData.AuxChannel[0].Settings.channelNum;
ChannelSettings[5].channelNum = &DeviceData.AuxChannel[1].Settings.channelNum;
ChannelSettings[6].channelNum = &DeviceData.AuxChannel[2].Settings.channelNum;
ChannelSettings[7].channelNum = &DeviceData.AuxChannel[3].Settings.channelNum;
ChannelSettings[8].channelNum = &DeviceData.AuxChannel[4].Settings.channelNum;
ChannelSettings[9].channelNum = &DeviceData.AuxChannel[5].Settings.channelNum;
ChannelSettings[10].channelNum = &DeviceData.AuxChannel[6].Settings.channelNum;
ChannelSettings[11].channelNum = &DeviceData.AuxChannel[7].Settings.channelNum;
ChannelSettings[12].channelNum = &DeviceData.AuxChannel[8].Settings.channelNum;
ChannelSettings[13].channelNum = &DeviceData.AuxChannel[9].Settings.channelNum;
ChannelSettings[14].channelNum = &DeviceData.AuxChannel[10].Settings.channelNum;
ChannelSettings[15].channelNum = &DeviceData.AuxChannel[11].Settings.channelNum;
ChannelSettings[0].pulseMin = &DeviceData.Sticks.Throttle.Settings.pulseMin;
ChannelSettings[1].pulseMin = &DeviceData.Sticks.Turn.Settings.pulseMin;
ChannelSettings[2].pulseMin = &DeviceData.Sticks.Elevation.Settings.pulseMin;
ChannelSettings[3].pulseMin = &DeviceData.Sticks.Azimuth.Settings.pulseMin;
ChannelSettings[4].pulseMin = &DeviceData.AuxChannel[0].Settings.pulseMin;
ChannelSettings[5].pulseMin = &DeviceData.AuxChannel[1].Settings.pulseMin;
ChannelSettings[6].pulseMin = &DeviceData.AuxChannel[2].Settings.pulseMin;
ChannelSettings[7].pulseMin = &DeviceData.AuxChannel[3].Settings.pulseMin;
ChannelSettings[8].pulseMin = &DeviceData.AuxChannel[4].Settings.pulseMin;
ChannelSettings[9].pulseMin = &DeviceData.AuxChannel[5].Settings.pulseMin;
ChannelSettings[10].pulseMin = &DeviceData.AuxChannel[6].Settings.pulseMin;
ChannelSettings[11].pulseMin = &DeviceData.AuxChannel[7].Settings.pulseMin;
ChannelSettings[12].pulseMin = &DeviceData.AuxChannel[8].Settings.pulseMin;
ChannelSettings[13].pulseMin = &DeviceData.AuxChannel[9].Settings.pulseMin;
ChannelSettings[14].pulseMin = &DeviceData.AuxChannel[10].Settings.pulseMin;
ChannelSettings[15].pulseMin = &DeviceData.AuxChannel[11].Settings.pulseMin;
ChannelSettings[0].pulseMax = &DeviceData.Sticks.Throttle.Settings.pulseMax;
ChannelSettings[1].pulseMax = &DeviceData.Sticks.Turn.Settings.pulseMax;
ChannelSettings[2].pulseMax = &DeviceData.Sticks.Elevation.Settings.pulseMax;
ChannelSettings[3].pulseMax = &DeviceData.Sticks.Azimuth.Settings.pulseMax;
ChannelSettings[4].pulseMax = &DeviceData.AuxChannel[0].Settings.pulseMax;
ChannelSettings[5].pulseMax = &DeviceData.AuxChannel[1].Settings.pulseMax;
ChannelSettings[6].pulseMax = &DeviceData.AuxChannel[2].Settings.pulseMax;
ChannelSettings[7].pulseMax = &DeviceData.AuxChannel[3].Settings.pulseMax;
ChannelSettings[8].pulseMax = &DeviceData.AuxChannel[4].Settings.pulseMax;
ChannelSettings[9].pulseMax = &DeviceData.AuxChannel[5].Settings.pulseMax;
ChannelSettings[10].pulseMax = &DeviceData.AuxChannel[6].Settings.pulseMax;
ChannelSettings[11].pulseMax = &DeviceData.AuxChannel[7].Settings.pulseMax;
ChannelSettings[12].pulseMax = &DeviceData.AuxChannel[8].Settings.pulseMax;
ChannelSettings[13].pulseMax = &DeviceData.AuxChannel[9].Settings.pulseMax;
ChannelSettings[14].pulseMax = &DeviceData.AuxChannel[10].Settings.pulseMax;
ChannelSettings[15].pulseMax = &DeviceData.AuxChannel[11].Settings.pulseMax;
ChannelSettings[0].pulseCenter = &DeviceData.Sticks.Throttle.Settings.pulseCenter;
ChannelSettings[1].pulseCenter = &DeviceData.Sticks.Turn.Settings.pulseCenter;
ChannelSettings[2].pulseCenter = &DeviceData.Sticks.Elevation.Settings.pulseCenter;
ChannelSettings[3].pulseCenter = &DeviceData.Sticks.Azimuth.Settings.pulseCenter;
ChannelSettings[4].pulseCenter = &DeviceData.AuxChannel[0].Settings.pulseCenter;
ChannelSettings[5].pulseCenter = &DeviceData.AuxChannel[1].Settings.pulseCenter;
ChannelSettings[6].pulseCenter = &DeviceData.AuxChannel[2].Settings.pulseCenter;
ChannelSettings[7].pulseCenter = &DeviceData.AuxChannel[3].Settings.pulseCenter;
ChannelSettings[8].pulseCenter = &DeviceData.AuxChannel[4].Settings.pulseCenter;
ChannelSettings[9].pulseCenter = &DeviceData.AuxChannel[5].Settings.pulseCenter;
ChannelSettings[10].pulseCenter = &DeviceData.AuxChannel[6].Settings.pulseCenter;
ChannelSettings[11].pulseCenter = &DeviceData.AuxChannel[7].Settings.pulseCenter;
ChannelSettings[12].pulseCenter = &DeviceData.AuxChannel[8].Settings.pulseCenter;
ChannelSettings[13].pulseCenter = &DeviceData.AuxChannel[9].Settings.pulseCenter;
ChannelSettings[14].pulseCenter = &DeviceData.AuxChannel[10].Settings.pulseCenter;
ChannelSettings[15].pulseCenter = &DeviceData.AuxChannel[11].Settings.pulseCenter;
ChannelSettings[0].pulse = &DeviceData.Sticks.Throttle.pulse;
ChannelSettings[1].pulse = &DeviceData.Sticks.Turn.pulse;
ChannelSettings[2].pulse = &DeviceData.Sticks.Elevation.pulse;
ChannelSettings[3].pulse = &DeviceData.Sticks.Azimuth.pulse;
ChannelSettings[4].pulse = &DeviceData.AuxChannel[0].pulse;
ChannelSettings[5].pulse = &DeviceData.AuxChannel[1].pulse;
ChannelSettings[6].pulse = &DeviceData.AuxChannel[2].pulse;
ChannelSettings[7].pulse = &DeviceData.AuxChannel[3].pulse;
ChannelSettings[8].pulse = &DeviceData.AuxChannel[4].pulse;
ChannelSettings[9].pulse = &DeviceData.AuxChannel[5].pulse;
ChannelSettings[10].pulse = &DeviceData.AuxChannel[6].pulse;
ChannelSettings[11].pulse = &DeviceData.AuxChannel[7].pulse;
ChannelSettings[12].pulse = &DeviceData.AuxChannel[8].pulse;
ChannelSettings[13].pulse = &DeviceData.AuxChannel[9].pulse;
ChannelSettings[14].pulse = &DeviceData.AuxChannel[10].pulse;
ChannelSettings[15].pulse = &DeviceData.AuxChannel[11].pulse;
ChannelSettings[0].reversed = &DeviceData.Sticks.Throttle.Settings.reversed;
ChannelSettings[1].reversed = &DeviceData.Sticks.Turn.Settings.reversed;
ChannelSettings[2].reversed = &DeviceData.Sticks.Elevation.Settings.reversed;
ChannelSettings[3].reversed = &DeviceData.Sticks.Azimuth.Settings.reversed;
ChannelSettings[4].reversed = &DeviceData.AuxChannel[0].Settings.reversed;
ChannelSettings[5].reversed = &DeviceData.AuxChannel[1].Settings.reversed;
ChannelSettings[6].reversed = &DeviceData.AuxChannel[2].Settings.reversed;
ChannelSettings[7].reversed = &DeviceData.AuxChannel[3].Settings.reversed;
ChannelSettings[8].reversed = &DeviceData.AuxChannel[4].Settings.reversed;
ChannelSettings[9].reversed = &DeviceData.AuxChannel[5].Settings.reversed;
ChannelSettings[10].reversed = &DeviceData.AuxChannel[6].Settings.reversed;
ChannelSettings[11].reversed = &DeviceData.AuxChannel[7].Settings.reversed;
ChannelSettings[12].reversed = &DeviceData.AuxChannel[8].Settings.reversed;
ChannelSettings[13].reversed = &DeviceData.AuxChannel[9].Settings.reversed;
ChannelSettings[14].reversed = &DeviceData.AuxChannel[10].Settings.reversed;
ChannelSettings[15].reversed = &DeviceData.AuxChannel[11].Settings.reversed;
ChannelSettings[0].deadband = &DeviceData.Sticks.Throttle.Settings.deadband;
ChannelSettings[1].deadband = &DeviceData.Sticks.Turn.Settings.deadband;
ChannelSettings[2].deadband = &DeviceData.Sticks.Elevation.Settings.deadband;
ChannelSettings[3].deadband = &DeviceData.Sticks.Azimuth.Settings.deadband;
// There is no deadband setting for aux channels...
// Now we create an array of form objects
highSlider[0] = ui->sliderThrottleHigh;
highSlider[1] = ui->sliderSteeringHigh;
highSlider[2] = ui->sliderElevationHigh;
highSlider[3] = ui->sliderRotationHigh;
highSlider[4] = ui->sliderAux1High;
highSlider[5] = ui->sliderAux2High;
highSlider[6] = ui->sliderAux3High;
highSlider[7] = ui->sliderAux4High;
highSlider[8] = ui->sliderAux5High;
highSlider[9] = ui->sliderAux6High;
highSlider[10] = ui->sliderAux7High;
highSlider[11] = ui->sliderAux8High;
highSlider[12] = ui->sliderAux9High;
highSlider[13] = ui->sliderAux10High;
highSlider[14] = ui->sliderAux11High;
highSlider[15] = ui->sliderAux12High;
lowSlider[0] = ui->sliderThrottleLow;
lowSlider[1] = ui->sliderSteeringLow;
lowSlider[2] = ui->sliderElevationLow;
lowSlider[3] = ui->sliderRotationLow;
lowSlider[4] = ui->sliderAux1Low;
lowSlider[5] = ui->sliderAux2Low;
lowSlider[6] = ui->sliderAux3Low;
lowSlider[7] = ui->sliderAux4Low;
lowSlider[8] = ui->sliderAux5Low;
lowSlider[9] = ui->sliderAux6Low;
lowSlider[10] = ui->sliderAux7Low;
lowSlider[11] = ui->sliderAux8Low;
lowSlider[12] = ui->sliderAux9Low;
lowSlider[13] = ui->sliderAux10Low;
lowSlider[14] = ui->sliderAux11Low;
lowSlider[15] = ui->sliderAux12Low;
lblChannelMin[0] = ui->lblThrottleMin;
lblChannelMin[1] = ui->lblSteeringMin;
lblChannelMin[2] = ui->lblElevationMin;
lblChannelMin[3] = ui->lblRotationMin;
lblChannelMin[4] = ui->lblAux1Min;
lblChannelMin[5] = ui->lblAux2Min;
lblChannelMin[6] = ui->lblAux3Min;
lblChannelMin[7] = ui->lblAux4Min;
lblChannelMin[8] = ui->lblAux5Min;
lblChannelMin[9] = ui->lblAux6Min;
lblChannelMin[10] = ui->lblAux7Min;
lblChannelMin[11] = ui->lblAux8Min;
lblChannelMin[12] = ui->lblAux9Min;
lblChannelMin[13] = ui->lblAux10Min;
lblChannelMin[14] = ui->lblAux11Min;
lblChannelMin[15] = ui->lblAux12Min;
lblChannelMax[0] = ui->lblThrottleMax;
lblChannelMax[1] = ui->lblSteeringMax;
lblChannelMax[2] = ui->lblElevationMax;
lblChannelMax[3] = ui->lblRotationMax;
lblChannelMax[4] = ui->lblAux1Max;
lblChannelMax[5] = ui->lblAux2Max;
lblChannelMax[6] = ui->lblAux3Max;
lblChannelMax[7] = ui->lblAux4Max;
lblChannelMax[8] = ui->lblAux5Max;
lblChannelMax[9] = ui->lblAux6Max;
lblChannelMax[10] = ui->lblAux7Max;
lblChannelMax[11] = ui->lblAux8Max;
lblChannelMax[12] = ui->lblAux9Max;
lblChannelMax[13] = ui->lblAux10Max;
lblChannelMax[14] = ui->lblAux11Max;
lblChannelMax[15] = ui->lblAux12Max;
lblChannelPulse[0] = ui->lblThrottlePulse;
lblChannelPulse[1] = ui->lblSteeringPulse;
lblChannelPulse[2] = ui->lblElevationPulse;
lblChannelPulse[3] = ui->lblRotationPulse;
lblChannelPulse[4] = ui->lblAux1Pulse;
lblChannelPulse[5] = ui->lblAux2Pulse;
lblChannelPulse[6] = ui->lblAux3Pulse;
lblChannelPulse[7] = ui->lblAux4Pulse;
lblChannelPulse[8] = ui->lblAux5Pulse;
lblChannelPulse[9] = ui->lblAux6Pulse;
lblChannelPulse[10] = ui->lblAux7Pulse;
lblChannelPulse[11] = ui->lblAux8Pulse;
lblChannelPulse[12] = ui->lblAux9Pulse;
lblChannelPulse[13] = ui->lblAux10Pulse;
lblChannelPulse[14] = ui->lblAux11Pulse;
lblChannelPulse[15] = ui->lblAux12Pulse;
lblChannelPosition[0] = ui->lblThrottleDirection;
lblChannelPosition[1] = ui->lblSteeringDirection;
lblChannelPosition[2] = ui->lblElevationDirection;
lblChannelPosition[3] = ui->lblRotationDirection;
lblChannelPosition[4] = ui->lblAux1Pos;
lblChannelPosition[5] = ui->lblAux2Pos;
lblChannelPosition[6] = ui->lblAux3Pos;
lblChannelPosition[7] = ui->lblAux4Pos;
lblChannelPosition[8] = ui->lblAux5Pos;
lblChannelPosition[9] = ui->lblAux6Pos;
lblChannelPosition[10] = ui->lblAux7Pos;
lblChannelPosition[11] = ui->lblAux8Pos;
lblChannelPosition[12] = ui->lblAux9Pos;
lblChannelPosition[13] = ui->lblAux10Pos;
lblChannelPosition[14] = ui->lblAux11Pos;
lblChannelPosition[15] = ui->lblAux12Pos;
// Apply css to the sliders
QFile file(":/css/channelsliderhigh.qss");
if(file.open(QIODevice::ReadOnly | QIODevice::Text))
{
for (int i=0; i<COUNT_OP_CHANNELS; i++ )
{
highSlider[i]->setStyleSheet(file.readAll());
file.seek(0); // Return to beginning of file
}
file.close();
}
QFile file2(":/css/channelsliderlow.qss");
if(file2.open(QIODevice::ReadOnly | QIODevice::Text))
{
for (int i=0; i<COUNT_OP_CHANNELS; i++ )
{
lowSlider[i]->setStyleSheet(file2.readAll());
file2.seek(0); // Return to beginning of file
}
file2.close();
}
// Populate the channel order combos. We pass true/false if this is an aux channel or not
ui->cboThrottleChannelNum->setup(false);
ui->cboTurnChannelNum->setup(false);
ui->cboElevationChannelNum->setup(false);
ui->cboAzimuthChannelNum->setup(false);
ui->cboAux1ChannelNum->setup(true);
ui->cboAux2ChannelNum->setup(true);
ui->cboAux3ChannelNum->setup(true);
ui->cboAux4ChannelNum->setup(true);
ui->cboAux5ChannelNum->setup(true);
ui->cboAux6ChannelNum->setup(true);
ui->cboAux7ChannelNum->setup(true);
ui->cboAux8ChannelNum->setup(true);
ui->cboAux9ChannelNum->setup(true);
ui->cboAux10ChannelNum->setup(true);
ui->cboAux11ChannelNum->setup(true);
ui->cboAux12ChannelNum->setup(true);
// Also create an array of these boxes so we can quickly do calculations on all of them in a loop
channelOrderCombo[0] = ui->cboThrottleChannelNum;
channelOrderCombo[1] = ui->cboTurnChannelNum;
channelOrderCombo[2] = ui->cboElevationChannelNum;
channelOrderCombo[3] = ui->cboAzimuthChannelNum;
channelOrderCombo[4] = ui->cboAux1ChannelNum;
channelOrderCombo[5] = ui->cboAux2ChannelNum;
channelOrderCombo[6] = ui->cboAux3ChannelNum;
channelOrderCombo[7] = ui->cboAux4ChannelNum;
channelOrderCombo[8] = ui->cboAux5ChannelNum;
channelOrderCombo[9] = ui->cboAux6ChannelNum;
channelOrderCombo[10] = ui->cboAux7ChannelNum;
channelOrderCombo[11] = ui->cboAux8ChannelNum;
channelOrderCombo[12] = ui->cboAux9ChannelNum;
channelOrderCombo[13] = ui->cboAux10ChannelNum;
channelOrderCombo[14] = ui->cboAux11ChannelNum;
channelOrderCombo[15] = ui->cboAux12ChannelNum;
// Array of aux channel types (analog or digital). These boxes have been promoted to AnalogDigitalComboBox-es,
// the values are filled in automatically on creation
auxTypeCombo[0] = ui->cboAux1Type;
auxTypeCombo[1] = ui->cboAux2Type;
auxTypeCombo[2] = ui->cboAux3Type;
auxTypeCombo[3] = ui->cboAux4Type;
auxTypeCombo[4] = ui->cboAux5Type;
auxTypeCombo[5] = ui->cboAux6Type;
auxTypeCombo[6] = ui->cboAux7Type;
auxTypeCombo[7] = ui->cboAux8Type;
auxTypeCombo[8] = ui->cboAux9Type;
auxTypeCombo[9] = ui->cboAux10Type;
auxTypeCombo[10] = ui->cboAux11Type;
auxTypeCombo[11] = ui->cboAux12Type;
// Array of aux channel switch positions, these are of type AuxChannelPositionsCombo
auxSwitchPosCombo[0] = ui->cboAux1NumSwitchPos;
auxSwitchPosCombo[1] = ui->cboAux2NumSwitchPos;
auxSwitchPosCombo[2] = ui->cboAux3NumSwitchPos;
auxSwitchPosCombo[3] = ui->cboAux4NumSwitchPos;
auxSwitchPosCombo[4] = ui->cboAux5NumSwitchPos;
auxSwitchPosCombo[5] = ui->cboAux6NumSwitchPos;
auxSwitchPosCombo[6] = ui->cboAux7NumSwitchPos;
auxSwitchPosCombo[7] = ui->cboAux8NumSwitchPos;
auxSwitchPosCombo[8] = ui->cboAux9NumSwitchPos;
auxSwitchPosCombo[9] = ui->cboAux10NumSwitchPos;
auxSwitchPosCombo[10] = ui->cboAux11NumSwitchPos;
auxSwitchPosCombo[11] = ui->cboAux12NumSwitchPos;
// Array of stick channel reversed settings
stickReversedCheck[0] = ui->chkThrottleReversed;
stickReversedCheck[1] = ui->chkTurnReversed;
stickReversedCheck[2] = ui->chkElevationReversed;
stickReversedCheck[3] = ui->chkRotationReversed;
// Array of aux channel reversed settings
auxReversedCheck[0] = ui->chkAux1_Reversed;
auxReversedCheck[1] = ui->chkAux2_Reversed;
auxReversedCheck[2] = ui->chkAux3_Reversed;
auxReversedCheck[3] = ui->chkAux4_Reversed;
auxReversedCheck[4] = ui->chkAux5_Reversed;
auxReversedCheck[5] = ui->chkAux6_Reversed;
auxReversedCheck[6] = ui->chkAux7_Reversed;
auxReversedCheck[7] = ui->chkAux8_Reversed;
auxReversedCheck[8] = ui->chkAux9_Reversed;
auxReversedCheck[9] = ui->chkAux10_Reversed;
auxReversedCheck[10] = ui->chkAux11_Reversed;
auxReversedCheck[11] = ui->chkAux12_Reversed;
// Signals and slots
// Save information when any aux channel number is changed, and enable/disable the channel type and position-count combos as required
// This is some extremely tricky stuff. I don't want to mess with six different slots for the six different aux channel combos,
// but I don't have an easy way to pass the aux channel number to the slot. QSignalMapper alas only works with parameter-less signals,
// otherwise I could use that. But I want to pass the new paramater channel number in *addition* to the existing parameters of the signal
// There is a way that works by some kind of C++ lambda shit, don't ask me what it means, but this amazingly does work.
// The only thing is I can't create these signals in a loop, but that is a small price to pay for replacing six slots with 1
// And - it only seems to work on custom signals emitted from a subclassed version, not QComboBox directly
connect(ui->cboThrottleChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 0);});
connect(ui->cboTurnChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 1);});
connect(ui->cboElevationChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 2);});
connect(ui->cboAzimuthChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 3);});
connect(ui->cboAux1ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 0);});
connect(ui->cboAux2ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 1);});
connect(ui->cboAux3ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 2);});
connect(ui->cboAux4ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 3);});
connect(ui->cboAux5ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 4);});
connect(ui->cboAux6ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 5);});
connect(ui->cboAux7ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 6);});
connect(ui->cboAux8ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 7);});
connect(ui->cboAux9ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 8);});
connect(ui->cboAux10ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 9);});
connect(ui->cboAux11ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 10);});
connect(ui->cboAux12ChannelNum, &ChannelOrderComboBox::channelNumberChanged, [this](const QString &oldChannel, const QString &newChannel, ChannelOrderComboBox* changedCombo) {SaveChannelNum(oldChannel, newChannel, changedCombo, 11);});
// I said above it only seems to work with promoted objects, but here I was able to do it from a regular QCheckbox.
// I think the issue is that you can't use an overloaded signal, there must only be a single definition for the signal paramater(s)
// This just updates the variable each time any of the reversed checkboxes is toggled.
connect(ui->chkThrottleReversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 0);});
connect(ui->chkTurnReversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 1);});
connect(ui->chkElevationReversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 2);});
connect(ui->chkRotationReversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 3);});
connect(ui->chkAux1_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 4);});
connect(ui->chkAux2_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 5);});
connect(ui->chkAux3_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 6);});
connect(ui->chkAux4_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 7);});
connect(ui->chkAux5_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 8);});
connect(ui->chkAux6_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 9);});
connect(ui->chkAux7_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 10);});
connect(ui->chkAux8_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 11);});
connect(ui->chkAux9_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 12);});
connect(ui->chkAux10_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 13);});
connect(ui->chkAux11_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 14);});
connect(ui->chkAux12_Reversed, &QCheckBox::toggled, [this](bool isChecked) {SaveChannelReversed(isChecked, 15);});
// Save the deadband whenever it is changed. This one doesn't work because valueChanged is overloaded to return either an
// int or a QString, and I guess this only works if it is singular. I could create a whole new class for these four spin boxes,
// but instead just make 4 slots.
//connect(ui->spinThrottleDeadband, &QSpinBox::valueChanged, [this](int whatVal) {SaveDeadband(whatVal, 0);});
connect(ui->spinThrottleDeadband, SIGNAL(valueChanged(int)), this, SLOT(SaveThrottleDeadband(int)));
connect(ui->spinTurnDeadband, SIGNAL(valueChanged(int)), this, SLOT(SaveTurnDeadband(int)));
connect(ui->spinElevationDeadband, SIGNAL(valueChanged(int)), this, SLOT(SaveElevationDeadband(int)));
connect(ui->spinAzimuthDeadband, SIGNAL(valueChanged(int)), this, SLOT(SaveAzimuthDeadband(int)));
// Save information when any aux channel type is changed, and enable/disable the position-count combo as required
connect(ui->cboAux1Type, &AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 0);});
connect(ui->cboAux2Type, &AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 1);});
connect(ui->cboAux3Type, &AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 2);});
connect(ui->cboAux4Type, &AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 3);});
connect(ui->cboAux5Type, &AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 4);});
connect(ui->cboAux6Type, &AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 5);});
connect(ui->cboAux7Type, &AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 6);});
connect(ui->cboAux8Type, &AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 7);});
connect(ui->cboAux9Type, &AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 8);});
connect(ui->cboAux10Type,&AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 9);});
connect(ui->cboAux11Type,&AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 10);});
connect(ui->cboAux12Type,&AnalogDigitalComboBox::analogDigitalChanged, [this](AnalogDigitalComboBox* changedCombo) {SaveAuxChannelType(changedCombo, 11);});
// Save information when any aux channel position-counts are changed
connect(ui->cboAux1NumSwitchPos, &AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 0);});
connect(ui->cboAux2NumSwitchPos, &AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 1);});
connect(ui->cboAux3NumSwitchPos, &AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 2);});
connect(ui->cboAux4NumSwitchPos, &AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 3);});
connect(ui->cboAux5NumSwitchPos, &AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 4);});
connect(ui->cboAux6NumSwitchPos, &AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 5);});
connect(ui->cboAux7NumSwitchPos, &AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 6);});
connect(ui->cboAux8NumSwitchPos, &AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 7);});
connect(ui->cboAux9NumSwitchPos, &AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 8);});
connect(ui->cboAux10NumSwitchPos,&AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 9);});
connect(ui->cboAux11NumSwitchPos,&AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 10);});
connect(ui->cboAux12NumSwitchPos,&AuxChannelPositionsCombo::AuxChannelPositionChanged, [this](AuxChannelPositionsCombo* changedCombo) {SaveAuxChannelPositions(changedCombo, 11);});
// ChannelOrderComboBoxes have a custom signal, we connect all of them to the ValidateChannelOrder slot
// This is to prevent the user from assigning the same channel number to more than one channel
connect(ui->cboThrottleChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboTurnChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboElevationChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAzimuthChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux1ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux2ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux3ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux4ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux5ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux6ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux7ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux8ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux9ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux10ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux11ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
connect(ui->cboAux12ChannelNum, SIGNAL(channelNumberChanged(QString,QString,ChannelOrderComboBox*)), this, SLOT(ValidateChannelOrder(QString,QString,ChannelOrderComboBox*)));
// Radio streaming buttons
ui->cmdRadioStream->setChecked(false); // Start not streaming
ui->cmdRadioStream->setEnabled(false); // Also start not enabled, it will get enabled after we connect to the device
ui->cmdSaveMinMax->setEnabled(false); // These are also disabled until streaming actually begins
ui->cmdSaveCenters->setEnabled(false); // "" ""
ui->frmChannelVals->hide(); // Finally, we hide the entire streaming frame
// Radio streaming button connections
connect(ui->cmdRadioStream, SIGNAL(clicked(bool)), this, SLOT(cmdToggleRadioStream_Click()));
connect(ui->cmdSaveMinMax, SIGNAL(released()), this, SLOT(cmdSaveMinMax_Click()));
connect(ui->cmdSaveCenters, SIGNAL(released()), this, SLOT(cmdSaveCenters_Click()));
connect(this, SIGNAL(PulseCentersSaved(boolean)), this, SLOT(ConfirmCentersSaved(boolean)));
// View saved values button connection
connect(ui->cmdToggleViewSavedValues, SIGNAL(clicked(bool)), this, SLOT(cmdToggleViewSavedValues_Click()));
// But hide it since we're not using it for now
ui->cmdToggleViewSavedValues->hide();
}
//------------------------------------------------------------------------------------------------------------------------>>
// FORM CONTROLS - RADIO TAB - RADIO STREAMING
//------------------------------------------------------------------------------------------------------------------------>>
// This is the "checkable" button we use to start/stop streaming. If not started already, clicking the button will first
// request the number of utilized channels, when the device responds, then streaming will start. If we are streaming, then clicking
// this button will request streaming to end. Either way, the actual actions that occur when streaming starts or stops are
// handlded in SetRadioStreamStatus below
void MainWindow::cmdToggleRadioStream_Click()
{
if (comm->isRadioStreaming())
{
comm->stopStreamRadio();
}
else
{
ui->cmdRadioStream->setChecked(true); // "Check" (depress) the button, but disable it and set the text to wait
ui->cmdRadioStream->setText("wait");
ui->cmdRadioStream->setEnabled(false);
// Before we actually start streaming, we first request the number of utilized channels
// When the response arrives we will then proceed to initiate streaming.
NumUtilizedChannels = 0; // reset
Flag_StartRadioStream = true; // The flag isn't to specify that streaming has started, it is to specify that we
// *want* streaming to start after the number of channels has been read.
comm->requestUtilizedRadioChannels(); // request
}
}
// This slot is connected to the comm object signal that fires when streaming has started or stopped.
void MainWindow::SetRadioStreamStatus(boolean streaming)
{
if (streaming)
{
SetStatusLabel("Streaming Radio",slNeutral);
ui->cmdRadioStream->setChecked(true); // "Check" stream button
ui->cmdRadioStream->setText("Done Reading"); // Change text to done
ui->cmdRadioStream->setEnabled(true);
ui->cmdSaveCenters->setEnabled(true); // Enable these buttons
ui->cmdSaveMinMax->setEnabled(true); //
// While streaming, we don't want the user to try reading/writing to the device
DisableDeviceActionsDuringRadioStream();
// Also initialize these to false, they will get set later if they apply
Flag_RadioValuesChanged = false;
Flag_SaveCenterValues = false;
Flag_SaveMinMaxValues = false;
//ui->frmChannelVals->show();
FadeInRadioStreaming();
}
else
{
ui->cmdConnect->setEnabled(true); // Enable stream button in case
ui->cmdRadioStream->setChecked(false); // Un-"check" stream button
ui->cmdRadioStream->setText("Read Radio");
ui->cmdRadioStream->setEnabled(true);
ui->cmdSaveCenters->setEnabled(false); // Disable these buttons
ui->cmdSaveMinMax->setEnabled(false); //
Flag_StartRadioStream = false; // Reset this
// Now streaming is over we can re-enable these, but only if we are still connected
EnableDeviceActionsAfterRadioStream(); // This function will check the connection status
// This flag means the user ran the save-center-values or the save-min/max-values routines while we were streaming
// In that case, we'd like to go ahead and post these changes to the device rather than relying on the user to remember
// to click the write-to-device button, and anyway, we might sometimes only want to update these radio values.
if (Flag_RadioValuesChanged)
{
if (comm->isConnected())
{
writeSomeSettingsToDevice(RADIO_SETTINGS_START_ID, RADIO_SETTINGS_END_ID);
}
}
FadeOutRadioStreaming();
// Or you could hide it right away
//ui->frmChannelVals->hide();
}
}
void MainWindow::DisableDeviceActionsDuringRadioStream()
{
// While streaming, we don't want the user to try reading/writing to the device
ui->actionRead->setEnabled(false);
ui->cmdReadDevice->setEnabled(false);
ui->actionWrite->setEnabled(false);
ui->cmdWriteDevice->setEnabled(false);
// Or this either
ui->actionResetAllVals->setEnabled(false);
}
void MainWindow::EnableDeviceActionsAfterRadioStream()
{
// Streaming is over, we can re-enable these, but only if we are still connected:
// Because one reason streaming may have stopped is because we disconnected.
if (comm->isConnected())
{
ui->actionRead->setEnabled(true);
ui->cmdReadDevice->setEnabled(true);
ui->actionWrite->setEnabled(true);
ui->cmdWriteDevice->setEnabled(true);
}
// This one can be re-enabled regardless of connection status
ui->actionResetAllVals->setEnabled(true);
}
void MainWindow::SaveNumUtilizedChannels(uint8_t numChannels)
{ // If the device responded with the number of utilized channels, this routine will get called
// Save it
NumUtilizedChannels = numChannels;
// Let's run through each channel order and make sure as many are active as they have utilized, but
// if they aren't utilizing the full amount, set the extras to NA
if (NumUtilizedChannels > STICKCHANNELS)
{
// Run through the utilized channels, make sure they show up.
for (int i=STICKCHANNELS; i<NumUtilizedChannels; i++)
{
if (channelOrderCombo[i+1]->currentText() == "N/A")
{ // Set the channel order to the 1 + the prior channel order
channelOrderCombo[i+1]->setCurrentIndex(channelOrderCombo[i]->currentIndex()+1);
}
}
// Run through the extra channels beyond the utilized ones and set them to NA
if (NumUtilizedChannels < COUNT_OP_CHANNELS)
{
for (int i=COUNT_OP_CHANNELS; i>NumUtilizedChannels;i--)
{
// Let's set the unused channels to N/A
channelOrderCombo[i-1]->setCurrentIndex(channelOrderCombo[i-1]->findText("N/A"));
}
}
}
// If they have at least 4 channels, proceed with radio streaming
if (NumUtilizedChannels >= STICKCHANNELS)
{
if (Flag_StartRadioStream)
{
// If Flag_StartRadioStream is set to true, it means that once we know the number of channels
// we want the device to start streaming radio data, so go ahead and send the command.
comm->startStreamRadio();
}
}
else
{
SetStatusLabel("Inadequate channels detected!", slBad);
msgBox(QString("The radio reports only %1 channels connected. A minimum of 4 is required.").arg(NumUtilizedChannels),vbOkOnly, "Inadequate Channels", vbExclamation);
}
}
void MainWindow::RadioNotReady()
{
// In this case, we tried to get the device to give us information about the radio, but the device tells us the
// radio is not ready (could also mean it is not on, or not connected)
// Abort whatever we had started
SetStatusLabel("Request failed", slNeutral);
SetRadioStreamStatus(false);
msgBox("The radio is not detected!", vbOkOnly, "Radio Not Ready", vbExclamation);
}
// Fade in/out effect for the radio streaming frame. Probably unecessary but it looks cool.
void MainWindow::FadeInRadioStreaming(void)
{
// Fade in the radio streaming objects
QFrame *w = ui->frmChannelVals;
QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this);
w->setGraphicsEffect(eff);
QPropertyAnimation *a = new QPropertyAnimation(eff,"opacity");
a->setDuration(RADIO_STREAM_FADEIN_TIME);
a->setStartValue(0);
a->setEndValue(1);
a->setEasingCurve(QEasingCurve::InBack);
w->show();
a->start(QPropertyAnimation::DeleteWhenStopped);
// Nothing needs to happen when the fade-in completes
//connect(a,SIGNAL(finished()),this,SLOT(SomeSlot()));
}
void MainWindow::FadeOutRadioStreaming()
{
// Fade out the label
QFrame *w = ui->frmChannelVals;
QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this);
w->setGraphicsEffect(eff);
QPropertyAnimation *a = new QPropertyAnimation(eff,"opacity");
a->setDuration(RADIO_STREAM_FADEOUT_TIME);
a->setStartValue(1);
a->setEndValue(0);
a->setEasingCurve(QEasingCurve::OutBack);
a->start(QPropertyAnimation::DeleteWhenStopped);
}
// This function first tells the user to center the sticks (we don't really save centers for the aux channels)
// then when they click "Ok" to the message box, center values are saved
void MainWindow::cmdSaveCenters_Click()
{
msgBox("Please center the sticks on your transmitter.\n\nWhen you click \"Ok\", the center values will be saved.",vbOkOnly,"Save Centers",vbExclamation);
// We set this flag to true. Now the ReadPulseWidths function below will take care of saving the center values
Flag_SaveCenterValues = true;
}
void MainWindow::cmdSaveMinMax_Click()
{
if (!Flag_SaveMinMaxValues)
{
msgBox("Move all the controls on your radio until the Min and Max values stop changing.\n\nWhen you are done, click the \"Save Min/Max\" button to complete.",vbOkOnly,"Save Min Max",vbExclamation);
// "Depress" the min/max button
ui->cmdSaveMinMax->setChecked(true);
// We set this flag to true. Now the ReadPulseWidths function below will take care of saving the min/max values
Flag_SaveMinMaxValues = true;
// While we're doing this, we need to disable the save min/max and streaming buttons
ui->cmdSaveCenters->setEnabled(false);
ui->cmdRadioStream->setChecked(false); // We "uncheck" this while disabling it to make the checked min/max button stand out more
ui->cmdRadioStream->setEnabled(false);
// To make it clearer what we're doing, we also hide pulses/and position labels
ShowHidePulsesPositions(false);
}
else
{
Flag_SaveMinMaxValues = false;
ui->cmdSaveMinMax->setChecked(false);
ui->cmdSaveCenters->setEnabled(true);
ui->cmdRadioStream->setChecked(true);
ui->cmdRadioStream->setEnabled(true);
// Now show these again
ShowHidePulsesPositions(true);
}
}
void MainWindow::cmdToggleViewSavedValues_Click()
{
static boolean show = false;
// It might be nice to see the saved min, max, and centerpoint values of each channel at other times than just when
// performing Radio Setup. You would need to hide some elements, and populate the labels with the values since they
// are not by default. Also would need to add some logic to handle transitions between "showing" and "streaming radio"
// if that were to occur.
// Right now this is just a placeholder that doesn't do much other than trap the click event of the cmdToggleViewSavedValues
// button, which is presently hidden.
if (show)
{
ui->cmdToggleViewSavedValues->setChecked(false); // "Un-check" the button
ui->cmdToggleViewSavedValues->setText("Show Saved Values");
ui->frmChannelVals->hide();
ShowHidePulsesPositions(false);
show = false;
}
else
{
ui->cmdToggleViewSavedValues->setChecked(true); // "Check" (depress) the button
ui->cmdToggleViewSavedValues->setText("Hide Saved Values");
ui->frmChannelVals->show();
ShowHidePulsesPositions(true);
show = true;
}
}
void MainWindow::ShowHidePulsesPositions(boolean show)
{
if (!show)
{
ui->lblPulseHeaderSticks->hide();
ui->lblPulseHeaderAux->hide();
ui->lblStickDirection->hide();
ui->lblSwitchPos->hide();
for (int i=0; i<COUNT_OP_CHANNELS; i++)
{
lblChannelPulse[i]->hide();
lblChannelPosition[i]->hide();
}
}
else
{
ui->lblPulseHeaderSticks->show();
ui->lblPulseHeaderAux->show();
ui->lblStickDirection->show();
ui->lblSwitchPos->show();
for (int i=0; i<STICKCHANNELS; i++)
{
lblChannelPulse[i]->show();
lblChannelPosition[i]->show();
}
for (int i=STICKCHANNELS; i<COUNT_OP_CHANNELS; i++)
{
if (channelOrderCombo[i]->currentText() != "N/A")
{
lblChannelPulse[i]->show();
lblChannelPosition[i]->show();
}
}
}
}
// This slot gets called by the comm object whenever a stream of PPM pulse-widths arrives. A pointer to the array
// of NumUtilizedChannels pulseWidths is passed for us to do with as we want. We apply the pulse widths to our visual
// slider objects, labels, and whatever.
void MainWindow::ReadPulseWidths(int16_t *pulseWidths)
{
// We'll use these to save stick centers. Unsigned long because we are going to add a stream of pulses which could get
// kind of large. Then we'll divide by the number of samples taken to get an average for the center.
static unsigned long TotPulseCenter[STICKCHANNELS]{0,0,0,0};
const int TOTAL_SAMPLES = 16; // This shouldn't take more than a quarter second at 115,200 baud
static int NumSamplesTaken = 0;
float TempFloat = 0.0;
// These variables will help with saving min/max values
static boolean runningMinMax = false;
if (Flag_SaveMinMaxValues == true && runningMinMax == false)
{ // This means the user has just started the save min/max routine
// We start by clearing all the min/max values. We do this by setting them all to center instead
for (int i=0; i<COUNT_OP_CHANNELS; i++)
{
*ChannelSettings[i].pulseMin = DEFAULT_PULSE_CENTER;
*ChannelSettings[i].pulseMax = DEFAULT_PULSE_CENTER;
lblChannelMin[i]->setText(QString::number(DEFAULT_PULSE_CENTER));
lblChannelMax[i]->setText(QString::number(DEFAULT_PULSE_CENTER));
}
runningMinMax = true;
}
// Here we display the radio stream. The sliders show the stick position, the pulse label shows the current pulse,
// and the direction/position labels show the direction/position of the channel
for (int i=0; i<NumUtilizedChannels; i++)
{
for (int j=0; j<COUNT_OP_CHANNELS; j++)
{
if ((*ChannelSettings[j].channelNum - 1) == i)
{
// If we are saving min/max values, we update the min/max value to the new pulse-width if the pulse-width
// exceeds the existing min/max value. We also handle the sliders a little bit different. Instead of showing
// the instantaneous pulse, we fill the sliders with min/max values, so as the min/max is filled in, the sliders
// become filled in as well.
if (runningMinMax)
{
if (pulseWidths[i] < *ChannelSettings[j].pulseMin)
{ // pulse width is less than our existing min - update the min,
// and set the low slider to the new min value, as well as the min label
*ChannelSettings[j].pulseMin = pulseWidths[i];
lowSlider[j]->setValue(pulseWidths[i]);
lblChannelMin[j]->setText(QString::number(pulseWidths[i]));
}
if (pulseWidths[i] > *ChannelSettings[j].pulseMax)
{ // pulse width is greater than our existing max - update the max,
// andset the high slider to the new max value, as well as the max label
*ChannelSettings[j].pulseMax = pulseWidths[i];
highSlider[j]->setValue(pulseWidths[i]);
lblChannelMax[j]->setText(QString::number(pulseWidths[i]));
}
}
else
{ // This is the default behavior - the sliders show the current stick position relative to center
lowSlider[j]->setValue(pulseWidths[i]);
highSlider[j]->setValue(pulseWidths[i]);
}
// Pulse label
lblChannelPulse[j]->setText(QString::number(pulseWidths[i]));
// Direction label (so the user knows which direction the stick is commanding)
if (j < STICKCHANNELS)
{
lblChannelPosition[j]->setText(calculateStickDirection(j, pulseWidths[i]));
// Also if this is a stick channel, and we are saving the center pulse width, then
// save it.
if (Flag_SaveCenterValues)
{
TotPulseCenter[j] += pulseWidths[i];
}
}
// Position label (so the user knows which switch position the device thinks it reads)
if (j>=STICKCHANNELS)
{
int AuxNum = j-STICKCHANNELS;
if (auxTypeCombo[AuxNum]->currentIndex()) // This check will return true if aux channel is digital
{
lblChannelPosition[j]->setText(QString("Pos %1").arg(calculateAuxSwitchPos(pulseWidths[i],auxSwitchPosCombo[AuxNum]->currentText().toUInt(), auxReversedCheck[AuxNum]->isChecked())));
}
else
{
// Channel is analog, there is no decoded "position"
lblChannelPosition[j]->setText("");
}
}
}
}
}
// SAVE CENTER VALUES
// We are going to count up to TOTAL_SAMPLES and then take an average for the stick centers
if (Flag_SaveCenterValues)
{
NumSamplesTaken += 1;
if (NumSamplesTaken >= TOTAL_SAMPLES)
{
// We're done. Take the average and save it to our variable (only for stick channels)
for (int j=0; j<STICKCHANNELS; j++)
{
TempFloat = (float)TotPulseCenter[j] / (float)TOTAL_SAMPLES;
*ChannelSettings[j].pulseCenter = (int16_t)TempFloat;
TotPulseCenter[j] = 0; // Reset for next time
//qDebug() << "Chan " << j+1 << " center: " << TempFloat;
}
// For AUX channels, we also save centers to DEFAULT_PULSE_CENTER (not actual center, because we don't know it, and it doesn't matter)
for (int j=STICKCHANNELS; j<COUNT_OP_CHANNELS; j++)
{
*ChannelSettings[j].pulseCenter = DEFAULT_PULSE_CENTER;
}
// Update the sliders to the new center values
UpdateChannelControls_MinMaxCenter();
// Set this flag to true, so we know to save these changes to device when we stop streaming
Flag_RadioValuesChanged = true;
// Now reset for next time
NumSamplesTaken = 0;
Flag_SaveCenterValues = false;
// This is kind of silly, but it just calls ConfirmCentersSaved. If we were going to implement a watchdog timer
// we could have the timer call ConfirmCentersSaved(false) but I'm going to skip that for now.
emit PulseCentersSaved(true);
}
}
// SAVE MIN MAX
// We're done saving min/max. The actual values will already be stored in their respective variables.
if (Flag_SaveMinMaxValues == false && runningMinMax == true)
{
// Stop the min/max process
runningMinMax = false;
SetStatusLabel("Min/Max values recorded",slNeutral);
// Set this flag to true, so we know to save these changes to the device when we stop streaming
Flag_RadioValuesChanged = true;
}
}
void MainWindow::UpdateChannelControls_MinMaxCenter(void)
{
for (int i=0; i<COUNT_OP_CHANNELS; i++)
{
lowSlider[i]->setRange(MIN_POSSIBLE_PULSE, *ChannelSettings[i].pulseCenter+SLIDER_CENTER_ADJUST);
highSlider[i]->setRange(*ChannelSettings[i].pulseCenter-SLIDER_CENTER_ADJUST, MAX_POSSIBLE_PULSE);
lowSlider[i]->setValue(*ChannelSettings[i].pulseCenter);
highSlider[i]->setValue(*ChannelSettings[i].pulseCenter);
lblChannelMin[i]->setText(QString::number(*ChannelSettings[i].pulseMin));
lblChannelMax[i]->setText(QString::number(*ChannelSettings[i].pulseMax));
}
}
void MainWindow::ConfirmCentersSaved(boolean saved)
{
if (saved)
{
SetStatusLabel("Center values recorded",slNeutral);
}
else
{
// For some reason this message box will also cause a disconnect...
msgBox("Unable to save pulse centers. Please retry.", vbOkOnly, "Error", vbCritical);
}
}
QString MainWindow::calculateStickDirection(uint8_t StickNum, int16_t Pulse)
{
QString lblText = "";
switch (StickNum)
{
// Throttle
case 0:
if (Pulse >= *ChannelSettings[StickNum].pulseCenter + *ChannelSettings[StickNum].deadband)
{
if (*ChannelSettings[StickNum].reversed) lblText = "Reverse";
else lblText = "Forward";
}
else if (Pulse <= *ChannelSettings[StickNum].pulseCenter - *ChannelSettings[StickNum].deadband)
{
if (*ChannelSettings[StickNum].reversed) lblText = "Forward";
else lblText = "Reverse";
}
else
{
lblText = "Stop";
}
break;
// Steering
case 1:
if (Pulse >= *ChannelSettings[StickNum].pulseCenter + *ChannelSettings[StickNum].deadband)
{
if (*ChannelSettings[StickNum].reversed) lblText = "Left";
else lblText = "Right";
}
else if (Pulse <= *ChannelSettings[StickNum].pulseCenter - *ChannelSettings[StickNum].deadband)
{
if (*ChannelSettings[StickNum].reversed) lblText = "Right";
else lblText = "Left";
}
else
{
lblText = "Straight";
}
break;
// Turret elevation
case 2:
if (Pulse >= *ChannelSettings[StickNum].pulseCenter + *ChannelSettings[StickNum].deadband)
{
if (*ChannelSettings[StickNum].reversed) lblText = "Down";
else lblText = "Up";
}
else if (Pulse <= *ChannelSettings[StickNum].pulseCenter - *ChannelSettings[StickNum].deadband)
{
if (*ChannelSettings[StickNum].reversed) lblText = "Up";
else lblText = "Down";
}
else
{
lblText = "Steady";
}
break;
// Turret rotation
case 3:
if (Pulse >= *ChannelSettings[StickNum].pulseCenter + *ChannelSettings[StickNum].deadband)
{
if (*ChannelSettings[StickNum].reversed) lblText = "Left";
else lblText = "Right";
}
else if (Pulse <= *ChannelSettings[StickNum].pulseCenter - *ChannelSettings[StickNum].deadband)
{
if (*ChannelSettings[StickNum].reversed) lblText = "Right";
else lblText = "Left";
}
else
{
lblText = "Stop";
}
break;