Android Open Source - android-rtlsdr R820 T






From Project

Back to project page android-rtlsdr.

License

The source code is released under:

GNU General Public License

If you think the Android project android-rtlsdr listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.rtlsdr.android.tuners;
//www  .  ja  v  a2s.c  om
import java.io.IOException;

import android.util.Log;

import com.rtlsdr.android.SdrSerialDriver;

public class R820T implements IRtlSdrTuner {
  private static final String TAG = R820T.class.getSimpleName();
  public static final byte R820T_I2C_ADDR = 0x34;
  public static final int R820T_CHECK_ADDR = 0x00;
  public static final int R820T_CHECK_VAL = 0x69;

  public static final int R820T_IF_FREQ = 3570000;

  public static final String VERSION = "R820T_v1.49_ASTRO";
  public static final int VER_NUM = 49;

  public static final boolean USE_16M_XTAL = false;
  public static final int R828_Xtal = 28800;

  public static final boolean USE_DIPLEXER = false;
  public static final boolean TUNER_CLK_OUT = true;

  // #ifndef _UINT_X_
  public static final int _UINT_X_ = 1;

  public static final int FUNCTION_SUCCESS = 0;
  public static final int FUNCTION_ERROR = -1;
  public static final int DIP_FREQ = 320000;
  public static final int IMR_TRIAL = 9;
  public static final int VCO_pwr_ref = 0x02;
  R828_I2C_TYPE R828_I2C = new R828_I2C_TYPE();
  R828_I2C_LEN_TYPE R828_I2C_Len = new R828_I2C_LEN_TYPE();

  // enum Rafael_Chip_Type //Don't modify chip list
  // {
  public static final int R828 = 0;
  public static final int R828D = 1;
  public static final int R828S = 2;
  public static final int R820T = 3;
  public static final int R820C = 4;
  public static final int R620D = 5;
  public static final int R620S = 6;
  // };
  // enum R828_Standard_Type //Don't remove standard list!!
  // {
  public static final int NTSC_MN = 0;
  public static final int PAL_I = 1;
  public static final int PAL_DK = 2;
  public static final int PAL_B_7M = 3; // no use
  public static final int PAL_BGH_8M = 4; // for PAL B/G, PAL G/H
  public static final int SECAM_L = 5;
  public static final int SECAM_L1_INV = 6; // for SECAM L'
  public static final int SECAM_L1 = 7; // no use
  public static final int ATV_SIZE = 8;
  public static final int DVB_T_6M = 8;
  public static final int DVB_T_7M = 9;
  public static final int DVB_T_7M_2 = 10;
  public static final int DVB_T_8M = 11;
  public static final int DVB_T2_6M = 12;
  public static final int DVB_T2_7M = 13;
  public static final int DVB_T2_7M_2 = 14;
  public static final int DVB_T2_8M = 15;
  public static final int DVB_T2_1_7M = 16;
  public static final int DVB_T2_10M = 17;
  public static final int DVB_C_8M = 18;
  public static final int DVB_C_6M = 19;
  public static final int ISDB_T = 20;
  public static final int DTMB = 21;
  public static final int R828_ATSC = 22;
  public static final int FM = 23;
  public static final int STD_SIZE = 23;
  // };
  // class R828_SetFreq_Type
  // {
  public static final boolean FAST_MODE = true;
  public static final boolean NORMAL_MODE = false;
  private static final int LOOP_THROUGH = 0;

  // private static final int true = 0;
  // private static final int false = 1;
  // private static final int TRUE = 1;
  // private static final int FALSE = 0;
  // };

  class R828_LoopThrough_Type {
    public static final boolean LOOP_THROUGH1 = true;
    public static final boolean SIGLE_IN = false;
  };

  class R828_InputMode_Type {
    public static final int AIR_IN = 0;
    public static final int CABLE_IN_1 = 1;
    public static final int CABLE_IN_2 = 2;
  };

  class R828_IfAgc_Type {
    public static final int IF_AGC1 = 0;
    public static final int IF_AGC2 = 1;
  };

  class R828_GPIO_Type {
    public static final boolean HI_SIG = true;
    public static final boolean LO_SIG = false;
  };

  class R828_Set_Info {
    long RF_Hz;
    long RF_KHz;
    int R828_Standard;
    R828_LoopThrough_Type RT_Input;
    R828_InputMode_Type RT_InputMode;
    R828_IfAgc_Type R828_IfAgc_Select;
  };

  class R828_RF_Gain_Info {
    byte RF_gain1;
    byte RF_gain2;
    byte RF_gain_comb;
  };

  class R828_RF_Gain_TYPE {
    int RF_AUTO = 0;
    int RF_MANUAL;
  };

  class R828_I2C_LEN_TYPE {
    byte RegAddr;
    byte[] Data = new byte[50];
    byte Len;
  };

  class R828_I2C_TYPE {
    byte RegAddr;
    byte Data;
  };

  byte[] R828_iniArry = { (byte) 0x83, 0x32, 0x75, (byte) 0xC0, 0x40,
      (byte) 0xD6, 0x6C, (byte) 0xF5, 0x63,
      /* 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D */

      0x75, 0x68, 0x6C, (byte) 0x83, (byte) 0x80, 0x00, 0x0F,
      0x00,
      (byte) 0xC0,// xtal_check
      /* 0x0E 0x0F 0x10 0x11 0x12 0x13 0x14 0x15 0x16 */

      0x30, 0x48, (byte) 0xCC, 0x60, 0x00, 0x54, (byte) 0xAE, 0x4A,
      (byte) 0xC0 };
  /*
   * 0x17 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F
   */
  int R828_ADDRESS = 0x34;
  int Rafael_Chip = R820T;
  byte[] R828_Arry = new byte[27];

  // ----------------------------------------------------------//
  // Internal Structs //
  // ----------------------------------------------------------//
  class R828_SectType {
    int Phase_Y;
    int Gain_X;
    int Value;
  };

  // class BW_Type
  // {
  byte BW_6M = 0;
  byte BW_7M = 1;
  byte BW_8M = 2;
  byte BW_1_7M = 3;
  byte BW_10M = 4;
  byte BW_200K = 5;

  // };

  class Sys_Info_Type {
    char IF_KHz;
    int BW;
    int FILT_CAL_LO;
    byte FILT_GAIN;
    byte IMG_R;
    byte FILT_Q;
    byte HP_COR;
    byte EXT_ENABLE;
    byte LOOP_THROUGH1;
    byte LT_ATT;
    byte FLT_EXT_WIDEST;
    byte POLYFIL_CUR;
  };

  class Freq_Info_Type {
    byte OPEN_D;
    byte RF_MUX_PLOY;
    byte TF_C;
    byte XTAL_CAP20P;
    byte XTAL_CAP10P;
    byte XTAL_CAP0P;
    byte IMR_MEM;
  };

  class SysFreq_Info_Type {
    byte LNA_TOP;
    byte LNA_VTH_L;
    byte MIXER_TOP;
    byte MIXER_VTH_L;
    byte AIR_CABLE1_IN;
    byte CABLE2_IN;
    byte PRE_DECT;
    byte LNA_DISbyteGE;
    byte CP_CUR;
    byte DIV_BUF_CUR;
    byte FILTER_CUR;
  };

  // ----------------------------------------------------------//
  // Internal Parameters //
  // ----------------------------------------------------------//
  // class XTAL_CAP_VALUE
  // {
  public static final int XTAL_LOW_CAP_30P = 0;
  public static final int XTAL_LOW_CAP_20P = 1;
  public static final int XTAL_LOW_CAP_10P = 2;
  public static final int XTAL_LOW_CAP_0P = 3;
  public static final int XTAL_HIGH_CAP_0P = 4;
  // };

  // byte [] R828_Arry = new byte[27];
  /*
   * R828_SectType [] IMR_Data_ = { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0,
   * 0}, {0, 0, 0} };//Please keep this array data for standby mode.
   */
  // R828_I2C_TYPE R828_I2C;
  // R828_I2C_LEN_TYPE R828_I2C_Len;
  R828_SectType[] IMR_Data = new R828_SectType[5];

  int R828_IF_khz;
  int R828_CAL_LO_khz;
  byte R828_IMR_point_num;
  boolean R828_IMR_done_flag = false;
  byte[] R828_Fil_Cal_flag = new byte[STD_SIZE];
  byte[] R828_Fil_Cal_code = new byte[STD_SIZE];

  int Xtal_cap_sel = XTAL_LOW_CAP_0P;
  int Xtal_cap_sel_tmp = XTAL_LOW_CAP_0P;
  // ----------------------------------------------------------//
  // Internal static struct //
  // ----------------------------------------------------------//
  static SysFreq_Info_Type SysFreq_Info1;
  static Sys_Info_Type Sys_Info1;
  // static Freq_Info_Type R828_Freq_Info;
  static Freq_Info_Type Freq_Info1;

  @Override
  public int init(int param) throws IOException {
    boolean r = R828_Init(param);
    r820t_SetStandardMode(param, DVB_T_6M);
    return 0;
  }

  @Override
  public int exit(int param) throws IOException {
    return r820t_SetStandby(param, 0);

  }

  @Override
  public int set_freq(int param, long freq) throws IOException {
    return r820t_SetRfFreqHz(param, freq);
  }

  @Override
  public int set_bw(int param, int bw) throws IOException {

    return 0;
  }

  @Override
  public int set_gain(int param, int gain) throws IOException {

    if (R828_SetRfGain(param, gain))
      return 0;
    else
      return -1;
  }

  @Override
  public int set_if_gain(int param, int stage, int gain) throws IOException {
    // TODO Auto-generated method stub
    return 0;
  }

  @Override
  public int set_gain_mode(int param, boolean manual) throws IOException {
    if (R828_RfGainMode(param, manual))
      return 0;
    else
      return -1;

  }

  int r820t_SetRfFreqHz(int pTuner, long RfFreqHz) {
    R828_Set_Info R828Info = new R828_Set_Info();

    // if(pExtra->IsStandardModeSet==NO)
    // goto error_status_set_tuner_rf_frequency;

    // R828Info.R828_Standard = (R828_Standard_Type)pExtra->StandardMode;
    R828Info.R828_Standard = 8;// R828_Standard_Type.DVB_T_6M;

    R828Info.RF_Hz = (RfFreqHz);
    R828Info.RF_KHz = (RfFreqHz / 1000);

    if (R828_SetFrequency(pTuner, R828Info, NORMAL_MODE) != true)
      return FUNCTION_ERROR;

    return FUNCTION_SUCCESS;
  }

  int r820t_SetStandardMode(int pTuner, int StandardMode) {
    if (R828_SetStandard(pTuner, StandardMode) != true)
      return FUNCTION_ERROR;

    return FUNCTION_SUCCESS;
  }

  int r820t_SetStandby(int pTuner, int LoopThroughType) {

    if (R828_Standby(pTuner, LoopThroughType) != true)
      return FUNCTION_ERROR;

    return FUNCTION_SUCCESS;
  }

  /* just reverses the bits of a byte */
  int r820t_Convert(int InvertNum) {
    int ReturnNum;
    int AddNum;
    int BitNum;
    int CountNum;

    ReturnNum = 0;
    AddNum = 0x80;
    BitNum = 0x01;

    for (CountNum = 0; CountNum < 8; CountNum++) {
      if ((BitNum & InvertNum) != 0)
        ReturnNum += AddNum;

      AddNum /= 2;
      BitNum *= 2;
    }

    return ReturnNum;
  }

  boolean I2C_Write_Len(int pTuner, R828_I2C_LEN_TYPE I2C_Info) {
    // byte DeviceAddr;

    int i = 0, j = 0;

    byte RegStartAddr;
    byte[] pWritingBytes = new byte[I2C_Info.Data.length];
    long ByteNum;
    // int count=0;
    byte[] WritingBuffer = new byte[2];
    long WritingByteNum, WritingByteNumMax, WritingByteNumRem;
    byte RegWritingAddr;

    // Get regiser start address, writing bytes, and byte number.
    RegStartAddr = I2C_Info.RegAddr;
    pWritingBytes = I2C_Info.Data;
    ByteNum = I2C_Info.Len;

    // Calculate maximum writing byte number.
    // WritingByteNumMax = pBaseInterface->I2cWritingByteNumMax -
    // LEN_1_BYTE;
    WritingByteNumMax = 2 - 1; // 9 orig

    // Set tuner register bytes with writing bytes.
    // Note: Set tuner register bytes considering maximum writing byte
    // number.
    for (i = 0; i < ByteNum; i += WritingByteNumMax) {
      // Set register writing address.
      RegWritingAddr = (byte) (RegStartAddr + i);

      // Calculate remainder writing byte number.
      WritingByteNumRem = (char) (ByteNum - i);

      // Determine writing byte number.
      WritingByteNum = (WritingByteNumRem > WritingByteNumMax) ? WritingByteNumMax
          : WritingByteNumRem;

      // Set writing buffer.
      // Note: The I2C format of tuner register byte setting is as
      // follows:
      // start_bit + (DeviceAddr | writing_bit) + RegWritingAddr +
      // writing_bytes (WritingByteNum bytes) +
      // stop_bit
      WritingBuffer[0] = RegWritingAddr;

      for (j = 0; j < WritingByteNum; j++)
        // WritingBuffer[j+1] = pWritingBytes[i + j];
        WritingBuffer[j + 1] = I2C_Info.Data[i + j];
      // Set tuner register bytes with writing buffer.
      // if(pI2cBridge->ForwardI2cWritingCmd(pI2cBridge, DeviceAddr,
      // WritingBuffer, WritingByteNum + LEN_1_BYTE) !=
      // FUNCTION_SUCCESS)
      // goto error_status_set_tuner_registers;
      Log.d(TAG, "WritingBuffer[0] " + WritingBuffer[0] + ","
          + " WritingBuffer[1] " + WritingBuffer[1] + " i= " + i);
      while (SdrSerialDriver.rtlsdr_i2c_write_fn(R820T_I2C_ADDR,
          WritingBuffer, (byte) (WritingByteNum + 1)) < 0) {
        Log.d(TAG, "WritingBuffer[0] " + WritingBuffer[0] + ","
            + " WritingBuffer[1] " + WritingBuffer[1] + " i= " + i
            + " FAILED!!!");
        int count = 0;
        count++;
        if (count > 5)
          return false;
      }
    }
    return true;
  }

