  
  ' Commands to set up LCD panel:
  '
  ' OPTION LCDPANEL SSD1963_5, LANDSCAPE, 48
  ' OPTION TOUCH 1, 40, 39
  ' GUI CALIBRATE

  OPTION EXPLICIT
  OPTION DEFAULT NONE
  
  CONST P0 = 90'20
  CONST P1 = 81
  CONST P2 = 80
  CONST P3 = 79
  CONST P4 = 72'14
  CONST P5 = 71'72
  CONST P6 = 70'71
  CONST P7 = 68'70
  CONST RELAY = 41
  CONST REF_OUTPUT = 22
  CONST TCXO_LE = 25
  CONST HF_LE = 43
  CONST LF_LE = 76
  CONST GPS_1PPS = 78
  CONST OC1_OUT = 43 ' gates T4CK
  CONST OC1_IN = 34
  CONST OC2_OUT = 76 ' gates T1CK
  CONST OC2_IN = 44
  DIM STRING VERSION LENGTH 10 = "v1.00"
  
  
  SETPIN P0, DOUT
  SETPIN P1, DOUT
  SETPIN P2, DOUT
  SETPIN P3, DOUT
  SETPIN P4, DOUT
  SETPIN P5, DOUT
  SETPIN P6, DOUT
  SETPIN P7, DOUT
  SETPIN RELAY, DOUT
  PIN(RELAY) = 0
  SETPIN TCXO_LE, DOUT
  PIN(TCXO_LE) = 0
  SETPIN HF_LE, DOUT
  PIN(HF_LE) = 1
  SETPIN LF_LE, DOUT
  PIN(LF_LE) = 1
  SETPIN REF_OUTPUT, DOUT
  
  CPU 100
  CONST MAX_DIV_RATIO = 600
  DIM TOUCH$ LENGTH 10
  DIM INTEGER cur_tx, cur_ty, init_tx, init_ty, dx, dy, temp, temp2, last_touch
  DIM INTEGER last_pulse_time
  
  DIM DispMode$ LENGTH 10 = "Freq"
  DIM FreqInput$ LENGTh 10 = "SMB"
  DIM FLOAT UpdateHz = 1
  DIM INTEGER InputImpedance = 1000000
  DIM INTEGER bl_bright = 50
  DIM INTEGER averaging_time = 0', averaging_ticks = 0, averaging_last_tick
  DIM INTEGER ref_freq = 0
  DIM INTEGER stored_tcxo_freq100 = 1636800000
  DIM INTEGER tcxo_accuracy_ppb
  DIM INTEGER stored_tcxo_accuracy_ppb = 2000
  CONST min_gps_tcxo_ppb = 100
  DIM INTEGER tcxo_freq100
  DIM INTEGER last_tcxo_freq100
  DIM INTEGER eeprom_present, changes_to_be_saved
  
  FONT 3
  DIM INTEGER f3w = MM.FONTWIDTH, f3h = MM.FONTHEIGHT
  FONT 5
  DIM INTEGER f5w = MM.FONTWIDTH, f5h = MM.FONTHEIGHT
  FONT 6
  DIM INTEGER f6w = MM.FONTWIDTH, f6h = MM.FONTHEIGHT
  
  FONT 5
  GUI SETUP 1
  PAGE 2
  GUI FRAME #1, "Calibration", MM.HRES/12, MM.VRES/10, MM.HRES-MM.HRES/6, MM.VRES*0.8, RGB(WHITE)
  GUI CAPTION #2, "TCXO Frequency:", MM.HRES*.12, MM.VRES*0.3, LT, RGB(WHITE), RGB(BLACK)
  GUI TEXTBOX #3, MM.HRES*0.57, MM.VRES*0.28, MM.HRES*0.32, MM.VRES/10, RGB(WHITE), RGB(BLACK)
  CTRLVAL(#3) = "16368000"
  GUI CAPTION #4, "Accuracy (ppb):", MM.HRES*.12, MM.VRES*0.5, LT, RGB(WHITE), RGB(BLACK)
  GUI NUMBERBOX #5, MM.HRES*0.57, MM.VRES*0.48, MM.HRES*0.32, MM.VRES/10, RGB(WHITE), RGB(BLACK)
  CTRLVAL(#5) = 3000
  GUI BUTTON #6, "Save", MM.HRES*0.2, MM.VRES*0.7, MM.HRES/4, MM.VRES/10, RGB(GREEN), RGB(128,128,128)
  GUI BUTTON #7, "Cancel", MM.HRES*0.55, MM.VRES*0.7, MM.HRES/4, MM.VRES/10, RGB(GREEN), RGB(128,128,128)
  
FUNCTION is_eeprom_present%()
  I2C open 100,100
  I2C write &H57, 0,2,0,0
  IF MM.I2C = 0 THEN
    is_eeprom_present% = 1
  ELSE
    is_eeprom_present% = 0
  ENDIF
  I2C CLOSE
END FUNCTION
  
Sub eeWriteInt (address, val%)
  Local msb, lsb, count
  
  I2C open 100,100
  msb=address\256
  lsb=address Mod 256
  
  FOR count = 0 TO 7
    I2C write &H57, 0, 3, msb, lsb+count, val% AND 255
    PAUSE 1
    val% = val% >> 8
  NEXT count
  I2C close
End Sub
  
Function eeReadInt(address) AS INTEGER
  Local msb, lsb, count
  LOCAL INTEGER eeReadB
  
  I2C open 100,100
  msb=address\256
  lsb=address Mod 256
  
  eeReadInt = 0
  FOR count = 0 TO 7
    I2C write &H57, 0,2,msb,lsb+count
    I2C read &H57, 0,1,eeReadB
    eeReadInt = eeReadInt + (eeReadB << (count*8))
  NEXT count
  I2C close
End Function
  
SUB save_variable num%, value%, delay_if_flash_write%
  IF eeprom_present THEN
    eeWriteInt num%*8, value%
  ELSE IF delay_if_flash_write% = 0 THEN
    VAR SAVE stored_tcxo_freq100, DispMode$, UpdateHz, FreqInput$, InputImpedance, averaging_time, ref_freq, bl_bright, stored_tcxo_accuracy_ppb
    IF changes_to_be_saved THEN
      changes_to_be_saved = 0
      TEXT MM.HRES, f3h*4, "           ", "RT", 3, 1, RGB(255,192,255), RGB(BLACK)
    ENDIF
  ELSE
    changes_to_be_saved = 1
    TEXT MM.HRES, f3h*4, "Save config", "RT", 3, 1, RGB(255,192,255), RGB(BLACK)
  ENDIF
END SUB
  
FUNCTION mmss$(seconds%)
  IF seconds% > 60 THEN
    mmss$ = STR$(seconds% \ 60) + "m" + STR$(seconds% MOD 60)
  ELSE
    mmss$ = STR$(seconds%) + "s"
  ENDIF
END FUNCTION
  
FUNCTION ddhhmmss$(seconds%)
  IF seconds% > 3600*24 THEN
    ddhhmmss$ = STR$(seconds% \ (3600*24)) + "d" + ddhhmmss$(seconds% MOD (3600*24))
  ELSEIF seconds% > 3600 THEN
    ddhhmmss$ = STR$(seconds% \ 3600) + "h" + ddhhmmss$(seconds% MOD 3600)
  ELSEIF seconds% > 60 THEN
    ddhhmmss$ = STR$(seconds% \ 60) + "m" + STR$(seconds% MOD 60) + "s"
  ELSE
    ddhhmmss$ = STR$(seconds%) + "s"
  ENDIF
END FUNCTION
  
FUNCTION lpad$(strin$, pad$, chars%)
  lpad$ = strin$
  WHILE LEN(lpad$) < chars%
    lpad$ = pad$ + lpad$
  WEND
END FUNCTION
  
SUB UpdateRefMode
  IF ref_freq = 0 THEN
    TEXT 0, f3h*3, "Ref : off          ", "LT", 3, 1, RGB(WHITE), RGB(BLACK)
  ELSEIF ref_freq = 1 THEN
    TEXT 0, f3h*3, "Ref : 1Hz          ", "LT", 3, 1, RGB(WHITE), RGB(BLACK)
  ELSEIF ref_freq = 1000 THEN
    TEXT 0, f3h*3, "Ref : 1kHz         ", "LT", 3, 1, RGB(WHITE), RGB(BLACK)
  ELSE
    IF FreqInput$ = "SMB" THEN
      TEXT 0, f3h*3, "Ref : Fin/1000     ", "LT", 3, 1, RGB(WHITE), RGB(BLACK)
    ELSE
      TEXT 0, f3h*3, "Ref : Fin/1000     ", "LT", 3, 1, RGB(WHITE), RGB(BLACK)
    ENDIF
  ENDIF
END SUB
  
SUB DrawMainScreen
  CLS RGB(Black)
  
  TEXT 0, MM.VRES-f5h*2, "Softw: " + VERSION, "LB", 3, 1, RGB(128,96,128), RGB(BLACK)
  
  TEXT f6w/2, MM.VRES/2 + f6h*1.5, "Precision:", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
  TEXT f6w/2 + f5w*11, MM.VRES/2 + f6h*1.5 + 3, "+", "LB", 3, 1, RGB(192,255,255), RGB(BLACK)
  LINE f6w/2 + f5w*11 + 3, MM.VRES/2 + f6h*1.5 + 3, f6w/2 + f5w*11 + 13, MM.VRES/2 + f6h*1.5 + 3, 1, RGB(192,255,255)
  TEXT f6w/2, MM.VRES/2 + f6h*2.2, "Accuracy :", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
  TEXT f6w/2 + f5w*11, MM.VRES/2 + f6h*2.2 + 3, "+", "LB", 3, 1, RGB(128,255,255), RGB(BLACK)
  LINE f6w/2 + f5w*11 + 3, MM.VRES/2 + f6h*2.2 + 3, f6w/2 + f5w*11 + 13, MM.VRES/2 + f6h*2.2 + 3, 1, RGB(128,255,255)
  TEXT f6w*(19+23)/2, MM.VRES/2 + f6h*2.2, "(est)", "LM", 5, 1, RGB(128,255,255), RGB(BLACK)
  
  UpdateMainScreen
  
  TEXT MM.HRES, MM.VRES, STR$(bl_bright, 3) + "% brightness", "RB", 3, 1, RGB(255,128,128), RGB(BLACK)
  TEXT 0, f3h*2, "Curr: " + STR$(611 + bl_bright * 3.44, 0, 0) + "mA", "LT", 3, 1, RGB(WHITE), RGB(BLACK)
END SUB
  
FUNCTION Freq$(freq_num%, freq_den%, dp%)
  LOCAL temp% = 1, i%
  FOR i% = 1 TO dp%
    temp% = temp% * 10
  NEXT i%
  
  IF freq_num% < freq_den% THEN
    Freq$ = STR$(freq_num% * 1000 \ freq_den%, 0, 0) + "." + STR$((freq_num% * 1000 * temp% \ freq_den%) MOD temp%, dp%, 0, "0") + "mHz"
  ELSEIF freq_num% < 1000 * freq_den% THEN
    Freq$ = STR$(freq_num% \ freq_den%, 0, 0) + "." + STR$((freq_num% * temp% \ freq_den%) MOD temp%, dp%, 0, "0") + "Hz"
  ELSEIF freq_num% < 1000000 * freq_den% THEN
    Freq$ = STR$(freq_num% \ (freq_den% * 1000), 0, 0) + "." + STR$((freq_num% * temp% \ (freq_den% * 1000)) MOD temp%, dp%, 0, "0") + "kHz"
  ELSEIF freq_num% < 1000000000 * freq_den% THEN
    Freq$ = STR$(freq_num% \ (freq_den% * 1000000), 0, 0) + "." + STR$((freq_num% * temp% \ (freq_den% * 1000000)) MOD temp%, dp%, 0, "0") + "MHz"
  ELSE
    Freq$ = STR$(freq_num% \ (freq_den% * 1000000000), 0, 0) + "." + STR$((freq_num% * (temp% \ 10) \ (freq_den% * 100000000)) MOD temp%, dp%, 0, "0") + "GHz"
  ENDIF
END FUNCTION
  
FUNCTION Period$(freq_num%, freq_den%, dp%)
  LOCAL temp% = 1, i%
  FOR i% = 1 TO dp%
    temp% = temp% * 10
  NEXT i%
  
  '  PRINT "num=" freq_num% " den=" freq_den% " temp=" temp%
  IF freq_num% = 0 THEN
    Period$ = "-------------"
  ELSEIF freq_num% < freq_den% THEN
    Period$ = STR$(freq_den% \ freq_num%, 0, 0) + "." + STR$((freq_den% * temp% \ freq_num%) MOD temp%, dp%, 0, "0") + "s  "
  ELSEIF freq_num% < 1000 * freq_den% THEN
    Period$ = STR$(freq_den% * 1000 \ freq_num%, 0, 0) + "." + STR$((freq_den% * temp% * 1000 \ freq_num%)) MOD temp%, dp%, 0, "0") + "ms "
  ELSEIF freq_num% < 1000000 * freq_den% THEN
    Period$ = STR$(freq_den% * 1000000 \ freq_num%, 0, 0) + "." + STR$((freq_den% * temp% * 1000000 \ freq_num%) MOD temp%, dp%, 0, "0") + "us "
  ELSEIF freq_num% < 1000000000 * freq_den% THEN
    Period$ = STR$(freq_den% * 1000000000 \ freq_num%, 0, 0) + "." + STR$(((freq_den% * temp% * 100000000 \ freq_num%) MOD (temp% \ 10)) * 10, dp%, 0, "0") + "ns "
  ELSE
    Period$ = STR$(freq_den% * 1000000000000 \ freq_num%, 0, 0) + "." + STR$(((freq_den% * temp% * 100000000 \ freq_num%) MOD (temp% \ 10000)) * 10000, dp%, 0, "0") + "ps "
  ENDIF
END FUNCTION
  
SUB UpdateMainScreen
  LOCAL f$ LENGTH 32
  TEXT 0, 0, "TCXO: " + STR$(tcxo_freq100 / 100000000.0, 2, 4) + "MHz  ", "LT", 3, 1, RGB(WHITE), RGB(BLACK)
  TEXT 0, f3h, "CPU :" + STR$(cpu_MHz * 2 / 1000000.0, 3, 4) + "MHz  ", "LT", 3, 1, RGB(WHITE), RGB(BLACK)
  IF DispMode$ = "Freq" THEN
    IF input_mode = 2 THEN
      f$ = Freq$(input_MHz100 * division_ratio, 100, 8)
    ELSE
      f$ = Freq$(input_MHz100, 100, 8)
    ENDIF
  ELSE
    IF input_mode = 2 THEN
      f$ = Period$(input_MHz100 * division_ratio, 100, 8)
    ELSE
      f$ = Period$(input_MHz100, 100, 8)
    ENDIF
  ENDIF
  f$ = LEFT$(f$, 10) + RIGHT$(f$, 3)
  
  LOCAL INTEGER precision_ppb, averaging_ticks = count_num
  LOCAL FLOAT precision_Hz
  IF averaging_ticks > averaging_time THEN averaging_ticks = averaging_time
  IF averaging_ticks > 0 THEN precision_ppb = 200000000000 / (tcxo_freq100 * averaging_ticks) ELSE precision_ppb = 2000000000000 / tcxo_freq100
  IF input_mode = 2 THEN precision_ppb = precision_ppb * division_ratio
  precision_Hz = input_MHz100 \ 100 * precision_ppb / 1000000000
  
  LOCAL INTEGER dot = INSTR(1, f$, ".")
  LOCAL FLOAT fade_start = 9 - LOG(precision_ppb) / LOG(10)
  IF fade_start >= dot THEN fade_start = fade_start + 1
  LOCAL INTEGER fade_start_int = fade_start - 0.5 ' round down
  LOCAL INTEGER fade_amt = 100 - (fade_start - fade_start_int) * 100
  TEXT f6w/2, MM.VRES/2 - f6h/2, LEFT$(f$, fade_start_int), "LM", 6, 2, RGB(WHITE), RGB(BLACK)
  IF fade_start_int < 10 THEN TEXT f6w*((4*fade_start_int)+1)/2, MM.VRES/2 - f6h/2, MID$(f$, fade_start_int+1, 1), "LM", 6, 2, RGB(200-fade_amt,200-fade_amt,200-fade_amt), RGB(BLACK)
  IF fade_start_int+1 < 10 THEN TEXT f6w*((4*fade_start_int)+5)/2, MM.VRES/2 - f6h/2, MID$(f$, fade_start_int+2, 9-fade_start_int), "LM", 6, 2, RGB(100,100,100), RGB(BLACK)
  TEXT MM.HRES/2 + f6w*8, MM.VRES/2 + f6h*1.23 - f6h/2, MID$(f$, 11, 3), "LB", 5, 2, RGB(WHITE), RGB(BLACK)
  
  IF precision_Hz < 0.01 THEN precision_Hz = 0.01
  IF precision_Hz > 99999 THEN precision_Hz = 99999
  IF precision_ppb > 999 THEN
    IF precision_Hz > 999 THEN
      TEXT f6w*19/2, MM.VRES/2 + f6h*1.5, STR$((precision_Hz + 999) \ 1000, 2) + "kHz (" + STR$((precision_ppb + 999) \ 1000, 3) + "ppm)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ELSEIF precision_Hz < 1 THEN
      TEXT f6w*19/2, MM.VRES/2 + f6h*1.5, "." + lpad$(STR$((precision_Hz * 100) >> 0, 1), "0", 2) + "Hz (" + STR$((precision_ppb + 999) \ 1000, 3) + "ppm)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ELSE
      TEXT f6w*19/2, MM.VRES/2 + f6h*1.5, STR$(precision_Hz >> 0, 3) + "Hz (" + STR$((precision_ppb + 999) \ 1000, 3) + "ppm)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ENDIF
  ELSE
    IF precision_Hz > 999 THEN
      TEXT f6w*19/2, MM.VRES/2 + f6h*1.5, STR$((precision_Hz + 999) \ 1000, 2) + "kHz (" + STR$(precision_ppb, 3) + "ppb)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ELSEIF precision_Hz < 1 THEN
      TEXT f6w*19/2, MM.VRES/2 + f6h*1.5, "." + lpad$(STR$((precision_Hz * 100) >> 0, 1), "0", 2) + "Hz (" + STR$(precision_ppb, 3) + "ppb)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ELSE
      TEXT f6w*19/2, MM.VRES/2 + f6h*1.5, STR$(precision_Hz >> 0, 3) + "Hz (" + STR$(precision_ppb, 3) + "ppb)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ENDIF
  ENDIF
  
  LOCAL INTEGER accuracy_ppb, tcxo_ppb
  LOCAL FLOAT accuracy_hz
  tcxo_ppb = tcxo_accuracy_ppb
  IF gps_locked AND gps_count >= 120 THEN
    tcxo_ppb = (min_gps_tcxo_ppb * gps_count + tcxo_ppb * (gps_max - gps_count)) / gps_max
  ENDIF
  accuracy_ppb = SQR(precision_ppb * precision_ppb + tcxo_ppb * tcxo_ppb)
  accuracy_Hz = input_MHz100 \ 100 * accuracy_ppb / 1000000000
  IF accuracy_Hz < 0.01 THEN accuracy_Hz = 0.01
  IF accuracy_Hz > 99999 THEN accuracy_Hz = 99999
  IF accuracy_ppb > 999 THEN
    IF accuracy_Hz > 999 THEN
      TEXT f6w*19/2, MM.VRES/2 + f6h*2.2, STR$((accuracy_Hz + 999) \ 1000, 2) + "kHz (" + STR$((accuracy_ppb + 999) \ 1000, 3) + "ppm)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ELSEIF accuracy_Hz < 1 THEN
      TEXT f6w*19/2, MM.VRES/2 + f6h*2.2, "." + lpad$(STR$((accuracy_Hz * 100) >> 0, 1), "0", 2) + "Hz (" + STR$((accuracy_ppb + 999) \ 1000, 3) + "ppm)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ELSE
      TEXT f6w*19/2, MM.VRES/2 + f6h*2.2, STR$(accuracy_Hz >> 0, 3) + "Hz (" + STR$((accuracy_ppb + 999) \ 1000, 3) + "ppm)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ENDIF
  ELSE
    IF precision_Hz > 999 THEN
      TEXT f6w*19/2, MM.VRES/2 + f6h*2.2, STR$((accuracy_Hz + 999) \ 1000, 2) + "kHz (" + STR$(accuracy_ppb, 3) + "ppb)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ELSEIF accuracy_Hz < 1 THEN
      TEXT f6w*19/2, MM.VRES/2 + f6h*2.2, "." + lpad$(STR$((accuracy_Hz * 100) >> 0, 1), "0", 2) + "Hz (" + STR$(accuracy_ppb, 3) + "ppb)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ELSE
      TEXT f6w*19/2, MM.VRES/2 + f6h*2.2, STR$(accuracy_Hz >> 0, 3) + "Hz (" + STR$(accuracy_ppb, 3) + "ppb)", "LM", 5, 1, RGB(192,255,255), RGB(BLACK)
    ENDIF
  ENDIF
  
  IF tcxo_ppb < 500 THEN tcxo_ppb = 500
  IF tcxo_ppb < stored_tcxo_accuracy_ppb - 100 THEN
    stored_tcxo_accuracy_ppb = tcxo_ppb
    save_variable 8, stored_tcxo_accuracy_ppb, 1
  ENDIF
  
  IF UpdateHz < 1 THEN
    TEXT MM.HRES, MM.VRES-f5h, " " + STR$(1/UpdateHz, 1, 0) + "s update", "RB", 3, 1, RGB(128,128,255), RGB(BLACK)
  ELSE
    TEXT MM.HRES, MM.VRES-f5h, STR$(UpdateHz, 1, 0) + "Hz update", "RB", 3, 1, RGB(128,128,255), RGB(BLACK)
  ENDIF
  IF FreqInput$ = "SMB" THEN
    TEXT 0, MM.VRES, "Input: SMB (20MHz-6GHz+) 50 ohms", "LB", 3, 1, RGB(255,128,255), RGB(BLACK)
    TEXT 0, f3h*4, "Div : " + STR$(division_ratio) + " ", "LT", 3, 1, RGB(WHITE), RGB(BLACK)
  ELSE
    IF InputImpedance = 1000000 THEN
      TEXT 0, MM.VRES, "Input: BNC (10mHz-50MHz) 1M ohms", "LB", 3, 1, RGB(255,128,255), RGB(BLACK)
    ELSE
      TEXT 0, MM.VRES, "Input: BNC (10mHz-50MHz) 75 ohms", "LB", 3, 1, RGB(255,128,255), RGB(BLACK)
    ENDIF
    TEXT 0, f3h*4, "         ", "LT", 3, 1, RGB(WHITE), RGB(BLACK)
  ENDIF
  IF averaging_time = 0 THEN
    TEXT 0, MM.VRES-f5h, "Mode : instantaneous update", "LB", 3, 1, RGB(255,192,255), RGB(BLACK)
  ELSE
    TEXT 0, MM.VRES-f5h, "Mode : " + mmss$(averaging_time) + " averaging (" + mmss$(averaging_ticks) + ")     ", "LB", 3, 1, RGB(255,192,255), RGB(BLACK)
  ENDIF
  
  LOCAL gps_fix_time$ LENGTH 32, gps_coords$ LENGTH 32
  TEXT MM.HRES, 0, gps_sats2$ + " sats, " + gps_time$ + " " + gps_date$, "RT", 3, 1, RGB(128,255,128), RGB(BLACK)
  UpdateRefMode
  gps_coords$ = gps_lat$+" "+gps_lon$
  TEXT MM.HRES, f3h, gps_coords$+" "+STR$(gps_alt, 5)+"m", "RT", 3, 1, RGB(255,255,128), RGB(BLACK)
  IF gps_locked THEN
    gps_fix_time$ = ddhhmmss$((current_tcxo_timestamp%() - gps_fix_start) \ (tcxo_freq100 \ 100))
  ELSE
    gps_fix_time$ = "------"
  ENDIF
  TEXT MM.HRES, f3h*2, lpad$("GPS lock for: " + gps_fix_time$, " ", 27), "RT", 3, 1, RGB(192,255,128), RGB(BLACK)
  CIRCLE f3w*21, f3h*5/2-1, f3w/2, 1, 1, RGB(WHITE), RGB(BLACK)
END SUB
  
SUB TouchInt
  LOCAL INTEGER tx = TOUCH(X), ty = TOUCH(Y)
  IF tx >= 0 AND ty >= 0 THEN
    IF tx > MM.HRES*2/3 AND ty >= f3h*2.5 AND ty < f3h*4.5 THEN
      TOUCH$ = "Save"
    ELSEIF ty > MM.VRES/2 - f6h*3/2 and ty < MM.VRES/2 + f6h*3/2 THEN
      TOUCH$ = "Freq"
    ELSEIF tx < MM.HRES / 3 AND ty < f3h * 2 THEN
      TOUCH$ = "Calib"
    ELSEIF tx < MM.HRES / 3 AND ty < f3h * 5 THEN
      TOUCH$ = "Ref"
    ELSEIF tx < MM.HRES * 3 / 4 THEN
      IF ty > MM.VRES - f5h THEN
        IF tx < MM.HRES / 2 THEN
          TOUCH$ = "Input"
        ELSE
          TOUCH$ = "InputImp"
        ENDIF
      ELSEIF ty > MM.VRES - f5h * 2 THEN
        IF tx < MM.HRES * 0.45 THEN
          TOUCH$ = "Avg"
        ELSE
          TOUCH$ = "AvgReset"
        ENDIF
      ENDIF
    ELSE
      IF ty > MM.VRES - f5h THEN
        TOUCH$ = "Bright"
        init_tx = tx
        init_ty = ty
      ELSEIF ty > MM.VRES - f5h * 2 THEN
        TOUCH$ = "Update"
      ENDIF
    ENDIF
  ENDIF
END SUB
  
  DIM INTEGER last_update, last_display_update, count_index, sub_count, count_num, gps_locked, gps_fix_start, gps_fix_last, gps_count, gps_index
  DIM INTEGER counts(3, 6, 100)
  DIM INTEGER gps_timestamps(15, 60)
  CONST max_count = 600
  CONST gps_max = 900
  
FUNCTION current_tcxo_timestamp%()
  LOCAL INTEGER counters(3), foo
  foo = FreqCounter6GHz(3, counters())
  current_tcxo_timestamp% = counters(1)
END FUNCTION
  
SUB update_counts
  LOCAL INTEGER counters(3), foo, diff
  foo = FreqCounter6GHz(3, counters())
  diff = counters(1) - last_update
  IF counters(1) > last_update AND counters(1) - last_update > tcxo_freq100\1000 THEN'100ms
    sub_count = sub_count + 1
    IF sub_count = 10 THEN
      sub_count = 0
    ELSEIF count_num > 0 THEN
      count_num = count_num - 1
      count_index = count_index - 1
      IF count_index < 0 THEN count_index = count_index + max_count
    ENDIF
    counts(1, count_index \ 100, count_index MOD 100) = counters(1)
    IF input_mode = 2 THEN
      counts(0, count_index \ 100, count_index MOD 100) = counters(0)
      counts(2, count_index \ 100, count_index MOD 100) = counters(2)
    ELSE
      counts(0, count_index \ 100, count_index MOD 100) = counters(2)
      counts(2, count_index \ 100, count_index MOD 100) = counters(0)
    ENDIF
    count_index = count_index + 1
    IF count_index = max_count THEN count_index = 0
    IF count_num < max_count THEN count_num = count_num + 1
    last_update = last_update + tcxo_freq100\1000'counters(1)
  ENDIF
END SUB
  
FUNCTION get_cpu_MHz%(num_avgs%)
  LOCAL INTEGER last_index, cur_index
  IF count_num > num_avgs% THEN
    last_index = count_index - num_avgs% - 1
    IF last_index < 0 THEN last_index = last_index + max_count
  ELSE
    last_index = 0
  ENDIF
  IF count_index = 0 THEN cur_index = max_count-1 ELSE cur_index = count_index - 1
  LOCAL INTEGER diff_tcxo = counts(1, cur_index \ 100, cur_index MOD 100) - counts(1, last_index \ 100, last_index MOD 100)
  LOCAL INTEGER diff_cpu = counts(0, cur_index \ 100, cur_index MOD 100) - counts(0, last_index \ 100, last_index MOD 100)
  IF diff_tcxo > 0 THEN
    IF diff_cpu > &HF000000000000000 / (tcxo_freq100/10) THEN
      get_cpu_MHz% = diff_cpu * (tcxo_freq100/100) / diff_tcxo
    ELSEIF diff_cpu > &HF000000000000000 / tcxo_freq100 THEN
      get_cpu_MHz% = diff_cpu * (tcxo_freq100/10) / (diff_tcxo*10)
    ELSE
      get_cpu_MHz% = diff_cpu * tcxo_freq100 / (diff_tcxo*100)
    ENDIF
  ENDIF
END FUNCTION
  
FUNCTION get_input_MHz100%(num_avgs%)
  LOCAL INTEGER last_index, cur_index
  IF count_num > num_avgs% THEN
    last_index = count_index - num_avgs% - 1
    IF last_index < 0 THEN last_index = last_index + max_count
  ELSE
    last_index = 0
  ENDIF
  IF count_index = 0 THEN cur_index = max_count-1 ELSE cur_index = count_index - 1
  LOCAL INTEGER diff_tcxo = counts(1, cur_index \ 100, cur_index MOD 100) - counts(1, last_index \ 100, last_index MOD 100)
  LOCAL INTEGER diff_input = counts(2, cur_index \ 100, cur_index MOD 100) - counts(2, last_index \ 100, last_index MOD 100)
  IF diff_tcxo > 0 THEN
    IF diff_input > &HF000000000000000 / (tcxo_freq100/10) THEN
      get_input_MHz100% = diff_input * (tcxo_freq100/100) / (diff_tcxo/100)
    ELSEIF diff_input > &HF000000000000000 / (tcxo_freq100/10) THEN
      get_input_MHz100% = diff_input * (tcxo_freq100/10) / (diff_tcxo/10)
    ELSE
      get_input_MHz100% = diff_input * tcxo_freq100 / diff_tcxo
    ENDIF
  ENDIF
END FUNCTION
  
FUNCTION get_tcxo_gps_pulses%(num_avgs%)
  LOCAL INTEGER last_index, cur_index, num
  IF gps_count > num_avgs% THEN
    last_index = gps_index - num_avgs% - 1
    IF last_index < 0 THEN last_index = last_index + gps_max
    num = num_avgs%
  ELSE
    last_index = 0
    num = gps_index-1
  ENDIF
  IF gps_index = 0 THEN cur_index = gps_max-1 ELSE cur_index = gps_index - 1
  LOCAL INTEGER diff = gps_timestamps(cur_index \ 60, cur_index MOD 60) - gps_timestamps(last_index \ 60, last_index MOD 60)
  IF num > 0 THEN get_tcxo_gps_pulses% = diff \ num
END FUNCTION
  
SUB set_divider_ratio ratio%
  LOCAL INTEGER val = 256 - ratio% / 5
  PIN(P0) = (VAL >> 0) AND 1
  PIN(P1) = (VAL >> 1) AND 1
  PIN(P2) = (VAL >> 2) AND 1
  PIN(P3) = (VAL >> 3) AND 1
  PIN(P4) = (VAL >> 4) AND 1
  PIN(P5) = (VAL >> 5) AND 1
  PIN(P6) = (VAL >> 6) AND 1
  PIN(P7) = (VAL >> 7) AND 1
END SUB
  
SUB copy_oc1_to_ref_output
  IF ref_freq > 0 THEN PIN(REF_OUTPUT) = PIN(OC1_IN) ELSE PIN(REF_OUTPUT) = 0
  IF PIN(OC1_IN) = 0 THEN
    LOCAL INTEGER params(3), ignore
    params(0) = (last_pulse_time\100 + tcxo_freq100\2000) AND &HFFFFFFFF
    params(1) = (last_pulse_time\100 + tcxo_freq100\1000) AND &HFFFFFFFF
    params(2) = 0
    last_pulse_time = last_pulse_time + tcxo_freq100\100
    IF last_pulse_time >= 429496729600 THEN last_pulse_time = last_pulse_time - 429496729600
    ignore = FreqCounter6GHz(4, params())
  ENDIF
END SUB
  
SUB copy_oc2_to_ref_output
  IF ref_freq > 0 THEN PIN(REF_OUTPUT) = PIN(OC2_IN) ELSE PIN(REF_OUTPUT) = 0
  IF PIN(OC2_IN) = 0 THEN
    LOCAL INTEGER params(3), ignore
    params(0) = (last_pulse_time\100 + tcxo_freq100\2000) AND &HFFFFFFFF
    params(1) = (last_pulse_time\100 + tcxo_freq100\1000) AND &HFFFFFFFF
    params(2) = 0
    last_pulse_time = last_pulse_time + tcxo_freq100\100
    IF last_pulse_time >= 429496729600 THEN last_pulse_time = last_pulse_time - 429496729600
    ignore = FreqCounter6GHz(5, params())
  ENDIF
END SUB
  
SUB set_input_mode_ mode%
  LOCAL INTEGER params(3)
  
  input_mode = mode%
  set_divider_ratio division_ratio
  IF mode% = 1 THEN PIN(LF_LE) = 0 ELSE PIN(LF_LE) = 1
  IF mode% = 2 THEN PIN(HF_LE) = 0 ELSE PIN(HF_LE) = 1
  foo = FreqCounter6GHz(input_mode)
  count_index = 0
  count_num = 0
  sub_count = 0
  
  params(0) = 0
  params(1) = 0
  params(2) = 0
  IF mode% = 1 THEN
    ' enable OC1, disable OC2
    SETPIN OC2_IN, DIN
    foo = FreqCounter6GHz(5, params())
    params(0) = (last_pulse_time\100 + tcxo_freq100\200) AND &HFFFFFFFF
    params(1) = (last_pulse_time\100 + tcxo_freq100\100) AND &HFFFFFFFF
    last_pulse_time = last_pulse_time + tcxo_freq100
    IF last_pulse_time >= 429496729600 THEN last_pulse_time = last_pulse_time - 429496729600
    foo = FreqCounter6GHz(4, params())
    SETPIN OC1_IN, INTB, copy_oc1_to_ref_output
  ELSE
    ' enable OC2, disable OC1
    SETPIN OC1_IN, DIN
    foo = FreqCounter6GHz(4, params())
    params(0) = (last_pulse_time\100 + tcxo_freq100\200) AND &HFFFFFFFF
    params(1) = (last_pulse_time\100 + tcxo_freq100\100) AND &HFFFFFFFF
    last_pulse_time = last_pulse_time + tcxo_freq100
    IF last_pulse_time >= 429496729600 THEN last_pulse_time = last_pulse_time - 429496729600
    foo = FreqCounter6GHz(5, params())
    SETPIN OC2_IN, INTB, copy_oc2_to_ref_output
  ELSE
  ENDIF
END SUB
  
SUB set_input_mode mode%
  division_ratio = MAX_DIV_RATIO
  set_input_mode_ mode%
END SUB
  
SUB SETBACKLIGHT bright%
  foo = FreqCounter6GHz(9, bright%)
END SUB
  
FUNCTION check_GPS_checksum$(gpsstrn$)
  IF LEN(gpsstrn$) >= 9 and LEFT$(gpsstrn$, 1) = "$" THEN
    IF MID$(gpsstrn$, LEN(gpsstrn$)-2, 1) = "*" THEN
      LOCAL INTEGER i, checksum
      FOR i = 2 TO LEN(gpsstrn$)-3
        checksum = checksum XOR ASC(MID$(gpsstrn$, i, 1))
      NEXT i
      IF RIGHT$(gpsstrn$, 2) = HEX$(checksum, 2) THEN
        check_GPS_checksum$ = MID$(gpsstrn$, 2, LEN(gpsstrn$)-4)
      ENDIF
    ENDIF
  ENDIF
END FUNCTION
  
FUNCTION explode%(strin$, maxnum%, maxlen%)
  LOCAL INTEGER cur, slen, last = 1, num = 0, max = maxnum%
  WHILE num < max
    cur = INSTR(last, strin$, ",")
    IF cur > 0 THEN
      slen = cur-last
      IF slen > maxlen% THEN slen = maxlen%
      gpsstr$(num) = MID$(strin$, last, slen)
      num = num + 1
      last = cur + 1
    ELSE
      IF last <= LEN(strin$) THEN
        slen = LEN(strin$)-last+1
        IF slen > maxlen% THEN slen = maxlen%
        gpsstr$(num) = MID$(strin$, last, slen)
        num = num + 1
      ENDIF
      max = num
    ENDIF
  WEND
  explode% = num
END FUNCTION
  
FUNCTION parse_gpstime$(text$)
  LOCAL integer dot = INSTR(1, text$, ".")
  LOCAL mytext$ LENGTH 32 = text$
  IF dot > 0 THEN mytext$ = LEFT$(mytext$, dot-1)
  LOCAL hours$ LENGTH 2 = LEFT$(mytext$, 2), ampm$ LENGTH 2 = "am"
  LOCAL INTEGER hour = VAL(hours$)
  IF hour >= 12 THEN
    ampm$ = "pm"
    IF hour > 12 THEN
      hours$ = STR$(hour - 12)
      IF len(hours$) = 1 THEN hours$ = "0" + hours$
    ENDIF
  ENDIF
  '  PRINT "!!" gpsstr$(1) "!!" RIGHT$(gpsstr$(1), 2)
  parse_gpstime$ = hours$ + ":" + MID$(mytext$, 3, 2) + ":" + RIGHT$(mytext$, 2) + ampm$
END FUNCTION
  
FUNCTION parse_latlon$(text$)
  LOCAL integer dot = INSTR(1, text$, ".")
  IF dot >= 2 THEN
    LOCAL INTEGER seconds = VAL(MID$(text$, dot+1))
    IF seconds > 10000 THEN
      seconds = (seconds + 499) \ 1000
    ELSEIF seconds > 1000 THEN
      seconds = (seconds + 49) \ 100
    ELSEIF seconds > 100 THEN
      seconds = (seconds + 4) \ 10
    ENDIF
    LOCAL sec$ = STR$(seconds)
    IF LEN(sec$) = 1 THEN sec$ = "0" + sec$
    parse_latlon$ = LEFT$(text$, dot-3) + "`" + MID$(text$, dot-2, 2) + "'" + sec$ + CHR$(34)
  ENDIF
END FUNCTION
  
SUB parse_gps_message num%
  IF num% > 0 THEN
    IF gpsstr$(0) = "GPRMC" and num% >= 12 THEN
      gps_time$ = parse_gpstime$(gpsstr$(1))
      gps_lat$ = parse_latlon$(gpsstr$(3)) + gpsstr$(4)
      gps_lon$ = parse_latlon$(gpsstr$(5)) + gpsstr$(6)
      gps_date$ = LEFT$(gpsstr$(9), 2) + "/" + MID$(gpsstr$(9), 3, 2) + "/20" + RIGHT$(gpsstr$(9), 2)
      IF gps_lat$ = "" THEN gps_lat$ = "--`--'--" + CHR$(34) + " "
      IF gps_lon$ = "" THEN gps_lon$ = "---`--'--" + CHR$(34) + " "
      IF gps_time$ = "" OR gps_time$ = "::am" THEN gps_time$ = "--:--:----"
      IF gps_date$ = "" OR gps_date$ = "//20" THEN gps_date$ = "--/--/----"
      IF gps_sats2$ = "" THEN gps_sats2$ = "--"
    ELSEIF gpsstr$(0) = "GPGGA" and num% >= 13 THEN
      gps_time$ = parse_gpstime$(gpsstr$(1))
      gps_lat$ = parse_latlon$(gpsstr$(2)) + gpsstr$(3)
      gps_lon$ = parse_latlon$(gpsstr$(4)) + gpsstr$(5)
      LOCAL INTEGER gps_fixgood = VAL(gpsstr$(6))
      IF gps_fixgood > 0 THEN
        IF gps_locked = 0 THEN
          gps_fix_start = current_tcxo_timestamp%()
        ENDIF
        gps_fix_last = current_tcxo_timestamp%()
        gps_locked = 1
      ENDIF
      gps_sats2$ = gpsstr$(7)
      IF gpsstr$(10) = "M" THEN gps_alt = VAL(gpsstr$(9)) ELSE gps_alt = 0
      IF gps_lat$ = "" THEN gps_lat$ = "--`--'--" + CHR$(34) + " "
      IF gps_lon$ = "" THEN gps_lon$ = "---`--'--" + CHR$(34) + " "
      IF gps_time$ = "" OR gps_time$ = "::am" THEN gps_time$ = "--:--:----"
      IF gps_date$ = "" OR gps_date$ = "//20" THEN gps_date$ = "--/--/----"
      IF gps_sats2$ = "" THEN gps_sats2$ = "--"
    ENDIF
  ENDIF
END SUB
  
SUB pulse_1pps
  IF PIN(GPS_1PPS) THEN
    CIRCLE f3w*21, f3h*5/2-1, f3w/2-2, 1, 1, RGB(GREEN), RGB(GREEN)
  ELSE
    CIRCLE f3w*21, f3h*5/2-1, f3w/2, 1, 1, RGB(WHITE), RGB(BLACK)
  ENDIF
END SUB
  
SUB receive_and_process_gps_serial_data
  LOCAL STRING char$
  LOCAL INTEGER l
  WHILE LOC(#1) > 0
    char$ = INPUT$(1, #1)
    gps_buf$ = gps_buf$ + char$
    IF char$ = CHR$(10) OR LEN(gps_buf$) = 255 THEN
      IF RIGHT$(gps_buf$, 2) = CHR$(13) + CHR$(10) THEN
        gps_buf$ = LEFT$(gps_buf$, LEN(gps_buf$)-2)
        '        PRINT gps_buf$
        parse_gps_message explode%(check_gps_checksum$(gps_buf$), 14, 20)
      ENDIF
      gps_buf$ = ""
    ENDIF
  WEND
END SUB
  
  DIM INTEGER foo, division_ratio, new_division_ratio, settling_time, cpu_MHz, input_MHz100, input_mode, input_capture, stored_tcxo_updated
  VAR RESTORE
  eeprom_present = is_eeprom_present%()
  IF eeprom_present THEN
    foo = eeReadInt(0)
    IF foo > 0 and foo < 10000000000 THEN stored_tcxo_freq100 = foo
    IF eeReadInt(8) = 1 THEN DispMode$ = "Period"
    foo = eeReadInt(2*8)
    IF foo >= 2 and foo <= 30 THEN UpdateHz = foo / 6
    IF eeReadInt(3*8) = 1 THEN FreqInput$ = "BNC"
    foo = eeReadInt(4*8)
    IF foo = 75 OR foo = 1000000 THEN InputImpedance = foo
    foo = eeReadInt(5*8)
    IF foo > 0 and foo <= 600 THEN averaging_time = foo
    foo = eeReadInt(6*8)
    IF foo >= 0 and foo <= 1001 THEN ref_freq = foo
    foo = eeReadInt(7*8)
    IF foo >= 0 and foo <= 100 THEN bl_bright = foo
    foo = eeReadInt(8*8)
    IF foo >= 10 and foo <= 5000 THEN stored_tcxo_accuracy_ppb = foo
  ENDIF
  DIM gps_lat$ LENGTH 12 = "--`--'--" + CHR$(34) + " ", gps_lon$ LENGTH 12 = "---`--'--" + CHR$(34) + " "
  DIM gps_sats2$ LENGTH 2 = "--", gps_time$ LENGTH 10 = "--:--:----", gps_date$ LENGTH 10 = "--/--/----"
  DIM gps_buf$
  DIM INTEGER gps_alt
  DIM STRING gpsstr$(14) LENGTH 20
  last_tcxo_freq100 = stored_tcxo_freq100
  tcxo_freq100 = last_tcxo_freq100
  tcxo_accuracy_ppb = stored_tcxo_accuracy_ppb
  '  PIN(TCXO_LE) = 1
  foo = FreqCounter6GHz(0)
  SETBACKLIGHT bl_bright
  foo = FreqCounter6GHz(7, 1) ' set up input capture for positive edges
  IF FreqInput$ = "SMB" THEN set_input_mode 2 ELSE set_input_mode 1
  IF InputImpedance = 75 THEN PIN(RELAY) = 1 ELSE PIN(RELAY) = 0
  SETPIN GPS_1PPS, INTB, pulse_1pps
  OPEN "COM1:9600" as #1
  
  DrawMainScreen
  
  DO
    receive_and_process_gps_serial_data
    IF TOUCH(X) <> -1 THEN
      IF last_touch = 0 THEN
        TouchInt
        last_touch = 1
      ENDIF
    ELSE
      IF last_touch = 1 THEN
        TouchInt
        last_touch = 0
      ENDIF
    ENDIF
    update_counts
    cpu_MHz = get_cpu_MHz%(10)
    IF averaging_time+1 < max_count THEN input_MHz100 = get_input_MHz100%(averaging_time+1) ELSE input_MHz100 = get_input_MHz100%(max_count)
    IF gps_locked AND gps_count >= 120 THEN
      tcxo_freq100 = (get_tcxo_gps_pulses%(900) * gps_count + last_tcxo_freq100 * (900 - gps_count) \ 100)\9
      IF tcxo_freq100 <> stored_tcxo_freq100 AND stored_tcxo_updated = 0 THEN
        stored_tcxo_freq100 = tcxo_freq100
        save_variable 0, stored_tcxo_freq100, 1
        stored_tcxo_updated = 60
      ELSEIF stored_tcxo_updated > 0 THEN
        stored_tcxo_updated = stored_tcxo_updated - 1
      ENDIF
      IF gps_count = 900 THEN last_tcxo_freq100 = tcxo_freq100
    ENDIF
    
    PRINT "division_ratio=" division_ratio " input_MHz=" input_MHz100\100 " freq=" input_MHz100*division_ratio/100
    IF settling_time > 0 THEN settling_time = settling_time - 1
    IF input_mode = 2 and settling_time = 0 and ((input_MHz100 > 1200000000 and division_ratio < MAX_DIV_RATIO) or (input_MHz100 < 800000000 AND division_ratio > 10)) THEN
      IF input_MHz100 = 0 THEN
        new_division_ratio = MAX_DIV_RATIO
      ELSE
        new_division_ratio = input_MHz100 * new_division_ratio \ 1000000000
        new_division_ratio = (new_division_ratio + 4.99999999999) \ 5 * 5
        IF new_division_ratio < 10 THEN new_division_ratio = 10 ELSE IF new_division_ratio > MAX_DIV_RATIO THEN new_division_ratio = MAX_DIV_RATIO
      ENDIF
      IF new_division_ratio <> division_ratio THEN
        division_ratio = new_division_ratio
        settling_time = 100
        set_input_mode_ 2
      ENDIF
    ENDIF
    
    IF gps_locked > 0 AND FreqCounter6GHz(8, input_capture) > 0 THEN
      gps_timestamps(gps_index \ 60, gps_index MOD 60) = input_capture
      IF gps_count < gps_max THEN gps_count = gps_count + 1
      gps_index = gps_index + 1
      IF gps_index = gps_max then gps_index = 0
    ENDIF
    
    IF (last_update - last_display_update) * UpdateHz * 100 >= tcxo_freq100 THEN
      UpdateMainScreen
      last_display_update = last_display_update + tcxo_freq100 / (UpdateHz * 100)
      IF last_display_update < last_update THEN last_display_update = last_update
    ENDIF
    
    IF TOUCH$ <> "" THEN
      IF TOUCH$ = "Freq" THEN
        IF DispMode$ = "Freq" THEN DispMode$ = "Period" ELSE DispMode$ = "Freq"
        IF DispMode$ = "Freq" THEN
          save_variable 1, 0, 1
        ELSE
          save_variable 1, 1, 1
        ENDIF
        UpdateMainScreen
      ELSEIF TOUCH$ = "Update" THEN
        IF UpdateHz = 0.333 THEN
          UpdateHz = 0.5
        ELSEIF UpdateHz = 0.5 THEN
          UpdateHz = 1
        ELSE
          UpdateHz = UpdateHz + 1
          IF UpdateHz > 5 THEN UpdateHz = 0.333
        ENDIF
        save_variable 2, UpdateHz * 6, 1
        UpdateMainScreen
      ELSEIF TOUCH$ = "Input" OR (TOUCH$ = "InputImp" and FreqInput$ = "SMB") THEN
        IF FreqInput$ = "SMB" THEN FreqInput$ = "BNC" ELSE FreqInput$ = "SMB"
        IF FreqInput$ = "SMB" THEN
          save_variable 3, 0, 0
        ELSE
          save_variable 3, 1, 0
        ENDIF
        '        VAR SAVE FreqInput$, UpdateHz, DispMode$, stored_tcxo_freq100
        IF FreqInput$ = "SMB" THEN set_input_mode 2 ELSE set_input_mode 1
        UpdateMainScreen
        UpdateRefMode
      ELSEIF TOUCH$ = "InputImp" THEN
        IF InputImpedance = 1000000 THEN InputImpedance = 75 ELSE InputImpedance = 1000000
        IF InputImpedance = 75 THEN PIN(RELAY) = 1 ELSE PIN(RELAY) = 0
        save_variable 4, InputImpedance, 1
        UpdateMainScreen
      ELSEIF TOUCH$ = "Bright" THEN
        cur_tx = TOUCH(X)
        cur_ty = TOUCH(Y)
        IF cur_tx > 0 and cur_ty > 0 THEN
          dx = cur_tx - init_tx
          dy = cur_ty - init_ty
          IF dx \ 10 <> 0 OR dy \ 10 <> 0 THEN
            bl_bright = bl_bright + dx \ 10 - dy \ 10
            init_tx = init_tx + dx \ 10 * 10
            init_ty = init_ty + dy \ 10 * 10
            IF bl_bright < 10 THEN bl_bright = 10
            IF bl_bright > 100 THEN bl_bright = 100
            SETBACKLIGHT bl_bright
            TEXT MM.HRES - f3w*12, MM.VRES, STR$(bl_bright, 3), "RB", 3, 1, RGB(255,128,128), RGB(BLACK)
            TEXT f3w*6, f3h*2, STR$(611 + bl_bright * 3.44, 0, 0), "LT", 3, 1, RGB(WHITE), RGB(BLACK)
          ENDIF
        ENDIF
      ELSEIF TOUCH$ = "Avg" or (TOUCH$ = "AvgReset" and averaging_time = 0) THEN
        IF averaging_time = 0 THEN
          averaging_time = 1
        ELSEIF averaging_time = 1 THEN
          averaging_time = 2
        ELSEIF averaging_time = 2 THEN
          averaging_time = 5
        ELSEIF averaging_time = 5 THEN
          averaging_time = 10
        ELSEIF averaging_time = 10 THEN
          averaging_time = 15
        ELSEIF averaging_time = 15 THEN
          averaging_time = 30
        ELSEIF averaging_time = 30 THEN
          averaging_time = 60
        ELSEIF averaging_time = 60 THEN
          averaging_time = 90
        ELSEIF averaging_time = 90 THEN
          averaging_time = 120
        ELSEIF averaging_time = 120 THEN
          averaging_time = 180
        ELSEIF averaging_time = 180 THEN
          averaging_time = 300
        ELSEIF averaging_time = 300 THEN
          averaging_time = 600
        ELSE
          averaging_time = 0
        ENDIF
        save_variable 5, averaging_time, 1
        UpdateMainScreen
      ELSEIF TOUCH$ = "AvgReset" THEN
        IF FreqInput$ = "SMB" THEN set_input_mode 2 ELSE set_input_mode 1
        UpdateMainScreen
      ELSEIF TOUCH$ = "Ref" THEN
        IF ref_freq = 0 THEN
          ref_freq = 1
        ELSEIF ref_freq = 1 THEN
          '          ref_freq = 1000
          '        ELSEIF ref_freq = 1000 THEN
          '          ref_freq = 1001
          '        ELSE
          ref_freq = 0
        ENDIF
        save_variable 6, ref_freq, 1
        UpdateRefMode
      ELSEIF TOUCH$ = "Calib" THEN
        CLS
        PAGE 1
        foo = FreqCounter6GHz(11)
        WHILE CTRLVAL(#6) = 0 AND CTRLVAL(#7) = 0
        WEND
        IF CTRLVAL(#6) > 0 THEN
          foo = VAL(CTRLVAL(#3))
          IF foo >= 10000000 AND foo <= 30000000 THEN
            stored_tcxo_freq100 = foo * 100
            VAR SAVE stored_tcxo_freq100
            last_tcxo_freq100 = stored_tcxo_freq100
            tcxo_freq100 = last_tcxo_freq100
            gps_count = 0
            gps_index = 0
          ENDIF
          foo = VAL(CTRLVAL(#5))
          IF foo >= 10 AND foo <= 5000 THEN
            stored_tcxo_accuracy_ppb = foo
            VAR SAVE stored_tcxo_accuracy_ppb
            tcxo_accuracy_ppb = stored_tcxo_accuracy_ppb
          ENDIF
          CTRLVAL(#6) = 0
        ELSE
          CTRLVAL(#7) = 0
        ENDIF
        PAGE 2
        IF FreqInput$ = "SMB" THEN set_input_mode 2 ELSE set_input_mode 1
        DrawMainScreen
      ELSEIF TOUCH$ = "Save" THEN
        IF changes_to_be_saved AND eeprom_present = 0 THEN
          save_variable 0, 0, 0
          IF FreqInput$ = "SMB" THEN set_input_mode 2 ELSE set_input_mode 1
        ENDIF
      ENDIF
      IF TOUCH$ <> "Bright" THEN
        TOUCH$ = ""
      ELSEIF TOUCH(X) = -1 THEN
        '        VAR SAVE bl_bright
        save_variable 7, bl_bright, 1
        TOUCH$ = ""
      ENDIF
    ENDIF
  LOOP
  
CFunction FreqCounter6GHz
  00000017
  'T1Int
  3C029D00 8C43008C 8C650000 3C040001 00A42021 AC640000 8C42008C 8C430000
  14600004 00000000 8C430004 24630001 AC430004 03E00008 00000000
  'getFPC
  27BDFFF8 AFBF0004 00852023 03E42021 ACC40000 8FBF0004 03E00008 27BD0008
  'main
  27BDFFE0 AFBF001C 8C820000 8C830004 00432025 1480005F 00A03021 3C059D00
  24A5008C 27A60010 0411FFED 00000000 8FA50010 3C029D00 8C4300AC 3C049D00
  24840000 00852021 AC640000 2404001C 3C03BF88 AC6410A4 24040004 3C03BF88
  AC6410A8 24030010 3C04BF88 AC831034 3C04BF88 AC831064 3C04BF88 AC831068
  3C04BF80 8C850800 8C43008C AC650010 3C08BF80 8D050810 8C43008C AC650014
  3C07BF80 8CE50820 8C43008C AC650018 3C03BF80 8C660A00 8C45008C ACA6001C
  3C06BF80 8CC90A10 8C45008C ACA90020 3C05BF80 8CAA0A20 8C49008C AD2A0024
  3C09BF80 8D2A0C00 8C49008C AD2A0028 3C09BF80 8D2A0C10 8C49008C AD2A002C
  3C09BF80 8D2A0C20 8C49008C AD2A0030 3C09BF80 8D2A0E00 8C49008C AD2A0034
  3C09BF80 8D2A0E10 8C49008C AD2A0038 3C09BF80 8D2A0E20 8C49008C AD2A003C
  AC800800 AC600A00 AD000810 ACC00A10 3406FFFF ACE60820 ACA60A20 3C05BF88
  8CA61030 7C067384 ACA61030 8C42008C AC400008 3C02BF81 AC40FA18 3402800A
  AC820800 AC600A00 00002021 100001E6 00002821 24040001 1444002A 24040002
  14600028 3C05BF80 ACA00600 3C04BF80 AC800C00 3C029D00 8C43008C AC600000
  8C43008C AC600004 3C03BF80 AC600610 3C03BF80 AC600C10 3C03BF80 AC600E10
  3403FFFF 3C06BF80 ACC30620 3C06BF80 ACC30C20 3C06BF80 ACC30E20 3C03BF88
  8C661030 7C06C604 AC661030 8C42008C AC40000C 34028002 ACA20600 24030002
  3C02BF81 AC43FA20 34028008 AC820C00 3C02BF80 AC400E00 00002021 100001BA
  00002821 1444002A 24040003 14600028 3C05BF80 ACA00600 3C04BF80 AC800C00
  3C029D00 8C43008C AC600000 8C43008C AC600004 3C03BF80 AC600610 3C03BF80
  AC600C10 3C03BF80 AC600E10 3403FFFF 3C06BF80 ACC30620 3C06BF80 ACC30C20
  3C06BF80 ACC30E20 3C03BF88 8C661030 7C06C604 AC661030 8C42008C AC40000C
  34028000 ACA20600 24030002 3C02BF81 AC43FA20 3402800A AC820C00 3C02BF80
  AC400E00 00002021 1000018F 00002821 14440066 24040004 14600064 3C08BF88
  24030010 AD031064 3C07BF88 ACE01068 3C02BF88 8C4E1030 7DCE0100 8C4D1030
  7DAD0380 8C4C1030 7D8C0600 3C049D00 8C84008C 3C05BF80 8CA90610 8C850004
  8C840000 01242025 ACC40000 ACC50004 24C50008 3C04BF80 8C840810 ACC40008
  ACA00004 24C40010 3C09BF80 8D290C10 ACC90010 AC800004 8C4B1030 7D6B0100
  8C4A1030 7D4A0380 8C491030 7D290600 AD031064 ACE31068 1160000C 00000000
  15C0000A 3C02FFFF 8CC70000 00E23824 8CC80004 3C020001 00E21021 0047382B
  00E83821 ACC20000 ACC70004 11400010 00001021 11A00003 00001821 8CC20008
  8CC3000C ACC20008 ACC3000C 3C029D00 8C42008C 8C430008 24630001 AC430008
  3C02BF88 8C431030 7C037384 AC431030 11200010 00001021 11800003 00001821
  8CC20010 8CC30014 ACC20010 ACC30014 3C029D00 8C42008C 8C43000C 24630001
  AC43000C 3C02BF88 8C431030 7C03C604 AC431030 3C029D00 8C43008C 8C630008
  8CA60004 00C31825 ACA30004 8C42008C 8C42000C 8C830004 00621025 AC820004
  24040003 10000128 00002821 54440031 24040005 5460002F 24040005 8CC20000
  8CC30004 00431025 10400020 3C02BF80 8CC20008 8CC3000C 00431025 1040001B
  3C02BF80 AC403000 8CC30000 3C02BF80 AC433010 8CC30008 3C02BF80 AC433020
  3C02BF88 8C431030 7C0339C4 AC431030 2403000C 3C02BF81 AC43FB78 8CC20010
  8CC30014 00431025 34038025 34048024 0082180A 00601021 3C03BF80 AC623000
  00002021 10000100 00002821 AC403000 3C02BF81 AC40FB78 3C02BF88 8C431030
  7C0339C4 AC431030 00002021 100000F6 00002821 54440031 24040006 5460002F
  24040006 8CC20000 8CC30004 00431025 10400020 3C02BF80 8CC20008 8CC3000C
  00431025 1040001B 3C02BF80 AC403200 8CC30000 3C02BF80 AC433210 8CC30008
  3C02BF80 AC433220 3C02BF88 8C431030 7C036304 AC431030 2403000B 3C02BF81
  AC43FBC4 8CC20010 8CC30014 00431025 34038025 34048024 0082180A 00601021
  3C03BF80 AC623200 00002021 100000CE 00002821 AC403200 3C02BF81 AC40FBC4
  3C02BF88 8C431030 7C036304 AC431030 00002021 100000C4 00002821 1444000D
  24040007 1460000B 00000000 3C02BF88 8C431030 7C6301C0 8C421030 7C420300
  00021040 00431025 00402021 100000B6 00002821 14440023 24040008 14600021
  00000000 3C02BF81 AC40FA34 3C02BF88 8C431030 7C03AD44 AC431030 8CC20000
  24030001 14430003 8CC40004 10800008 34038103 24030002 1443000E 3C02BF80
  1480000C 34038102 10000006 00000000 3C02BF80 AC432600 24040001 1000009A
  00002821 AC432600 24040002 10000096 00002821 AC402600 00002021 10000092
  00002821 14440031 24040009 1460002F 00000000 3C02BF88 8C421030 7C420540
  14400008 3C02BF80 3C02BF80 8C422600 30420008 00002021 10400083 00002821
  3C02BF80 8C422610 3C039D00 8C63008C 8C630008 ACC20000 ACC30004 3C04BF88
  8C841030 30844000 10800006 3C04BF88 04400004 00000000 24630001 1000000C
  ACC30004 8C841030 30844000 54800009 3C02BF88 3C04BF80 8C840810 0082202B
  10800003 2463FFFF ACC20000 ACC30004 3C02BF88 8C431030 7C03AD44 AC431030
  24040001 10000060 00002821 14440015 2404000A 14600013 00000000 2403000B
  3C02BF81 AC43FBFC 34038006 3C02BF80 AC433600 8CC20000 00022080 000219C0
  00831821 00621023 00021880 00431021 3C03BF80 AC623620 00002021 1000004A
  00002821 14440023 2404000B 14600021 00000000 3C04BF80 AC800800 3C03BF88
  8C621030 7C024A44 AC621030 3C029D00 8C42008C 8C460018 3C05BF80 ACA60820
  8C460014 3C05BF80 ACA60810 8C450010 AC850800 3C04BF80 AC800A00 8C651030
  7C057384 AC651030 8C450024 3C03BF80 AC650A20 8C450020 3C03BF80 AC650A10
  8C42001C AC820A00 00002021 10000026 00002821 14440023 00002021 54600022
  00002821 3C04BF80 AC800C00 3C03BF88 8C621030 7C029CC4 AC621030 3C029D00
  8C42008C 8C460030 3C05BF80 ACA60C20 8C46002C 3C05BF80 ACA60C10 8C450028
  AC850C00 3C04BF80 AC800E00 8C651030 7C05C604 AC651030 8C45003C 3C03BF80
  AC650E20 8C450038 3C03BF80 AC650E10 8C420034 AC820E00 00002021 10000002
  00002821 00002821 00801021 00A01821 8FBF001C 03E00008 27BD0020
End CFunction
