DVDプレーヤーのディスプレイをマイクロコントローラーに接続する









背景から始めましょう。なぜこれがすべて必要なのですか。 私は大宇DV-500 DVDプレーヤーのケースに基づいてHTPCコンピューターを作り始めました。私は外見が好きで、中に必要な鉄を取り付けるのに十分な空きスペースがあります。 しかし、すべてに加えて、私は独自のインジケータを残して、それを使用してさまざまな情報を表示することにしました。 この記事では、ディスプレイをマイクロコントローラーに接続し、このディスプレイの交換プロトコルをデコードする方法について説明します。



そのような作業は情報の検索から始めなければなりません。まずプレイヤーのスキームを見つけましたが、これには問題はありませんでしたが、驚いたことに。 スキームによれば、私は何を扱うべきかを理解できましたが、ディスプレイコントローラー上の説明をすぐに見つけることができませんでした 図で正しく署名されていません。 残念ながら、偶然、コントローラーのドキュメントを最後の瞬間に見つけましたが、この時点でプロトコルをほぼ完全に分解していました。



だから私たちは何を持っています:











NEC D16312ディスプレイ用のVECコントローラーがあります(ダイアグラム上でコントローラーがどのように署名されているかに注意してください、私はすぐにそれを見つけることができなかったことは驚くことではありません)、VFDディスプレイ、キーボードマトリックス、LEDが接続されています。 「外界」では、コントローラーはコネクターCN1を介してシリアルインターフェースを介して接続されます。



メインボードコントローラーからディスプレイコントローラーへのメッセージをインターセプトするには、ロジックアナライザーを使用します。 たとえば、私は中国のクローンUSBee AX PROを使用します。それはその機能を完全に実行し、安価です。







Data、Clk、およびCsの検出結果をロジックアナライザーの3つのピンに接続します。グランドも接続することを忘れないでください。 次に、USB経由でアナライザーをコンピューターに接続し、USBee Suiteを起動します(ロジックアナライザーのドライバーとソフトウェアのインストールプロセスは省略します。これは記事の範囲外です)。 速度とサンプルの設定で、次のパラメーターを設定します:サンプルレート-2Msps、バッファーサイズ-10Mサンプル。 これは、5秒の交換フレームをキャプチャするのに十分です。



私の追加のアクションは次のとおりです。1回のキャプチャを実行し(Capture Onceボタン)、すぐにプレーヤーをオンにします。 最初の情報が画面に表示されたらすぐに、キャプチャをオフにします。 表示されたテキストのさまざまなオプションに対してこのようなアクションを実行した後、受け取った情報の分析を開始しました。



だから、チームのすべての前提の規則性は何ですか? まず、すぐに目を引いたのは、コード0x42とその後の3つの空のバイトでコマンドを送信する頻度です。 ビデオプレーヤーが休んでいるときでも、チームの発生頻度は厳格です。 これはキーボードポーリングコマンドであることを提案しました。理論を確認するのは非常に簡単です。プレーヤーのボタンを押したまま、プログラムのフレームをキャプチャします。











バイト0x42の直後にゼロバイトはありませんでしたが、0バイトになる前に! したがって、0x42はメインボードコントローラーからディスプレイコントローラーに送信されるキーボードポーリングコマンドであり、このコマンドに応答して、ディスプレイコントローラーはキーコードを押して応答します(何も押さない場合は0)。



次の行はコード0x40のチームで、画面に情報が表示されたときにのみ表示されました。 常に2バイトが続き、最初のバイトは常に0xCXで始まります。Xは変化する値です。 3番目のバイトには任意の値がありますが、主なことは、最初にオンにしたときに常に0になることです。







このスクリーンショットでは、0x40グループを送信するたびに2番目のバイトが大きくなり、文字のアドレスが設定され、文字の値が3番目のバイトに書き込まれる可能性が高いことがわかります。 この場合、0は文字をクリアします。 常にコード0x40ですべてのグループを送信した後、2バイト0x02 0x8Fが続きます。







さて、データの最後のグループは、コード0x41で始まり、その後に続くゼロバイトのコマンドです。 このコマンドは、ビデオプレーヤーを初めてオンにしたときにのみ表示されます。



データ分析により、コントローラの多かれ少なかれ明確な絵が描かれましたが、実際にすべてをチェックするだけです。 LPCXpressoデバッグハンカチを使用しました。これは、NXPとの競合のフレームワークで「無料」になりました。 スカーフには、単純な32ビットコントローラーLPC1114が装備されています。 なぜなら コントローラーは3.3Vで駆動され、ディスプレイコントローラーD16312は5ボルトであるため、出力を直接接続することを敢えてしませんでした。 おそらく、マイクロコントローラーの出力は5Vに耐性がありますが、3.3-5Vのマッチングボードがあり、それを使用しました。











したがって、メインボードに接続するコネクタから、Data、Cs、Clkの各ピンを担当する3本のワイヤ、ピン1、2、3を抽出します。Data、Clk、Csの接続点にワイヤをはんだ付けし、ディスプレイコントローラのボードに接続します。 GNDおよび+ 5V VCC。 初めて、メインボードから抽出した3つのピンをロジックアナライザーに接続して、送信された情報をデバッグしました。











それが私のデバッグスカーフのようです











