FX3のI2Cを使ってADV7511の設定をしよう~I2C設定編~【2014/01/25】
      新製品として、HDMI対応モニターボードSVM-03を発表しました。
      このSVM-03はカメラなどの入力画像をHDMIモニターに直接出力することができます。
      詳細は
SVM-03のページをご確認ください。
      
      SVM-03にはHDMIに出力するためにADV7511を使用しています。
      また、USB3.0接続用のFX3も搭載しています。
      そこで、今回はFX3のI2C機能を使用して、ADV7511の初期設定を行いたいと思います。
      
      FX3でI2Cを行うために使用するFX3のSDKサンプルは、「serialif_examples」フォルダにある「cyfxusbi2cregmode」です。
      このサンプルはI2Cをレジスターモードで行うサンプルになっています。
      また、コントロールセンターを使用してI2Cの設定コマンドを送受信することができるようになっています。
      ADV7511の設定は、FX3の起動時に1度呼出す形として実装を行います。
      本来はエラー処理なども検討して実装を行う必要がありますが、説明のため簡略化しています。
      また、その後はPCからのI2C送受信が行えるようになります。
      システム構成は次のようになります。
      
      

 SVM-03はUSB3.0経由でPCと接続します。このPCは次の2つの役割を果たします。
      
      ・USBポートからの給電(SVM-03はUSB給電のみ対応。ACアダプタ無し)
      ・PC上のcontrol center からI2Cの送受信を行う
      
      また、HDMIから正しく映像が出力されていることを確認するために、HDMI接続にてモニターに接続をしています。 
      モニターに出力される画像はこのボードに搭載されているFPGA(Spartan-6 XC6SLX15)にて1080p、60fpsのYUV形式でのカラーバー画像を作成しています。 
      
      では、I2Cを行うサンプルソースを眺めていきましょう。
      「cyfxusbi2cregmode」フォルダ内の「cyfxusbi2cregmode.c」を開きます。このファイルにI2Cの初期化や送信などの処理を行うコードが書かれています。
      
      

 このサンプルの基本的な動作フローを説明します。 
      
      まず、FX3起動後に既定の処理を行い、スレッドを起動します。起動したスレットでは次の動作を行います。(既定の処理については以前掲載した「FX3プログラミング Hello Worldを出してみよう」のブログをご覧ください。)
      
      初めにI2Cの初期化を行い、I2Cが使用できるようにします。次にADV7511のレジスタの初期化設定をI2Cにて行います。
      その後は、control centerからのI2CのRead/Writeの指令があるまで待機をします。これが一連の動作フローとなります。
      
      今回はADV7511とFX3でI2C通信するためにSDKのソースを一部変更しましたが、変更した関数に絞って変更内容を紹介いたします。
      
      
      
<CyFxUSBSetupCB関数>
      主な変更は次の箇所です。
      
      1.関数内で指定されているローカル変数の名前を、「wIndex」→「wSubAddr」に変更します。
      これは、わかりやすさのためにそのようにしています。
      
      2.switch (bRequest)の条件CY_FX_RQT_I2C_EEPROM_WRITEとCY_FX_RQT_I2C_EEPROM_READにあるi2cAddrの値を「i2cAddr = 0xA0 | ((wValue &smp; 0x0007) << 1);」→「i2cAddr = 0x7A;」に変更。
      これは、ADV7511のメインレジスターアドレスになります。 
      
      
      
<CyFxUsbI2cTransfer関数>
      主な変更は次の箇所です。
      
      1.「pageCount」と「glI2cPageSize」を使用して繰り返しI2Cを行う作りとなっていますが、不要なので関連する記載を削除します。
      
      2.I2CのRead部分(if (isRead)がTrueの時に呼び出される部分)を以下のように修正します。
      preamble.length   = 3;     // preambleバッファサイズ
      preamble.buffer[0] = devAddr;           // Slave address.
      preamble.buffer[1] = (uint8_t)(byteAddress & 0xFF); // Sub address
      preamble.buffer[2] = (devAddr | 0x01);  // Read用Slave address.
      preamble.ctrlMask = 0x0002;            // Read用アドレス格納位置
      status = CyU3PI2cReceiveBytes (&preamble, buffer, byteCount, 0);
      if (status != CY_U3P_SUCCESS)
      {
      return status;
      }
      3.I2CのWrite部分(if (isRead)がTrueの時に呼び出される部分)を以下のように修正します。
      preamble.length   = 2;         // preambleバッファサイズ
      preamble.buffer[0] = devAddr;   // Slave address
      preamble.buffer[1] = (uint8_t)(byteAddress & 0xFF); // Sub address
      preamble.ctrlMask = 0x0000;    // Read用アドレス格納位置
      status = CyU3PI2cTransmitBytes (&preamble, buffer, byteCount, 0);
      
      preamble.ctrlMaskに関しては、Read用アドレスが格納されたpreamble bufferの配列位置を指定するもののようです。
      2バイトアドレッシングモード時には、0x04を、1バイトアドレッシングモード時には0x02を指定して読み込み(CyU3PI2cReceiveBytes)を行います。
      当然Writeではこの値は0x00となるようです。
      
      詳細はCypressの開発者コミュニティのフォーラム
「I2C preamble question」の回答「FX3_I2C_DETAILS.zip」があります。
      PDFファイルに詳細が記載されておりますのでご確認ください。
      
      次回は、ADV7511の初期設定について記載をしていきます。