  boolean I2C_Read_Len(int pTuner, R828_I2C_LEN_TYPE I2C_Info) {
    // byte DeviceAddr;

    int i;

    byte[] RegStartAddr = { 0x00 };
    byte[] ReadingBytes = new byte[128];
    byte ByteNum;

    // Get regiser start address, writing bytes, and byte number.
    // RegStartAddr = 0x00;
    ByteNum = I2C_Info.Len;

    // Set tuner register reading address.
    // Note: The I2C format of tuner register reading address setting is as
    // follows:
    // start_bit + (DeviceAddr | writing_bit) + RegReadingAddr + stop_bit
    // if(pI2cBridge->ForwardI2cWritingCmd(pI2cBridge, DeviceAddr,
    // &RegStartAddr, LEN_1_BYTE) != FUNCTION_SUCCESS)
    // goto error_status_set_tuner_register_reading_address;

    if (SdrSerialDriver.rtlsdr_i2c_write_fn(R820T_I2C_ADDR, RegStartAddr,
        (byte) 1) < 0)
      return false;

    // Get tuner register bytes.
    // Note: The I2C format of tuner register byte getting is as follows:
    // start_bit + (DeviceAddr | reading_bit) + reading_bytes
    // (ReadingByteNum bytes) + stop_bit
    // if(pI2cBridge->ForwardI2cReadingCmd(pI2cBridge, DeviceAddr,
    // ReadingBytes, ByteNum) != FUNCTION_SUCCESS)
    // goto error_status_get_tuner_registers;

    if (SdrSerialDriver.rtlsdr_i2c_read_fn(R820T_I2C_ADDR, ReadingBytes,
        ByteNum) < 0)
      return false;

    for (i = 0; i < ByteNum; i++) {
      I2C_Info.Data[i] = (byte) r820t_Convert(ReadingBytes[i]);
    }

    return true;

    // error_status_get_tuner_registers:
    // error_status_set_tuner_register_reading_address:

    // return false;
  }

  boolean I2C_Write(int pTuner, R828_I2C_TYPE I2C_Info) {
    byte[] WritingBuffer = new byte[2];

    // Set writing bytes.
    // Note: The I2C format of tuner register byte setting is as follows:
    // start_bit + (DeviceAddr | writing_bit) + addr + data + stop_bit
    WritingBuffer[0] = I2C_Info.RegAddr;
    WritingBuffer[1] = I2C_Info.Data;

    // Set tuner register bytes with writing buffer.
    // if(pI2cBridge->ForwardI2cWritingCmd(pI2cBridge, DeviceAddr,
    // WritingBuffer, LEN_2_BYTE) != FUNCTION_SUCCESS)
    // goto error_status_set_tuner_registers;

    // printf("called %s: %02x -> %02x\n", __FUNCTION__, WritingBuffer[0],
    // WritingBuffer[1]);

    if (SdrSerialDriver.rtlsdr_i2c_write_fn(R820T_I2C_ADDR, WritingBuffer,
        (byte) 2) < 0)
      return false;

    return true;
  }

  void R828_Delay_MS(int pTuner, long WaitTimeMs) {
    /* simply don't wait for now */
    return;
  }

  /*
   * int R828_RfGainMode(int pTuner, boolean manual) { int MixerGain; int
   * LnaGain;
   * 
   * MixerGain = 0; LnaGain = 0;
   * 
   * if (manual) { //LNA auto off R828_I2C.RegAddr = 0x05; R828_Arry[0] =
   * (byte) (R828_Arry[0] | 0x10); R828_I2C.Data = R828_Arry[0];
   * if(I2C_Write(pTuner, R828_I2C) != true) return false;
   * 
   * //Mixer auto off R828_I2C.RegAddr = 0x07; R828_Arry[2] = (byte)
   * (R828_Arry[2] & 0xEF); R828_I2C.Data = R828_Arry[2]; if(I2C_Write(pTuner,
   * R828_I2C) != true) return false;
   * 
   * R828_I2C_Len.RegAddr = 0x00; R828_I2C_Len.Len = 4;
   * if(I2C_Read_Len(pTuner, R828_I2C_Len) != true) return false;
   * 
   * set fixed VGA gain for now (16.3 dB) R828_I2C.RegAddr = 0x0C;
   * R828_Arry[7] = (byte) ((R828_Arry[7] & 0x60) | 0x08); R828_I2C.Data =
   * R828_Arry[7]; if(I2C_Write(pTuner, R828_I2C) != true) return false;
   * 
   * 
   * } else { //LNA R828_I2C.RegAddr = 0x05; R828_Arry[0] = (byte)
   * (R828_Arry[0] & 0xEF); R828_I2C.Data = R828_Arry[0]; if(I2C_Write(pTuner,
   * R828_I2C) != true) return false;
   * 
   * //Mixer R828_I2C.RegAddr = 0x07; R828_Arry[2] = (byte) (R828_Arry[2] |
   * 0x10); R828_I2C.Data = R828_Arry[2]; if(I2C_Write(pTuner, R828_I2C) !=
   * true) return false;
   * 
   * set fixed VGA gain for now (26.5 dB) R828_I2C.RegAddr = 0x0C;
   * R828_Arry[7] = (byte) ((R828_Arry[7] & 0x60) | 0x0B); R828_I2C.Data =
   * R828_Arry[7]; if(I2C_Write(pTuner, R828_I2C) != true) return false; }
   * 
   * return true; }
   */
  Sys_Info_Type R828_Sys_Sel(int R828_Standard) {
    Sys_Info_Type R828_Sys_Info = new Sys_Info_Type();

    switch (R828_Standard) {

    case DVB_T_6M:
    case DVB_T2_6M:
      R828_Sys_Info.IF_KHz = 3570;
      R828_Sys_Info.BW = BW_6M;
      R828_Sys_Info.FILT_CAL_LO = 56000; // 52000->56000
      R828_Sys_Info.FILT_GAIN = 0x10; // +3dB, 6MHz on
      R828_Sys_Info.IMG_R = 0x00; // image negative
      R828_Sys_Info.FILT_Q = 0x10; // R10[4]:low Q(1'b1)
      R828_Sys_Info.HP_COR = 0x6B; // 1.7M disable, +2cap, 1.0MHz
      R828_Sys_Info.EXT_ENABLE = 0x60; // R30[6]=1 ext enable; R30[5]:1
                        // ext at LNA max-1
      R828_Sys_Info.LOOP_THROUGH1 = 0x00; // R5[7], LT ON
      R828_Sys_Info.LT_ATT = 0x00; // R31[7], LT ATT enable
      R828_Sys_Info.FLT_EXT_WIDEST = 0x00;// R15[7]: FLT_EXT_WIDE OFF
      R828_Sys_Info.POLYFIL_CUR = 0x60; // R25[6:5]:Min
      break;

    case DVB_T_7M:
    case DVB_T2_7M:
      R828_Sys_Info.IF_KHz = 4070;
      R828_Sys_Info.BW = BW_7M;
      R828_Sys_Info.FILT_CAL_LO = 60000;
      R828_Sys_Info.FILT_GAIN = 0x10; // +3dB, 6MHz on
      R828_Sys_Info.IMG_R = 0x00; // image negative
      R828_Sys_Info.FILT_Q = 0x10; // R10[4]:low Q(1'b1)
      R828_Sys_Info.HP_COR = 0x2B; // 1.7M disable, +1cap, 1.0MHz
      R828_Sys_Info.EXT_ENABLE = 0x60; // R30[6]=1 ext enable; R30[5]:1
                        // ext at LNA max-1
      R828_Sys_Info.LOOP_THROUGH1 = 0x00; // R5[7], LT ON
      R828_Sys_Info.LT_ATT = 0x00; // R31[7], LT ATT enable
      R828_Sys_Info.FLT_EXT_WIDEST = 0x00;// R15[7]: FLT_EXT_WIDE OFF
      R828_Sys_Info.POLYFIL_CUR = 0x60; // R25[6:5]:Min
      break;

    case DVB_T_7M_2:
    case DVB_T2_7M_2:
      R828_Sys_Info.IF_KHz = 4570;
      R828_Sys_Info.BW = BW_7M;
      R828_Sys_Info.FILT_CAL_LO = 63000;
      R828_Sys_Info.FILT_GAIN = 0x10; // +3dB, 6MHz on
      R828_Sys_Info.IMG_R = 0x00; // image negative
      R828_Sys_Info.FILT_Q = 0x10; // R10[4]:low Q(1'b1)
      R828_Sys_Info.HP_COR = 0x2A; // 1.7M disable, +1cap, 1.25MHz
      R828_Sys_Info.EXT_ENABLE = 0x60; // R30[6]=1 ext enable; R30[5]:1
                        // ext at LNA max-1
      R828_Sys_Info.LOOP_THROUGH1 = 0x00; // R5[7], LT ON
      R828_Sys_Info.LT_ATT = 0x00; // R31[7], LT ATT enable
      R828_Sys_Info.FLT_EXT_WIDEST = 0x00;// R15[7]: FLT_EXT_WIDE OFF
      R828_Sys_Info.POLYFIL_CUR = 0x60; // R25[6:5]:Min
      break;

    case DVB_T_8M:
    case DVB_T2_8M:
      R828_Sys_Info.IF_KHz = 4570;
      R828_Sys_Info.BW = BW_8M;
      R828_Sys_Info.FILT_CAL_LO = 68500;
      R828_Sys_Info.FILT_GAIN = 0x10; // +3dB, 6MHz on
      R828_Sys_Info.IMG_R = 0x00; // image negative
      R828_Sys_Info.FILT_Q = 0x10; // R10[4]:low Q(1'b1)
      R828_Sys_Info.HP_COR = 0x0B; // 1.7M disable, +0cap, 1.0MHz
      R828_Sys_Info.EXT_ENABLE = 0x60; // R30[6]=1 ext enable; R30[5]:1
                        // ext at LNA max-1
      R828_Sys_Info.LOOP_THROUGH1 = 0x00; // R5[7], LT ON
      R828_Sys_Info.LT_ATT = 0x00; // R31[7], LT ATT enable
      R828_Sys_Info.FLT_EXT_WIDEST = 0x00;// R15[7]: FLT_EXT_WIDE OFF
      R828_Sys_Info.POLYFIL_CUR = 0x60; // R25[6:5]:Min
      break;

    case ISDB_T:
      R828_Sys_Info.IF_KHz = 4063;
      R828_Sys_Info.BW = BW_6M;
      R828_Sys_Info.FILT_CAL_LO = 59000;
      R828_Sys_Info.FILT_GAIN = 0x10; // +3dB, 6MHz on
      R828_Sys_Info.IMG_R = 0x00; // image negative
      R828_Sys_Info.FILT_Q = 0x10; // R10[4]:low Q(1'b1)
      R828_Sys_Info.HP_COR = 0x6A; // 1.7M disable, +2cap, 1.25MHz
      R828_Sys_Info.EXT_ENABLE = 0x40; // R30[6], ext enable; R30[5]:0 ext
                        // at LNA max
      R828_Sys_Info.LOOP_THROUGH1 = 0x00; // R5[7], LT ON
      R828_Sys_Info.LT_ATT = 0x00; // R31[7], LT ATT enable
      R828_Sys_Info.FLT_EXT_WIDEST = 0x00;// R15[7]: FLT_EXT_WIDE OFF
      R828_Sys_Info.POLYFIL_CUR = 0x60; // R25[6:5]:Min
      break;

    default: // DVB_T_8M
      R828_Sys_Info.IF_KHz = 4570;
      R828_Sys_Info.BW = BW_8M;
      R828_Sys_Info.FILT_CAL_LO = 68500;
      R828_Sys_Info.FILT_GAIN = 0x10; // +3dB, 6MHz on
      R828_Sys_Info.IMG_R = 0x00; // image negative
      R828_Sys_Info.FILT_Q = 0x10; // R10[4]:low Q(1'b1)
      R828_Sys_Info.HP_COR = 0x0D; // 1.7M disable, +0cap, 0.7MHz
      R828_Sys_Info.EXT_ENABLE = 0x60; // R30[6]=1 ext enable; R30[5]:1
                        // ext at LNA max-1
      R828_Sys_Info.LOOP_THROUGH1 = 0x00; // R5[7], LT ON
      R828_Sys_Info.LT_ATT = 0x00; // R31[7], LT ATT enable
      R828_Sys_Info.FLT_EXT_WIDEST = 0x00;// R15[7]: FLT_EXT_WIDE OFF
      R828_Sys_Info.POLYFIL_CUR = 0x60; // R25[6:5]:Min
      break;

    }

    return R828_Sys_Info;
  }

