Vol.912 14.Feb.2025

グラフィックカラー表示ユニット スマホの機種変

P PICミニBBシリーズ(21) 〜グラフィックカラー表示ユニット

by fjk

 abc907から小型で使いやすいOLED(Organic Electro Luminescence Diode:有機発光ダイオード)としてSSD1306を紹介したが、今度はフルカラーのOLEDユニットのQT095B(0.95inch96x64dotRGB、秋月#114435、1,480円、コントローラはSSD1331)を使ってみた。

参考データ(秋月電子):   ・QT095B   ・SSD1331

 QT095Bは、ラズパイやアルディーノで、Adafruitのライブラリを使った例があるが、PICを使って制御した報告はなさそう。
 そこで、mgo-tecさんのESP32使用でSPIコマンドを使った例を参考にさせていただいた。

【QT095B(SSD1331)の概要】
・解像度: 96RGB x 64 ドット マトリックス カラーパネル
・組み込みの 96 x 64 x 16 ビット GDDRAM による 65k 色(5/6/5bit)深度のサポート
・電源: VDD = 2.4V 〜 3.5V (IC ロジック用)、パネル駆動用電源(8〜18V)は内部で作成
・各色コンポーネントの 256 ステップのコントラスト制御と 16 ステップのマスター電流制御
・インターフェイス:8/9/16 ビットパラレル、4SPIインターフェイス
・水平、垂直、対角の連続スクロールを備えたグラフィックアクセラレーションコマンド (GAC)
<QT095Bのピン>

<異なるモードでのRAMアクアセス>

<アドレス増分モード>
<グラフィックアクセラレーションコマンド>
@ 線を描く (21h)
21H,X0,Y0,X1,Y1,Col
X0,X1:開始、終了列アドレス
Y0,Y1:開始、終了行アドレス
Col:描画カラー
A 四角形を描く (22h) [塗りつぶしは26HがOn時]
22H,X0,Y0,X1,Y1,Col1,Col2
X0,X1:開始、終了列アドレス
Y0,Y1:開始、終了行アドレス
Col1:枠カラー、Col2:塗りつぶしカラー
B コピー (23h)
23H,X0,Y0,X1,Y1,X2,Y2
X0,X1:コピー元、開始、終了列アドレス
Y0,Y1:コピー元、開始、終了行アドレス
X2,Y2:コピー先、開始列、開始行アドレス
C ウィンドウを暗くする (24h)
24H,X0,Y0,X1,Y1
D ウィンドウをクリア (25h)
25H,X0,Y0,X1,Y1
E 塗りつぶしの有効化/無効化 (26h)
26H,A0[0/1]: 0:NoFill/1:Fill
F 連続水平および垂直スクロールの設定 (27h)
27H,H-ofs,R-start,R-scroll,V-scroll,Scroll-time
G スクロールをアクティブにする (2Fh)
2EH:Scroll-Off/2FH:Scroll-On

 

 

【ハード】 (PICは本テストのみならPIC16F18325などでもOK)

回路図

試作ブレッドボード回路
(RCリセット付き)
【トラブルと注意点】
  1. QT095B(SSD1331)のリセット
     当初、OLED のRST端子にVdd(3.3V)を直接接続したところ、上手く初期設定ができなかった。そこで、未使用のRA1端子(CS1)を使ってRSTにリセット信号を送ると、正常にSSD1331を初期化ができた。そして、RST端子にRCによるリセット回路を取り付けたところ、ソフト制御無しでSSD1331の初期化ができた。
    (データシートを見ると、電源投入3μS後に、3μS以上のリセット信号を送り、その後300mS以上の初期化時間が必要となっている)
     ただし、OLEDをリセットするには電源を入れ直すこと(開発時はCS1を使ってリセットするのが楽)。
  2. SPIマスターのスタートとモード
     MCC-classicによるSPI設定は、abc895で報告したようにバグがあり、SSPEN=1に設定すること。
     また、QT095B(SSD1331)制御のSPIモードは「Mode3」に設定すること
【ソフト】
ソースリスト
 
【結 果】
とりあえず、PIC制御でカラーOLEDの表示ができたが、描画速度が遅いなど課題あり。・・・続く

MCC画面(Pin Module)

System設定

MSSP(SPI)設定

test1画面
(カラー表示)

test2画面
(256色カラーマップ)

test3画面
(256colorでも64k色で指定)


S スマホの機種変  〜AQUOS_Sense9(5Gスマホ)

by fjk

 6年間使っていたスマホ(AQUOS_Sense3)の操作への反応が悪くなり、画面フリーズが頻発し、電話の応答もできない状態になった。仕方が無いので、ドコモショップに出かけ、機種変更を相談したところ、昨年の暮れに発売された後継機であるAQUOS_Sense9を勧められ、機種変更を決めた。
 併せて、電話回線の接続変更も、「セットにするとスマホの使用料金が安くなる」と勧められた。今まで使っていたフレッツ光+コーラルネットから、接続変更するとどうなるか聞いてみたところ、「コーラルのホームページは使えなくなるが、メールとレンタルサーバーはそのまま使える」とのことで、接続変更も行うことにした。・・・、その後、Webやメールは問題なく使えたが、FTPで以下の問題発生。

★ 回線切り替え後、汎用FTPソフト(FFFTPなど)でレンタルサーバーに接続できなくなった
−>専用接続ソフトで何とか接続(プロバイダ、ネットサービスで確認してもらっても原因不明)

●アプリの引っ越し
 次の問題は、スマホの色々なアプリの引っ越しができるか不安があったが、とりあえず、ショップ店頭で引っ越しできる分は引っ越し処理をしてもらった。その結果、

@ 電話帳
ドコモショップで引っ越してもらい、全て引越しできた。◎
A メッセージツール
LINE、+Messageはショップ作業で概ね引っ越しできていたが、
どちらも事前に保存しなかった写真が失われた【要、事前に写真保存!】)、△
B 電子マネー
Edyは○(事前に楽天で引越し手続きが必要だが、旧機種の動作が安定せず最初は×。その後、再トライで成功)
SUICAは×(旧機種の動作不良により引っ越しできず、新規に再登録)
C ショップアプリ
アイコンはあるが、再度ユーザ登録が必要、△
D カレンダー
Jorteは×−>アプリを再インストール後、ユーザ登録、連携設定
E その他
・ホームページ
MyNifty以外は全て×−>再度登録(Niftyも再度ユーザ設定が必要)
・オフィスソフト
Micrsoft365、 OfficeSuitsは共に×−>再インストール
・マイナンバー
マイナポータル、マイナポイントは△−>再度ユーザー登録
・カメラ連携
OI.Shar、instaxは共に×−>再インストール後、再度登録
・ドローン制御
DJI_Flyは×−>再インストール後、再度登録
・健康管理
Fitbit、HealthPlanetは×−>再度ユーザー登録

 ※基本的に、アイコンが残っていても、ほとんどのアプリはユーザの再登録が必要でした。


