/*************************************************************************** * NYK-064SC012F カラーOLEDモジュール駆動用ライブラリーソースファイル * 制御IC:SSD1332 * * 2017.12.2 N.Ishii *****************************************************************************/ #include "p24FJ64GA002.h" #include "SSD1332_OLEDlibPIC24F.h" #include "ASCII_font.h" #include "imagedata.h" //#include "imagedata_2.h" /************************************ * コマンド 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(10); OLED_RESET = 1; delay_ms(200); OLED_VCC_ON = 1; // パネル電源ON delay_ms(300); /// 初期化データ送信 OLEDCmdOne(0xAE); // Display Off OLEDCmdOne(0x15); // Column Address OLEDCmdOne(0x00); // Set OLEDCmdOne(0x5F); // Set OLEDCmdOne(0x75); // Row Addess OLEDCmdOne(0x00); // Set OLEDCmdOne(0x3F); // Set OLEDCmdOne(0x81); // Set Contrast for Color A OLEDCmdOne(0x5A); // Set OLEDCmdOne(0x82); // Set Contrast for Color B OLEDCmdOne(0x2C); // Set OLEDCmdOne(0x83); // Set Contrast for Color C Now setting value is 15V, 100cd. OLEDCmdOne(0x54); // Set OLEDCmdOne(0x87); // Master Current Control the OLED Brightnees. OLEDCmdOne(0x09); // Set OLEDCmdOne(0xA0); // Set Re-map & Data Format OLEDCmdOne(0x70); // Set:65Kカラー・フォーマット・Horizontal address inc.・Column address 0 is mapped to SEG0(左上原点) OLEDCmdOne(0xA1); // Set Display Start Line OLEDCmdOne(0x00); // Set OLEDCmdOne(0xA2); // Set Display OffSet OLEDCmdOne(0x00); // Set OLEDCmdOne(0xA8); // Set Multiplex Ratio OLEDCmdOne(0x3F); // Set OLEDCmdOne(0xAD); // Set Master Configuration --> 8F->8e External Vcc OLEDCmdOne(0x8E); // Set OLEDCmdOne(0xB1); // Set Adjust Driving period OLEDCmdOne(0x11); // Set OLEDCmdOne(0xB3); // Set Colock Divider Oscillator Frequency OLEDCmdOne(0xD0); // Set OLEDCmdOne(0xBB); // Set Pre_charge Voltage OLEDCmdOne(0x00); // Set OLEDCmdOne(0xBC); // Set Pre_charge Voltage--> Now setting value is 15V, 100cd. OLEDCmdOne(0x2A); // Set OLEDCmdOne(0xBD); // Pre_charge Voltage Setting the OLED Brightnees. OLEDCmdOne(0x00); // Set OLEDCmdOne(0xBE); // Set VCOMH Level OLEDCmdOne(0x3F); // Set OLEDCmdOne(0xB9); // Enable Linear Gray Scale delay_ms(200); OLEDCmdOne(0x25); // Clear Window 0, 0 to 95, 63 OLEDCmdOne(0); // Set OLEDCmdOne(0); // Set OLEDCmdOne(95); // Set OLEDCmdOne(63); // Set delay_ms(2); OLEDCmdOne(0xAF); // Display On } /************************************ * ディスプレイの ON/OFFを切り替える *************************************/ void OLEDDispON(void){ OLEDCmdOne(0xAF); // Disable All Pixels ON } void OLEDDispOFF(void){ OLEDCmdOne(0xAE); // All Pixels OFF } /******************************** * 画面全体を消去・指定色で埋める *********************************/ void GCls(unsigned short color){ // OLEDFillBox(0, 0, ENDCOL+1, ENDPAGE+1, color); // 171126 OLEDFillBox(0, 0, ENDCOL, ENDROW, color); // 171130 } /************************************* * Box領域をバックグラウンド色で埋める **************************************/ void OLEDFillBox(short x, short y, short dx, short dy, unsigned short color){ unsigned char x2, y2, ca, cb, cc; x2= (unsigned char)(x+dx-1); y2= (unsigned char)(y+dy-1); /// 16bitカラーコード(RGB565)から色成分を取得 cc= (unsigned char)((color & 0x001F) << 1); // Color C (blue)→ コードをblueマスク=0x001F演算で、0b000BBBBBとし、 // さらにこのコマンドのデータセットフォーマットに従い、1bit左シフトで、0b00BBBBB0とする。 cb= (unsigned char)((color & 0x07E0) >> 5); // Color B (green)→ コードをgreenマスク=0x07E0演算し5bit右シフトで、0b00GGGGGGになる。 ca= (unsigned char)(((color & 0xF800) >> 11) << 1); // Color A (red)→ コードをredマスク=0xF800演算で、0b000RRRRRとし、 // さらにこのコマンドのデータセットフォーマットに従い、1bit左シフトで、0b00RRRRR0とする。 SetWindowParam(x, y, x2, y2); OLEDCmdOne(0x26); // Fill Enable / Disable OLEDCmdOne(0b00000001); // Disable Reverce Copy and Enable Fill for Draw OLEDCmdOne(0x22); // Drawing Rectangle OLEDCmdOne((unsigned char)x); // Column Address of Start OLEDCmdOne((unsigned char)y); // Row Address of Start OLEDCmdOne(x2); // Column Address of End OLEDCmdOne(y2); // Row Address of End OLEDCmdOne(cc); // Color C of the Line OLEDCmdOne(cb); // Color B of the Line OLEDCmdOne(ca); // Color A of the Line OLEDCmdOne(cc); // Color C of the Fill area OLEDCmdOne(cb); // Color B of the Fill area OLEDCmdOne(ca); // Color A of the Fill area delay_ms(2); // 描画コマンド発行後安定するまでの時間待ち } /************************************* * Box領域サイズ設定 **************************************/ void SetWindowParam(short x1, short y1, short x2, short y2){ OLEDCmdOne(0x15); // Set Column Addres OLEDCmdOne((unsigned char)x1); OLEDCmdOne((unsigned char)x2); OLEDCmdOne(0x75); // Set Row Addres OLEDCmdOne((unsigned char)y1); OLEDCmdOne((unsigned char)y2); } /*********************************************************************************** * 1ピクセル表示関数 * 座標は(0,0)-(95,63) * *  始点・終点座標を同じにしてSSD1332のアクセレータLineコマンドを使い、ドット描画している。 *************************************************************************************/ void OLED_Pixel(short Xpos, short Ypos, unsigned short color){ unsigned char ca, cb, cc; /// 16bitカラーコード(RGB565)から色成分を取得 cc= (unsigned char)((color & 0x001F) << 1); // Color C (blue) cb= (unsigned char)((color & 0x07E0) >> 5); // Color B (green) ca= (unsigned char)(((color & 0xF800) >> 11) << 1); // Color A (red) /// if raw>64 or colum >96 then do nothing if((Xpos<=ENDCOL-1) && (Ypos<=ENDROW-1)){ OLEDCmdOne(0x21); // ライン描画コマンド送信 OLEDCmdOne(Xpos); // 始点座標セット OLEDCmdOne(Ypos); OLEDCmdOne(Xpos); // 終点座標セット OLEDCmdOne(Ypos); OLEDCmdOne(cc); // Color C of the Line OLEDCmdOne(cb); // Color B of the Line OLEDCmdOne(ca); // Color A of the Line } } /*************************** * 直線描画関数 ***************************/ #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; } } } /* //////////////////////////////////////////////////////////////////////////////////////////// // 直線描画関数 // SSD1332アクセレータコマンドのライン描画関数で、右肩上がり線描画すると、上下にラインが // バラケル現象が起きる。これはチップのバグと思われる。 なので未使用にした。 171130 //////////////////////////////////////////////////////////////////////////////////////////// void OLED_Line(short x0, short y0, short x1, short y1, unsigned short color){ /// 座標制限 if(x0 > 95) x0 = 95; if(x1 > 95) x1 = 95; if(y0 > 63) y0 = 63; // if(y1 > 63) y0 = 63; if(y1 > 63) y1 = 63; // 171129 unsigned char ca, cb, cc; /// 16bitカラーコード(RGB565)から色成分を取得 cc= (unsigned char)((color & 0x001F) << 1); // Color C (blue) cb= (unsigned char)((color & 0x07E0) >> 5); // Color B (green) ca= (unsigned char)(((color & 0xF800) >> 11) << 1); // Color A (red) OLEDCmdOne(0x21); // ライン描画コマンド送信 OLEDCmdOne(x0); // 始点座標セット OLEDCmdOne(y0); OLEDCmdOne(x1); // 終点座標セット OLEDCmdOne(y1); OLEDCmdOne(cc); // Color C of the Line OLEDCmdOne(cb); // Color B of the Line OLEDCmdOne(ca); // Color A of the Line } */ /************************************* * 円を描く関数 * 中心点と半径を指定 * (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ドット * 96/8=12文字/行 64/8=8行 * (0, 0) - (11, 7)の範囲 ******************************************/ void OLED_Char(char colum, char line, unsigned char letter, unsigned short color1, unsigned short color2){ unsigned char j, i, Mask; if((colum < 12) && (line < 8)){ // 範囲チェック 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); //背景色 } } } } /****************************** * 文字列描画関数 * 12文字x8行で指定 ******************************/ 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; } } } /******************************************************** * 16bitBMPカラーイメージ表示関数 * 96x64dot対応 *********************************************************/ void OLED_Image(void) { short Xpos, Ypos; int ptr; /// BMPフォーマットのデータは、左下から右上に向かって配列されているので /// この順で描画すると、上下逆様の画像表示になってしまう。 /// 右上の画素(ptr=(12426/2)-1)=6212, Xpos= 95, Ypos= 0)から下に向かって描画する必要がある。 ptr= 6212; for(Ypos=0; Ypos < ENDROW; Ypos++){ for(Xpos=ENDCOL-1; Xpos > -1; Xpos--){ OLED_Pixel(Xpos, Ypos, ImageData[ptr--]); } } } /********************************** * ループ遅延関数 usec単位 **********************************/ void delay_us(int usec){ usec = (int)(CLOCK*usec)/ 10; while(usec) { asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); usec--; } } /********************************** * ループ遅延関数 msec単位 **********************************/ void delay_ms(int msec){ int i; for(i=0; i< msec; i++) delay_us(1000); }