2014/05/18

PSoC 4 で有機ELディスプレイ


有機ELディスプレイ(I2C、128x64、二値表示)をスイッチサイエンスから買ったので実装してみました。
2、3日かかると思ったのですが、2時間で動いてしまってちょっと拍子抜けですね。

状況

・PSOC Creator3.0 SP1
・PSoC4 4 Pioneer Kit

・GROVE - I2C OLEDディスプレイ128×64 SEEED-OLE35046P
国内 : http://www.switch-science.com/catalog/829/
輸入 : http://www.seeedstudio.com/depot/grove-oled-display-12864-p-781.html
詳細 : http://www.seeedstudio.com/wiki/Grove_-_OLED_Display_128*64
専用ライブラリ : https://github.com/Seeed-Studio/Grove_OLED_Display_128X64

コントロールチップ : SSD1308 [PDF] http://garden.seeedstudio.com/images/4/46/SSD1308_1.0.pdf
ディスプレイ : LY190-128064 [PDF] http://garden.seeedstudio.com/images/c/c4/LY190-128064.pdf
ライブラリと2つのデータシートを参考にしながら必要な部分を作成しました。

※SSD13xx系をAVRで制御されている方がいらっしゃったので参考にさせて頂きました。
UG-2864HSWEG01/SSD1306 I2Cで動作テスト
http://jsdiy.web.fc2.com/oled_ssd1306/
このページによく纏まっているのですが、このチップのデータの単位であるPage、Segmentの関係はよく理解しておく必要があります。

ディスプレイは二値情報のみなので、1x8の縦長のピクセルを1グループ(Segment)として、扱います。これは、計算機は1Byteでデータを扱う事が多いので理にかなっていますね。1x8ピクセルのグループを横に128個並べて1Page、Pageを縦に8段並べる事で1frame(1画面)になります。

I2C

I2C Componentのコンフィグを下図に示します。オーバーサンプリングの設定が中途半端なのは、ビットレートをちょうど400kbpsにするためです。なお、400kbpsにこだわった理由はフレームレート試算の為です。

PSoC 4はSCB利用のComponentを使用する場合、ピン配置が固定されるので注意が必要です。

CommandのWrite

以下のように実装を行いました。コマンドモードに遷移後、Command入力を行います。ADDRはスレーブアドレスです。

#define ADDR 0b0111100
void OLED_Write_Cmd(uint8 command){
    i2cMasterWriteBuf[0] = 0x80;
    i2cMasterWriteBuf[1] = command;
    I2C_I2CMasterWriteBuf(ADDR, (uint8 *) i2cMasterWriteBuf, 2u,  I2C_I2C_MODE_COMPLETE_XFER);

    while(0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT)){}
    (void) I2C_I2CMasterClearStatus();
}


OLEDの起動

OffのCommand、ディレイ、ONのCommand、ディレイのみです。本当はもう少し初期化が必要なのですが、デフォルト値として省略。

void OLED_Init()
{
    OLED_Write_Cmd(0xAE);
    CyDelay(5u);
    OLED_Write_Cmd(0xAF);
    CyDelay(5u);
}


BitmapのWrite

データモードに遷移後、所定のByte数のデータ入力を行います。
void drawBitmap(const uint8* bitmaparray,int bytes)
{
    int i;
    for(i = 0 ; i < bytes ; i++)
    {
        OLED_Write_Data(bitmaparray[i]);
    }
    while(0u == (I2C_I2CMasterStatus() & I2C_I2C_MSTAT_WR_CMPLT));
    (void) I2C_I2CMasterClearStatus();
}

 

最適化

ライブラリの通り、全部のセグメントでアドレス→コントロールバイト→データバイトを書くという実装では遅いです。
I2Cのクロックは最大400kbpsという仕様なのですが、この実装の場合10fps程度しか出ません。なので高速化を施します。
アドレス、コントロールバイトは1フレームに一度だけの転送で、残りのデータ1024バイトは一気に転送します。これによってACK等も含めた転送bit量は 1/3.22 に減少します。

 void drawBitmap_fast(uint8* bitmaparray,int bytes)
{
    int i;
    I2C_I2CMasterSendStart(ADDR, I2C_I2C_WRITE_XFER_MODE);
    I2C_I2CMasterWriteByte(0x40);
   
    for(i = 0 ; i < bytes ; i++)
    {
        I2C_I2CMasterWriteByte(bitmaparray[i]);
    }
    I2C_I2CMasterSendStop();
    (void) I2C_I2CMasterClearStatus();
}


なお、オーバークロックして1000kbpsでも稼働可能です。当方としては定格超えですので常用はしません。クロックを上げるとRESETをかけた後にデータを受け取れなくなる事がまれに発生します。

使用例

int main()
{
    I2C_Start();
  
    CyGlobalIntEnable;
    OLED_Init();

 
    //Set Brightness
    OLED_Write_Cmd(0x81);
    OLED_Write_Cmd(0x00);
   
    //Set Freq
    OLED_Write_Cmd(0xD5);
    OLED_Write_Cmd(0xF0);
   
    //Set Hori-mode
    OLED_Write_Cmd(0x20);
    OLED_Write_Cmd(0x00);
   
    //Set First Seg
    OLED_Write_Cmd(0x00);
    OLED_Write_Cmd(0x10);
    OLED_Write_Cmd(0x40);
   
    //OLED_Write_Cmd(0xA7); //Inverse color if needed

 
    //Draw
    drawBitmap(Image_array,1024);

 
    return 0;
}

画像データ生成ツール

このようなデータの扱い方に対応した配列を生成するツールが存在します。
Bitmap converter for mono and color LCD displays
http://en.radzio.dxp.pl/bitmap_converter/

今回の構成の場合、設定は以下のようにします。
Fileから画像のLoad、Saveが可能で、出力はテキストの配列データになります。
 
生成されたファイルとincludeするか、ソース内に貼り付けることで利用可能です。
リサイズ、二値化はPaint.NET等で行う必要があります。また、今回は8bit Bitmapの画像を使用しました。

 

画像の置き場所

画像1枚で1KBなのでメモリ上に展開してしまうと、メモリが圧迫されます。なので、チップのSRAMではなく、const unsigned char 変数名[]{0x00, ・・・・・};という風に、比較的容量に余裕のあるFlash内に画像を置くことが必要だと思われます。

0 件のコメント:

コメントを投稿