/*************************************************************************** * NVK-128SC008F カラーOLEDモジュール駆動用ライブラリーソースファイル * 制御IC:LD50T5128M * * 2017.12.26 N.Ishii *****************************************************************************/ #include "p24FJ64GA002.h" #include "LD50T5128M_OLEDlibPIC24F.h" #include "ASCII_font.h" // ANK文字 8x8ドット #include "ASCII12dot.h" // ANK文字 12x12ドット /************************************ * コマンド 1バイト出力関数 *************************************/ void OLEDCmdOne(unsigned char cmd){ unsigned int temp; OLED_RS = 0; OLED_CS = 0; temp = (unsigned int)cmd; LATB = (temp << 8) | (LATB & 0x00FF); // 8bitバスは、RB15-8使用。下位8bit(RB7-0もOLED制御ビット) OLED_WR = 0; Nop(); OLED_WR = 1; OLED_CS = 1; OLED_RS = 1; } /************************************ * データ 1バイト出力関数 *************************************/ void OLEDDataOne(unsigned char data){ unsigned int temp; OLED_CS = 0; temp = (unsigned int)data; LATB = (temp << 8) | (LATB & 0x00FF); // 8bitバスは、RB15-8使用。下位8bit(RB7-0もOLED制御ビット) OLED_WR = 0; Nop(); OLED_WR = 1; OLED_CS = 1; } /**************************** * OLED初期化関数 *****************************/ void OLEDInit(void){ delay_ms(50); OLED_VCC_ON = 0; // パネル電源OFF OLED_CS = 1; // CS High OLED_RS = 1; // RS High OLED_WR = 1; // WR High OLED_RD = 1; // RD High OLED_RESET = 1; // Reset off delay_ms(10); OLED_RESET = 0; // ハード・リセット出力 delay_ms(20); OLED_RESET = 1; delay_ms(10); OLEDCmdOne(0x01); // ソフト・リセット出力 delay_ms(10); /// 初期化データ送信 OLEDCmdOne(0x02); // Display Off OLEDDataOne(0x00); OLEDCmdOne(0x14); // Standby Off OLEDDataOne(0x00); OLEDCmdOne(0x1A); // Frame Rate OLEDDataOne(0x04); // 120Hz(8.33mS) /* /// 以下8項目、defult(RESET)設定でOKなので、コメントアウトにしてある。 OLEDCmdOne(0x1D); // Memory Write Direction OLEDDataOne(0x00); OLEDCmdOne(0x09); // Scan Direction OLEDDataOne(0x00); OLEDCmdOne(0x38); // Column Start Address OLEDDataOne(0x00); OLEDCmdOne(0x39); // Row Start Address OLEDDataOne(0x00); OLEDCmdOne(0x30); // Display Size X OLEDDataOne(0x00); OLEDDataOne(0x7F); OLEDCmdOne(0x32); // Display Size Y OLEDDataOne(0x00); OLEDDataOne(0x7F); OLEDCmdOne(0x0D); // Interface OLEDDataOne(0x00); // 8bit OLEDCmdOne(0x1E); // Data Masking OLEDDataOne(0x07); */ OLEDCmdOne(0x16); // Peak Delay OLEDDataOne(0x05); // 5uS相当 aitendoのサンプルコード例と同じ OLEDCmdOne(0x3A); // Peak Width R // OLEDDataOne(0x03); // 3uS相当 aitendoのサンプルコード例と同じ OLEDDataOne(0x06); // 6uS相当 OLEDCmdOne(0x3B); // Peak Width G // OLEDDataOne(0x0F); // 15uS相当 aitendoのサンプルコードと同じ OLEDDataOne(0x1E); // 30uS相当 OLEDCmdOne(0x3C); // Peak Width B // OLEDDataOne(0x05); // 5uS相当 aitendoのサンプルコード例と同じ OLEDDataOne(0x0A); // 10uS相当 OLEDCmdOne(0x40); // Dot Current R // OLEDDataOne(0x40); // 64uA相当 aitendoのサンプルコード例と同じ OLEDDataOne(0xC0); // 192uA相当 OLEDCmdOne(0x41); // Dot Current G // OLEDDataOne(0x1A); // 26uA aitendoのサンプルコード例と同じ OLEDDataOne(0x4E); // 78uA相当 OLEDCmdOne(0x42); // Dot Current B // OLEDDataOne(0x31); // 49uA aitendoのサンプルコード例と同じ OLEDDataOne(0x93); // 147uA相当 OLEDCmdOne(0x18); // Pre-Charge Width OLEDDataOne(0x04); // 4uS相当 OLEDCmdOne(0x44); // Pre-Charge Select OLEDDataOne(0x01); // Pre-Charge= Every Time(常にプリチャージ) /* /// 以下項目、defult(RESET)設定でOKなので、コメントアウトにしてある。 OLEDCmdOne(0x17); // Row Scan OLEDDataOne(0x00); */ OLEDCmdOne(0x48); // Row Overlap Timing OLEDDataOne(0x00); // Normal Row Scan delay_ms(1); OLED_VCC_ON = 1; // パネル電源ON delay_ms(100); OLEDCmdOne(0x02); // Display On OLEDDataOne(0x01); } /*************************** * 画面消去関数 * 消去用色指定あり ****************************/ void OLED_Clear(unsigned short color){ short i; /// Data Writing Box→ 描画エリア設定コマンド OLEDCmdOne(0x34); // X Box Start Address OLEDDataOne(0x00); OLEDCmdOne(0x35); // X Box End Address OLEDDataOne(ENDCOL-1); OLEDCmdOne(0x36); // Y Box Start Address OLEDDataOne(0x00); OLEDCmdOne(0x37); // Y Box End Address OLEDDataOne(ENDROW-1); /// 全エリアを指定色で埋める。 OLEDCmdOne(0x08); // Dot Matrix Display Data Write→ ドット描画コマンド // 16bit color mode for(i=0; i<(ENDCOL)*(ENDROW); i++){ OLEDDataOne((unsigned char)(color >> 8)); OLEDDataOne((unsigned char)color); } } /*********************************** * 1ピクセル表示関数 * 座標は(0,0)-(127,127) ***********************************/ void OLED_Pixel(short Xpos, short Ypos, unsigned short color){ /* if raw>128 or colum >128 then do nothing */ if((Xpos<=ENDCOL-1) && (Ypos<=ENDROW-1)){ OLEDCmdOne(0x34); // 列(COLUM)始点アドレスセット OLEDDataOne(Xpos); OLEDCmdOne(0x35); // 列(COLUM)終点アドレスセット OLEDDataOne(Xpos); OLEDCmdOne(0x36); // 行(RAW)始点アドレスセット OLEDDataOne(Ypos); OLEDCmdOne(0x37); // 行(RAW)終点アドレスセット OLEDDataOne(Ypos); OLEDCmdOne(0x08); // ドット描画コマンド OLEDDataOne((unsigned char)(color >> 8)); OLEDDataOne((unsigned char)color); } } /*************************** * 直線描画関数 ***************************/ #define abs(a) (((a)>0) ? (a) : -(a)) void OLED_Line(short x0, short y0, short x1, short y1, unsigned short color) { short steep, t; short deltax, deltay, error; short x, y; short ystep; y0=ENDROW-y0 -1; // ※ Y座標反転(左下原点) y1=ENDROW-y1 -1; /// 差分の大きいほうを求める steep = (abs(y1 - y0) > abs(x1 - x0)); /// x、yの入れ替え if(steep){ t = x0; x0 = y0; y0 = t; t = x1; x1 = y1; y1 = t; } if(x0 > x1) { t = x0; x0 = x1; x1 = t; t = y0; y0 = y1; y1 = t; } deltax = x1 - x0; // 傾き計算 deltay = abs(y1 - y0); error = 0; y = y0; /// 傾きでステップの正負を切り替え if(y0 < y1) ystep = 1; else ystep = -1; /// 直線を点で描画 for(x=x0; x<=x1; x++) { if(steep) OLED_Pixel(y,x,color); else OLED_Pixel(x,y,color); error += deltay; if((error << 1) >= deltax) { y += ystep; error -= deltax; } } } /************************************* * 円を描く関数 * 中心点と半径を指定 * (Fussyさんのアルゴリズムを使用) **************************************/ void OLED_Circle(int x0, int y0, int r, unsigned short color){ int x = r; int y = 0; int F = -2 * r + 3; while(x >= y){ OLED_Pixel(x0+x, y0+y, color); OLED_Pixel(x0-x, y0+y, color); OLED_Pixel(x0+x, y0-y, color); OLED_Pixel(x0-x, y0-y, color); OLED_Pixel(x0+y, y0+x, color); OLED_Pixel(x0-y, y0+x, color); OLED_Pixel(x0+y, y0-x, color); OLED_Pixel(x0-y, y0-x, color); if(F >= 0){ x--; F -= 4 * x; } y++; F += 4 * y + 2; } } /***************************************** * ANK文字表示関数 8x8ドット * 128/8=16文字/行 128/8=16行 * (0, 0) - (15, 15)の範囲 ******************************************/ /* void OLED_Char(char colum, char line, unsigned char letter, unsigned short color1, unsigned short color2){ unsigned char j, i, Mask; if((colum < 16) && (line < 16)){ // 範囲チェック for(j=0; j<5; j++){ // 横5ドット Mask = 0x80; // 上位ビットから表示 for(i=0; i<8; i++){ // 縦1ライン分表示 if((chrom[letter-0x20][j] & Mask) != 0) OLED_Pixel(colum*8+j+3, (line+1)*8-i, color1); else OLED_Pixel( colum*8+j+3, (line+1)*8-i, color2); //背景色 Mask = Mask >> 1; } } /// フォントは、5bot幅、残りの、3dot*8dotスペースを背景色で塗りつぶす。 for(j=5; j<8; j++){ for(i=0; i<8; i++){ OLED_Pixel(colum*8+j+3, (line+1)*8-i, color2); //背景色 } } } } */ /******************************************************* * ANK文字表示関数 12x12ドット * 128/12=10文字/行 128/14=9行 * (0, 0) - (9, 8)の範囲 ********************************************************/ void OLED_Char(char colum, char line, unsigned char letter, unsigned short color1, unsigned short color2){ unsigned char j, i, Mask; if((colum < XChar) && (line < YLine)){ // 範囲チェック // ANK表示出力 3バイトの2ラインずつを6回繰り返す for(j=0; j<6; j++){ // 8ドット連続部の表示 Mask = 0x80; for(i=0; i<8; i++){ // 1ライン目前半8ドット表示 if((ANKFont[letter][j*3] & Mask) != 0) OLED_Pixel(colum*12+i, line*14+j*2, color1); else OLED_Pixel(colum*12+i, line*14+j*2, color2); //背景色 // 2ライン目後半8ドット表示 if((ANKFont[letter][j*3+2] & Mask) != 0) OLED_Pixel(colum*12+i+4, line*14+j*2+1, color1); else OLED_Pixel(colum*12+i+4, line*14+j*2+1, color2); //背景色 Mask = Mask >> 1; } // 分割部4ドットずつ表示 Mask = 0x80; // 1ライン目後半4ドット表示 for(i=0; i<4; i++){ if((ANKFont[letter][j*3+1] & Mask) != 0) OLED_Pixel(colum*12+i+8, line*14+j*2, color1); else OLED_Pixel(colum*12+i+8, line*14+j*2, color2); //背景色 Mask = Mask >> 1; } // 2ライン目前半4ドット表示 for(i=4; i<8; i++){ if((ANKFont[letter][j*3+1] & Mask) != 0) OLED_Pixel(colum*12+i-4, line*14+j*2+1, color1); else OLED_Pixel(colum*12+i-4, line*14+j*2+1, color2); //背景色 Mask = Mask >> 1; } } } } /******************************************* * 文字列描画関数 * 8x8dot Fontの場合:16文字x16行で指定 * 12x12dot Fontの場合:10文字x9行で指定 ********************************************/ void OLED_Str(char colum, char line, char *s, unsigned short color1, unsigned short color2){ while (*s){ OLED_Char(colum++, line, *s++, color1, color2); if(colum >= XChar){ line++; colum = 0; if(line >= YLine) line = 0; } } } /********************************************************* * イメージ表示関数(単色イメージ) *  データは縦方向8ライン分が1バイトで格納されている * 128×128/8=2kバイト/画面 * グラフィック色(color1)と背景色(color2)両方を指定 **********************************************************/ void OLED_Image(char line, const unsigned char *ptr, unsigned short color1, unsigned color2) { unsigned char Mask; short i, vline, colum; for(vline=line; vline