AQUOS_Sense9(正面、アプリ表示中)

AQUOS_Sense9(カメラ面、ケース付き)


【QT095Bのプログラム】 abc912-18326.c(zip)


/****************************************(abc912-18326.c)***********
  *  有機ELカラーグラフィック テスト 	QT095B(SSD1331)
 *******************************************************************/
#include "mcc_generated_files/mcc.h"

//---  SSD1331 初期化   	( []はデフォルト値 )
void SSD1331_Init(){
  CS1_SetLow();                 // Reset OLED (SSD1331))
  __delay_ms(50);               // 最終的にOLCDリセットは省略可
  CS1_SetHigh();
    
  __delay_ms(500);
  gCS_SetLow();                 //  Select gCS
  gDC_SetLow();                 //  Select Command

  SPI1_ExchangeByte(0xAE);      //  Set Display Off
  SPI1_ExchangeByte(0xA0);      //  Remap & Color Depth setting
    SPI1_ExchangeByte(0x20);    // =20H [40H],(0b00100000)
                                //   A[7:6] = 00; 256 color
                                //   A[5] = 1; Enable COM Sprit
                                //   A[4] = 0; Scan from 0-COMn
                                //   A[3] = 0; Disable Swaping
                                //   A[2] = 0; Norma Order (RGB)
                                //   A[1] = 0; RAM Colum Seg:95-0
                                //   A[0] = 0; Horizontal Address Incriment
  SPI1_ExchangeByte(0xA1);      //  Set Display Start Line
    SPI1_ExchangeByte(0);       // = 0 [00H]
  SPI1_ExchangeByte(0xA2);      //  Set Display Offset
    SPI1_ExchangeByte(0);       // = 0 [00H]
  SPI1_ExchangeByte(0xA4);      //  Set Display Mode (Normal)
  SPI1_ExchangeByte(0xA8);      //  Set Multiplex Ratio
    SPI1_ExchangeByte(63);      // = 63 [63]
  SPI1_ExchangeByte(0xAD);      //  Set Master Configration
    SPI1_ExchangeByte(0x8E);    // =8E [8FH],a[0]=0 Select external Vcc supply
  SPI1_ExchangeByte(0xB0);      //  Power Save Mode
    SPI1_ExchangeByte(0x1A);    // = 1AH [1AH},Enable power save mode
  SPI1_ExchangeByte(0xB1);      //  Phase 1 and 2 period adjustment
    SPI1_ExchangeByte(0x74);    // = 74H [74H]
  SPI1_ExchangeByte(0xB3);      //  Display Clock DIV
    SPI1_ExchangeByte(0xF0);    // = F0H [D0H]
  SPI1_ExchangeByte(0x8A);      //  Pre Charge A
    SPI1_ExchangeByte(0x81);    // = 81H [81H]
  SPI1_ExchangeByte(0x8B);      //  Pre Charge B
    SPI1_ExchangeByte(0x82);    // = 82H [82H]
  SPI1_ExchangeByte(0x8C);      //  Pre Charge C
    SPI1_ExchangeByte(0x83);    // = 83H [83H]
  SPI1_ExchangeByte(0xBB);      //  Set Pre-charge level
    SPI1_ExchangeByte(0x3A);    // = 3AH [3EH]
  SPI1_ExchangeByte(0xBE);      //  Set VcomH
    SPI1_ExchangeByte(0x3E);    // = 3EH [3EH]
  SPI1_ExchangeByte(0x87);      //  Set Master Current Control
    SPI1_ExchangeByte(0x06);    // = 06H [0FH]
  SPI1_ExchangeByte(0x15);      //  Set Column Address
    SPI1_ExchangeByte(0);       // = 00 [00]
    SPI1_ExchangeByte(95);      // = 95 [95]
  SPI1_ExchangeByte(0x75);      //  Set Row Address
    SPI1_ExchangeByte(0);       // = 00 [00]
    SPI1_ExchangeByte(63);      // = 63 [63]
  SPI1_ExchangeByte(0x81);      //  Set Contrast for Color A
    SPI1_ExchangeByte(255);     // = 255 [80H]
  SPI1_ExchangeByte(0x82);      //  Set Contrast for Color B
    SPI1_ExchangeByte(255);     // = 255 [80H]
  SPI1_ExchangeByte(0x83);      //  Set Contrast for Color C
    SPI1_ExchangeByte(255);     // = 255 [80H]
  SPI1_ExchangeByte(0xAF);      //  Set Display On
  __delay_ms(110);              //  0xAFコマンド後最低100ms必要
  gCS_SetHigh();                //  DeSelect gCS
}

