OLED通信速度アップ

  • PROG03_OLED_BMPを使って、OLED通信速度アップに挑戦。 (2011/6/1)
  • さらに改善。(2011/6/11)
  • さらに改善。(2011/6/22)
  • APIを追加。(2011/6/25)

結果

改善前    →929msec.
2.3.4. →249msec. (2011/6/1)
5.     →198msec. (2011/6/11)
6.7.   →183msec. (2011/6/22)
8.9.10.→42msec. (2011/6/25)

プログラム

詳細

1.表示開始と表示終了のタイミングをLED出力。ロジアナで測定。→929msec.
main.c
   int main(void)
   {
       ...
       Init_SysTick();
       Init_Color_LED();
       Init_OLED();
   
       // [2011/06/01 NanaCraft]
       Set_Color_LED(7);
       //
       // Send Bitmap Data
       //
       ...
       //
       // Finish Sign
       //
       while(1)
       {
           // [2011/06/01 NanaCraft]
           //Draw_Color_LED();
           Set_Color_LED(0);
       }
       return 0;
   }
2.Optimization LevelをNoneからOptimize Mostに変更。→501msec.
3.SPIのFIFOを有効に使用。→261msec.
spi.c
   void SPI_TxData(uint32_t txdata)
   {
       // [2011/06/01 NanaCraft]
       while (!(LPC_SSP0->SR & SSPSR_TNF));
       LPC_SSP0->DR = txdata;
   }
4.OLED_Send_Command()のコードを最適化。→249msec.
oled.c
   void OLED_Send_Command(uint32_t *oled)
   {
       // [2011/06/01 NanaCraft]
   
       uint32_t countAndCommand;
       uint32_t end;
       uint32_t i;
   
       countAndCommand = oled[OLED_COMMAND];
   
       SPI_TxData(countAndCommand & 0x0ff);
   
       end = OLED_DATA + ((countAndCommand >> 8) & 0x0ff);
       for (i = OLED_DATA; i < end; i++)
       {
           SPI_TxData(oled[i] | 0x100);
       }
   }
5.OLED_Fill_Rect()のコードを最適化。→198msec.
oled.c
   void OLED_Fill_Rect(int32_t x0, int32_t y0, int32_t xsize, int32_t ysize, uint32_t color)
   {
       // [2011/06/11 NanaCraft]
   
       uint32_t x1, y1;
       uint32_t col0, col1, row0, row1;
       uint32_t oled[3];
       uint32_t i;
       uint32_t pixels;
   
       if (xsize < 1) return;
       x1 = x0 + xsize - 1;
       if (x0 < 0) x0 = 0;
       else if (x0 > 127) return;
       if (x1 < 0) return;
       else if (x1 > 127) x1 = 127;
   
       if (ysize < 1) return;
       y1 = y0 + ysize - 1;
       if (y0 < 0) y0 = 0;
       else if (y0 > 127) return;
       if (y1 < 0) return;
       else if (y1 > 127) y1 = 127;
   
       switch (gOELD_Orientation_Mode)
       {
           case OLED_TOP_N:
           case OLED_TOP_S:
               col0 = x0;
               col1 = x1;
               row0 = y0;
               row1 = y1;
               break;
           case OLED_TOP_W:
           case OLED_TOP_E:
               col0 = y0;
               col1 = y1;
               row0 = x0;
               row1 = x1;
               break;
           default:
               return;
       }
   
       oled[OLED_COMMAND] = C_SET_COLUMN_ADDRESS;
       oled[D_START_ADDRESS] = col0;
       oled[D_END_ADDRESS]   = col1;
       OLED_Send_Command(oled);
   
       oled[OLED_COMMAND] = C_SET_ROW_ADDRESS;
       oled[D_START_ADDRESS] = row0;
       oled[D_END_ADDRESS]   = row1;
       OLED_Send_Command(oled);
   
       oled[OLED_COMMAND] = C_WRITE_RAM_COMMAND;
       OLED_Send_Command(oled);
   
       pixels = (x1 - x0 + 1) * (y1 - y0 + 1);
       for (i = 0; i < pixels; i++)
       {
           OLED_Send_Pixel(color);
       }
   }