  Freq_Info_Type R828_Freq_Sel(int LO_freq) {
    Freq_Info_Type R828_Freq_Info = new Freq_Info_Type();

    if (LO_freq < 50000) {
      R828_Freq_Info.OPEN_D = 0x08; // low
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = (byte) 0xDF; // R27[7:0] band2,band0
      R828_Freq_Info.XTAL_CAP20P = 0x02; // R16[1:0] 20pF (10)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 0;
    }

    else if (LO_freq >= 50000 && LO_freq < 55000) {
      R828_Freq_Info.OPEN_D = 0x08; // low
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = (byte) 0xBE; // R27[7:0] band4,band1
      R828_Freq_Info.XTAL_CAP20P = 0x02; // R16[1:0] 20pF (10)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 0;
    } else if (LO_freq >= 55000 && LO_freq < 60000) {
      R828_Freq_Info.OPEN_D = 0x08; // low
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = (byte) 0x8B; // R27[7:0] band7,band4
      R828_Freq_Info.XTAL_CAP20P = 0x02; // R16[1:0] 20pF (10)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 0;
    } else if (LO_freq >= 60000 && LO_freq < 65000) {
      R828_Freq_Info.OPEN_D = 0x08; // low
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x7B; // R27[7:0] band8,band4
      R828_Freq_Info.XTAL_CAP20P = 0x02; // R16[1:0] 20pF (10)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 0;
    } else if (LO_freq >= 65000 && LO_freq < 70000) {
      R828_Freq_Info.OPEN_D = 0x08; // low
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x69; // R27[7:0] band9,band6
      R828_Freq_Info.XTAL_CAP20P = 0x02; // R16[1:0] 20pF (10)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 0;
    } else if (LO_freq >= 70000 && LO_freq < 75000) {
      R828_Freq_Info.OPEN_D = 0x08; // low
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x58; // R27[7:0] band10,band7
      R828_Freq_Info.XTAL_CAP20P = 0x02; // R16[1:0] 20pF (10)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 0;
    } else if (LO_freq >= 75000 && LO_freq < 80000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x44; // R27[7:0] band11,band11
      R828_Freq_Info.XTAL_CAP20P = 0x02; // R16[1:0] 20pF (10)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 0;
    } else if (LO_freq >= 80000 && LO_freq < 90000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x44; // R27[7:0] band11,band11
      R828_Freq_Info.XTAL_CAP20P = 0x02; // R16[1:0] 20pF (10)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 0;
    } else if (LO_freq >= 90000 && LO_freq < 100000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x34; // R27[7:0] band12,band11
      R828_Freq_Info.XTAL_CAP20P = 0x01; // R16[1:0] 10pF (01)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 0;
    } else if (LO_freq >= 100000 && LO_freq < 110000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x34; // R27[7:0] band12,band11
      R828_Freq_Info.XTAL_CAP20P = 0x01; // R16[1:0] 10pF (01)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 0;
    } else if (LO_freq >= 110000 && LO_freq < 120000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x24; // R27[7:0] band13,band11
      R828_Freq_Info.XTAL_CAP20P = 0x01; // R16[1:0] 10pF (01)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 1;
    } else if (LO_freq >= 120000 && LO_freq < 140000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x24; // R27[7:0] band13,band11
      R828_Freq_Info.XTAL_CAP20P = 0x01; // R16[1:0] 10pF (01)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 1;
    } else if (LO_freq >= 140000 && LO_freq < 180000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x14; // R27[7:0] band14,band11
      R828_Freq_Info.XTAL_CAP20P = 0x01; // R16[1:0] 10pF (01)
      R828_Freq_Info.XTAL_CAP10P = 0x01;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 1;
    } else if (LO_freq >= 180000 && LO_freq < 220000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x13; // R27[7:0] band14,band12
      R828_Freq_Info.XTAL_CAP20P = 0x00; // R16[1:0] 0pF (00)
      R828_Freq_Info.XTAL_CAP10P = 0x00;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 1;
    } else if (LO_freq >= 220000 && LO_freq < 250000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x13; // R27[7:0] band14,band12
      R828_Freq_Info.XTAL_CAP20P = 0x00; // R16[1:0] 0pF (00)
      R828_Freq_Info.XTAL_CAP10P = 0x00;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 2;
    } else if (LO_freq >= 250000 && LO_freq < 280000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x11; // R27[7:0] highest,highest
      R828_Freq_Info.XTAL_CAP20P = 0x00; // R16[1:0] 0pF (00)
      R828_Freq_Info.XTAL_CAP10P = 0x00;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 2;
    } else if (LO_freq >= 280000 && LO_freq < 310000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x02; // R26[7:6]=0 (LPF) R26[1:0]=2
                        // (low)
      R828_Freq_Info.TF_C = 0x00; // R27[7:0] highest,highest
      R828_Freq_Info.XTAL_CAP20P = 0x00; // R16[1:0] 0pF (00)
      R828_Freq_Info.XTAL_CAP10P = 0x00;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 2;
    } else if (LO_freq >= 310000 && LO_freq < 450000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x41; // R26[7:6]=1 (bypass) R26[1:0]=1
                        // (middle)
      R828_Freq_Info.TF_C = 0x00; // R27[7:0] highest,highest
      R828_Freq_Info.XTAL_CAP20P = 0x00; // R16[1:0] 0pF (00)
      R828_Freq_Info.XTAL_CAP10P = 0x00;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 2;
    } else if (LO_freq >= 450000 && LO_freq < 588000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x41; // R26[7:6]=1 (bypass) R26[1:0]=1
                        // (middle)
      R828_Freq_Info.TF_C = 0x00; // R27[7:0] highest,highest
      R828_Freq_Info.XTAL_CAP20P = 0x00; // R16[1:0] 0pF (00)
      R828_Freq_Info.XTAL_CAP10P = 0x00;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 3;
    } else if (LO_freq >= 588000 && LO_freq < 650000) {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x40; // R26[7:6]=1 (bypass) R26[1:0]=0
                        // (highest)
      R828_Freq_Info.TF_C = 0x00; // R27[7:0] highest,highest
      R828_Freq_Info.XTAL_CAP20P = 0x00; // R16[1:0] 0pF (00)
      R828_Freq_Info.XTAL_CAP10P = 0x00;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 3;
    } else {
      R828_Freq_Info.OPEN_D = 0x00; // high
      R828_Freq_Info.RF_MUX_PLOY = 0x40; // R26[7:6]=1 (bypass) R26[1:0]=0
                        // (highest)
      R828_Freq_Info.TF_C = 0x00; // R27[7:0] highest,highest
      R828_Freq_Info.XTAL_CAP20P = 0x00; // R16[1:0] 0pF (00)
      R828_Freq_Info.XTAL_CAP10P = 0x00;
      R828_Freq_Info.XTAL_CAP0P = 0x00;
      R828_Freq_Info.IMR_MEM = 4;
    }

    return R828_Freq_Info;
  }

  SysFreq_Info_Type R828_SysFreq_Sel(
  /* R828_Standard_Type */int R828_Standard, int RF_freq) {
    SysFreq_Info_Type R828_SysFreq_Info = new SysFreq_Info_Type();

    switch (R828_Standard) {

    case DVB_T_6M:
    case DVB_T_7M:
    case DVB_T_7M_2:
    case DVB_T_8M:
      if ((RF_freq == 506000) || (RF_freq == 666000)
          || (RF_freq == 818000)) {
        R828_SysFreq_Info.MIXER_TOP = 0x14; // MIXER TOP:14 , TOP-1,
                          // low-disbytege
        R828_SysFreq_Info.LNA_TOP = (byte) 0xE5; // Detect BW 3, LNA
                              // TOP:4, PreDet
                              // Top:2
        R828_SysFreq_Info.CP_CUR = 0x28; // 101, 0.2
        R828_SysFreq_Info.DIV_BUF_CUR = 0x20; // 10, 200u
      } else {
        R828_SysFreq_Info.MIXER_TOP = 0x24; // MIXER TOP:13 , TOP-1,
                          // low-disbytege
        R828_SysFreq_Info.LNA_TOP = (byte) 0xE5; // Detect BW 3, LNA
                              // TOP:4, PreDet
                              // Top:2
        R828_SysFreq_Info.CP_CUR = 0x38; // 111, auto
        R828_SysFreq_Info.DIV_BUF_CUR = 0x30; // 11, 150u
      }
      R828_SysFreq_Info.LNA_VTH_L = 0x53; // LNA VTH 0.84 , VTL 0.64
      R828_SysFreq_Info.MIXER_VTH_L = 0x75; // MIXER VTH 1.04, VTL 0.84
      R828_SysFreq_Info.AIR_CABLE1_IN = 0x00;
      R828_SysFreq_Info.CABLE2_IN = 0x00;
      R828_SysFreq_Info.PRE_DECT = 0x40;
      R828_SysFreq_Info.LNA_DISbyteGE = 14;
      R828_SysFreq_Info.FILTER_CUR = 0x40; // 10, low
      break;

    case DVB_T2_6M:
    case DVB_T2_7M:
    case DVB_T2_7M_2:
    case DVB_T2_8M:
      R828_SysFreq_Info.MIXER_TOP = 0x24; // MIXER TOP:13 , TOP-1,
                        // low-disbytege
      R828_SysFreq_Info.LNA_TOP = (byte) 0xE5; // Detect BW 3, LNA TOP:4,
                            // PreDet Top:2
      R828_SysFreq_Info.LNA_VTH_L = 0x53; // LNA VTH 0.84 , VTL 0.64
      R828_SysFreq_Info.MIXER_VTH_L = 0x75; // MIXER VTH 1.04, VTL 0.84
      R828_SysFreq_Info.AIR_CABLE1_IN = 0x00;
      R828_SysFreq_Info.CABLE2_IN = 0x00;
      R828_SysFreq_Info.PRE_DECT = 0x40;
      R828_SysFreq_Info.LNA_DISbyteGE = 14;
      R828_SysFreq_Info.CP_CUR = 0x38; // 111, auto
      R828_SysFreq_Info.DIV_BUF_CUR = 0x30; // 11, 150u
      R828_SysFreq_Info.FILTER_CUR = 0x40; // 10, low
      break;

    case ISDB_T:
      R828_SysFreq_Info.MIXER_TOP = 0x24; // MIXER TOP:13 , TOP-1,
                        // low-disbytege
      R828_SysFreq_Info.LNA_TOP = (byte) 0xE5; // Detect BW 3, LNA TOP:4,
                            // PreDet Top:2
      R828_SysFreq_Info.LNA_VTH_L = 0x75; // LNA VTH 1.04 , VTL 0.84
      R828_SysFreq_Info.MIXER_VTH_L = 0x75; // MIXER VTH 1.04, VTL 0.84
      R828_SysFreq_Info.AIR_CABLE1_IN = 0x00;
      R828_SysFreq_Info.CABLE2_IN = 0x00;
      R828_SysFreq_Info.PRE_DECT = 0x40;
      R828_SysFreq_Info.LNA_DISbyteGE = 14;
      R828_SysFreq_Info.CP_CUR = 0x38; // 111, auto
      R828_SysFreq_Info.DIV_BUF_CUR = 0x30; // 11, 150u
      R828_SysFreq_Info.FILTER_CUR = 0x40; // 10, low
      break;

    default: // DVB-T 8M
      R828_SysFreq_Info.MIXER_TOP = 0x24; // MIXER TOP:13 , TOP-1,
                        // low-disbytege
      R828_SysFreq_Info.LNA_TOP = (byte) 0xE5; // Detect BW 3, LNA TOP:4,
                            // PreDet Top:2
      R828_SysFreq_Info.LNA_VTH_L = 0x53; // LNA VTH 0.84 , VTL 0.64
      R828_SysFreq_Info.MIXER_VTH_L = 0x75; // MIXER VTH 1.04, VTL 0.84
      R828_SysFreq_Info.AIR_CABLE1_IN = 0x00;
      R828_SysFreq_Info.CABLE2_IN = 0x00;
      R828_SysFreq_Info.PRE_DECT = 0x40;
      R828_SysFreq_Info.LNA_DISbyteGE = 14;
      R828_SysFreq_Info.CP_CUR = 0x38; // 111, auto
      R828_SysFreq_Info.DIV_BUF_CUR = 0x30; // 11, 150u
      R828_SysFreq_Info.FILTER_CUR = 0x40; // 10, low
      break;

    } // end switch

    // DTV use Diplexer
    /*
     * #if(USE_DIPLEXER==TRUE) if ((Rafael_Chip==R820C) ||
     * (Rafael_Chip==R820T) || (Rafael_Chip==R828S)) { // Air-in
     * (>=DIP_FREQ) & cable-1(<DIP_FREQ) if(RF_freq >= DIP_FREQ) {
     * R828_SysFreq_Info.AIR_CABLE1_IN = 0x00; //air in, cable-1 off
     * R828_SysFreq_Info.CABLE2_IN = 0x00; //cable-2 off } else {
     * R828_SysFreq_Info.AIR_CABLE1_IN = 0x60; //cable-1 in, air off
     * R828_SysFreq_Info.CABLE2_IN = 0x00; //cable-2 off } } #endif
     */
    return R828_SysFreq_Info;

  }

  boolean R828_Xtal_Check(int pTuner) {
    int ArrayNum;

    ArrayNum = 27;
    for (ArrayNum = 0; ArrayNum < 27; ArrayNum++) {
      R828_Arry[ArrayNum] = R828_iniArry[ArrayNum];
    }

    // cap 30pF & Drive Low
    R828_I2C.RegAddr = 0x10;
    R828_Arry[11] = (byte) ((R828_Arry[11] & 0xF4) | 0x0B);
    R828_I2C.Data = R828_Arry[11];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // set pll autotune = 128kHz
    R828_I2C.RegAddr = 0x1A;
    R828_Arry[21] = (byte) (R828_Arry[21] & 0xF3);
    R828_I2C.Data = R828_Arry[21];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // set manual initial reg = 111111;
    R828_I2C.RegAddr = 0x13;
    R828_Arry[14] = (byte) ((R828_Arry[14] & 0x80) | 0x7F);
    R828_I2C.Data = R828_Arry[14];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // set auto
    R828_I2C.RegAddr = 0x13;
    R828_Arry[14] = (byte) (R828_Arry[14] & 0xBF);
    R828_I2C.Data = R828_Arry[14];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // R828_Delay_MS(pTuner, 5);

    R828_I2C_Len.RegAddr = 0x00;
    R828_I2C_Len.Len = 3;
    if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
      return false;

    // if 30pF unlock, set to cap 20pF
    /*
     * #if (USE_16M_XTAL==TRUE) //VCO=2360MHz for 16M Xtal. VCO band 26
     * if(((R828_I2C_Len.Data[2] & 0x40) == 0x00) || ((R828_I2C_Len.Data[2]
     * & 0x3F) > 29) || ((R828_I2C_Len.Data[2] & 0x3F) < 23)) #else
     */
    if (((R828_I2C_Len.Data[2] & 0x40) == 0x00)
        || ((R828_I2C_Len.Data[2] & 0x3F) == 0x3F))
    // #endif
    {
      // cap 20pF
      R828_I2C.RegAddr = 0x10;
      R828_Arry[11] = (byte) ((R828_Arry[11] & 0xFC) | 0x02);
      R828_I2C.Data = R828_Arry[11];
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      R828_Delay_MS(pTuner, 5);

      R828_I2C_Len.RegAddr = 0x00;
      R828_I2C_Len.Len = 3;
      if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
        return false;

      // if 20pF unlock, set to cap 10pF
      /*
       * #if (USE_16M_XTAL==TRUE) if(((R828_I2C_Len.Data[2] & 0x40) ==
       * 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) > 29) ||
       * ((R828_I2C_Len.Data[2] & 0x3F) < 23)) #else
       */
      if (((R828_I2C_Len.Data[2] & 0x40) == 0x00)
          || ((R828_I2C_Len.Data[2] & 0x3F) == 0x3F))
      // #endif
      {
        // cap 10pF
        R828_I2C.RegAddr = 0x10;
        R828_Arry[11] = (byte) ((R828_Arry[11] & 0xFC) | 0x01);
        R828_I2C.Data = R828_Arry[11];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        R828_Delay_MS(pTuner, 5);

        R828_I2C_Len.RegAddr = 0x00;
        R828_I2C_Len.Len = 3;
        if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
          return false;

        // if 10pF unlock, set to cap 0pF
        /*
         * #if (USE_16M_XTAL==TRUE) if(((R828_I2C_Len.Data[2] & 0x40) ==
         * 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) > 29) ||
         * ((R828_I2C_Len.Data[2] & 0x3F) < 23)) #else
         */
        if (((R828_I2C_Len.Data[2] & 0x40) == 0x00)
            || ((R828_I2C_Len.Data[2] & 0x3F) == 0x3F))
        // #endif
        {
          // cap 0pF
          R828_I2C.RegAddr = 0x10;
          R828_Arry[11] = (byte) ((R828_Arry[11] & 0xFC) | 0x00);
          R828_I2C.Data = R828_Arry[11];
          if (I2C_Write(pTuner, R828_I2C) != true)
            return false;

          R828_Delay_MS(pTuner, 5);

          R828_I2C_Len.RegAddr = 0x00;
          R828_I2C_Len.Len = 3;
          if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
            return false;

          // if unlock, set to high drive
          /*
           * #if (USE_16M_XTAL==TRUE) if(((R828_I2C_Len.Data[2] &
           * 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) > 29) ||
           * ((R828_I2C_Len.Data[2] & 0x3F) < 23)) #else
           */
          if (((R828_I2C_Len.Data[2] & 0x40) == 0x00)
              || ((R828_I2C_Len.Data[2] & 0x3F) == 0x3F))
          // #endif
          {
            // X'tal drive high
            R828_I2C.RegAddr = 0x10;
            R828_Arry[11] = (byte) (R828_Arry[11] & 0xF7);
            R828_I2C.Data = R828_Arry[11];
            if (I2C_Write(pTuner, R828_I2C) != true)
              return false;

            // R828_Delay_MS(15);
            R828_Delay_MS(pTuner, 20);

            R828_I2C_Len.RegAddr = 0x00;
            R828_I2C_Len.Len = 3;
            if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
              return false;

            /*
             * #if (USE_16M_XTAL==TRUE) if(((R828_I2C_Len.Data[2] &
             * 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) >
             * 29) || ((R828_I2C_Len.Data[2] & 0x3F) < 23)) #else
             */
            if (((R828_I2C_Len.Data[2] & 0x40) == 0x00)
                || ((R828_I2C_Len.Data[2] & 0x3F) == 0x3F))
            // #endif
            {
              return false;
            } else // 0p+high drive lock
            {
              Xtal_cap_sel_tmp = XTAL_HIGH_CAP_0P;
            }
          } else // 0p lock
          {
            Xtal_cap_sel_tmp = XTAL_LOW_CAP_0P;
          }
        } else // 10p lock
        {
          Xtal_cap_sel_tmp = XTAL_LOW_CAP_10P;
        }
      } else // 20p lock
      {
        Xtal_cap_sel_tmp = XTAL_LOW_CAP_20P;
      }
    } else // 30p lock
    {
      Xtal_cap_sel_tmp = XTAL_LOW_CAP_30P;
    }

    return true;
  }