//---  画面クリア
void gOLED_Clr(uint8_t x0,uint8_t y0,uint8_t x1,uint8_t y1){
  gCS_SetLow();                 // Select gCS
  gDC_SetLow();                 // Select Comand
  SPI1_ExchangeByte(0x25);      // Line Command
  SPI1_ExchangeByte(x0);        // Start X
  SPI1_ExchangeByte(y0);        // Start Y
  SPI1_ExchangeByte(x1);        // End X
  SPI1_ExchangeByte(y1);        // End Y
  gCS_SetHigh();                // DeSelect gCS
  __delay_ms(1);
}

//----  Set 256Color   ( R = 0-7, G = 0-7, B = 0-3 )
uint8_t gRGB256(uint8_t r,uint8_t g, uint8_t b){
  return (uint8_t)((r << 5) | (g << 2) | b);
}

//---  塗りつぶし指定
void gOLED_Fill(uint8_t md){
  gCS_SetLow();                 // Select gCs
  gDC_SetLow();                 // Select Comand
  SPI1_ExchangeByte(0x26);      // Fill Command
  SPI1_ExchangeByte(md);        // set Mode
  gCS_SetHigh();                // DeSelect gCs
  __delay_ms(1);
}

//----  線描画
void gOLED_Line(uint8_t x0,uint8_t y0, uint8_t x1,uint8_t y1, uint8_t r, uint8_t g ,uint8_t b){
  gCS_SetLow();                 // Select gCs
  gDC_SetLow();                 // Select Comand
  SPI1_ExchangeByte(0x21);      // Line Command
  SPI1_ExchangeByte(x0);        // Start X
  SPI1_ExchangeByte(y0);        // Start Y
  SPI1_ExchangeByte(x1);        // End X
  SPI1_ExchangeByte(y1);        // End Y
  SPI1_ExchangeByte(r);         // Line color Red
  SPI1_ExchangeByte(g);         // Line color Green
  SPI1_ExchangeByte(b);         // Line color Blue
  gCS_SetHigh();                // DeSelect gCs
  __delay_ms(1);
}

