-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrebel_1.pde
6252 lines (5204 loc) · 214 KB
/
rebel_1.pde
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
/* uno32 program for the TenTec REBEL with some hardware mods */
/* use at your own risk */
/* before using: */
/* change the call sign in the CQ message */
/* change the WSPR message before transmitting WSPR */
/* change the macro's */
/* by K1URC */
/*
Hardware mods:
The code read function has been changed to the cw speed pot. The center of the pot is connected to the output
of the AGC op amp( junction of C97 and R48) via a 1k resister and 0.1uf cap in series. The pot is centered.
The signal level on the original code read pin is too low to be useful. The mod gives the signal more gain.
If this mod is not done, the code read function and band scope will not work. All else will be ok.
PSK31 AM modulator:
/
0----------\/\/\/\/----------0-----------0 0------------- to center of R21 the Final FET Bias Pot
pin 4 Ra | you can wire this on the top of the board
| Rb no need to remove the bottom case
--------/\/\/\/\------|
|
---
/ / /
For the switch, I repurposed the on/off switch. It enables the modulator and provides low power for WSPR, RTTY, JT65.
You could use a jumper in place of the switch if you normally leave the cover off.
For Ra and Rb you would be best served with a couple of 1k trim pots. Rb will set the power out and
Ra should be adjusted for best IMD. For fixed values I have tried Ra = 330 and Rb = 510 which provided about
1/2 watt or so out. Ra = 270 and Rb = 820 provided about 1 watt or so out. The value of Ra is fairly critical
for example with Rb at 510; Ra = 330 gave -33 IMD, 300 gave -20 IMD. There are two software parameters for tweaking the IMD,
the mimimum pwm duty cycle and the modulation delay count. I put these in the menu system for easy testing.
Their effect is minimal, you may gain 2 to 5 db in IMD with adjustment. I am using the 330,510 resistor pair which I
think may be ok to use without a heatsink mod. I am getting -30 or better IMD readings.
The code read and bandscope needs the nokia display in order to be useful. Coderead will work without
the display but it will be extremely difficult to tune the signal in correctly without the bandscope. An
alternate to the nokia display would be to run the radio audio to a waterfall display like in fldigi
and use the serial terminal and serial menu options.
***************************************************************************************
for buttons
tap = forward
double tap = back
long press = select for user - toggles an option on or off
long press function = frequency announce
8 options for user functions - long press of select will toggle the function on/off
mode menu - cw or rtty or one of the added modes ( psk,mfsk,hell,wspr,jt65,memory tuning )
CodeRead ( or turns on the LED s meter if no display )
Spot auto tune
Send CQ
Band Change
Split mode
VFO B mode
Lock VFO's
The LED's blank when not pressing buttons to save rx current.
The basic idea of this program for the rebel is it can be used portable without the display, or used in the
shack with the display and computer control. The default is currently field mode with battery saving 80 ma current.
On startup, the mode menu will display and one can easily change to display mode when in the shack.
The nokia display contrast adjustment or Macro menu is a long press of select when the function is BW.
The keyer speed adjustment is a long press of select when the function is STEP.
Make adjustments using the tuning encoder.
Press the function button to exit.
The nokia display has help text on the S meter line as what you will get with a long press of select.
Changes:
Rev 4.3 3/11/16
MFSK16 modem and decoder.
Moved the MFSK offset to 878 hz so it can be close to a multiple of 15.625 when mixed to lower tones.
The decoder will only work when the narrow bandwidth filter is selected.
Rev 4.2 2/20/16
Fixed some issues with the new terminal code - rtty carriage return and hellschreiber idle characters.
Added a software scope debug tool to allow viewing the waveforms in the decoders and digitial filters.
(Set up the probes ( ch1 and ch2 ). Compile and upload. Enable with long press of function.)
RTTY Decoder - reworked the clock recovery code. Previous code was more suitable for syncronous clock
recovery.
PSK31 decoder - wrote a 2nd decoder and some functions so it could be compared to the original. The new
decoder is active when the bandwidth selected is narrow. It is sometimes better but not always depending upon
the signal being recieved, fading, noise, distortion etc.
Removed the mode specific nature of the macro's. We now we have a pool of 20 general purpose macro's.
Rev 4.1 2/10/16
Added a PSK31 decoder. It works ok when signals are in the clear( more than 100 hz away ).
Added MFSK16 mode transmit. Got lazy with the mode specific macro's and MFSK and RTTY share the same macro's.
The offset is 878 (900) hz to the low tone which centers the signal at 995(1017) hz in the narrow bandwidth filter.
If set up in a memory channel for 60 meters, the channel offset should be specified as -995(1017) to transmit
in the center of the channel. This is a USB mode.
Use FLDIGI, Airlink Express or similar program for receive.
Did not include the extended character set ( values above 127 ) as the auto_tx routine uses bit 7 for something else.
Changed some memory channels to have 3 W1AW digital channels, one each for RTTY, PSK31 and MFSK16.
Changed the WSPR timing to 1.46484375 baud. Previously 1.4648.
Played around with user help to display the mode and sideband when function is user and select is menu.
Memory channel tuning also displays this info.
Added a menu to allow user to override the sideband in use for some modes. Default is the most used option.
When in serial terminal mode, enabled the decoders to always write to the terminal even if not writing to the nokia.
In terminal mode, Control Q or Control S will toggle the receive decode stream on and off. Characters are
discarded when the stream is off.
To summarize the terminal mode commands:
Control T - start transmit. CW and Hellschreiber do not need this command, just start typing.
Control R - change to receive when buffer is empty. CW and Hellschreiber do not need this command.
Control U - flush buffer and return to receive quickly.
Control Q or Control S - toggles quiet mode on and off. Decoded text is discarded.
Pulled the serial terminal code out of loop() and re-wrote it so the logic is easier to understand.
Made the S meter a bit more conservative in the readings it displays.
(Thinking about removing the mode specific nature of the macro's and just having a pool of 16 or 20.)
Rev 4.0 1/21/16
PSK31 mode transmit - proof of concept. The offset is 1000 hz. 40 meters tunes on LSB, so you will need to tune above
the normal frequency by 2 khz. For now, use FLDigi or Digipan type programs to receive.
Enabled the PSK mod pin and driving it high for JT65 and RTTY modes to provide about 1/2 watt out on those modes
where before it was 1/4 watt when using the 510 resistor low power mod as explained below somewhere.
Rev 3.7 1/16/16
Enabled sending Hellschreiber via the key jack. In using the key jack an external program would provide all the timing,
and fonts needed to transmit the characters via a hardware interace. ( much like using the keyjack for rtty sending ).
Basically the key jack is forced to be in straight key mode.
Changes to the save restore feature to hopefully not save memory tuning information. Added saving the band we were on.
Added AE6RQ memory setups to the memory stucture array. Fixed some setup issues, mine and his.
Rev 3.6 1/08/16
Added preset memory channels. They are general purpose. They are enabled in the mode menu. There are more menu choices
in the mode menu than lines available on the nokia display, so keep going past JT65 in the menu and the Memory Tuning mode
will appear.
Made RTTY mode always USB and removed the rty_invert code.
Swapped the position of RTTY and HELL in the menu's. Adjusted *menu[15] array to account for this change.
Added a sliding offset where upon turning RIT fully clockwise the signal will center in the middle of the passband.
Turn back to middle to use the RIT at the new offset.
Turn back to fully counterclockwise to return the offset to the value chosen in the menu.
This is a CW mode only feature.
Rev 3.5 1/07/16
Adding tx macro's over the display contrast option. Macro's available for CW, Hell, and RTTY modes. The contrast adjust
is only available when in WSPR or JT65 modes as macro's have no use in those modes.
I notice HFWST hangs on loading FSK values sometimes. I tried the original Skunk Werx sketch and it also hung. The issue
could be my very old slow laptop. Renamed my morse header file as it conflicted with the morse library file.
Rev 3.4 1/04/16
Changed the frequency calculation method from a VFO +- IF to a VFO +-BFO +- Offset type. I think this will make the
offsets for WSPR and JT65 easier to understand and manipulate.
It is easier to calibrate the radio. See some discussion below where Reference and bfo are defined.
When in CW mode and narrow or medium bandwidth the display will show actual CW frequency, else SSB carrier freq.
Add to the menu's a choice of CW offset tone/pitch. Many like a low tone but the use of a low tone puts the desired signal
on the edge of the IF filter passband. I think we can go as low as 600 but the center of the passband is about 1K Hz.
Corrected an assumption I had about the center of the JT65 waterfall - the center is at 1270 hz and not 1500.
Fix missing start bit on rtty transmit characters.
Rev 3.3 12/28/15
Fixed the CR/LF behavior of the SERIAL MENU's. Fixed the cq message not transmitting when in RTTY mode with the key
interface selected.
Add JT65 mode. Use in conjuction with the HFWST program provided by the Skunk Werks group.
This implementation is somewhat different as the Rebel controls the band and frequency of operation. Keep HFWST thinking it is
on 20 meters at 14076. HFWST did not decode for me until I moved it to a simple directory \hfwst and created a shortcut on
the desktop. I did not investigate why, perhaps the former path was too long or the spaces in the path were an issue.
(Have experienced some crashes during debug which seem to be related to itoa() or prints to the screen.)
Disabled RIT when in WSPR or JT65 modes.
JT65 uses the split vfo feature but the tuning is in lock step keeping the same offset as original. The VFO is originally locked
but you can unlock and tune around and still stay frequency netted to what you see on the JT65 waterfall. Useful for when
the band is busy and users spread out.
Returning to CW,Hell,RTTY from WSPR or JT65 was annoying as the split setup was still in place - so saving the setup and restoring it
before and after the menu's for the non-split modes.
Rev 3.2 12/18/15
See no reason why the dumb terminal send method shouldn't also work for CW and Hellschreiber.
New send methods are using the key jack, Perl GUI program, or a plain dumb terminal program ( like hyperterm or putty ).
Dumb terminal control:
For RTTY: Control T enables the transmitter. Control R to return to receive. Control U flushes the buffer and aborts.
For Hell: control T and control R enable and stop idle characters. Otherwise for Hell and CW the keyboard is always live.
When using the terminal method, no CAT emulation is possible as the serial port is in use.
The terminal baud rate is 1200 but you can change it to whatever you want and recompile. Look in top_menu() for the
hardcoded number.
If the user doesn't have a nokia display, the menu's can be viewed in a terminal screen. If you don't want this feature
you can disable it at compile time with defining SERIAL_MENUS as zero.
Added WSPR mode. Tuning is via the split feature. The 40 meters display will look odd as the split is wide in order to tune USB.
Added a time sync up to WWV for WSPR. Runs about every 40 minutes for 20 seconds.
Initial time sync up is via pressing a button at the correct time in the menu's.
See below for some instructions for setting up the WSPR message and defaults for other menu items.
Rev 3.1 12/14/15
Converted the mode power up menu to a general menu'ing system and went crazy with putting all the compile time options
into the menu's making them run time options - Cat Control Emulation, band limits, serial decode,etc.
Make menu selections by turning the tuning knob and pressing select or function when choice is highlighted.
Re-enter the menu's with user function zero - function led red and select led's blank.
Added RTTY send via a dumb terminal program for example hyperterm ( default baud is 1200 )
Rev 3.0 12/03/15
Add RTTY decoder and send via the paddle inputs. Dah input will key the transmitter and Dit input will alter the tone
transmitted.
*** IMPORTANT - you must do a heat sink mod if you wish to send RTTY at full power ***
Implemented a top menu at powerup. Use the Tuning knob to make a choice. Press select or function to exit.
The selection will timeout in 20 seconds if there is no activity on the knob or buttons.
The default selection is CW in the field mode without a display as this choice will be blind if not using a display.
The display on/off selection ( user selection 0 - no LED's lit ) has been changed to show the menu.
The transmit indicator has been removed from the TenTec LED and a RIT active indicator(dimly lit) has been added.
Transmit indicator is change in nokia display and the battery status that is displayed in the select LED's
Rev 2.2 12/20/14
Changed the refresh rate of the bandscope from 100 frames/sec to about 12. This was an attempt to reduce the
noise generated by the lcd writes to the nokia display. Also some types of signals were difficult to see with
the fast refresh rate.
Rev 2.1 11/22/14
Add 30 and 17 meter bands to the bandswitching routines. The extra bands can be easily skipped-look for comment(++band) in the code.
Add auto spot function in place of the s meter on/off function.
Use the dsp signal for the s meter when the display is active.
Add battery reading and low battery warning.
Swap positions of the band change and spot functions in the user rotation.
Fix some Rebels not powering up in receive dds mode.
Rev 2.0 11/01/14
The cut numbers option is now a home/portable option called DISPLAY. When enabled, the display code runs.
When display is disabled the cut numbers are active and the battery saver mode is also active.
Hardware mod for coderead. Connected the output of the AGC op-amp to a 1k resistor and .1uf cap in series. The cap is
connected to the CW speed pot center connection. The pot is centered. CodeRead is assigned to this input instead of the original.
(The signal level on the original CodeRead input is too low)
Add DFT spectrum display of the passband. Add coderead function as a user option.( user option 1-green )
Rev 1.9 10/16/14
Nokia 5110 display code added.
Removed choice of tuning digits to display in the LED's. Changed that menu function to code read for future use.
Rev 1.8 9/30/14
Keyer code speed adjust on longpress select when in the Step function and adjust using the tuning encoder knob.
Exit with a function button press.
Rev 1.7 8/26/14
Code support for the band switch module. If the unit boots up with the jumper detect low, this feature is
disabled to avoid driving the output pin with a jumper in place.
Rev 1.6 5/24/14
Battery saver mode with cpu sleep/idle and LED's out when not pushing buttons or tuning.
Rx current about 80ma as opposed to 150ma or so.
Added choice of tuning digits to display in the LED's ( see user functions below )
Rev 1.5 4/20/14
Add hellschreiber and cw keyboard transmit with a windows gui written in perl.
Add .7 volts to the battery reading to compensate for the protection diode voltage drop.
Rev 1.4
Add a battery low indication on the red select led.
Add no tuning zones to prevent hearing damage when using headphones.
Rev 1.3
Added a choice of TenTec Argonaut cat emulation at 1200 baud in addition to the K3 emulation.
Keep CTS,RTS and DTR off as it helps with the reset issue mentioned below.
Rev 1.2
Add Elecraft style K3 cat emulation at 38400 baud. HRD works but sometimes fails to start -
the radio is sometimes held in reset. There is mention of an etch cut on the Uno32 board to avoid this.
I didn't cut, I just try it again and it works.
All indications are that serial.print blocks. Added serial write staging buffer to maintain the loop timing.
Rev 1.1
Change split indication from the function leds to the tentec led, blinks twice or once depending
upon swap or not. User split is set to on when changing swap split, enter split with either option.
Rev 1.0 3/21/14
*/
#include "TT.h" // original TT defines for pinmode setup
#include "K1_morse.h" // also has baudot table. Renamed as conflicts with Library with name morse.h
#include "helldefs.h"
#include "sine_cosine.h"
#include "varicode1.h"
#include "fec_table.h"
/* !!!! change this to your call or whatever message you wish to auto transmit */
const char cq_msg[] = "CQ CQ CQ CQ DE K1URC K1URC K1URC K"; /* must use capital letters here */
/* !!! change this if you will use the WSPR transmitting feature */
// Download WSPRcode.exe from http://physics.princeton.edu/pulsar/K1JT/WSPRcode.exe and run it in a dos window
// Type (for example): WSPRcode "K1ABC FN33 37" 37 is 5 watts, 30 is 1 watt, 33 is 2 watts, 27 is 1/2 watt
// ( Use capital letters in your call and locator when typing in the message string. No extra spaces )
// Using the editing features of the dos window, mark and copy the last group of numbers
// Paste into notepad and replace all 3 with "3," all 2 with "2," all 1 with "1," all 0 with "0,"
// Remove the comma on the end
// Paste the result below in place of this group of numbers
// WSPR is a high duty cycle mode with a key down time of almost 2 minutes. You will need a heat sink mod or reduce power.
// the current message is "K1URC FN54 23"
const char wspr_msg[] = {
3, 3, 2, 2, 2, 0, 0, 2, 1, 2, 0, 2, 1, 1, 1, 2, 2, 2, 3, 0, 0, 1, 0, 1, 1, 3, 3, 2, 2, 0,
2, 2, 0, 0, 3, 2, 0, 3, 0, 1, 2, 0, 2, 0, 0, 2, 3, 0, 1, 3, 2, 0, 1, 1, 2, 1, 0, 2, 0, 3,
3, 2, 3, 2, 2, 2, 2, 1, 3, 2, 3, 0, 3, 0, 3, 0, 3, 2, 0, 3, 2, 0, 3, 0, 3, 1, 0, 2, 0, 1,
1, 2, 1, 2, 3, 0, 2, 2, 3, 2, 2, 0, 2, 2, 1, 0, 2, 1, 2, 0, 3, 3, 1, 2, 3, 1, 2, 2, 3, 1,
2, 1, 2, 0, 0, 1, 1, 3, 2, 2, 2, 2, 0, 1, 0, 1, 2, 0, 3, 1, 0, 2, 0, 0, 2, 2, 0, 1, 3, 0,
1, 2, 3, 1, 0, 2, 2, 1, 3, 0, 2, 2
};
/* Macro's - Enable with long press of select when function is bandwidth, exit with a press of function */
/* a tap of select will send the text */
// Put whatever you wish in these but keep in mind the tx buffer is 128 characters long without any overfill checking.
const char mmc0[] = "CQ CQ CQ CQ de K1URC K1URC K1URC k \r\x12";
const char mmc1[] = "de K1URC K1URC K1URC k \r\x12 "; // ( x12 is control R, back to RX mode )
const char mmc2[] = "ur rst is ";
const char mmc3[] = "Name is Ron Ron QTH is China, Me. China, Me. ";
const char mmc4[] = "Rig hr is a TenTec Rebel - 5 watts to G5RV ant up 30 ft. \r";
const char mmh0[] = "TKS fer qso - 73 ES GL ";
const char mmh1[] = "";
const char mmh2[] = "...CQ CQ CQ FELD HELL SPRINT DE K1URC K1URC K1URC...\r\x12";
const char mmh3[] = "TU 599 599 ME ME #4630 #4630 FN54 FN54 ";
const char mmh4[] = "73 AND GOOD LUCK DE K1URC\x12";
const char mmp0[] = "";
const char mmp1[] = "Hello OM and Thanks for the call/report\r ";
const char mmp2[] = "Name is Ron Ron, QTH is China,Me. China,Me.\r ";
const char mmp3[] = "Locator FN54fk FN54fk ";
const char mmp4[] = "\rMY STATION:\r TenTec Rebel at 1/2 watt\r G5RV antenna up 30 feet\r ";
const char mmr0[] = "";
const char mmr1[] = "QTH is Liberty, Me. Liberty, Me.";
const char mmr2[] = "Running portable with TenTec Rebel and BuddiStick Antenna \r";
const char mmr3[] = "";
const char mmr4[] = "SOTA summit is ";
// edit the above and leave this alone
const char *macro[20] = { mmc0,mmc1,mmc2,mmc3,mmc4,mmh0,mmh1,mmh2,mmh3,mmh4,mmp0,mmp1,mmp2,mmp3,mmp4,mmr0,mmr1,mmr2,mmr3,mmr4};
#define WSPR_TX_OFFSET 38 // enter a number between -100 and 100 ( compile time option )
#define SERIAL_MENUS 0 // define as 1 if wanted. Useful if you don't have a nokia display. May interfer with CAT control.
/******* menu defaults - set to what you use the most but can always change via the menu when operating *******/
/* leave the defines alone and just change what is assigned to the variables */
/* computer control emulation */
#define NO_EMU 0
#define ARGO_EMU 1
#define K3_EMU 2
int cat_emu = ARGO_EMU; // must use Argonaut V emulation if running the Perl control program, otherwise your preference
/* tx lockout by license class, allow general coverage receive */
#define EXTRA 0
#define ADVANCED 1
#define GENERAL 2
#define NOVICE 3
#define EUROPE 4
int band_limits = ADVANCED; // change this line for a different default
int serial_decode = 0; // when enabled sends the decoded morse or rtty on the serial line
// one can use hyperterm (for example) to see the text on a larger screen than the nokia display
// this might interfer with CAT control but am alowing both to be enabled at the same time.
#define JUMPERS 0
#define TWO_BAND 1
#define FOUR_BAND 2
int band_switch = FOUR_BAND; // type of band switch module installed
// you probably will want to change this to TWO_BAND
int cut_num_enable = 0; // cut_num_enable = 1 may be useful for when using the radio without a display
// when enabled each change of 10 khz is announced in morse
// this is not a menu item as it is most useful when lacking a display
int rtty_on_leds = 0; // when enabled the green led's will flash with the decoded rtty signal
/* sending method - for rtty one can use a hardware interface wired to the key jack, or use a terminal program */
/* this also allows CW and Hellschreiber to be sent via a terminal program */
/* the key jack will always send CW if not using RTTY with the hardware interface wired to the key jack */
#define CRH_TX_KEY 0
#define CRH_TX_TERM 1
#define CRH_TX_PERL 2 // using the Perl GUI - I don't think many users have tried this
int crh_tx_method = CRH_TX_KEY;
// CW offset tone must be 600 or above or the bandscope/auto spot/decode will be broken I think
// the tones need to be on multiples of 100 because of the way the fft and cw decoder works.
// if you really want a different pitch that is not a multiple of 100 and don't care about the decoder,
// look in top_menu() at how the mode_offset for CW is calculated. Changing stuff here won't do anything.
#define CW_TONE_600 0
#define CW_TONE_700 1
#define CW_TONE_800 2
#define CW_TONE_900 3
#define CW_TONE_1000 4
int cw_offset_tone = CW_TONE_900; // 1000 or 1100 is the center of the narrow filter
/* modes */
#define CW 0
#define HELL 1
#define PSK31 2
#define RTTY 3 // rtty and above always tune USB
#define MFSK 4
#define WSPR 5
#define JT65 6
#define WEFAX 7
#define MEM_TUNE 7 // overlays WEFAX as a mode
#define SSB 7 // sort of a dummy mode for the memory channels
int wpm = 12; /* default paddle speed - you may want to change this */
const int sliding_offset_enable = 1; // The offset change via RIT control feature ( compile time option )
/**************** End of user options and default values - remember can always change in menu at runtime *****************/
#define LSB 0
#define USB 1
struct MEMORY {
char name[15];
long freq;
int band; // use only 0 and 2 for a 2 bandswitching module, 0=40 1=30 2=20 3=17
int sideband;
int offset;
int mode; // JT65 and WSPR not allowed as memory tune modes
};
// Edit the below for your needs. If you have a 2 band module you will want to pick frequencies close to 20 and 40 meters
// The TenTec filters are pretty sharp in the Rebel, so your choices may be limited.
// Frequencies close to 9 mhz tuned USB will have poor image rejection.
// The channels can be used for any general purpose. I just loaded them with WEFAX cause I like to watch paint dry.
// You can add more or remove some by changing the NOMEM definition and the memory structure array below.
// USB offsets should normally be negative and LSB positive.
// The combination of the freq and offset specify the suppressed carrier freq the radio is tuned to.
// As an example you can tune 60 meter SSB memory channel two ways
// { "60 Meters 1", 5332000, 0, USB, -1500 , SSB }, here the memory channed center is specified and an offset of 1500
// { "60 Meters 1", 5330500, 0, USB, 0 , SSB }, here the suppressed carrier freq is entered directly
// The first way is handy when channel centers are specified as in WEFAX and 60 meters
// The 2nd way is handy when you know the ssb suppressed carrier frequency directly as in net frequecies or tuning WWV.
// For CW you need an offset or your transmit freq will result in a zero freq tone in the other guys receiver, he won't hear you.
// You can tune around a memory channel by unlocking the VFO.
#define NOMEM 52
const struct MEMORY memory[NOMEM] = {
{ "40m QRP", 7030000, 0, LSB, 800, CW },
{ "40m QRP", 7040000, 0, LSB, 800, CW },
{ "40m QRP", 7060000, 0, LSB, 800, CW },
{ "TT 40m CW Net", 7063000, 0, LSB, 800, CW },
{ "TT 40m SSB Net", 7263000, 0, LSB, 0, SSB },
{ "20m QRP", 14060000, 2, USB, 800, CW },
{ "20m Beacon", 14100000, 2, USB, 800, CW },
{ "TT 20m SSB Net", 14325000, 2, USB, 0, SSB },
{ "W1AW PSK31", 7095000, 0, LSB, 1000 , PSK31 },
{ "W1AW MFSK16", 7095000, 0, USB, -995 , MFSK },
{ "W1AW RTTY", 7095000, 0, USB, -1000 , RTTY },
{ "W1AW Code" , 7047500, 0, LSB, 900, CW },
{ "60 Meters 1", 5332000, 0, USB, -1500 , SSB }, // way down on the 40 meters passband
{ "60 Meters 2", 5348000, 0, USB, -1500 , SSB }, // but may hear very load stations
{ "60 Meters 3", 5358500, 0, USB, -1500 , SSB },
{ "60 Meters 4", 5373000, 0, USB, -1500 , SSB },
{ "60 Meters 5", 5405000, 0, USB, -1500 , SSB },
{ "60 Meters CW 1", 5332000, 0, LSB, 900 , CW },
{ "60 Meters CW 2", 5348000, 0, LSB, 900 , CW },
{ "60 Meters CW 3", 5358500, 0, LSB, 900 , CW },
{ "60 Meters CW 4", 5373000, 0, LSB, 900 , CW },
{ "60 Meters CW 5", 5405000, 0, LSB, 900 , CW },
{ "Boston", 6340500, 0, USB, -1900 , WEFAX },
{ "Halifax", 6496400, 0, USB, -1900 , WEFAX }, // may not be active according to my list
{ "Sydney NS", 6915100, 0, USB, -1900 , WEFAX },
{ "Murmansk USSR",6444500, 0, USB, -1900 , WEFAX },
{ "New Orleans", 8503900, 1, USB, -1900 , WEFAX },
{ "Pt. Reyes", 8682000, 1, USB, -1900 , WEFAX },
{ "Northwood UK", 8040000, 1, USB, -1900 , WEFAX },
{ "Boston", 9110000, 1, USB, -1900 , WEFAX }, // the dds will be 110 khz for this one, image on 8890000
{ "Boston", 12750000, 1, USB, -1900 , WEFAX },
{ "New Orleans", 12789900, 1, USB, -1900 , WEFAX },
{ "Pt. Reyes", 12786000, 1, USB, -1900 , WEFAX },
{ "Kodiak", 12412500, 1, USB, -1900 , WEFAX },
{ "Honolulu", 11090000, 1, USB, -1900 , WEFAX },
{ "Tokoyo", 13988500, 2, USB, -1900 , WEFAX },
{ "Hamburg", 13882500, 2, USB, -1900 , WEFAX },
{ "New Orleans", 17146400, 3, USB, -1900 , WEFAX },
{ "Pt. Reyes", 17151200, 3, USB, -1900 , WEFAX },
{ "Taipei", 18560000, 3, USB, -1900 , WEFAX },
{ "Air Volmet", 6604000, 0, USB, 0 , SSB },
{ "Air NY E", 6628000, 0, USB, 0 , SSB },
{ "Air Carib A", 6577000, 0, USB, 0 , SSB },
{ "Air Carib B", 6586000, 0, USB, 0 , SSB },
{ "Air LDOC", 6640000, 0, USB, 0 , SSB },
{ "Air NY A", 13306000, 2, USB, 0 , SSB },
{ "Air NY E", 13354000, 2, USB, 0 , SSB },
{ "Air Carib B", 13297000, 2, USB, 0 , SSB },
{ "Air LDOC", 13330000, 2, USB, 0 , SSB },
{ "CHU Canada", 7850000, 0, USB, 0 , SSB }, // chu is usb with carrier re-inserted
{ "WWV", 10000000, 1, LSB, 0 , SSB },
{ "WWV", 15000000, 2, USB, 0 , SSB }
};
int channel = 0; // current memory channel.
int mem_tune = 0;
// Other mods I have done that do not need to be implemented.
// I implemented a low power feature by removing the wiring from the on/off switch, jumpering the power on the board so
// that the Rebel is always on. I wired the switch so that a 510 resistor to ground is added to the center of the final
// FET bias pot. When the switch is down/off the power out is 250 mw and when up/On it is the normal 5 watts.
// All the wiring was done on the top side of the board, so removal from the case was not required.
// Low power is used for WSPR and JT65 and RTTY if transmission is long. CW and Hell are low duty cycle modes and high power is OK.
// WSPR does drift a bit so I may be adding a heat sink mod or a temperature stabilization method.
// I have since converted the low power feature into the PSK31 AM modulator.
// AGC - I removed U$91 from the circuit with etch cuts and added an agc controlled attenuator in front of the 1st mixer.
// Power out - I added and since removed a 8.2 k resistor from the power out test point to ground. The power out voltage exceeds
// 3.3 volts preventing an accurate reading at 5 watts out. The very small coupling cap also complicates resistor divider calculations.
// I unsoldered one side of C22 and effectivly removed it from the circuit. This reduces the gain of the LM386 by 20db but more
// importantly it removes all the hiss noise. The waterfall on fldigi is much cleaner with this mod.
#define PWR_WARN 1 // set to 1 if you have a low power mod and wish to be notified if the power out is incorrent for the mode in use.
#define NUMBANDS 7 // general has 6 segments 40 to 17 meters
const int bandstart[5][NUMBANDS] = {
{7000,14000,10100,18068,5331,0,0}, //extra
{7025,14025,14175,10100,18068,5331,0}, //advanced
{7025,7175,14025,14225,10100,18068,5331}, //general
{7025,0,0,0,0,0,0}, //novice
{7000,14000,10100,18068,0,0,0} //europe - add 60 meters if you want it enabled
};
const int bandend[5][NUMBANDS] = {
{7300,14350,10150,18168,5406,0,0},
{7300,14150,14350,10150,18168,5406,0},
{7125,7300,14150,14350,10150,18168,5406},
{7125,0,0,0,0,0,0},
{7200,14350,10150,18168,0,0,0} // I left out enabling 60 meters for Europe
}; // Set up your channels in the memory struct and enable here
int msec = 0; // keep time for wspr
int sec = 0;
#define SAVE 0
#define RESTORE 1
/* LEDs */
#define FGRN 0x20 // all on port D
#define FYEL 0x0800
#define FRED 0x40
#define SGRN 0x80 // on port D
#define SYEL 0x10 // on port F
#define SRED 0x20 // on port F
#define TTLED 0x2000
/* button states */
#define NOTACTIVE 0 // idle is a used constant in lib? - expected unqualified ID before numeric constant error
#define ARM 1
#define DTDELAY 2
#define FINI 3 // done is a used constant in lib
#define TAP 4
#define DTAP 5
#define LONGPRESS 6
#define DBOUNCE 60
/* band widths */
#define WIDE 1
#define MEDIUM 2
#define NARROW 3
#define ON 1
#define OFF 0
#define TXENABLE 0x40
#define DDS_SEL 0x80
#define PSEL 0x40 // mask value for bit RG6
#define PSK_MOD 2 // mask for pin on RF1
#define BATTERYCHK A2
#define POWEROUT A3
#define SIGNAL A1
#define RIT_PIN A0
// #define CODEREAD_PIN A6
/* coderead changed from A6 to A7 - the cw speed pot.
it is connected to pin 7 of agc op amp via a 1 k resister and 0.1 uf cap in series.
The pot is set to center
*/
#define CODEREAD_PIN A7
#define NO_DISPLAY_UPDATE 0
#define DISPLAY_UPDATE 1
#define MFSK_LOOPBACK 2 // software loopback for testing mfsk decoder algorithm - normally this should be zero
// greater than 1 is the percentage of errors introduced into the bit stream ( 4 bit errors at a time )
/* ************************************************* */
/* globals */
const long Reference = 50000352L; // was 49.99975e6
// noticed freq was off 200 hz on 20 meters, and 100 hz on 40 meters
// tuned as 50000468 on a station receiver
// recent check was 50000352
// this drifts enough that the 1st JT65 transmission in my testing
// does not decode
long bfo = 8999334L; // the bfo drifts alot with heat and the parts are very close to the final FET
// hot it may be 8999317 or lower, and cool 8999340 or higher.
/*
Calibrate the rebel with a station receiver. Allow both to warm up. You should transmit a bit.
Run the audio of the station receiver to a program like fldigi. Run a short antenna lead from the
station receiver to near the BFO test point. A direct connection is not wanted nor needed.
Tune near 9 mhz using USB. Expand the scale in fldidi to 4X. Tune the signal in
so the waterfall trace is on 1K audio. Add 1 K to the reading on the station receiver. This is the bfo frequency.
Repeat with the antenna lead near the Ref test point and tune near 50 Mhz. This will be the Reference frequency.
Don't forget to add the 1K audio offset to the reading of the station receiver.
*/
int fleds[] = {FGRN,FYEL,FRED}; // display for function button state
int sleds[] = {0,SGRN,SYEL,SRED,SGRN+SYEL,SGRN+SRED,SYEL+SRED,SGRN+SYEL+SRED}; // extra for user functions
int sw_state[2] = {NOTACTIVE,NOTACTIVE}; /* state of the two switches */
int wspr_duty = 0; // good idea to start at zero so tx doesn't take off when unwanted
int wspr_tx_enable = 0; // tx this next 2 minute interval flag
int wspr_wwv = 3; // different message depending upon how long ago wwv was successfully found
const char wspr_wwv_msg[4][4] = {
"WWV", "wwv", "...", " "
};
/* states of functions and selections and startup defaults */
int fun_selected[] = {2,1,0};
// 2, bandwidth yel = medium - 3 positions
// 1, step 100 - use 0 for step 10 - 4 positions
// 0 user function menu ( total of 8 user functions )
int function = 2; /* start out in user - menu */
unsigned long tx_vfo,rx_vfo;
unsigned long tuning_rate;
unsigned long listen_vfo;
int rit_offset = 0;
int tdec, thun, tunits;
unsigned int led_on_timer= 0;
int tx_inhibit= 0;
int tdown = 0;
int split = 0;
/* user options - general idea is when red led shows then be careful as it is a special function */
/* long press the select button to toggle the options on and off */
/* when the option is enabled, the function green led will be lit */
#define DISPLAY 0 /* no select LED's lit - this now brings up the menu */
#define CODEREAD 1 /* green - Nokia display of decoded text vs normal freq display */
#define SPOT 2 /* yellow - auto tune signal */
#define BEACON 3 /* red - auto call CQ */
#define BAND 4 /* green yellow - band change */
#define SPLIT 5 /* green red -leds are split - extended RIT range */
#define SWAPVFO 6 /* yellow red - swap - tune and listen on TX freq - press again to exit or hit the paddle */
#define LOCK 7 /* green yellow red - lock vfo's */
/* simple split operation */
/* longpress 5 = enter split - listen on RX freq - Tune RX - TX freq fixed - TT led blinks once */
/* longpress 6 = swapvfo - listen on TX freq - Tune TX - RX freq fixed - TT led blinks twice */
/* press swapvfo again or hit the paddle = swap back to listen on RX - Tune RX - xmit TX */
/*
freq display in LED - turns on when tuning, off after a delay
display the 100khz and 10khz digits or the 10khz and 1khz digits depending upon step size
digits 8 and 9 are displayed in the 3 LED's by dimming the Yellow and Red for 8 and Yellow for 9
this only runs when no display is selected in the menu's ( what I am calling field mode )
*/
unsigned char user[8] = {0,0,0,0,0,0,0,0}; /* user flags */
/* announce and beacon buffer - set msb on characters to key xmit */
#define ANNOUNCE_WPM 20 /* hardcoded */
#define TXQUESIZE 128 /* must be power of two */
unsigned char tx_queue[TXQUESIZE];
int tx_in= 0;
int tx_out= 0;
int tx_state= 0;
int autotx_timer= 0;
#define STQUESIZE 128
unsigned char stg_buf[STQUESIZE]; /* stage buffer to avoid blocking on serial writes */
int stg_in = 0;
int stg_out = 0;
unsigned char cut_numbers[] =
{ 0b11000000, 0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100, 0b10000100, 0b10001000, 0b10010000, 0b10100000 };
int straightkey = 0;
int transmitting = 0;
int cel,nel; /* current element, next element */
int tholdoff; /* debounce straight key */
int tprotect = 0; /* are you sitting on the key - enable again by hitting the function button */
long keyuptime = 0;
unsigned int counter; // used for paddle timing and idle characters in rtty and hell
#define DIT 0x40
#define DAH 0x80
/* encoder */
int en_lval;
int en_dir;
/* no tune areas - eardrum saver */
#define NUMNOZONE 4
unsigned long nozone[NUMNOZONE] = {9000000,11250000,13500000,18000000};
/* a bit of a hack to show 10 numbers in 3 LED's - leds are dim when displaying 8 and 9 to show overflow */
int fled89 = 0;
int sled89 = 0;
int bat_low = 0;
int bat_interlock = 0;
int hchar; /* single char buffer for hell */
int hflag = 0;
int pchar; /* same type of buffer for psk31 */
int pflag;
int psk_dn_count; // variable to produce steady carrier at end of transmission
int psk_mod_pwr; // desired power out
int fflag; // one character buffer for mfsk16
int fchar;
// psk IMD tweaking parameters. These interact with the resister used for the pwm.
// putting these in the menu's so they can be easily investigated
int psk_min_duty = 600; // Low power out min duty cycle.
int psk_min_du = 2; // menu option for the above
int psk_mod_delay = 4; // delay in counts of the phase reversal compared to the pwm minimun power out
#define MARK_OFF 85 // rtty offsets from center. Produce 170 hz shift
#define SPACE_OFF -85
/* band switch variables */
#define MAX_BAND 4
int bandswitch_enable = 1; /* enabled or disabled */
int band;
long save_tx_vfo[] = {7031000L, 10107000L, 14060000L, 18096000L}; // these are now ssb carrier frequencies
long save_rx_vfo[] = {7031000L, 10107000L, 14060000L, 18096000L};
int save_split[] = {0,0,0,0};
int mode = CW; /* default is CW and no display - ie field mode */
int sliding_offset;
// flags to modify what the tuning knob does
int wpm_adjust = 0; /* code speed adjust using the tuning knob */
int contrast_adjust = 0; /* nokia adjustment on the tuning knob */
int top_active= 0; /* top menu on the tuning knob */
int select_macro= 0; /* selecting a macro on the tuning knob */
/* nokia display */
#include <LCD5110_Basic.h>
extern unsigned char SmallFont[];
extern unsigned char MediumNumbers[];
extern unsigned char BigNumbers[];
#define NO_DISPLAY 0
#define NORM_D 1
#define SPLIT_D 2
#define DECODE_D 3
#define WPM_D 4
#define CONTRAST_D 5
#define MACRO_D 6
int nokia = NO_DISPLAY; // must be zero the first time we put up the menu as the dsp_core isn't running - otherwise weird bug
int contrast = 65;
int timeout_ok = 0;
int save_nokia; // save display setting when change to contrast or keyer speed screen
int nokia_s_inhibit= 0; // separate nokia s meter from the LED s meter
LCD5110 LCD( 30,29,28,26,27 ); /* should reset be on I/O or tied to system reset. I used system reset */
/* dsp variables */
long samples[8]; /* buffer so samples are not lost due to cpu timing */
int s_in, s_out;
int rty_in, rty_out; /* rtty decode indexes into the same sample array */
int rty_modem_out;
#define OFFSET 16 // cosine offset from sine
#define MOD 63 /* mask for index value */
#define FFTSIZE 64
int sideband = USB; // radio powers up on 20 meters in order to check for a band switching module
#define NORMAL 0 // sideband selection in menu now, normal is LSB on 40 meters and USB on 20
#define USB_ONLY 1 // can't have LSB only as 20 meters can't tune the vfo that high ( 14 + 9 beyond dds filter cutoff )
int sideband_mode = NORMAL;
// starting CW offset, the filter center is 1000 or 1100. Below 900 one is on the edge of the passband.
int mode_offset = 900; // this will change with each mode
int goalpost = 9; // tuning slightly on the low side of the filter with these settings
int vals[FFTSIZE/2 + 1]; /* sin value */
int valc[FFTSIZE/2 + 1]; /* cos value */
int workval[FFTSIZE/2+1];
int plotval[FFTSIZE/2+1];
int workval1[FFTSIZE/2+1];
int workval2[FFTSIZE/2+1];
int w_max;
int w_max1;
int w_max2;
int mfsk_afc;
int go_plot;
int fast_plot;
int cread_buf[16]; /* code read buffer */
int cread_indx;
int quiet_mode; // Control S or Q to suppress decoded garbage characters
/*
With the 64 point fft and 6400 sample frequency we have about 10ms sample time for looking at morse decode.
Based upon 1200/wpm we get this table for counts
Speed
10 15 20 25 30
element 12 8 6 5 4 dit
3 els 36 24 18 15 12 dah
7 els 84 56 42 34 28
slicer 18 12 9 7 6
average anything equal to or over 12 counts as dah's to figure speed. force slicer in bounds of 6 to 24.
Goal is to have it work from 10 to 30 wpm
*/
int dah_table[8] = {20,20,20,20,20,20,20,20};
int dah_in;
int shi5; /* an attempt to extend the high speed decode above the designed 30 wpm limit
/*
For RTTY the dsp core sample rate is 4000 ( instead of 6400 as in CW ).
Each bucket in the DFT will represent 62.5 Hz. ( In CW mode each DFT bucket is 100 hz )
The center is at 1000 hz. The low tone is 915 hz. The high tone is 1085 hz. This puts it nicely in the center
of the narrow passband.
RTTY should be tuned with the narrow filter to avoid alias signals due to the low sample rate
*/
/* analogRead does not look re-entrant, so we are reading all analog values in the same core function and storing the
results in these global values for general use. In battery saver mode the core function is disabled so
in that case each analog routine will need to read the pin and refresh the global value */
int rit_value, power_value, battery_value, smeter_value;
int smeter_value2; // dsp s meter
/* auto spot vars */
int spot_timer;
int spot[11];
unsigned long oldtime; // made these global so can sync up the timer for wspr when in the menu's
unsigned long time; // ( mainly they are loop() variables )
// for WSPR - try tuning to WWV and syncing up the seconds clock once each 59 minutes
// using 59 minutes to avoid a possible condition of always tuning when the 1500 hz tone is sent by wwv
// the actual checking time is 40 minutes not 59
// two band board will tune to 15 mhz, 4 band board to 10 mhz
#define WWV_TONE_DET 60 // # of counts needed for detection out of a possible 80 counts
int wwv_tone; // the counter
long jt_buf[128];
long jt_fcalc0; // rx dds word, saved so we can send it back on serial
int jt_tx_on; // controls transmit
int jt_tx_index; // where we are in 126 tx tones
int jt_time; // serial timer to avoid blocking on writes to serial port
#define MFSK_GO 1
#define MFSK_STOP 3
int mfsk_flag = 0; // mfsk16 transmit control
/* SoftScopeTM - a software oscilloscope */
#define SOFTSCOPE 1 // 1 to enable the overlay of annouce frequency ( long press of function ), 0 for normal operation
int scope_active; // control flag
int timebase; // basically a sample decimate factor
int timeb; // for the menu
int ch1, ch2, ch3; // probes ch3 overlays part of ch1
int ch1_data[80]; // sample storage
int ch2_data[80];
/* **************************************************** */
/* **************************************************** */
/* local Nokia routines specific to the Rebel hardware */
/* these are much faster than the Library routines */
#define SETROW 0x40
#define SETCOL 0x80
#define CLK_B 0x10
#define DAT_B 0x08
#define DC_B 0x04
#define CS_B 0x02
void lcd_write(char dat){ /* write one byte, data or command */
unsigned int mask;
if( scope_active > 3 ) return; // stop all writes to the screen
/* signals on port E. D/C bit has been set as appropriate */
LATECLR = CLK_B + CS_B; // CS asserted low
mask= 0x0080;
while( mask ){
if( dat & mask ) LATESET = DAT_B;
else LATECLR = DAT_B;
/* setup time data to clock */
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
LATESET = CLK_B; // clock high
mask >>= 1; // next bit
/* hold time */
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
LATECLR = CLK_B; // clock low
}
LATESET = CS_B; // chip select unasserted
}
void lcd_command( char command ){
LATECLR = DC_B;
lcd_write( command );
LATESET = DC_B;
}
void lcd_goto( int row, int col ){ // 6 rows, 84 columns
lcd_command( SETROW | row );
lcd_command( SETCOL | col );
}
void lcd_putch( char c ){ /* write one char from small font table */
int offset;
int i;
offset = 6 * (c - ' ') + 4;
for( i = 0 ; i < 6; ++i ){
lcd_write(SmallFont[offset + i]);
}
}
void lcd_puts( char * p ){ /* write string using small font */
char c;
while( c= *p++ ) lcd_putch(c);
}
void scope_display(){
int active;
active = scope_active + 1;
if( active == 4 ) scope_display1();
else if( active == 5 ) scope_display2();
else if( active == 6 ) active = 0;
scope_active = active;
if( active == 0 ){
LCD.clrScr();
tuning_display();
}
}
int max1,max2;
int min1,min2;
void scope_display2(){ // graph
int gmax,gmin;
timeout_ok = 2;
scope_active = 3; // allow screen writes for this function
LCD.clrScr();
// gmax = ( max1 > max2 ) ? max1 : max2;
// gmin = ( min1 < min2 ) ? min1 : min2;
// if( gmin > 0 ) gmin = 0;
// if( gmax < 0 ) gmax = 0;
gmax = ( max1 < 0 ) ? 0 : max1;
gmin = ( min1 > 0 ) ? 0 : min1;
scope_graph( gmin,gmax,ch1_data,0 );
gmax = ( max2 < 0 ) ? 0 : max2;
gmin = ( min2 > 0 ) ? 0 : min2;
scope_graph( gmin,gmax,ch2_data,3 );
}
void scope_display1(){ // data summary
int i;
int ave1,ave2;
char buf[35];
scope_active = 3; // sllow screen writes
LCD.clrScr();
ave1 = ave2 = 0;
max1 = max2 = -9999999;
min1 = min2 = 9999999;
for( i = 0; i < 80; ++i ){
ave1 += ch1_data[i];
ave2 += ch2_data[i];
if( ch1_data[i] > max1 ) max1 = ch1_data[i];
if( ch2_data[i] > max2 ) max2 = ch2_data[i];
if( ch1_data[i] < min1 ) min1 = ch1_data[i];
if( ch2_data[i] < min2 ) min2 = ch2_data[i];
}
ave1 /= 80;
ave2 /= 80;
lcd_goto(0,0);
lcd_puts("max ");
itoa(max1,buf,10);
lcd_puts(buf);