  boolean R828_Init(int pTuner) {
    // R820T_EXTRA_MODULE *pExtra;
    int i;

    // Get tuner extra module.
    // pExtra = &(pTuner->Extra.R820t);

    // write initial reg
    if (R828_InitReg(pTuner) != true)
      return false;

    if (R828_IMR_done_flag == false) {

      // write initial reg
      // if(R828_InitReg(pTuner) != true)
      // return false;

      // Do Xtal check
      if ((Rafael_Chip == R820T) || (Rafael_Chip == R828S)
          || (Rafael_Chip == R820C)) {
        Xtal_cap_sel = XTAL_HIGH_CAP_0P;
      } else {
        if (R828_Xtal_Check(pTuner) != true) // 1st
          return false;

        Xtal_cap_sel = Xtal_cap_sel_tmp;

        if (R828_Xtal_Check(pTuner) != true) // 2nd
          return false;

        if (Xtal_cap_sel_tmp > Xtal_cap_sel) {
          Xtal_cap_sel = Xtal_cap_sel_tmp;
        }

        if (R828_Xtal_Check(pTuner) != true) // 3rd
          return false;

        if (Xtal_cap_sel_tmp > Xtal_cap_sel) {
          Xtal_cap_sel = Xtal_cap_sel_tmp;
        }

      }

      // reset filter cal.
      for (i = 0; i < STD_SIZE; i++) {
        R828_Fil_Cal_flag[i] = 0;// FALSE=0
        R828_Fil_Cal_code[i] = 0;
      }

      /*
       * #if 0 //start imr cal. if(R828_InitReg(pTuner) != true) //write
       * initial reg before doing cal return false;
       * 
       * if(R828_IMR_Prepare(pTuner) != true) return false;
       * 
       * if(R828_IMR(pTuner, 3, TRUE) != true) //Full K node 3 return
       * false;
       * 
       * if(R828_IMR(pTuner, 1, FALSE) != true) return false;
       * 
       * if(R828_IMR(pTuner, 0, FALSE) != true) return false;
       * 
       * if(R828_IMR(pTuner, 2, FALSE) != true) return false;
       * 
       * if(R828_IMR(pTuner, 4, FALSE) != true) return false;
       * 
       * R828_IMR_done_flag = TRUE; #endif
       */
    }

    // write initial reg
    if (R828_InitReg(pTuner) != true)
      return false;

    return true;
  }

  boolean R828_InitReg(int pTuner) {
    int InitArryCount;
    int InitArryNum;

    InitArryCount = 0;
    InitArryNum = 27;

    // int LO_KHz = 0;

    // Write Full Table
    R828_I2C_Len.RegAddr = 0x05;
    R828_I2C_Len.Len = (byte) InitArryNum;
    for (InitArryCount = 0; InitArryCount < InitArryNum; InitArryCount++) {
      R828_I2C_Len.Data[InitArryCount] = R828_iniArry[InitArryCount];
    }
    if (I2C_Write_Len(pTuner, R828_I2C_Len) != true)
      return false;

    return true;
  }

  boolean R828_IMR_Prepare(int pTuner)

  {
    int ArrayNum;

    ArrayNum = 27;

    for (ArrayNum = 0; ArrayNum < 27; ArrayNum++) {
      R828_Arry[ArrayNum] = R828_iniArry[ArrayNum];
    }
    // IMR Preparation
    // lna off (air-in off)
    R828_I2C.RegAddr = 0x05;
    R828_Arry[0] = (byte) (R828_Arry[0] | 0x20);
    R828_I2C.Data = R828_Arry[0];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    // mixer gain mode = manual
    R828_I2C.RegAddr = 0x07;
    R828_Arry[2] = (byte) (R828_Arry[2] & 0xEF);
    R828_I2C.Data = R828_Arry[2];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    // filter corner = lowest
    R828_I2C.RegAddr = 0x0A;
    R828_Arry[5] = (byte) (R828_Arry[5] | 0x0F);
    R828_I2C.Data = R828_Arry[5];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    // filter bw=+2cap, hp=5M
    R828_I2C.RegAddr = 0x0B;
    R828_Arry[6] = (byte) ((R828_Arry[6] & 0x90) | 0x60);
    R828_I2C.Data = R828_Arry[6];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    // adc=on, vga code mode, gain = 26.5dB
    R828_I2C.RegAddr = 0x0C;
    R828_Arry[7] = (byte) ((R828_Arry[7] & 0x60) | 0x0B);
    R828_I2C.Data = R828_Arry[7];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    // ring clk = on
    R828_I2C.RegAddr = 0x0F;
    R828_Arry[10] &= 0xF7;
    R828_I2C.Data = R828_Arry[10];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    // ring power = on
    R828_I2C.RegAddr = 0x18;
    R828_Arry[19] = (byte) (R828_Arry[19] | 0x10);
    R828_I2C.Data = R828_Arry[19];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    // from ring = ring pll in
    R828_I2C.RegAddr = 0x1C;
    R828_Arry[23] = (byte) (R828_Arry[23] | 0x02);
    R828_I2C.Data = R828_Arry[23];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    // sw_pdect = det3
    R828_I2C.RegAddr = 0x1E;
    R828_Arry[25] = (byte) (R828_Arry[25] | 0x80);
    R828_I2C.Data = R828_Arry[25];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    // Set filt_3dB
    R828_Arry[1] = (byte) (R828_Arry[1] | 0x20);
    R828_I2C.RegAddr = 0x06;
    R828_I2C.Data = R828_Arry[1];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    return true;
  }

  boolean R828_IMR(int pTuner, int IMR_MEM, boolean IM_Flag) {

    int RingVCO;
    int RingFreq;
    int RingRef;
    int n_ring;
    int n;

    R828_SectType[] IMR_POINT = new R828_SectType[1];

    RingVCO = 0;
    RingFreq = 0;
    RingRef = 0;
    n_ring = 0;

    if (R828_Xtal > 24000)
      RingRef = R828_Xtal / 2;
    // else
    // RingRef = R828_Xtal;

    for (n = 0; n < 16; n++) {
      if ((16 + n) * 8 * RingRef >= 3100000) {
        n_ring = n;
        break;
      }

      if (n == 15) // n_ring not found
      {
        // return false;
        n_ring = n;
      }

    }

    R828_Arry[19] &= 0xF0; // set ring[3:0]
    R828_Arry[19] |= n_ring;
    RingVCO = (16 + n_ring) * 8 * RingRef;
    R828_Arry[19] &= 0xDF; // clear ring_se23
    R828_Arry[20] &= 0xFC; // clear ring_seldiv
    R828_Arry[26] &= 0xFC; // clear ring_att

    switch (IMR_MEM) {
    case 0:
      RingFreq = RingVCO / 48;
      R828_Arry[19] |= 0x20; // ring_se23 = 1
      R828_Arry[20] |= 0x03; // ring_seldiv = 3
      R828_Arry[26] |= 0x02; // ring_att 10
      break;
    case 1:
      RingFreq = RingVCO / 16;
      R828_Arry[19] |= 0x00; // ring_se23 = 0
      R828_Arry[20] |= 0x02; // ring_seldiv = 2
      R828_Arry[26] |= 0x00; // pw_ring 00
      break;
    case 2:
      RingFreq = RingVCO / 8;
      R828_Arry[19] |= 0x00; // ring_se23 = 0
      R828_Arry[20] |= 0x01; // ring_seldiv = 1
      R828_Arry[26] |= 0x03; // pw_ring 11
      break;
    case 3:
      RingFreq = RingVCO / 6;
      R828_Arry[19] |= 0x20; // ring_se23 = 1
      R828_Arry[20] |= 0x00; // ring_seldiv = 0
      R828_Arry[26] |= 0x03; // pw_ring 11
      break;
    case 4:
      RingFreq = RingVCO / 4;
      R828_Arry[19] |= 0x00; // ring_se23 = 0
      R828_Arry[20] |= 0x00; // ring_seldiv = 0
      R828_Arry[26] |= 0x01; // pw_ring 01
      break;
    default:
      RingFreq = RingVCO / 4;
      R828_Arry[19] |= 0x00; // ring_se23 = 0
      R828_Arry[20] |= 0x00; // ring_seldiv = 0
      R828_Arry[26] |= 0x01; // pw_ring 01
      break;
    }

    // write pw_ring,n_ring,ringdiv2 to I2C

    // ------------n_ring,ring_se23----------//
    R828_I2C.RegAddr = 0x18;
    R828_I2C.Data = R828_Arry[19];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    // ------------ring_sediv----------------//
    R828_I2C.RegAddr = 0x19;
    R828_I2C.Data = R828_Arry[20];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    // ------------pw_ring-------------------//
    R828_I2C.RegAddr = 0x1f;
    R828_I2C.Data = R828_Arry[26];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Must do before PLL()
    if (R828_MUX(pTuner, RingFreq - 5300) != true) // MUX input freq ~ RF_in
                            // Freq
      return false;

    if (R828_PLL(pTuner, (RingFreq - 5300) * 1000, STD_SIZE) != true) // set
                                      // pll
                                      // freq
                                      // =
                                      // ring
                                      // freq
                                      // -
                                      // 6M
      return false;

    if (IM_Flag == true) {
      if (R828_IQ(pTuner, IMR_POINT) != true)
        return false;
    } else {
      IMR_POINT[0].Gain_X = IMR_Data[3].Gain_X;
      IMR_POINT[0].Phase_Y = IMR_Data[3].Phase_Y;
      IMR_POINT[0].Value = IMR_Data[3].Value;

      if (R828_F_IMR(pTuner, IMR_POINT) != true)
        return false;
    }

    // Save IMR Value
    switch (IMR_MEM) {
    case 0:
      IMR_Data[0].Gain_X = IMR_POINT[0].Gain_X;
      IMR_Data[0].Phase_Y = IMR_POINT[0].Phase_Y;
      IMR_Data[0].Value = IMR_POINT[0].Value;
      break;
    case 1:
      IMR_Data[1].Gain_X = IMR_POINT[0].Gain_X;
      IMR_Data[1].Phase_Y = IMR_POINT[0].Phase_Y;
      IMR_Data[1].Value = IMR_POINT[0].Value;
      break;
    case 2:
      IMR_Data[2].Gain_X = IMR_POINT[0].Gain_X;
      IMR_Data[2].Phase_Y = IMR_POINT[0].Phase_Y;
      IMR_Data[2].Value = IMR_POINT[0].Value;
      break;
    case 3:
      IMR_Data[3].Gain_X = IMR_POINT[0].Gain_X;
      IMR_Data[3].Phase_Y = IMR_POINT[0].Phase_Y;
      IMR_Data[3].Value = IMR_POINT[0].Value;
      break;
    case 4:
      IMR_Data[4].Gain_X = IMR_POINT[0].Gain_X;
      IMR_Data[4].Phase_Y = IMR_POINT[0].Phase_Y;
      IMR_Data[4].Value = IMR_POINT[0].Value;
      break;
    default:
      IMR_Data[4].Gain_X = IMR_POINT[0].Gain_X;
      IMR_Data[4].Phase_Y = IMR_POINT[0].Phase_Y;
      IMR_Data[4].Value = IMR_POINT[0].Value;
      break;
    }
    return true;
  }