6.SPI_TxData()の呼び出し回数を削減。→194msec.
spi.h
   void SPI_BulkTxData(uint32_t* txdata, uint32_t length);     // [2011/06/22 NanaCraft]
spi.c
   void SPI_BulkTxData(uint32_t* txdata, uint32_t length)
   {
       uint32_t i;
       for (i = 0; i < length; i++)
       {
           while (!(LPC_SSP0->SR & SSPSR_TNF));
           LPC_SSP0->DR = txdata[i];
       }
   }
oled.c
   void OLED_Fill_Rect(int32_t x0, int32_t y0, int32_t xsize, int32_t ysize, uint32_t color)
   {
       // [2011/06/11 NanaCraft]
   
       uint32_t x1, y1;
       uint32_t col0, col1, row0, row1;
       uint32_t oled[3];
       uint32_t i;
       uint32_t pixels;
   
       if (xsize < 1) return;
       x1 = x0 + xsize - 1;
       if (x0 < 0) x0 = 0;
       else if (x0 > 127) return;
       if (x1 < 0) return;
       else if (x1 > 127) x1 = 127;
   
       if (ysize < 1) return;
       y1 = y0 + ysize - 1;
       if (y0 < 0) y0 = 0;
       else if (y0 > 127) return;
       if (y1 < 0) return;
       else if (y1 > 127) y1 = 127;
   
       switch (gOELD_Orientation_Mode)
       {
           case OLED_TOP_N:
           case OLED_TOP_S:
               col0 = x0;
               col1 = x1;
               row0 = y0;
               row1 = y1;
               break;
           case OLED_TOP_W:
           case OLED_TOP_E:
               col0 = y0;
               col1 = y1;
               row0 = x0;
               row1 = x1;
               break;
           default:
               return;
       }
   
       // [2011/06/22 NanaCraft]
   
       oled[0] = 0x15;         // Set Column Address
       oled[1] = col0 | 0x100;
       oled[2] = col1 | 0x100;
       SPI_BulkTxData(oled, 3);
   
       oled[0] = 0x75;         // Set Row Address
       oled[1] = row0 | 0x100;
       oled[2] = row1 | 0x100;
       SPI_BulkTxData(oled, 3);
   
       SPI_TxData(0x5c);       // Write RAM Command
       pixels = (x1 - x0 + 1) * (y1 - y0 + 1);
       for (i = 0; i < pixels; i++)
       {
           oled[0] = ((color >> 8) & 0xff) | 0x100;
           oled[1] = ( color       & 0xff) | 0x100;
           SPI_BulkTxData(oled, 2);
       }
   }
7.OLED_Draw_Dot()->OLED_Fill_Rect()のオーバーヘッドを削減。→183msec.
oled.h
   // [2011/06/22 NanaCraft]
   //void OLED_Draw_Dot(int32_t x, int32_t y, int32_t size, uint32_t color);
   #define OLED_Draw_Dot(x, y, size, color)    OLED_Fill_Rect(x, y, size, size, color)
oled.c
   // [2011/06/22 NanaCraft]
   /*
   void OLED_Draw_Dot(int32_t x, int32_t y, int32_t size, uint32_t color)
   {
       OLED_Fill_Rect(x, y, size, size, color);
   }
   */
8.OLED関連APIを追加。
(プログラムの20110625に同封。)
9.WRITE_RAM_BUFFERを調整。
NcOledFill8()を使い、128pixel分を一括表示したときの、1画面分の処理時間。
10.8~9を反映して、NcOledFill16()を使用。→42msec.
main.c
   #include "NcOb.h"

   uint16_t pixels[128];

   // [2011/06/25 NanaCraft]
   i = 0;
   for (y = 0; y < 128; y++)
   {
       for (x = 0; x < 128; x++)
       {
           index = BMP_RGB[i++];
           palette = BMP_PLT[index];
           
           red = (palette >> (16 + 3)) & 0x01f;
           grn = (palette >> ( 8 + 2)) & 0x03f;
           blu = (palette >> ( 0 + 3)) & 0x01f;
           pixel = (red << 11) + (grn << 5) + (blu << 0);
           
           pixels[x] = pixel;
       }
       
       NcOledFillBegin(0, y, 128, 1);
       NcOledFill16(pixels, 128);
   }
最終更新:2011年06月25日 14:32