//----  四角形描画
void gOLED_Rect(uint8_t x0,uint8_t y0, uint8_t x1,uint8_t y1, uint8_t r, uint8_t g ,uint8_t b){
  gCS_SetLow();                 // Select gCs
  gDC_SetLow();                 // Select Comand
  SPI1_ExchangeByte(0x22);      // Rect Command
  SPI1_ExchangeByte(x0);        // Start X
  SPI1_ExchangeByte(y0);        // Star Y
  SPI1_ExchangeByte(x1);        // End X
  SPI1_ExchangeByte(y1);        // End Y
  SPI1_ExchangeByte(r);         // Line color Red
  SPI1_ExchangeByte(g);         // Line color Green
  SPI1_ExchangeByte(b);         // Line color Blue
  SPI1_ExchangeByte(r);         // Fill color Red
  SPI1_ExchangeByte(g);         // Fill color Green
  SPI1_ExchangeByte(b);         // Fill color Blue
  gCS_SetHigh();                // DeSelect gCS
  __delay_ms(1);
}

//---  Test QT095 (1)
void test1(){
  uint8_t i, j;
  uint8_t Dot1, Dot2, Dot3, Dot4;
  Dot1 = gRGB256(0,7,0);
  Dot2 = gRGB256(7,0,0);
  Dot3 = gRGB256(0,0,3);
  Dot4 = gRGB256(7,7,0);  
  gOLED_Clr(0,0,95,63);
  gCS_SetLow();                 // Selct gCS
  gDC_SetHigh();                // Selct data
  for(j = 0; j < 64; j++){
    for(i = 0; i < 96; i++){
      if(j < 32){
          if(i < 32) SPI1_ExchangeByte(Dot1);
          else       SPI1_ExchangeByte(Dot3);
      }else{
          if(i < 48) SPI1_ExchangeByte(Dot2);
          else       SPI1_ExchangeByte(Dot4);
      }
    }
  }
  gCS_SetHigh();                // DeSelect gCS
}

//---  Test QT095 (2) (Color Map)
void test2(){
  uint8_t i,j,r,g,b,col;
  gOLED_Clr(0,0,95,63);
  gCS_SetLow();                 // Selct gCS
  gDC_SetHigh();                // Selct data
  for(g=0; g<8; g++){
    for(i=0; i<8; i++){
      for(b=0;b<4;b++){
        for(r=0;r<8;r++){
          col=(uint8_t)((r<<5)+(g<<2)+b);
          SPI1_ExchangeByte(col);	
          SPI1_ExchangeByte(col);	
          SPI1_ExchangeByte(col);	
        }
      }     
    }
  }
  gCS_SetHigh();                // DeSelect gCS
 }



//--- Test QT095 (3) (Draw Command)
void test3(){
  gOLED_Clr(0,0,95,63);
  gOLED_Line( 0, 0,95,63,63,63,63);
  gOLED_Line( 0,63,95, 0, 0, 0,63);
  gOLED_Fill(0);                // 塗りつぶし無し
  gOLED_Rect(16,12,78,51,63, 0, 0);
  gOLED_Fill(1);                // 塗りつぶし有り
  gOLED_Rect(32,24,63,40, 0,63, 0);
}

/**************************************
 *    Main application
 ***************************************/
void main(void){
  SYSTEM_Initialize();
  SSP1CON1bits.SSPEN = 1;
  SSD1331_Init();      

    // Enable the Global Interrupts
    //INTERRUPT_GlobalInterruptEnable();

    // Enable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptEnable();

  IO_RA4_SetHigh(); 
  
  while (1)
    {
    test1();  
    __delay_ms(2000);
    IO_RA4_Toggle();        
     
    test2();
    __delay_ms(2000);
    IO_RA4_Toggle();

    test3();
    __delay_ms(2000);
     IO_RA4_Toggle();     
    }
}
/****   End of File   *****/


【おまけ】



※プログラムのリストをハイライト付きのスタイルで見る場合はここをクリック


※ 本レポートの参考・利用は、あくまでも自己責任でお願いします。


グラフィックカラー表示ユニット スマホの機種変