すべての鉄の部分の準備ができたら、ソフトウェアを起動します。 まず、分析中に取得したデータを繰り返すプログラムを作成します。 LPCXpressoは、Eclipseに基づいた同名のLPCXpresso IDEを使用します。 まず、新しいワークスペースへのパスを指定して、2つの標準ライブラリCMSIS_CORE_LPC11xxとLPC11xx_cmsis2_Libをインポートします。これらは開発に必要です。 次に、新しいプロジェクトを作成しますFile-> New-> C / C ++-> LPCXpresso C Project次にLPC11 / LPC12-> LPC11xx / ...-> C Project プロジェクト名を設定し、次のウィンドウでターゲットコントローラーを選択します。私の場合はLPC1114 / 302です。 次のステップで、CMSIS_CORE_LPC11xxライブラリが既にリストに表示されているはずです。 以前にインポートしました。 DSPジョブウィンドウでは、何も変更せず、次の手順ではデフォルトですべてをそのままにして、[完了]をクリックします。



生成されたファイル<プロジェクト名> .cに次のコードを追加します

#ifdef __USE_CMSIS #include "LPC11xx.h" #include "clkconfig.h" #include "gpio.h" #endif #include <cr_section_macros.h> void Delay(int32_t ticks); void BeginCommand(uint8_t cmd, uint8_t isSingle); void EndCommand(); void Clock(); void WriteData(uint8_t data); #define PORT 3 #define DATA_BIT 2 #define CLK_BIT 0 #define CS_BIT 1 int main(void) { GPIOInit(); // Set pins to output GPIOSetDir(PORT, CLK_BIT, 1); GPIOSetDir(PORT, CS_BIT, 1); GPIOSetDir(PORT, DATA_BIT, 1); while(1) { BeginCommand(0x40, 1); BeginCommand(0xC0, 0); WriteData(0xFF); EndCommand(); BeginCommand(0x02, 1); BeginCommand(0x8F, 1); Delay(3000000); } return 0 ; } void Delay(int32_t ticks) { volatile int32_t i = ticks; while(i--); } void BeginCommand(uint8_t cmd, uint8_t isSingle) { GPIOSetValue(PORT, CLK_BIT, 1); GPIOSetValue(PORT, CS_BIT, 0); Delay(10); WriteData(cmd); if (isSingle) { EndCommand(); } } void EndCommand() { GPIOSetValue(PORT, CLK_BIT, 1); GPIOSetValue(PORT, CS_BIT, 1); Delay(10); } void Clock() { Delay(10); GPIOSetValue(PORT, CLK_BIT, 0); Delay(10); GPIOSetValue(PORT, CLK_BIT, 1); } void WriteData(uint8_t data) { GPIOSetDir(PORT, DATA_BIT, 1); uint8_t i = 0; for (i = 0; i < 8; ++i) { uint8_t isSet = (data & 0x01); GPIOSetValue(PORT, DATA_BIT, isSet); Clock(); data = data >> 1; } }
      
      





ここでは、シリアルポートを操作するためのいくつかの関数を示します。 ファイルの一番上で、データ、同期、ストロボのポートとピンの設定が設定されます。 私の場合、すべてがポート3でハングし、ピン2がデータ信号を担当し、0-同期と1-ゲーティングを行います。



BeginCommand関数はポートにコマンドを送信します。この関数には2番目の興味深いパラメーターがあります。 上記の信号のグラフをよく見ると、データを送信する前にゲーティング信号がアクティブ(低)レベルに設定され、2つの独立したコマンド間で変化していることがわかります。 ただし、コマンドを送信した後にデータを送信する必要がある場合は切り替わりません











したがって、2番目のパラメーターは、isSingle == 1の場合、コマンドがアトミックであることを示します。非アトミックコマンドの場合、データの送信後に呼び出されるEndCommand関数が意図されています。



データはWriteData関数で送信され、順番にビットごとに送信されます。データは最も低いものから始まり、データピンに情報を送信します。 各データ設定には同期信号が付随し、クロック機能がそれを生成します。



メイン関数では、最初にI / O入力で作業を初期化し、次にデータ、Clk、およびCsピンを出力に設定します。 無限ループでは、データ分析段階で以前に受信したコマンドをシミュレートします。 T.O. 一連のデータ0x40 0xC0 0xFF 0x02 0x8Fをディスプレイコントローラーに送信し、コントローラーは_8で応答しました











T.O. 以下のコマンドが見つかりました:

-0x42-キーボードの処理を担当します。 ディスプレイコントローラーに送信した後、データポートを入力に設定し、そこからデータを読み取る必要があります。事前にClk信号と同期させてください

-0x40-ディスプレイにデータを書き込むコマンド。その後、シンボルのアドレスを書き込むコマンドを指定し、アドレスを指定した後、データを書き込みます

-0x41-これは、LEDをオンにするかどうかのデータを含むバイトが来た後、LEDを制御するコマンドです。

詳細については、このD16312ディスプレイコントローラーのマニュアルを参照してください。コマンドの作成方法について説明しています。 さて、私はすべての作業をgithubにある小さなライブラリーで設計しました。 このライブラリを使用すると、テキストの表示、特殊文字の制御、ドライブシンボルのパーセント表記、キーボードの読み取り、ディスプレイの輝度の変更、LEDの制御を行うことができます。 それだけです。これを読んでいる人が役に立つと面白いことを願っています。 まず、ライブラリーのデモ動画を残します






All Articles