  boolean R828_PLL(int pTuner, int LO_Freq, /* R828_Standard_Type */
      int R828_Standard) {

    // R820T_EXTRA_MODULE *pExtra;

    int MixDiv;
    int DivBuf;
    int Ni;
    int Si;
    int DivNum;
    int Nint;
    int VCO_Min_kHz;
    int VCO_Max_kHz;
    long VCO_Freq; // was 64 bit aew
    int PLL_Ref; // Max 24000 (kHz)
    int VCO_Fra; // VCO contribution by SDM (kHz)
    char Nsdm;
    char SDM;
    char SDM16to9;
    char SDM8to1;
    // int Judge = 0;
    int VCO_fine_tune;

    MixDiv = 2;
    DivBuf = 0;
    Ni = 0;
    Si = 0;
    DivNum = 0;
    Nint = 0;
    VCO_Min_kHz = 1770000;
    VCO_Max_kHz = VCO_Min_kHz * 2;
    VCO_Freq = 0;
    PLL_Ref = 0; // Max 24000 (kHz)
    VCO_Fra = 0; // VCO contribution by SDM (kHz)
    Nsdm = 2;
    SDM = 0;
    SDM16to9 = 0;
    SDM8to1 = 0;
    // int Judge = 0;
    VCO_fine_tune = 0;
    /*
     * #if 0 if ((Rafael_Chip==R620D) || (Rafael_Chip==R828D) ||
     * (Rafael_Chip==R828)) / /X'tal can't not exceed 20MHz for ATV {
     * if(R828_Standard <= SECAM_L1) / /ref set refdiv2, reffreq = Xtal/2 on
     * ATV application { R828_Arry[11] |= 0x10; //b4=1 PLL_Ref = R828_Xtal
     * /2; } else //DTV, FilCal, IMR { R828_Arry[11] &= 0xEF; PLL_Ref =
     * R828_Xtal; } } else { if(R828_Xtal > 24000) { R828_Arry[11] |= 0x10;
     * //b4=1 PLL_Ref = R828_Xtal /2; } else { R828_Arry[11] &= 0xEF;
     * PLL_Ref = R828_Xtal; } } #endif
     */
    // FIXME hack
    R828_Arry[11] &= 0xEF;
    PLL_Ref = SdrSerialDriver.rtlsdr_get_tuner_clock();

    R828_I2C.RegAddr = 0x10;
    R828_I2C.Data = R828_Arry[11];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // set pll autotune = 128kHz
    R828_I2C.RegAddr = 0x1A;
    R828_Arry[21] = (byte) (R828_Arry[21] & 0xF3);
    R828_I2C.Data = R828_Arry[21];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Set VCO current = 100
    R828_I2C.RegAddr = 0x12;
    R828_Arry[13] = (byte) ((R828_Arry[13] & 0x1F) | 0x80);
    R828_I2C.Data = R828_Arry[13];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Divider
    while (MixDiv <= 64) {
      if ((((LO_Freq / 1000) * MixDiv) >= VCO_Min_kHz)
          && (((LO_Freq / 1000) * MixDiv) < VCO_Max_kHz)) {
        DivBuf = MixDiv;
        while (DivBuf > 2) {
          DivBuf = DivBuf >> 1;
          DivNum++;
        }
        break;
      }
      MixDiv = MixDiv << 1;
    }

    R828_I2C_Len.RegAddr = 0x00;
    R828_I2C_Len.Len = 5;
    if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
      return false;

    VCO_fine_tune = (R828_I2C_Len.Data[4] & 0x30) >> 4;

    if (VCO_fine_tune > VCO_pwr_ref)
      DivNum = DivNum - 1;
    else if (VCO_fine_tune < VCO_pwr_ref)
      DivNum = DivNum + 1;

    R828_I2C.RegAddr = 0x10;
    R828_Arry[11] &= 0x1F;
    R828_Arry[11] |= (DivNum << 5);
    R828_I2C.Data = R828_Arry[11];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    VCO_Freq = (LO_Freq * (long) MixDiv);
    Nint = (int) (VCO_Freq / 2 / PLL_Ref);
    VCO_Fra = (char) ((VCO_Freq - 2 * PLL_Ref * Nint) / 1000);

    // FIXME hack
    PLL_Ref /= 1000;

    Log.d(TAG,
        "VCO_Freq " + Long.toString(VCO_Freq) + " Nint "
            + Long.toString(Nint) + " VCO_Fra "
            + Long.toString(VCO_Fra) + " LO_Freq "
            + Long.toString(LO_Freq) + " MixDiv "
            + Long.toString(MixDiv));

    // boundary spur prevention
    if (VCO_Fra < PLL_Ref / 64) // 2*PLL_Ref/128
      VCO_Fra = 0;
    else if (VCO_Fra > PLL_Ref * 127 / 64) // 2*PLL_Ref*127/128
    {
      VCO_Fra = 0;
      Nint++;
    } else if ((VCO_Fra > PLL_Ref * 127 / 128) && (VCO_Fra < PLL_Ref)) // >
                                      // 2*PLL_Ref*127/256,
                                      // <
                                      // 2*PLL_Ref*128/256
      VCO_Fra = PLL_Ref * 127 / 128; // VCO_Fra = 2*PLL_Ref*127/256
    else if ((VCO_Fra > PLL_Ref) && (VCO_Fra < PLL_Ref * 129 / 128)) // >
                                      // 2*PLL_Ref*128/256,
                                      // <
                                      // 2*PLL_Ref*129/256
      VCO_Fra = PLL_Ref * 129 / 128; // VCO_Fra = 2*PLL_Ref*129/256
    else
      VCO_Fra = VCO_Fra + 0;

    if (Nint > 63) {
      Log.d(TAG, String.format("[R820T] No valid PLL values for %u Hz! ",
          LO_Freq));
      return false;
    }

    // N & S
    Ni = (Nint - 13) / 4;
    Si = Nint - 4 * Ni - 13;
    R828_I2C.RegAddr = 0x14;
    R828_Arry[15] = 0x00;
    R828_Arry[15] |= (Ni + (Si << 6));
    R828_I2C.Data = R828_Arry[15];

    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // pw_sdm
    R828_I2C.RegAddr = 0x12;
    R828_Arry[13] &= 0xF7;
    if (VCO_Fra == 0)
      R828_Arry[13] |= 0x08;
    R828_I2C.Data = R828_Arry[13];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // SDM calculator
    while (VCO_Fra > 1) {
      if (VCO_Fra > (2 * PLL_Ref / Nsdm)) {
        SDM = (char) (SDM + 32768 / (Nsdm / 2));
        VCO_Fra = VCO_Fra - 2 * PLL_Ref / Nsdm;
        if (Nsdm >= 0x8000)
          break;
      }
      Nsdm = (char) (Nsdm << 1);
    }

    SDM16to9 = (char) (SDM >> 8);
    SDM8to1 = (char) (SDM - (SDM16to9 << 8));

    R828_I2C.RegAddr = 0x16;
    R828_Arry[17] = (byte) SDM16to9;
    R828_I2C.Data = R828_Arry[17];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;
    R828_I2C.RegAddr = 0x15;
    R828_Arry[16] = (byte) SDM8to1;
    R828_I2C.Data = R828_Arry[16];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // R828_Delay_MS(10);

    if ((Rafael_Chip == R620D) || (Rafael_Chip == R828D)
        || (Rafael_Chip == R828)) {
      if (R828_Standard <= SECAM_L1)
        R828_Delay_MS(pTuner, 20);
      else
        R828_Delay_MS(pTuner, 10);
    } else {
      R828_Delay_MS(pTuner, 10);
    }

    // check PLL lock status
    R828_I2C_Len.RegAddr = 0x00;
    R828_I2C_Len.Len = 3;
    if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
      return false;

    if ((R828_I2C_Len.Data[2] & 0x40) == 0x00) {
      Log.d(TAG, "[R820T] PLL not locked for %u Hz! " + LO_Freq);
      R828_I2C.RegAddr = 0x12;
      R828_Arry[13] = (byte) ((R828_Arry[13] & 0x1F) | 0x60); // increase
                                  // VCO
                                  // current
      R828_I2C.Data = R828_Arry[13];
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      return false;
    }

    // set pll autotune = 8kHz
    R828_I2C.RegAddr = 0x1A;
    R828_Arry[21] = (byte) (R828_Arry[21] | 0x08);
    R828_I2C.Data = R828_Arry[21];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    return true;
  }

  boolean R828_MUX(int pTuner, int RF_KHz) {
    int RT_Reg08;
    int RT_Reg09;

    RT_Reg08 = 0;
    RT_Reg09 = 0;

    // Freq_Info_Type Freq_Info1;
    Freq_Info1 = R828_Freq_Sel(RF_KHz);

    // Open Drain
    R828_I2C.RegAddr = 0x17;
    R828_Arry[18] = (byte) ((R828_Arry[18] & 0xF7) | Freq_Info1.OPEN_D);
    R828_I2C.Data = R828_Arry[18];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // RF_MUX,Polymux
    R828_I2C.RegAddr = 0x1A;
    R828_Arry[21] = (byte) ((R828_Arry[21] & 0x3C) | Freq_Info1.RF_MUX_PLOY);
    R828_I2C.Data = R828_Arry[21];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // TF BAND
    R828_I2C.RegAddr = 0x1B;
    R828_Arry[22] &= 0x00;
    R828_Arry[22] |= Freq_Info1.TF_C;
    R828_I2C.Data = R828_Arry[22];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // XTAL CAP & Drive
    R828_I2C.RegAddr = 0x10;
    R828_Arry[11] &= 0xF4;
    switch (Xtal_cap_sel) {
    case XTAL_LOW_CAP_30P:
    case XTAL_LOW_CAP_20P:
      R828_Arry[11] = (byte) (R828_Arry[11] | Freq_Info1.XTAL_CAP20P | 0x08);
      break;

    case XTAL_LOW_CAP_10P:
      R828_Arry[11] = (byte) (R828_Arry[11] | Freq_Info1.XTAL_CAP10P | 0x08);
      break;

    case XTAL_LOW_CAP_0P:
      R828_Arry[11] = (byte) (R828_Arry[11] | Freq_Info1.XTAL_CAP0P | 0x08);
      break;

    case XTAL_HIGH_CAP_0P:
      R828_Arry[11] = (byte) (R828_Arry[11] | Freq_Info1.XTAL_CAP0P | 0x00);
      break;

    default:
      R828_Arry[11] = (byte) (R828_Arry[11] | Freq_Info1.XTAL_CAP0P | 0x08);
      break;
    }
    R828_I2C.Data = R828_Arry[11];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Set_IMR
    if (R828_IMR_done_flag == true) {
      RT_Reg08 = IMR_Data[Freq_Info1.IMR_MEM].Gain_X & 0x3F;
      RT_Reg09 = IMR_Data[Freq_Info1.IMR_MEM].Phase_Y & 0x3F;
    } else {
      RT_Reg08 = 0;
      RT_Reg09 = 0;
    }

    R828_I2C.RegAddr = 0x08;
    R828_Arry[3] = (byte) (R828_iniArry[3] & 0xC0);
    R828_Arry[3] = (byte) (R828_Arry[3] | RT_Reg08);
    R828_I2C.Data = R828_Arry[3];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    R828_I2C.RegAddr = 0x09;
    R828_Arry[4] = (byte) (R828_iniArry[4] & 0xC0);
    R828_Arry[4] = (byte) (R828_Arry[4] | RT_Reg09);
    R828_I2C.Data = R828_Arry[4];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    return true;
  }

  boolean R828_IQ(int pTuner, R828_SectType[] IQ_Pont) {
    R828_SectType[] Compare_IQ = new R828_SectType[3];
    // R828_SectType CompareTemp;
    // byte IQ_Count = 0;
    byte VGA_Count;
    char[] VGA_Read = new char[1];
    byte[] X_Direction = new byte[1]; // 1:X, 0:Y

    VGA_Count = 0;
    VGA_Read[0] = 0;

    // increase VGA power to let image significant
    for (VGA_Count = 12; VGA_Count < 16; VGA_Count++) {
      R828_I2C.RegAddr = 0x0C;
      R828_I2C.Data = (byte) ((R828_Arry[7] & 0xF0) + VGA_Count);
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      R828_Delay_MS(pTuner, 10); //

      if (R828_Muti_Read(pTuner, (byte) 0x01, VGA_Read) != true)
        return false;

      if (VGA_Read[0] > 40 * 4)
        break;
    }

    // initial 0x08, 0x09
    // Compare_IQ[0].Gain_X = 0x40; //should be 0xC0 in R828, Jason
    // Compare_IQ[0].Phase_Y = 0x40; //should be 0x40 in R828
    Compare_IQ[0].Gain_X = R828_iniArry[3] & 0xC0; // Jason modified, clear
                            // b[5], b[4:0]
    Compare_IQ[0].Phase_Y = R828_iniArry[4] & 0xC0; //

    // while(IQ_Count < 3)
    // {
    // Determine X or Y
    if (R828_IMR_Cross(pTuner, Compare_IQ, X_Direction) != true)
      return false;

    // if(X_Direction==1)
    // {
    // if(R828_IQ_Tree(Compare_IQ[0].Phase_Y, Compare_IQ[0].Gain_X, 0x09,
    // &Compare_IQ[0]) != true) //X
    // return false;
    // }
    // else
    // {
    // if(R828_IQ_Tree(Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08,
    // &Compare_IQ[0]) != true) //Y
    // return false;
    // }

    /*
     * //--- X direction ---// //X: 3 points
     * if(R828_IQ_Tree(Compare_IQ[0].Phase_Y, Compare_IQ[0].Gain_X, 0x09,
     * &Compare_IQ[0]) != true) // return false;
     * 
     * //compare and find min of 3 points. determine I/Q direction
     * if(R828_CompreCor(&Compare_IQ[0]) != true) return false;
     * 
     * //increase step to find min value of this direction
     * if(R828_CompreStep(&Compare_IQ[0], 0x08) != true) return false;
     */

    if (X_Direction[0] == 1) {
      // compare and find min of 3 points. determine I/Q direction
      if (R828_CompreCor(Compare_IQ) != true)
        return false;

      // increase step to find min value of this direction
      if (R828_CompreStep(pTuner, Compare_IQ, (byte) 0x08) != true) // X
        return false;
    } else {
      // compare and find min of 3 points. determine I/Q direction
      if (R828_CompreCor(Compare_IQ) != true)
        return false;

      // increase step to find min value of this direction
      if (R828_CompreStep(pTuner, Compare_IQ, (byte) 0x09) != true) // Y
        return false;
    }
    /*
     * //--- Y direction ---// //Y: 3 points
     * if(R828_IQ_Tree(Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08,
     * &Compare_IQ[0]) != true) // return false;
     * 
     * //compare and find min of 3 points. determine I/Q direction
     * if(R828_CompreCor(&Compare_IQ[0]) != true) return false;
     * 
     * //increase step to find min value of this direction
     * if(R828_CompreStep(&Compare_IQ[0], 0x09) != true) return false;
     */

    // Another direction
    if (X_Direction[0] == 1) {
      if (R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X,
          Compare_IQ[0].Phase_Y, 0x08, Compare_IQ) != true) // Y
        return false;

      // compare and find min of 3 points. determine I/Q direction
      if (R828_CompreCor(Compare_IQ) != true)
        return false;

      // increase step to find min value of this direction
      if (R828_CompreStep(pTuner, Compare_IQ, (byte) 0x09) != true) // Y
        return false;
    } else {
      if (R828_IQ_Tree(pTuner, Compare_IQ[0].Phase_Y,
          Compare_IQ[0].Gain_X, 0x09, Compare_IQ) != true) // X
        return false;

      // compare and find min of 3 points. determine I/Q direction
      if (R828_CompreCor(Compare_IQ) != true)
        return false;

      // increase step to find min value of this direction
      if (R828_CompreStep(pTuner, Compare_IQ, (byte) 0x08) != true) // X
        return false;
    }
    // CompareTemp = Compare_IQ[0];

    // --- Check 3 points again---//
    if (X_Direction[0] == 1) {
      if (R828_IQ_Tree(pTuner, Compare_IQ[0].Phase_Y,
          Compare_IQ[0].Gain_X, 0x09, Compare_IQ) != true) // X
        return false;
    } else {
      if (R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X,
          Compare_IQ[0].Phase_Y, 0x08, Compare_IQ) != true) // Y
        return false;
    }

    // if(R828_IQ_Tree(Compare_IQ[0].Phase_Y, Compare_IQ[0].Gain_X, 0x09,
    // &Compare_IQ[0]) != true) //
    // return false;

    if (R828_CompreCor(Compare_IQ) != true)
      return false;

    // if((CompareTemp.Gain_X == Compare_IQ[0].Gain_X) &&
    // (CompareTemp.Phase_Y == Compare_IQ[0].Phase_Y))//Ben Check
    // break;

    // IQ_Count ++;
    // }
    // if(IQ_Count == 3)
    // return false;

    // Section-4 Check
    /*
     * CompareTemp = Compare_IQ[0]; for(IQ_Count = 0;IQ_Count < 5;IQ_Count
     * ++) { if(R828_Section(&Compare_IQ[0]) != true) return false;
     * 
     * if((CompareTemp.Gain_X == Compare_IQ[0].Gain_X) &&
     * (CompareTemp.Phase_Y == Compare_IQ[0].Phase_Y)) break; }
     */

    // Section-9 check
    // if(R828_F_IMR(&Compare_IQ[0]) != true)
    if (R828_Section(pTuner, Compare_IQ) != true)
      return false;

    IQ_Pont[0] = Compare_IQ[0];

    // reset gain/phase control setting
    R828_I2C.RegAddr = 0x08;
    R828_I2C.Data = (byte) (R828_iniArry[3] & 0xC0); // Jason
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    R828_I2C.RegAddr = 0x09;
    R828_I2C.Data = (byte) (R828_iniArry[4] & 0xC0);
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    return true;
  }

  // --------------------------------------------------------------------------------------------
  // Purpose: record IMC results by input gain/phase location
  // then adjust gain or phase positive 1 step and negtive 1 step, both record
  // results
  // input: FixPot: phase or gain
  // FlucPot phase or gain
  // PotReg: 0x08 or 0x09
  // CompareTree: 3 IMR trace and results
  // output: TREU or FALSE
  // --------------------------------------------------------------------------------------------
  boolean R828_IQ_Tree(int pTuner, int FixPot, int FlucPot, int PotReg,
      R828_SectType[] CompareTree) {
    byte TreeCount;
    byte TreeTimes;
    byte TempPot;
    byte PntReg;

    TreeCount = 0;
    TreeTimes = 3;
    TempPot = 0;
    PntReg = 0;

    if (PotReg == 0x08)
      PntReg = 0x09; // phase control
    else
      PntReg = 0x08; // gain control

    for (TreeCount = 0; TreeCount < TreeTimes; TreeCount++) {
      R828_I2C.RegAddr = (byte) PotReg;
      R828_I2C.Data = (byte) FixPot;
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      R828_I2C.RegAddr = PntReg;
      R828_I2C.Data = (byte) FlucPot;
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;
      char[] value = new char[1];

      if (R828_Muti_Read(pTuner, (byte) 0x01, /*
                           * CompareTree[TreeCount].Value
                           */value) != true)
        return false;
      CompareTree[TreeCount].Value = value[0];
      if (PotReg == 0x08) {
        CompareTree[TreeCount].Gain_X = FixPot;
        CompareTree[TreeCount].Phase_Y = FlucPot;
      } else {
        CompareTree[TreeCount].Phase_Y = FixPot;
        CompareTree[TreeCount].Gain_X = FlucPot;
      }

      if (TreeCount == 0) // try right-side point
        FlucPot++;
      else if (TreeCount == 1) // try left-side point
      {
        if ((FlucPot & 0x1F) < 0x02) // if absolute location is 1,
                        // change I/Q direction
        {
          TempPot = (byte) (2 - (FlucPot & 0x1F));
          if ((FlucPot & 0x20) != 0) // b[5]:I/Q selection. 0:Q-path,
                        // 1:I-path
          {
            FlucPot &= 0xC0;
            FlucPot |= TempPot;
          } else {
            FlucPot |= (0x20 | TempPot);
          }
        } else
          FlucPot -= 2;
      }
    }

    return true;
  }

  // -----------------------------------------------------------------------------------/
  // Purpose: compare IMC result aray [0][1][2], find min value and store to
  // CorArry[0]
  // input: CorArry: three IMR data array
  // output: TRUE or FALSE
  // -----------------------------------------------------------------------------------/
  boolean R828_CompreCor(R828_SectType[] CorArry) {
    byte CompCount;
    R828_SectType CorTemp;

    CompCount = 0;

    for (CompCount = 3; CompCount > 0; CompCount--) {
      if (CorArry[0].Value > CorArry[CompCount - 1].Value) // compare IMC
                                  // result
                                  // [0][1][2],
                                  // find min
                                  // value
      {
        CorTemp = CorArry[0];
        CorArry[0] = CorArry[CompCount - 1];
        CorArry[CompCount - 1] = CorTemp;
      }
    }

    return true;
  }

  // -------------------------------------------------------------------------------------//
  // Purpose: if (Gain<9 or Phase<9), Gain+1 or Phase+1 and compare with min
  // value
  // new < min => update to min and continue
  // new > min => Exit
  // input: StepArry: three IMR data array
  // Pace: gain or phase register
  // output: TRUE or FALSE
  // -------------------------------------------------------------------------------------//
  boolean R828_CompreStep(int pTuner, R828_SectType[] StepArry, byte Pace) {
    // byte StepCount = 0;
    R828_SectType StepTemp = new R828_SectType();

    // min value already saved in StepArry[0]
    StepTemp.Phase_Y = StepArry[0].Phase_Y;
    StepTemp.Gain_X = StepArry[0].Gain_X;

    while (((StepTemp.Gain_X & 0x1F) < IMR_TRIAL)
        && ((StepTemp.Phase_Y & 0x1F) < IMR_TRIAL)) // 5->10
    {
      if (Pace == 0x08)
        StepTemp.Gain_X++;
      else
        StepTemp.Phase_Y++;

      R828_I2C.RegAddr = 0x08;
      R828_I2C.Data = (byte) StepTemp.Gain_X;
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      R828_I2C.RegAddr = 0x09;
      R828_I2C.Data = (byte) StepTemp.Phase_Y;
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;
      char[] value = new char[1];
      if (R828_Muti_Read(pTuner, (byte) 0x01, /* StepTemp.Value */value) != true)
        return false;

      StepTemp.Value = value[0];

      if (StepTemp.Value <= StepArry[0].Value) {
        StepArry[0].Gain_X = StepTemp.Gain_X;
        StepArry[0].Phase_Y = StepTemp.Phase_Y;
        StepArry[0].Value = StepTemp.Value;
      } else {
        break;
      }

    } // end of while()

    return true;
  }

  // -----------------------------------------------------------------------------------/
  // Purpose: read multiple IMC results for stability
  // input: IMR_Reg: IMC result address
  // IMR_Result_Data: result
  // output: TRUE or FALSE
  // -----------------------------------------------------------------------------------/
  boolean R828_Muti_Read(int pTuner, byte IMR_Reg, char[] IMR_Result_Data) // jason
                                        // modified
  {
    byte ReadCount;
    char ReadAmount;
    byte ReadMax;
    byte ReadMin;
    byte ReadData;

    ReadCount = 0;
    ReadAmount = 0;
    ReadMax = 0;
    ReadMin = (byte) 255;
    ReadData = 0;

    R828_Delay_MS(pTuner, 5);

    for (ReadCount = 0; ReadCount < 6; ReadCount++) {
      R828_I2C_Len.RegAddr = 0x00;
      R828_I2C_Len.Len = (byte) (IMR_Reg + 1); // IMR_Reg = 0x01
      if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
        return false;

      ReadData = R828_I2C_Len.Data[1];

      ReadAmount = (char) (ReadAmount + ReadData);

      if (ReadData < ReadMin)
        ReadMin = ReadData;

      if (ReadData > ReadMax)
        ReadMax = ReadData;
    }
    IMR_Result_Data[0] = (char) (ReadAmount - ReadMax - ReadMin);

    return true;
  }

  boolean R828_Section(int pTuner, R828_SectType[] IQ_Pont) {
    R828_SectType[] Compare_IQ = new R828_SectType[3];
    R828_SectType[] Compare_Bet = new R828_SectType[3];

    // Try X-1 column and save min result to Compare_Bet[0]
    if ((IQ_Pont[0].Gain_X & 0x1F) == 0x00) {
      /*
       * if((IQ_Pont->Gain_X & 0xE0) == 0x40) //bug => only compare b[5],
       * Compare_IQ[0].Gain_X = 0x61; // Gain=1, I-path //Jason else
       * Compare_IQ[0].Gain_X = 0x41; // Gain=1, Q-path
       */
      Compare_IQ[0].Gain_X = ((IQ_Pont[0].Gain_X) & 0xDF) + 1; // Q-path,
                                    // Gain=1
    } else
      Compare_IQ[0].Gain_X = IQ_Pont[0].Gain_X - 1; // left point
    Compare_IQ[0].Phase_Y = IQ_Pont[0].Phase_Y;

    if (R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y,
        0x08, Compare_IQ) != true) // y-direction
      return false;

    if (R828_CompreCor(Compare_IQ) != true)
      return false;

    Compare_Bet[0].Gain_X = Compare_IQ[0].Gain_X;
    Compare_Bet[0].Phase_Y = Compare_IQ[0].Phase_Y;
    Compare_Bet[0].Value = Compare_IQ[0].Value;

    // Try X column and save min result to Compare_Bet[1]
    Compare_IQ[0].Gain_X = IQ_Pont[0].Gain_X;
    Compare_IQ[0].Phase_Y = IQ_Pont[0].Phase_Y;

    if (R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y,
        0x08, Compare_IQ) != true)
      return false;

    if (R828_CompreCor(Compare_IQ) != true)
      return false;

    Compare_Bet[1].Gain_X = Compare_IQ[0].Gain_X;
    Compare_Bet[1].Phase_Y = Compare_IQ[0].Phase_Y;
    Compare_Bet[1].Value = Compare_IQ[0].Value;

    // Try X+1 column and save min result to Compare_Bet[2]
    if ((IQ_Pont[0].Gain_X & 0x1F) == 0x00)
      Compare_IQ[0].Gain_X = ((IQ_Pont[0].Gain_X) | 0x20) + 1; // I-path,
                                    // Gain=1
    else
      Compare_IQ[0].Gain_X = IQ_Pont[0].Gain_X + 1;
    Compare_IQ[0].Phase_Y = IQ_Pont[0].Phase_Y;

    if (R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y,
        0x08, Compare_IQ) != true)
      return false;

    if (R828_CompreCor(Compare_IQ) != true)
      return false;

    Compare_Bet[2].Gain_X = Compare_IQ[0].Gain_X;
    Compare_Bet[2].Phase_Y = Compare_IQ[0].Phase_Y;
    Compare_Bet[2].Value = Compare_IQ[0].Value;

    if (R828_CompreCor(Compare_Bet) != true)
      return false;

    IQ_Pont[0] = Compare_Bet[0];

    return true;
  }

  boolean R828_IMR_Cross(int pTuner, R828_SectType[] IQ_Pont, byte[] X_Direct) {

    R828_SectType[] Compare_Cross = new R828_SectType[5]; // (0,0)(0,Q-1)(0,I-1)(Q-1,0)(I-1,0)
    R828_SectType Compare_Temp = new R828_SectType();
    byte CrossCount;
    byte Reg08;
    byte Reg09;

    CrossCount = 0;
    Reg08 = (byte) (R828_iniArry[3] & 0xC0);
    Reg09 = (byte) (R828_iniArry[4] & 0xC0);

    // memset(&Compare_Temp,0, sizeof(R828_SectType));
    Compare_Temp.Gain_X = 0;
    Compare_Temp.Phase_Y = 0;
    Compare_Temp.Value = 0;

    Compare_Temp.Value = 255;

    for (CrossCount = 0; CrossCount < 5; CrossCount++) {

      if (CrossCount == 0) {
        Compare_Cross[CrossCount].Gain_X = Reg08;
        Compare_Cross[CrossCount].Phase_Y = Reg09;
      } else if (CrossCount == 1) {
        Compare_Cross[CrossCount].Gain_X = Reg08; // 0
        Compare_Cross[CrossCount].Phase_Y = Reg09 + 1; // Q-1
      } else if (CrossCount == 2) {
        Compare_Cross[CrossCount].Gain_X = Reg08; // 0
        Compare_Cross[CrossCount].Phase_Y = (Reg09 | 0x20) + 1; // I-1
      } else if (CrossCount == 3) {
        Compare_Cross[CrossCount].Gain_X = Reg08 + 1; // Q-1
        Compare_Cross[CrossCount].Phase_Y = Reg09;
      } else {
        Compare_Cross[CrossCount].Gain_X = (Reg08 | 0x20) + 1; // I-1
        Compare_Cross[CrossCount].Phase_Y = Reg09;
      }

      R828_I2C.RegAddr = 0x08;
      R828_I2C.Data = (byte) Compare_Cross[CrossCount].Gain_X;
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      R828_I2C.RegAddr = 0x09;
      R828_I2C.Data = (byte) Compare_Cross[CrossCount].Phase_Y;
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      char[] value = new char[1];

      if (R828_Muti_Read(pTuner, (byte) 0x01, /*
                           * Compare_Cross[CrossCount].
                           * Value
                           */value) != true)
        return false;

      Compare_Cross[CrossCount].Value = value[0];

      if (Compare_Cross[CrossCount].Value < Compare_Temp.Value) {
        Compare_Temp.Value = Compare_Cross[CrossCount].Value;
        Compare_Temp.Gain_X = Compare_Cross[CrossCount].Gain_X;
        Compare_Temp.Phase_Y = Compare_Cross[CrossCount].Phase_Y;
      }
    } // end for loop

    if ((Compare_Temp.Phase_Y & 0x1F) == 1) // y-direction
    {
      X_Direct[0] = (byte) 0;
      IQ_Pont[0].Gain_X = Compare_Cross[0].Gain_X;
      IQ_Pont[0].Phase_Y = Compare_Cross[0].Phase_Y;
      IQ_Pont[0].Value = Compare_Cross[0].Value;

      IQ_Pont[1].Gain_X = Compare_Cross[1].Gain_X;
      IQ_Pont[1].Phase_Y = Compare_Cross[1].Phase_Y;
      IQ_Pont[1].Value = Compare_Cross[1].Value;

      IQ_Pont[2].Gain_X = Compare_Cross[2].Gain_X;
      IQ_Pont[2].Phase_Y = Compare_Cross[2].Phase_Y;
      IQ_Pont[2].Value = Compare_Cross[2].Value;
    } else // (0,0) or x-direction
    {
      X_Direct[0] = (byte) 1;
      IQ_Pont[0].Gain_X = Compare_Cross[0].Gain_X;
      IQ_Pont[0].Phase_Y = Compare_Cross[0].Phase_Y;
      IQ_Pont[0].Value = Compare_Cross[0].Value;

      IQ_Pont[1].Gain_X = Compare_Cross[3].Gain_X;
      IQ_Pont[1].Phase_Y = Compare_Cross[3].Phase_Y;
      IQ_Pont[1].Value = Compare_Cross[3].Value;

      IQ_Pont[2].Gain_X = Compare_Cross[4].Gain_X;
      IQ_Pont[2].Phase_Y = Compare_Cross[4].Phase_Y;
      IQ_Pont[2].Value = Compare_Cross[4].Value;
    }
    return true;
  }

  // ----------------------------------------------------------------------------------------//
  // purpose: search surrounding points from previous point
  // try (x-1), (x), (x+1) columns, and find min IMR result point
  // input: IQ_Pont: previous point data(IMR Gain, Phase, ADC Result, RefRreq)
  // will be updated to final best point
  // output: TRUE or FALSE
  // ----------------------------------------------------------------------------------------//
  boolean R828_F_IMR(int pTuner, R828_SectType[] IQ_Pont) {
    R828_SectType[] Compare_IQ = new R828_SectType[3];
    R828_SectType[] Compare_Bet = new R828_SectType[3];
    byte VGA_Count;
    char VGA_Read;

    VGA_Count = 0;
    VGA_Read = 0;

    // VGA
    for (VGA_Count = 12; VGA_Count < 16; VGA_Count++) {
      R828_I2C.RegAddr = 0x0C;
      R828_I2C.Data = (byte) ((R828_Arry[7] & 0xF0) + VGA_Count);
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      R828_Delay_MS(pTuner, 10);
      char[] value = new char[1];
      if (R828_Muti_Read(pTuner, (byte) 0x01, /* VGA_Read */value) != true)
        return false;
      VGA_Read = value[0];
      if (VGA_Read > 40 * 4)
        break;
    }

    // Try X-1 column and save min result to Compare_Bet[0]
    if ((IQ_Pont[0].Gain_X & 0x1F) == 0x00) {
      Compare_IQ[0].Gain_X = ((IQ_Pont[0].Gain_X) & 0xDF) + 1; // Q-path,
                                    // Gain=1
    } else
      Compare_IQ[0].Gain_X = IQ_Pont[0].Gain_X - 1; // left point
    Compare_IQ[0].Phase_Y = IQ_Pont[0].Phase_Y;

    if (R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y,
        0x08, Compare_IQ) != true) // y-direction
      return false;

    if (R828_CompreCor(Compare_IQ) != true)
      return false;

    Compare_Bet[0].Gain_X = Compare_IQ[0].Gain_X;
    Compare_Bet[0].Phase_Y = Compare_IQ[0].Phase_Y;
    Compare_Bet[0].Value = Compare_IQ[0].Value;

    // Try X column and save min result to Compare_Bet[1]
    Compare_IQ[0].Gain_X = IQ_Pont[0].Gain_X;
    Compare_IQ[0].Phase_Y = IQ_Pont[0].Phase_Y;

    if (R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y,
        0x08, Compare_IQ) != true)
      return false;

    if (R828_CompreCor(Compare_IQ) != true)
      return false;

    Compare_Bet[1].Gain_X = Compare_IQ[0].Gain_X;
    Compare_Bet[1].Phase_Y = Compare_IQ[0].Phase_Y;
    Compare_Bet[1].Value = Compare_IQ[0].Value;

    // Try X+1 column and save min result to Compare_Bet[2]
    if ((IQ_Pont[0].Gain_X & 0x1F) == 0x00)
      Compare_IQ[0].Gain_X = ((IQ_Pont[0].Gain_X) | 0x20) + 1; // I-path,
                                    // Gain=1
    else
      Compare_IQ[0].Gain_X = IQ_Pont[0].Gain_X + 1;
    Compare_IQ[0].Phase_Y = IQ_Pont[0].Phase_Y;

    if (R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y,
        0x08, Compare_IQ) != true)
      return false;

    if (R828_CompreCor(Compare_IQ) != true)
      return false;

    Compare_Bet[2].Gain_X = Compare_IQ[0].Gain_X;
    Compare_Bet[2].Phase_Y = Compare_IQ[0].Phase_Y;
    Compare_Bet[2].Value = Compare_IQ[0].Value;

    if (R828_CompreCor(Compare_Bet) != true)
      return false;

    IQ_Pont[0] = Compare_Bet[0];

    return true;
  }

  boolean R828_GPIO(int pTuner, /* R828_GPIO_Type */boolean R828_GPIO_Conrl) {
    if (R828_GPIO_Conrl == /* HI_SIG */true)
      R828_Arry[10] |= 0x01;
    else
      R828_Arry[10] &= 0xFE;

    R828_I2C.RegAddr = 0x0F;
    R828_I2C.Data = R828_Arry[10];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    return true;
  }

  boolean R828_SetStandard(int pTuner, /* R828_Standard_Type */int RT_Standard) {

    // Used Normal Arry to Modify
    byte ArrayNum;

    ArrayNum = 27;
    for (ArrayNum = 0; ArrayNum < 27; ArrayNum++) {
      R828_Arry[ArrayNum] = R828_iniArry[ArrayNum];
    }

    // Record Init Flag & Xtal_check Result
    if (R828_IMR_done_flag == true)
      R828_Arry[7] = (byte) ((R828_Arry[7] & 0xF0) | 0x01 | (Xtal_cap_sel << 1));
    else
      R828_Arry[7] = (byte) ((R828_Arry[7] & 0xF0) | 0x00);

    R828_I2C.RegAddr = 0x0C;
    R828_I2C.Data = R828_Arry[7];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Record version
    R828_I2C.RegAddr = 0x13;
    R828_Arry[14] = (byte) ((R828_Arry[14] & 0xC0) | VER_NUM);
    R828_I2C.Data = R828_Arry[14];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // for LT Gain test
    if (RT_Standard > SECAM_L1) {
      R828_I2C.RegAddr = 0x1D; // [5:3] LNA TOP
      R828_I2C.Data = (byte) ((R828_Arry[24] & 0xC7) | 0x00);
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      // R828_Delay_MS(1);
    }

    // Look Up System Dependent Table
    Sys_Info1 = R828_Sys_Sel(RT_Standard);
    R828_IF_khz = Sys_Info1.IF_KHz;
    R828_CAL_LO_khz = Sys_Info1.FILT_CAL_LO;

    // Filter Calibration
    if (R828_Fil_Cal_flag[RT_Standard] == 0) {
      // do filter calibration
      if (R828_Filt_Cal(pTuner, Sys_Info1.FILT_CAL_LO, Sys_Info1.BW) != true)
        return false;

      // read and set filter code
      R828_I2C_Len.RegAddr = 0x00;
      R828_I2C_Len.Len = 5;
      if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
        return false;

      R828_Fil_Cal_code[RT_Standard] = (byte) (R828_I2C_Len.Data[4] & 0x0F);

      // Filter Cali. Protection
      if (R828_Fil_Cal_code[RT_Standard] == 0
          || R828_Fil_Cal_code[RT_Standard] == 15) {
        if (R828_Filt_Cal(pTuner, Sys_Info1.FILT_CAL_LO, Sys_Info1.BW) != true)
          return false;

        R828_I2C_Len.RegAddr = 0x00;
        R828_I2C_Len.Len = 5;
        if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
          return false;

        R828_Fil_Cal_code[RT_Standard] = (byte) (R828_I2C_Len.Data[4] & 0x0F);

        if (R828_Fil_Cal_code[RT_Standard] == 15) // narrowest
          R828_Fil_Cal_code[RT_Standard] = 0;

      }
      R828_Fil_Cal_flag[RT_Standard] = 1;
    }

    // Set Filter Q
    R828_Arry[5] = (byte) ((R828_Arry[5] & 0xE0) | Sys_Info1.FILT_Q | R828_Fil_Cal_code[RT_Standard]);
    R828_I2C.RegAddr = 0x0A;
    R828_I2C.Data = R828_Arry[5];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Set BW, Filter_gain, & HP corner
    R828_Arry[6] = (byte) ((R828_Arry[6] & 0x10) | Sys_Info1.HP_COR);
    R828_I2C.RegAddr = 0x0B;
    R828_I2C.Data = R828_Arry[6];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Set Img_R
    R828_Arry[2] = (byte) ((R828_Arry[2] & 0x7F) | Sys_Info1.IMG_R);
    R828_I2C.RegAddr = 0x07;
    R828_I2C.Data = R828_Arry[2];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Set filt_3dB, V6MHz
    R828_Arry[1] = (byte) ((R828_Arry[1] & 0xCF) | Sys_Info1.FILT_GAIN);
    R828_I2C.RegAddr = 0x06;
    R828_I2C.Data = R828_Arry[1];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // channel filter extension
    R828_Arry[25] = (byte) ((R828_Arry[25] & 0x9F) | Sys_Info1.EXT_ENABLE);
    R828_I2C.RegAddr = 0x1E;
    R828_I2C.Data = R828_Arry[25];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Loop through
    R828_Arry[0] = (byte) ((R828_Arry[0] & 0x7F) | Sys_Info1.LOOP_THROUGH1);
    R828_I2C.RegAddr = 0x05;
    R828_I2C.Data = R828_Arry[0];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Loop through attenuation
    R828_Arry[26] = (byte) ((R828_Arry[26] & 0x7F) | Sys_Info1.LT_ATT);
    R828_I2C.RegAddr = 0x1F;
    R828_I2C.Data = R828_Arry[26];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // filter extention widest
    R828_Arry[10] = (byte) ((R828_Arry[10] & 0x7F) | Sys_Info1.FLT_EXT_WIDEST);
    R828_I2C.RegAddr = 0x0F;
    R828_I2C.Data = R828_Arry[10];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // RF poly filter current
    R828_Arry[20] = (byte) ((R828_Arry[20] & 0x9F) | Sys_Info1.POLYFIL_CUR);
    R828_I2C.RegAddr = 0x19;
    R828_I2C.Data = R828_Arry[20];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    return true;
  }

  boolean R828_Filt_Cal(int pTuner, int Cal_Freq, int R828_BW) {
    // set in Sys_sel()
    /*
     * if(R828_BW == BW_8M) { //set filt_cap = no cap R828_I2C.RegAddr =
     * 0x0B; //reg11 R828_Arry[6] &= 0x9F; //filt_cap = no cap R828_I2C.Data
     * = R828_Arry[6]; } else if(R828_BW == BW_7M) { //set filt_cap = +1 cap
     * R828_I2C.RegAddr = 0x0B; //reg11 R828_Arry[6] &= 0x9F; //filt_cap =
     * no cap R828_Arry[6] |= 0x20; //filt_cap = +1 cap R828_I2C.Data =
     * R828_Arry[6]; } else if(R828_BW == BW_6M) { //set filt_cap = +2 cap
     * R828_I2C.RegAddr = 0x0B; //reg11 R828_Arry[6] &= 0x9F; //filt_cap =
     * no cap R828_Arry[6] |= 0x60; //filt_cap = +2 cap R828_I2C.Data =
     * R828_Arry[6]; }
     * 
     * 
     * if(I2C_Write(pTuner, R828_I2C) != true) return false;
     */

    // Set filt_cap
    R828_I2C.RegAddr = 0x0B;
    R828_Arry[6] = (byte) ((R828_Arry[6] & 0x9F) | (Sys_Info1.HP_COR & 0x60));
    R828_I2C.Data = R828_Arry[6];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // set cali clk =on
    R828_I2C.RegAddr = 0x0F; // reg15
    R828_Arry[10] |= 0x04; // calibration clk=on
    R828_I2C.Data = R828_Arry[10];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // X'tal cap 0pF for PLL
    R828_I2C.RegAddr = 0x10;
    R828_Arry[11] = (byte) ((R828_Arry[11] & 0xFC) | 0x00);
    R828_I2C.Data = R828_Arry[11];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Set PLL Freq = Filter Cali Freq
    if (R828_PLL(pTuner, Cal_Freq * 1000, STD_SIZE) != true)
      return false;

    // Start Trigger
    R828_I2C.RegAddr = 0x0B; // reg11
    R828_Arry[6] |= 0x10; // vstart=1
    R828_I2C.Data = R828_Arry[6];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // delay 0.5ms
    R828_Delay_MS(pTuner, 1);

    // Stop Trigger
    R828_I2C.RegAddr = 0x0B;
    R828_Arry[6] &= 0xEF; // vstart=0
    R828_I2C.Data = R828_Arry[6];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // set cali clk =off
    R828_I2C.RegAddr = 0x0F; // reg15
    R828_Arry[10] &= 0xFB; // calibration clk=off
    R828_I2C.Data = R828_Arry[10];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    return true;

  }

  boolean R828_SetFrequency(int pTuner, R828_Set_Info R828_INFO, /* R828_SetFreq_Type */
      boolean R828_SetFreqMode) {
    int LO_Hz;
    /*
     * #if 0 // Check Input Frequency Range if((R828_INFO.RF_KHz<40000) ||
     * (R828_INFO.RF_KHz>900000)) { return false; } #endif
     */

    Sys_Info1 = R828_Sys_Sel(DVB_T_6M); // 8=DVB_T_6M

    if (R828_INFO.R828_Standard == SECAM_L1)
      LO_Hz = (int) (R828_INFO.RF_Hz - (Sys_Info1.IF_KHz * 1000));
    else
      LO_Hz = (int) (R828_INFO.RF_Hz + (Sys_Info1.IF_KHz * 1000));

    // Set MUX dependent var. Must do before PLL( )
    if (R828_MUX(pTuner, LO_Hz / 1000) != true)
      return false;

    // Set PLL
    if (R828_PLL(pTuner, LO_Hz, R828_INFO.R828_Standard) != true)
      return false;

    R828_IMR_point_num = Freq_Info1.IMR_MEM;

    // Set TOP,VTH,VTL
    SysFreq_Info1 = R828_SysFreq_Sel(R828_INFO.R828_Standard,
        (int) R828_INFO.RF_KHz);

    // write DectBW, pre_dect_TOP
    R828_Arry[24] = (byte) ((R828_Arry[24] & 0x38) | (SysFreq_Info1.LNA_TOP & 0xC7));
    R828_I2C.RegAddr = 0x1D;
    R828_I2C.Data = R828_Arry[24];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // write MIXER TOP, TOP+-1
    R828_Arry[23] = (byte) ((R828_Arry[23] & 0x07) | (SysFreq_Info1.MIXER_TOP & 0xF8));
    R828_I2C.RegAddr = 0x1C;
    R828_I2C.Data = R828_Arry[23];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // write LNA VTHL
    R828_Arry[8] = (byte) ((R828_Arry[8] & 0x00) | SysFreq_Info1.LNA_VTH_L);
    R828_I2C.RegAddr = 0x0D;
    R828_I2C.Data = R828_Arry[8];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // write MIXER VTHL
    R828_Arry[9] = (byte) ((R828_Arry[9] & 0x00) | SysFreq_Info1.MIXER_VTH_L);
    R828_I2C.RegAddr = 0x0E;
    R828_I2C.Data = R828_Arry[9];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Cable-1/Air in
    R828_I2C.RegAddr = 0x05;
    R828_Arry[0] &= 0x9F;
    R828_Arry[0] |= SysFreq_Info1.AIR_CABLE1_IN;
    R828_I2C.Data = R828_Arry[0];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Cable-2 in
    R828_I2C.RegAddr = 0x06;
    R828_Arry[1] &= 0xF7;
    R828_Arry[1] |= SysFreq_Info1.CABLE2_IN;
    R828_I2C.Data = R828_Arry[1];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // CP current
    R828_I2C.RegAddr = 0x11;
    R828_Arry[12] &= 0xC7;
    R828_Arry[12] |= SysFreq_Info1.CP_CUR;
    R828_I2C.Data = R828_Arry[12];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // div buffer current
    R828_I2C.RegAddr = 0x17;
    R828_Arry[18] &= 0xCF;
    R828_Arry[18] |= SysFreq_Info1.DIV_BUF_CUR;
    R828_I2C.Data = R828_Arry[18];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Set channel filter current
    R828_I2C.RegAddr = 0x0A;
    R828_Arry[5] = (byte) ((R828_Arry[5] & 0x9F) | SysFreq_Info1.FILTER_CUR);
    R828_I2C.Data = R828_Arry[5];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Air-In only for Astrometa
    R828_Arry[0] = (byte) ((R828_Arry[0] & 0x9F) | 0x00);
    R828_Arry[1] = (byte) ((R828_Arry[1] & 0xF7) | 0x00);

    R828_I2C.RegAddr = 0x05;
    R828_I2C.Data = R828_Arry[0];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    R828_I2C.RegAddr = 0x06;
    R828_I2C.Data = R828_Arry[1];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    // Set LNA
    if (R828_INFO.R828_Standard > SECAM_L1) {

      if (R828_SetFreqMode == FAST_MODE) // FAST mode
      {
        // R828_Arry[24] = (R828_Arry[24] & 0xC7) | 0x20; //LNA TOP:4
        R828_Arry[24] = (byte) ((R828_Arry[24] & 0xC7) | 0x00); // LNA
                                    // TOP:lowest
        R828_I2C.RegAddr = 0x1D;
        R828_I2C.Data = R828_Arry[24];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        R828_Arry[23] = (byte) (R828_Arry[23] & 0xFB); // 0: normal mode
        R828_I2C.RegAddr = 0x1C;
        R828_I2C.Data = R828_Arry[23];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        R828_Arry[1] = (byte) (R828_Arry[1] & 0xBF); // 0: PRE_DECT off
        R828_I2C.RegAddr = 0x06;
        R828_I2C.Data = R828_Arry[1];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        // agc clk 250hz
        R828_Arry[21] = (byte) ((R828_Arry[21] & 0xCF) | 0x30);
        R828_I2C.RegAddr = 0x1A;
        R828_I2C.Data = R828_Arry[21];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;
      } else // NORMAL mode
      {

        R828_Arry[24] = (byte) ((R828_Arry[24] & 0xC7) | 0x00); // LNA
                                    // TOP:lowest
        R828_I2C.RegAddr = 0x1D;
        R828_I2C.Data = R828_Arry[24];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        R828_Arry[23] = (byte) (R828_Arry[23] & 0xFB); // 0: normal mode
        R828_I2C.RegAddr = 0x1C;
        R828_I2C.Data = R828_Arry[23];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        R828_Arry[1] = (byte) (R828_Arry[1] & 0xBF); // 0: PRE_DECT off
        R828_I2C.RegAddr = 0x06;
        R828_I2C.Data = R828_Arry[1];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        // agc clk 250hz
        R828_Arry[21] = (byte) ((R828_Arry[21] & 0xCF) | 0x30); // 250hz
        R828_I2C.RegAddr = 0x1A;
        R828_I2C.Data = R828_Arry[21];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        R828_Delay_MS(pTuner, 250);

        // PRE_DECT on
        /*
         * R828_Arry[1] = (R828_Arry[1] & 0xBF) |
         * SysFreq_Info1.PRE_DECT; R828_I2C.RegAddr = 0x06;
         * R828_I2C.Data = R828_Arry[1]; if(I2C_Write(pTuner, R828_I2C)
         * != true) return false;
         */
        // write LNA TOP = 3
        // R828_Arry[24] = (R828_Arry[24] & 0xC7) |
        // (SysFreq_Info1.LNA_TOP & 0x38);
        R828_Arry[24] = (byte) ((R828_Arry[24] & 0xC7) | 0x18); // TOP=3
        R828_I2C.RegAddr = 0x1D;
        R828_I2C.Data = R828_Arry[24];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        // write disbytege mode
        R828_Arry[23] = (byte) ((R828_Arry[23] & 0xFB) | (SysFreq_Info1.MIXER_TOP & 0x04));
        R828_I2C.RegAddr = 0x1C;
        R828_I2C.Data = R828_Arry[23];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        // LNA disbytege current
        R828_Arry[25] = (byte) ((R828_Arry[25] & 0xE0) | SysFreq_Info1.LNA_DISbyteGE);
        R828_I2C.RegAddr = 0x1E;
        R828_I2C.Data = R828_Arry[25];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        // agc clk 60hz
        R828_Arry[21] = (byte) ((R828_Arry[21] & 0xCF) | 0x20);
        R828_I2C.RegAddr = 0x1A;
        R828_I2C.Data = R828_Arry[21];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;
      }
    } else {
      if (R828_SetFreqMode == NORMAL_MODE
          || R828_SetFreqMode == FAST_MODE) {
        /*
         * // PRE_DECT on R828_Arry[1] = (R828_Arry[1] & 0xBF) |
         * SysFreq_Info1.PRE_DECT; R828_I2C.RegAddr = 0x06;
         * R828_I2C.Data = R828_Arry[1]; if(I2C_Write(pTuner, R828_I2C)
         * != true) return false;
         */
        // PRE_DECT off
        R828_Arry[1] = (byte) (R828_Arry[1] & 0xBF); // 0: PRE_DECT off
        R828_I2C.RegAddr = 0x06;
        R828_I2C.Data = R828_Arry[1];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        // write LNA TOP
        R828_Arry[24] = (byte) ((R828_Arry[24] & 0xC7) | (SysFreq_Info1.LNA_TOP & 0x38));
        R828_I2C.RegAddr = 0x1D;
        R828_I2C.Data = R828_Arry[24];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        // write disbytege mode
        R828_Arry[23] = (byte) ((R828_Arry[23] & 0xFB) | (SysFreq_Info1.MIXER_TOP & 0x04));
        R828_I2C.RegAddr = 0x1C;
        R828_I2C.Data = R828_Arry[23];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        // LNA disbytege current
        R828_Arry[25] = (byte) ((R828_Arry[25] & 0xE0) | SysFreq_Info1.LNA_DISbyteGE);
        R828_I2C.RegAddr = 0x1E;
        R828_I2C.Data = R828_Arry[25];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        // agc clk 1Khz, external det1 cap 1u
        R828_Arry[21] = (byte) ((R828_Arry[21] & 0xCF) | 0x00);
        R828_I2C.RegAddr = 0x1A;
        R828_I2C.Data = R828_Arry[21];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;

        R828_Arry[11] = (byte) ((R828_Arry[11] & 0xFB) | 0x00);
        R828_I2C.RegAddr = 0x10;
        R828_I2C.Data = R828_Arry[11];
        if (I2C_Write(pTuner, R828_I2C) != true)
          return false;
      }
    }

    return true;

  }

  boolean R828_Standby(int pTuner, int R828_LoopSwitch) {
    if (R828_LoopSwitch == LOOP_THROUGH) {
      R828_I2C.RegAddr = 0x06;
      R828_I2C.Data = (byte) 0xB1;
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;
      R828_I2C.RegAddr = 0x05;
      R828_I2C.Data = 0x03;

      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;
    } else {
      R828_I2C.RegAddr = 0x05;
      R828_I2C.Data = (byte) 0xA3;
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      R828_I2C.RegAddr = 0x06;
      R828_I2C.Data = (byte) 0xB1;
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;
    }

    R828_I2C.RegAddr = 0x07;
    R828_I2C.Data = 0x3A;
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    R828_I2C.RegAddr = 0x08;
    R828_I2C.Data = 0x40;
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    R828_I2C.RegAddr = 0x09;
    R828_I2C.Data = (byte) 0xC0; // polyfilter off
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    R828_I2C.RegAddr = 0x0A;
    R828_I2C.Data = 0x36;
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    R828_I2C.RegAddr = 0x0C;
    R828_I2C.Data = 0x35;
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    R828_I2C.RegAddr = 0x0F;
    R828_I2C.Data = 0x68; /* was 0x78, which turns off CLK_Out */
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    R828_I2C.RegAddr = 0x11;
    R828_I2C.Data = 0x03;
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    R828_I2C.RegAddr = 0x17;
    R828_I2C.Data = (byte) 0xF4;
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    R828_I2C.RegAddr = 0x19;
    R828_I2C.Data = 0x0C;
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    return true;
  }

  boolean R828_GetRfGain(int pTuner, R828_RF_Gain_Info[] pR828_rf_gain) {

    R828_I2C_Len.RegAddr = 0x00;
    R828_I2C_Len.Len = 4;
    if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
      return false;

    pR828_rf_gain[0].RF_gain1 = (byte) (R828_I2C_Len.Data[3] & 0x0F);
    pR828_rf_gain[0].RF_gain2 = (byte) ((R828_I2C_Len.Data[3] & 0xF0) >> 4);
    pR828_rf_gain[0].RF_gain_comb = (byte) (pR828_rf_gain[0].RF_gain1 * 2 + pR828_rf_gain[0].RF_gain2);

    return true;
  }

  /*
   * measured with a Racal 6103E GSM test set at 928 MHz with -60 dBm input
   * power, for raw results see:
   * http://steve-m.de/projects/rtl-sdr/gain_measurement/r820t/
   */

  static final int VGA_BASE_GAIN = -47;
  static int[] r820t_vga_gain_steps = { 0, 26, 26, 30, 42, 35, 24, 13, 14,
      32, 36, 34, 35, 37, 35, 36 };

  static int[] r820t_lna_gain_steps = { 0, 9, 13, 40, 38, 13, 31, 22, 26, 31,
      26, 14, 19, 5, 35, 13 };

  static int[] r820t_mixer_gain_steps = { 0, 5, 10, 10, 19, 9, 10, 25, 17,
      10, 8, 16, 13, 6, 3, -8 };

  boolean R828_SetRfGain(int pTuner, int gain) {
    int i, total_gain = 0;
    byte mix_index = 0, lna_index = 0;

    for (i = 0; i < 15; i++) {
      if (total_gain >= gain)
        break;

      total_gain += r820t_lna_gain_steps[++lna_index];

      if (total_gain >= gain)
        break;

      total_gain += r820t_mixer_gain_steps[++mix_index];
    }

    /* set LNA gain */
    R828_I2C.RegAddr = 0x05;
    R828_Arry[0] = (byte) ((R828_Arry[0] & 0xF0) | lna_index);
    R828_I2C.Data = R828_Arry[0];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    /* set Mixer gain */
    R828_I2C.RegAddr = 0x07;
    R828_Arry[2] = (byte) ((R828_Arry[2] & 0xF0) | mix_index);
    R828_I2C.Data = R828_Arry[2];
    if (I2C_Write(pTuner, R828_I2C) != true)
      return false;

    return true;
  }

  boolean R828_RfGainMode(int pTuner, boolean manual) {
    byte MixerGain;
    byte LnaGain;

    MixerGain = 0;
    LnaGain = 0;

    if (manual) {
      // LNA auto off
      R828_I2C.RegAddr = 0x05;
      R828_Arry[0] = (byte) (R828_Arry[0] | 0x10);
      R828_I2C.Data = R828_Arry[0];
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      // Mixer auto off
      R828_I2C.RegAddr = 0x07;
      R828_Arry[2] = (byte) (R828_Arry[2] & 0xEF);
      R828_I2C.Data = R828_Arry[2];
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      R828_I2C_Len.RegAddr = 0x00;
      R828_I2C_Len.Len = 4;
      if (I2C_Read_Len(pTuner, R828_I2C_Len) != true)
        return false;

      /* set fixed VGA gain for now (16.3 dB) */
      R828_I2C.RegAddr = 0x0C;
      R828_Arry[7] = (byte) ((R828_Arry[7] & 0x60) | 0x08);
      R828_I2C.Data = R828_Arry[7];
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      Log.d(TAG, "set manual gain mode");
    } else {
      // LNA
      R828_I2C.RegAddr = 0x05;
      R828_Arry[0] = (byte) (R828_Arry[0] & 0xEF);
      R828_I2C.Data = R828_Arry[0];
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      // Mixer
      R828_I2C.RegAddr = 0x07;
      R828_Arry[2] = (byte) (R828_Arry[2] | 0x10);
      R828_I2C.Data = R828_Arry[2];
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;

      /* set fixed VGA gain for now (26.5 dB) */
      R828_I2C.RegAddr = 0x0C;
      R828_Arry[7] = (byte) ((R828_Arry[7] & 0x60) | 0x0B);
      R828_I2C.Data = R828_Arry[7];
      if (I2C_Write(pTuner, R828_I2C) != true)
        return false;
      Log.d(TAG, "set auto gain mode");
    }

    return true;
  }

}




Java Source Code List

com.hoho.android.usbserial.driver.CdcAcmSerialDriver.java
com.hoho.android.usbserial.driver.CommonUsbSerialPort.java
com.hoho.android.usbserial.driver.Cp21xxSerialDriver.java
com.hoho.android.usbserial.driver.FtdiSerialDriver.java
com.hoho.android.usbserial.driver.ProbeTable.java
com.hoho.android.usbserial.driver.ProlificSerialDriver.java
com.hoho.android.usbserial.driver.UsbId.java
com.hoho.android.usbserial.driver.UsbSerialDriver.java
com.hoho.android.usbserial.driver.UsbSerialPort.java
com.hoho.android.usbserial.driver.UsbSerialProber.java
com.hoho.android.usbserial.driver.UsbSerialRuntimeException.java
com.hoho.android.usbserial.util.HexDump.java
com.hoho.android.usbserial.util.SerialInputOutputManager.java
com.rtlsdr.android.SdrSerialDriverOrig.java
com.rtlsdr.android.SdrSerialDriver.java
com.rtlsdr.android.SdrUsbId.java
com.rtlsdr.android.tuners.E4K.java
com.rtlsdr.android.tuners.FC0012.java
com.rtlsdr.android.tuners.FC0013.java
com.rtlsdr.android.tuners.FC2580.java
com.rtlsdr.android.tuners.IRtlSdrTuner.java
com.rtlsdr.android.tuners.R820T.java