OLED Multi-Font IC Problems

Comments

4 comments

  • Kon-L

    Well my good folks, I have figured this out on my own.  Below are the relevant sections, but I will also post my full code for you to try! I am using a PIC18F26J50 for this project with a 16MHz crystal and NHD-2.8-25664UMB3 in 4 wire serial mode(SPI).  It is compiled using Microchip's XC8 compiler. Hope this helps others! I know I wrestled with it for too long myself.


    /******************************************************************
       Function Name:  OLED_Init                                       
       Return Value:                                             
       Parameters:                         
       Description:    Initializes OLED Display
    ******************************************************************/
    void OLED_Init(void){
       
       RES = 1;
       Delay_ms(200);
       RES = 0;
       Delay_ms(750);
       RES = 1;
       Delay_ms(750);
       
       comlock(0x12);
       onoff(0x00);
       column(0x1c,0x5B);
       row(0x00,0x3f);
       disclock(0x91);
       ratio(0x3F);
       offset(0x00);
       start(0x00);
       remap(0x14);    /*set in Horizontal incriment mode aka Row Major Addressing*/
       GPIO(0x00);
       funsel(0x01);
       disen(0xA0, 0xFD);
       contrast(0x9F);
       master(0x0F);
       LGST();
       phase(0xE2);
       disenb(0x20);
       prevolt(0x1F);
       preper(0x08);
       vcom(0x07);
       mode(0x02);
       partial(0x01, 0x00 ,0x00);
       Clear_OLED();
       onoff(0x01);
    }


    void column(unsigned char a, unsigned char b) {            //
       OLED_command(0x15);                 //Set Column Address
       OLED_data(a);                    //Default - 00
       OLED_data(b);                    //total columns divided by 2 (Default 77)
    }

    void row(unsigned char a, unsigned char b) {            //
       OLED_command(0x75);                 // Row Address
       OLED_data(a);                    // default 00
       OLED_data(b);                       // default 7F
    }

    void wram(void){                  //Write to RAM command
       OLED_command(0x5c);
    }


    /******************************************************************
       Function Name:    Clear_OLED                               
       Return Value:                                             
       Parameters:                            
       Description:      Clears OLED display
    ******************************************************************/
    void Clear_OLED(void) {
       unsigned char i,j;
     
       column(0x00,0x77);
       row(0x00,0x7F);
       wram();

       for(i=0;i<64;i++){
          for(j=0;j<120;j++){
             OLED_data(0x00);
             OLED_data(0x00);
          }
          for(j=0;j<120;j++){
             OLED_data(0x00);
             OLED_data(0x00);
          }
       }
    }


    /******************************************************************
       Function Name:    Data_processing                               
       Return Value:                                             
       Parameters:       temp                       
       Description:      turns 1byte B/W data to 4 btyes gray data for
                   display on OLED Display
    ******************************************************************/
    void Data_processing(unsigned char temp){   

          switch(temp >> 6){                     //Comes from New Haven Display sample code. Was in Image routine.
             case 0:
                OLED_data(0x00);
                break;
             case 1:
                OLED_data(0x0F);
                break;
             case 2:
                OLED_data(0xF0);
                break;
             case 3:
                OLED_data(0xFF);
                break;
             default:
                break;
          }
             
          switch((temp >> 4) & 0x03){
             case 0:
                OLED_data(0x00);
                break;
             case 1:
                OLED_data(0x0F);
                break;
             case 2:
                OLED_data(0xF0);
                break;
             case 3:
                OLED_data(0xFF);
                break;
             default:
                break;
          }
                 
          switch((temp >> 2) & 0x03){
             case 0:
                OLED_data(0x00);
                break;
             case 1:
                OLED_data(0x0F);
                break;
             case 2:
                OLED_data(0xF0);
                break;
             case 3:
                OLED_data(0xFF);
                break;
             default:
                break;
          }
             
          switch((temp) & 0x03){
             case 0:
                OLED_data(0x00);
                break;
             case 1:
                OLED_data(0x0F);
                break;
             case 2:
                OLED_data(0xF0);
                break;
             case 3:
                OLED_data(0xFF);
                break;
             default:
                break;
          }
    }


    /******************************************************************
       Function Name:    OLED_JIS0208                               
       Return Value:                                             
       Parameters:       character, oled_column, line                       
       Description:      Gets character data from the Multi-Font IC of the OLED Display
    ******************************************************************/
    void OLED_JIS0208 (int character, unsigned char oled_column, char line){

       unsigned char MSB, LSB, byte1, byte2, byte3;
       unsigned char readByte, h, i, j, k, m, n;
       unsigned char colSta, colFin, rowSta, rowFin;
       unsigned char FontBuffer[32];
       unsigned char RotatedFont[4][8];
       unsigned char z = 0;                     //Make sure z always starts at 0.
       
       unsigned long Address = 0;                  //unsigned long is 32-bits
       
        //Need to split character into 2 8-bit words MSB and LSB   
       MSB = (character >>  & 0xFF;               //Could define each or the array as int or char or whatever
       LSB = character & 0xFF;
       
        MSB = MSB - 0x21;                        //Need to adjust to the reference of 0x0000 before the Address calculation
       LSB = LSB - 0x21;
       
       //Parameters: JIS0208 Japanese                                 
       //MSB: Higher byte of JIS code               I think we should use Japanese JIS 0208
       //LSB: Lower byte of JIS code               This will include English and the Infinity symbol
       //Address: Address of character data         Note though ALL characters will be double height 15x16 pixels
       //if((MSB >= 0x01 && MSB <= 0x5E) && (LSB >= 0x01 && LSB <= 0x5E)){
           
            Address = MSB * 0x5E;
            Address = Address + LSB;
            Address = Address * 0x20;
            Address = Address + 0x077C80;


       //To split the resulting number into bytes
       byte1 = (Address >> 16) & 0xFF;               
       byte2 = (Address >>  & 0xFF;               //uses bitshifting and Bitwise AND to form 8-bit values
       byte3 = Address & 0xFF;      
       
       //Send READ command and Address to Multi-Font IC.
        OLEDen = 1;
       MuFen = 0;                              //make rc5 of PIC18 go low to enable the Multi-Font IC
       MultiFont_OUT(0x0B);                      //READ command      This SPI_OUT is for the Multi-Font IC NOT the OLED
       MultiFont_OUT(byte1);                      //Address Byte1 (MSB)      
       MultiFont_OUT(byte2);                      //Address Byte2            
       MultiFont_OUT(byte3);                      //Address Byte3 (LSB)      
       MultiFont_OUT(0xFF);                      //Dummy Byte         Datasheet says 0x00, but their example has 0xFF. 0xFF is Correct.
       
       for(i = 0 ; i < 32 ; i++ ){                  //For i number of bytes to gather from Multi-Font IC.  In this case its 32.
          FontBuffer = MultiFont_IN();
       }   
       
       MuFen = 1;                              //make rc5 of PIC18 go high to disable the Multi-Font IC
       OLEDen = 0;
       
       //Need to Rotate the BitMap for each character couter-clockwise.
       //To do this we will break the 16x16 image apart into 4 8x8 bit blocks.
       //Image 0 is bytes 0-7.  Image 1 is bytes 8-15.
       //Image 2 is bytes 16-23.  Image 3 is bytes 24-31.
       for(m = 0; m < 4; m++){                     //There are 4 8x8 bit blocks to be rotated
          for(n = 0; n < 8; n++){                  //Make sure the RotatedFont array is filled with 0.
             RotatedFont[m][n] = 0;                     //m represents each image. n represents each byte in that image
          }
       }
       
       for(h = 0; h < 4; h++) {                  //There are 4 8x8 bit blocks to be rotated.
          for(k = 0; k < 8; k++) {               //There are 8 bytes per image
             for(j = 0; j < 8; j++) {            //There are 8 bits per byte
                
                if(FontBuffer[((h*+j)] & 1<<k){    //Use bitswise operations to break and reform the bytes
                   RotatedFont[h][k] |= 1<<(7-j);       //And form it into an array
                }
                
             }
          }
       }
       
       //End of rotate functions
       
        rowSta = ((line-1)*16);                     //gives row value to lines starting with count 1.
       
       colSta = oled_column + 28;                  //28 is the 0 column reference
       colFin = colSta + 3;                     //Each character is 16 pixels wide or 2 double hex numbers.  That is 4 columns. So colSta and 3 more.
       
       rowFin = rowSta + 15;                     //Each character is 16 rows tall. So oled_row and 15 more.
       
       column(colSta, colFin);                     //Set column address from Column Start to Column Finish
       row(rowSta, rowFin);                     //Set row address from oled_row (the start row) to Row Finish
       
       wram();
       
       //Now we display the rotated image from the 2D array.
       for(i = 0; i < 8; i++){                     //We have two arrays of 8 1-byte characters each
                                        
          Data_processing(RotatedFont[0]);            //First the top half of the image
          Data_processing(RotatedFont[1]);            //We need Image0B0, Image1B0, Image0B1, Image1B1, Image0B2, ..., Image1B7
        }
       
       for(i = 0; i < 8; i++){                     //Again we have two arrays of 8 1-byte characters each
                                           //Now the bottom half of the image.
          Data_processing(RotatedFont[2]);            //We need Image2B0, Image3B0, Image2B1, Image3B1, Image2B2, ..., Image3B7
          Data_processing(RotatedFont[3]);
        }
    }

       
    /******************************************************************
       Function Name: display_oled_init                                         
       Return Value:  void                                         
       Parameters:    void                     
       Description:   Detects the OLED display and initializes it 
    *******************************************************************/
    void display_oled_init(void){

        unsigned char m;
        unsigned char q = 1;
        unsigned char n;
        unsigned short long character;
        unsigned char charcolumn;
       unsigned char num_char = 16;               //Maximum characters per line.
       
       Delay_ms(250);
       
        OLED_Init();

        int init_text[2][16] = {{0x2121, 0x2121, 0x2349, 0x236E, 0x2369, 0x2374, 0x2369, 0x2361, 0x236C, 0x2369, 0x237A, 0x2369, 0x236E, 0x2367, 0x2121, 0x2121},
                         {0x2121, 0x2350, 0x236C, 0x2365, 0x2361, 0x2373, 0x2365, 0x2124, 0x2121, 0x2377, 0x2361, 0x2369, 0x2374, 0x2125, 0x2121, 0x2121}};
                                           //Displays 'Intializing' on line 2, and 'Please, wait.' on line 3.
                                           //line 3 needs to be shifted by half a character to center under line 2.
     
       for(m = 0; m < num_char; m++){               //num_char should be changed to the exact number of characters in line_text
           
          charcolumn = (m * 4);                  //each nibble is a column, a byte is 2 columns. Each charater is 2 Bytes wide
          OLED_JIS0208(init_text[0][m], charcolumn, 2);
          charcolumn = charcolumn + 2;            //Shifts charcolumn over by 2 columns (half a character width).
          OLED_JIS0208(init_text[1][m], charcolumn, 3);      
       }

       Delay_ms(1500);
       
       Clear_OLED();                           //clears oled display
    }


    /******************************************************************
       Function Name:    OLED_ASCII                               
       Return Value:                                             
       Parameters:       *pAscii, colS, rowS, FontType)                     
       Description:      displays ASCII characters in one of three font types
    ******************************************************************/
    void OLED_ASCII (unsigned char *pAscii, unsigned char colS, unsigned char rowS, unsigned char FontType){      
       
       unsigned char readByte, h, i, j, k, m, n;
       unsigned char RotatedFont[2][8];
       unsigned char FontBuffer[16];               //characters have 8 bytes of data
       unsigned long Address;                     //unsigned char is 8-bits or 1 byte, Address will be 3 bytes
       unsigned char colF, rowF, block;
       unsigned char MSB, LSB, byte1, byte2, byte3;
       
       //Parameters: Ascii code
       block = 1;
       
       Address = (*pAscii - 0x20);
       Address = Address * 8;
       colF = colS + 1;                     //All 3 Font Types are 8-bits wide. Thats 2 columns.
       
       if (FontType == 1){                     //5x7 Font
          rowF = rowS + 7;                     //Each 5x7 character covers 8x8 pixels. Thats 8 rows and 2 columns.                     
       }
       
       else if (FontType == 2){               //7x8 Font
          Address = Address + 768;
          rowF = rowS + 7;                     //Each 7x8 character covers 8x8 pixels. Thats 8 rows and 2 columns.                     
       }
       
       else if (FontType == 3){               //8x16 Font
          Address = Address * 2;
          Address = Address + 1536;
          rowF = rowS + 15;                     //Each 8x16 character covers 8x16 pixels. Thats 16 rows and 2 columns.
          block = 2;
       }
       
       
       //To split the resulting number into bytes
       byte1 = (Address >> 16) & 0xFF;               
       byte2 = (Address >>  & 0xFF;               //uses bitshifting and Bitwise AND to form 8-bit values
       byte3 = Address & 0xFF;   
       
       
       for(m = 0; m < 2; m++){                     //There are 4 8x8 bit blocks to be rotated
          for(n = 0; n < 8; n++){                  //Make sure the Temp array is filled with 0.
             RotatedFont[m][n] = 0;                     //m represents each image. n represents each byte in that image
          }
       }
       
       //Send READ command and Address to Multi-Font IC.
        OLEDen = 1;
       MuFen = 0;                              //make rc5 of PIC18 go low to enable the Multi-Font IC
       MultiFont_OUT(0x0B);                      //READ command      This SPI_OUT is for the Multi-Font IC NOT the OLED
       MultiFont_OUT(byte1);                      //Address Byte1 (MSB)      
       MultiFont_OUT(byte2);                      //Address Byte2            
       MultiFont_OUT(byte3);                      //Address Byte3 (LSB)      
       MultiFont_OUT(0xFF);                      //Dummy Byte         Datasheet says 0x00, but their example has 0xFF. 0xFF is Correct.
       
       if (block == 1){
          for(i = 0 ; i < 8 ; i++ ){               //For i number of bytes to gather from Multi-Font IC.  In this case its 8.
             FontBuffer = MultiFont_IN();             //read one byte From the Multi-Font IC
          }      
       }
       
       else if (block == 2){
          for(i = 0 ; i < 16 ; i++ ){               //For i number of bytes to gather from Multi-Font IC.  In this case its 8.
             FontBuffer = MultiFont_IN();            //read one byte From the Multi-Font IC
          }      
       }
       
       MuFen = 1;                           //make rc5 of PIC18 go high to disable the Multi-Font IC
       OLEDen = 0;
       
       //Need to rotate the character counter-clockwise   
       for(h = 0; h < block; h++) {                  //There are 4 8x8 bit blocks to be rotated.
          for(k = 0; k < 8; k++) {               //There are 8 bytes per image
             for(j = 0; j < 8; j++) {            //There are 8 bits per byte
                
                if(FontBuffer[((h*+j)] & 1<<k){    //Use bitswise operations to break and reform the bytes
                   RotatedFont[h][k] |= 1<<(7-j);       //And form it into an array
                }
                
             }
          }
       }
       //End of rotate functions
             
       column(colS, colF);                     //Set column address from Column Start to Column Finish
       row(rowS, rowF);                     //Set row address from oled_row (the start row) to Row Finish
       
       wram();
       
       for(h = 0; h < block; h++) {
          for(i = 0 ; i < 8 ; i++ ){                //for the 8 bytes of font data
             Data_processing(RotatedFont[h]);       //write byte to display
          }
       }
    }


    /******************************************************************
       Function Name:    OLED_String                               
       Return Value:                                             
       Parameters:       *pStr, colS, rowS, FontType)                     
       Description:      displays a string of ASCII characters in one of three font types
    ******************************************************************/
    void OLED_String(unsigned char *pStr, unsigned char col, unsigned char rowS, unsigned char FontType){

        unsigned char colS;
       
       colS = col + 28;                  //28 is the 0 column reference
        while(1)
        {
            if (*pStr == 0)
            {
                return;
            }

          OLED_ASCII (pStr, colS, rowS, FontType);
          colS += 2;
          pStr += 1;             
           
        }   
    }
    0
  • Kon-L

    As promised, here is the complete code! It is split in 2 parts due to size limitations of attachments.  Also NHD does not allow txt or c files to be attached, so I have it in pdf files.  Again I am using a PIC18F26J50 for this project with a 16MHz crystal and NHD-2.8-25664UMB3 in 4 wire serial mode(SPI).  It is compiled using Microchip's XC8 compiler.
    Part 2 to follow!

     

    0
  • Kon-L

    Here is Part 2! 

    1
    2 /*************************************************************
    3 ************END*OLED*INITIALIZATION*FUNCTIONS*****************
    4 *************************************************************/
    5
    6
    7 void disp(void){ //appears to be a checkerboard pattern display
    8 unsigned char i,j;
    9
    10 column(0x00,0x77);
    11 row(0x00,0x7F);
    12 wram();
    13
    14 for(i=0;i<64;i++){
    15 for(j=0;j<120;j++){
    16 OLED_data(0xF0);
    17 OLED_data(0xF0);
    18 }
    19 for(j=0;j<120;j++){
    20 OLED_data(0x0F);
    21 OLED_data(0x0F);
    22 }
    23 }
    24 }
    25
    26
    27 /******************************************************************
    28 Function Name: Clear_OLED
    29 Return Value:
    30 Parameters:
    31 Description: Clears OLED display
    32 ******************************************************************/
    33 void Clear_OLED(void) {
    34 unsigned char i,j;
    35
    36 column(0x00,0x77);
    37 row(0x00,0x7F);
    38 wram();
    39
    40 for(i=0;i<64;i++){
    41 for(j=0;j<120;j++){
    42 OLED_data(0x00);
    43 OLED_data(0x00);
    44 }
    45 for(j=0;j<120;j++){
    46 OLED_data(0x00);
    47 OLED_data(0x00);
    48 }
    49 }
    50 }
    51
    52
    53 /******************************************************************
    54 Function Name: Data_processing
    55 Return Value:
    56 Parameters: temp
    57 Description: turns 1byte B/W data to 4 btyes gray data for
    58 display on OLED Display
    59 ******************************************************************/
    60 void Data_processing(unsigned char temp){
    61
    62 switch(temp >> 6){ //Comes from New Haven Display sample code. Was in Image routine.
    63 case 0:
    64 OLED_data(0x00);
    65 break;
    66 case 1:
    67 OLED_data(0x0F);
    68 break;
    69 case 2:
    70 OLED_data(0xF0);
    71 break;
    72 case 3:
    73 OLED_data(0xFF);
    74 break;
    75 default:
    76 break;
    77 }
    78
    79 switch((temp >> 4) & 0x03){
    80 case 0:
    81 OLED_data(0x00);
    82 break;
    83 case 1:
    84 OLED_data(0x0F);
    85 break;
    86 case 2:
    87 OLED_data(0xF0);
    88 break;
    89 case 3:
    90 OLED_data(0xFF);
    91 break;
    92 default:
    93 break;
    94 }
    95
    96 switch((temp >> 2) & 0x03){
    97 case 0:
    98 OLED_data(0x00);
    99 break;
    100 case 1:
    101 OLED_data(0x0F);
    102 break;
    103 case 2:
    104 OLED_data(0xF0);
    105 break;
    106 case 3:
    107 OLED_data(0xFF);
    108 break;
    109 default:
    110 break;
    111 }
    112
    113 switch((temp) & 0x03){
    114 case 0:
    115 OLED_data(0x00);
    116 break;
    117 case 1:
    118 OLED_data(0x0F);
    119 break;
    120 case 2:
    121 OLED_data(0xF0);
    122 break;
    123 case 3:
    124 OLED_data(0xFF);
    125 break;
    126 default:
    127 break;
    128 }
    129 }
    130
    131
    132 /******************************************************************
    133 Function Name: Image
    134 Return Value:
    135 Parameters: array[]
    136 Description: Displays image contained in bitmaped array using
    137 the full 64x256 pixels of OLED Display
    138 ******************************************************************/
    139 void Image(const unsigned char array[]){
    140 int i;
    141 column(28,91);
    142 row(0,63);
    143 wram();
    144
    145 for(i = 0; i < 2048; i++){ //We have (64 rows)(64 columns)/(2 bytes)= 2048 hex characters in our array
    146 Data_processing(array[i]);
    147 }
    148
    149 }
    150
    151
    152 /******************************************************************
    153 Function Name: Delay_ms
    154 Return Value:
    155 Parameters: num_ms
    156 Description: Creates a millisecond delay
    157 ******************************************************************/
    158 void Delay_ms(long num_ms){
    159 long n;
    160
    161 for(n = 0; n < num_ms; n++){
    162 INTCONbits.TMR0IF = 0; //Clear flag
    163 TMR0H = 0xFC; //We only count from FC18h to FFFF
    164 TMR0L = 0x1A; //Deducting one because each line takes time to execute also
    165 while(!INTCONbits.TMR0IF); //Wait for timer flag to set
    166 }
    167 }
    168
    169
    170 /******************************************************************
    171 Function Name: OLED_JIS0208
    172 Return Value:
    173 Parameters: character, oled_column, line
    174 Description: Gets character data from the Multi-Font IC of the OLED Display
    175 ******************************************************************/
    176 void OLED_JIS0208 (int character, unsigned char oled_column, char line){
    177
    178 unsigned char MSB, LSB, byte1, byte2, byte3;
    179 unsigned char readByte, h, i, j, k, m, n;
    180 unsigned char colSta, colFin, rowSta, rowFin;
    181 unsigned char FontBuffer[32];
    182 unsigned char RotatedFont[4][8];
    183 unsigned char z = 0; //Make sure z always starts at 0.
    184
    185 unsigned long Address = 0; //unsigned long is 32-bits
    186
    187 //Need to split character into 2 8-bit words MSB and LSB
    188 MSB = (character >> 8) & 0xFF; //Could define each or the array as int or char or whatever
    189 LSB = character & 0xFF;
    190
    191 MSB = MSB - 0x21; //Need to adjust to the reference of 0x0000 before the Address calculation
    192 LSB = LSB - 0x21;
    193
    194 //Parameters: JIS0208 Japanese
    195 //MSB: Higher byte of JIS code I think we should use Japanese JIS 0208
    196 //LSB: Lower byte of JIS code This will include English and the Infinity symbol
    197 //Address: Address of character data Note though ALL characters will be double height 15x16 pixels
    198 //if((MSB >= 0x01 && MSB <= 0x5E) && (LSB >= 0x01 && LSB <= 0x5E)){
    199
    200 Address = MSB * 0x5E;
    201 Address = Address + LSB;
    202 Address = Address * 0x20;
    203 Address = Address + 0x077C80;
    204
    205
    206 //To split the resulting number into bytes
    207 byte1 = (Address >> 16) & 0xFF;
    208 byte2 = (Address >> 8) & 0xFF; //uses bitshifting and Bitwise AND to form 8-bit values
    209 byte3 = Address & 0xFF;
    210
    211 //Send READ command and Address to Multi-Font IC.
    212 OLEDen = 1;
    213 MuFen = 0; //make rc5 of PIC18 go low to enable the Multi-Font IC
    214 MultiFont_OUT(0x0B); //READ command This SPI_OUT is for the Multi-Font IC NOT the OLED
    215 MultiFont_OUT(byte1); //Address Byte1 (MSB)
    216 MultiFont_OUT(byte2); //Address Byte2
    217 MultiFont_OUT(byte3); //Address Byte3 (LSB)
    218 MultiFont_OUT(0xFF); //Dummy Byte Datasheet says 0x00, but their example has 0xFF. 0xFF is Correct.
    219
    220 for(i = 0 ; i < 32 ; i++ ){ //For i number of bytes to gather from Multi-Font IC. In this case its 32.
    221 FontBuffer[i] = MultiFont_IN();
    222 }
    223
    224 MuFen = 1; //make rc5 of PIC18 go high to disable the Multi-Font IC
    225 OLEDen = 0;
    226
    227 //Need to Rotate the BitMap for each character couter-clockwise.
    228 //To do this we will break the 16x16 image apart into 4 8x8 bit blocks.
    229 //Image 0 is bytes 0-7. Image 1 is bytes 8-15.
    230 //Image 2 is bytes 16-23. Image 3 is bytes 24-31.
    231 for(m = 0; m < 4; m++){ //There are 4 8x8 bit blocks to be rotated
    232 for(n = 0; n < 8; n++){ //Make sure the RotatedFont array is filled with 0.
    233 RotatedFont[m][n] = 0; //m represents each image. n represents each byte in that image
    234 }
    235 }
    236
    237 for(h = 0; h < 4; h++) { //There are 4 8x8 bit blocks to be rotated.
    238 for(k = 0; k < 8; k++) { //There are 8 bytes per image
    239 for(j = 0; j < 8; j++) { //There are 8 bits per byte
    240
    241 if(FontBuffer[((h*8)+j)] & 1<<k){ //Use bitswise operations to break and reform the bytes
    242 RotatedFont[h][k] |= 1<<(7-j); //And form it into an array
    243 }
    244
    245 }
    246 }
    247 }
    248
    249 //End of rotate functions
    250
    251 rowSta = ((line-1)*16); //gives row value to lines starting with count 1.
    252
    253 colSta = oled_column + 28; //28 is the 0 column reference
    254 colFin = colSta + 3; //Each character is 16 pixels wide or 2 double hex numbers. That is 4 columns. So colSta and 3 more.
    255
    256 rowFin = rowSta + 15; //Each character is 16 rows tall. So oled_row and 15 more.
    257
    258 column(colSta, colFin); //Set column address from Column Start to Column Finish
    259 row(rowSta, rowFin); //Set row address from oled_row (the start row) to Row Finish
    260
    261 wram();
    262
    263 //Now we display the rotated image from the 2D array.
    264 for(i = 0; i < 8; i++){ //We have two arrays of 8 1-byte characters each
    265
    266 Data_processing(RotatedFont[0][i]); //First the top half of the image
    267 Data_processing(RotatedFont[1][i]); //We need Image0B0, Image1B0, Image0B1, Image1B1, Image0B2, ..., Image1B7
    268 }
    269
    270 for(i = 0; i < 8; i++){ //Again we have two arrays of 8 1-byte characters each
    271 //Now the bottom half of the image.
    272 Data_processing(RotatedFont[2][i]); //We need Image2B0, Image3B0, Image2B1, Image3B1, Image2B2, ..., Image3B7
    273 Data_processing(RotatedFont[3][i]);
    274 }
    275 }
    276
    277
    278 /******************************************************************
    279 Function Name: display_oled_init
    280 Return Value: void
    281 Parameters: void
    282 Description: Detects the OLED display and initializes it
    283 *******************************************************************/
    284 void display_oled_init(void){
    285
    286 unsigned char m;
    287 unsigned char q = 1;
    288 unsigned char n;
    289 unsigned short long character;
    290 unsigned char charcolumn;
    291 unsigned char num_char = 16; //Maximum characters per line.
    292
    293 //Delay_ms(250);
    294
    295 //OLED_Init();
    296
    297 int init_text[2][16] = {{0x2121, 0x2121, 0x2349, 0x236E, 0x2369, 0x2374, 0x2369, 0x2361, 0x236C, 0x2369, 0x237A, 0x2369, 0x236E, 0x2367, 0x2121, 0x2121},
    298 {0x2121, 0x2350, 0x236C, 0x2365, 0x2361, 0x2373, 0x2365, 0x2124, 0x2121, 0x2377, 0x2361, 0x2369, 0x2374, 0x2125, 0x2121, 0x2121}};
    299 //Displays 'Intializing' on line 2, and 'Please, wait.' on line 3.
    300 //line 3 needs to be shifted by half a character to center under line 2.
    301
    302 for(m = 0; m < num_char; m++){ //num_char should be changed to the exact number of characters in line_text
    303
    304 charcolumn = (m * 4); //each nibble is a column, a byte is 2 columns. Each charater is 2 Bytes wide
    305 OLED_JIS0208(init_text[0][m], charcolumn, 2);
    306 charcolumn = charcolumn + 2; //Shifts charcolumn over by 2 columns (half a character width).
    307 OLED_JIS0208(init_text[1][m], charcolumn, 3);
    308 }
    309
    310 //Would like to have these two lines centered. Can do this by adding blank spaces in front of each line.
    311 Delay_ms(1500);
    312
    313 Clear_OLED(); //clears oled display
    314 }
    315
    316
    317 /******************************************************************
    318 Function Name: OLED_ASCII
    319 Return Value:
    320 Parameters: *pAscii, colS, rowS, FontType)
    321 Description: displays ASCII characters in one of three font types
    322 ******************************************************************/
    323 void OLED_ASCII (unsigned char *pAscii, unsigned char colS, unsigned char rowS, unsigned char FontType){
    324
    325 unsigned char readByte, h, i, j, k, m, n;
    326 unsigned char RotatedFont[2][8];
    327 unsigned char FontBuffer[16]; //characters have 8 bytes of data
    328 unsigned long Address; //unsigned char is 8-bits or 1 byte, Address will be 3 bytes
    329 unsigned char colF, rowF, block;
    330 unsigned char MSB, LSB, byte1, byte2, byte3;
    331
    332 //Parameters: Ascii code
    333 block = 1;
    334
    335 Address = (*pAscii - 0x20);
    336 Address = Address * 8;
    337 colF = colS + 1; //All 3 Font Types are 8-bits wide. Thats 2 columns.
    338
    339 if (FontType == 1){ //5x7 Font
    340 rowF = rowS + 7; //Each 5x7 character covers 8x8 pixels. Thats 8 rows and 2 columns.
    341 }
    342
    343 else if (FontType == 2){ //7x8 Font
    344 Address = Address + 768;
    345 rowF = rowS + 7; //Each 7x8 character covers 8x8 pixels. Thats 8 rows and 2 columns.
    346 }
    347
    348 else if (FontType == 3){ //8x16 Font
    349 Address = Address * 2;
    350 Address = Address + 1536;
    351 rowF = rowS + 15; //Each 8x16 character covers 8x16 pixels. Thats 16 rows and 2 columns.
    352 block = 2;
    353 }
    354
    355
    356 //To split the resulting number into bytes
    357 byte1 = (Address >> 16) & 0xFF;
    358 byte2 = (Address >> 8) & 0xFF; //uses bitshifting and Bitwise AND to form 8-bit values
    359 byte3 = Address & 0xFF;
    360
    361
    362 for(m = 0; m < 2; m++){ //There are 4 8x8 bit blocks to be rotated
    363 for(n = 0; n < 8; n++){ //Make sure the Temp array is filled with 0.
    364 RotatedFont[m][n] = 0; //m represents each image. n represents each byte in that image
    365 }
    366 }
    367
    368 //Send READ command and Address to Multi-Font IC.
    369 OLEDen = 1;
    370 MuFen = 0; //make rc5 of PIC18 go low to enable the Multi-Font IC
    371 MultiFont_OUT(0x0B); //READ command This SPI_OUT is for the Multi-Font IC NOT the OLED
    372 MultiFont_OUT(byte1); //Address Byte1 (MSB)
    373 MultiFont_OUT(byte2); //Address Byte2
    374 MultiFont_OUT(byte3); //Address Byte3 (LSB)
    375 MultiFont_OUT(0xFF); //Dummy Byte Datasheet says 0x00, but their example has 0xFF. 0xFF is Correct.
    376
    377 if (block == 1){
    378 for(i = 0 ; i < 8 ; i++ ){ //For i number of bytes to gather from Multi-Font IC. In this case its 8.
    379 FontBuffer[i] = MultiFont_IN(); //read one byte From the Multi-Font IC
    380 }
    381 }
    382
    383 else if (block == 2){
    384 for(i = 0 ; i < 16 ; i++ ){ //For i number of bytes to gather from Multi-Font IC. In this case its 8.
    385 FontBuffer[i] = MultiFont_IN(); //read one byte From the Multi-Font IC
    386 }
    387 }
    388
    389 MuFen = 1; //make rc5 of PIC18 go high to disable the Multi-Font IC
    390 OLEDen = 0;
    391
    392 //Need to rotate the character counter-clockwise
    393 for(h = 0; h < block; h++) { //There are 4 8x8 bit blocks to be rotated.
    394 for(k = 0; k < 8; k++) { //There are 8 bytes per image
    395 for(j = 0; j < 8; j++) { //There are 8 bits per byte
    396
    397 if(FontBuffer[((h*8)+j)] & 1<<k){ //Use bitswise operations to break and reform the bytes
    398 RotatedFont[h][k] |= 1<<(7-j); //And form it into an array
    399 }
    400
    401 }
    402 }
    403 }
    404 //End of rotate functions
    405
    406 column(colS, colF); //Set column address from Column Start to Column Finish
    407 row(rowS, rowF); //Set row address from oled_row (the start row) to Row Finish
    408
    409 wram();
    410
    411 for(h = 0; h < block; h++) {
    412 for(i = 0 ; i < 8 ; i++ ){ //for the 8 bytes of font data
    413 Data_processing(RotatedFont[h][i]); //write byte to display
    414 }
    415 }
    416 }
    417
    418
    419 /******************************************************************
    420 Function Name: OLED_String
    421 Return Value:
    422 Parameters: *pStr, colS, rowS, FontType)
    423 Description: displays a string of ASCII characters in one of three font types
    424 ******************************************************************/
    425 void OLED_String(unsigned char *pStr, unsigned char col, unsigned char rowS, unsigned char FontType){
    426
    427 unsigned char colS;
    428
    429 colS = col + 28; //28 is the 0 column reference
    430 while(1)
    431 {
    432 if (*pStr == 0)
    433 {
    434 return;
    435 }
    436
    437 OLED_ASCII (pStr, colS, rowS, FontType);
    438 colS += 2;
    439 pStr += 1;
    440
    441 }
    442 }
    443
    444
    445 /******************************************************************
    446 Function Name: PICinit
    447 Return Value:
    448 Parameters:
    449 Description: Initializes PIC18F
    450 ******************************************************************/
    451 static void PICinit(void) {
    452
    453 OSCTUNE = 0x40; //enable the 96MHz PLL
    454
    455 //PORTA: all inputs, no interrupt-on-change facility
    456 //PORTA = 0;
    457 PORTA = 0x00;
    458 TRISA = 0xFF; //A all inputs
    459 ADCON0 = 0;
    460 ANCON0 = 0xFF;
    461 ANCON1 = 0x1F; //disable AD converter, all digital IO
    462
    463 //PORTB: use all-input config, use open-drain output style
    464 //The I2C pins must also be configured in input mode.
    465 //There is an Errata for several PIC18F devices, saying
    466 //that a more extensive reset is needed for I2C operation
    467 //TRISB = 0xCF; //1. first make I2C SDA and SCL as output
    468 //Only for SPI on MSSP2!!!
    469 //TRISBbits.RB0 = 0xFF; // 2.now make all pins inputs
    470 PORTB = 0x00;
    471 LATBbits.LATB1 = 0; //SPI2 Clock
    472 LATBbits.LATB2 = 0; //SPI2 Data Output
    473 TRISBbits.TRISB2 = 0; //SPI2 Data Output
    474 TRISBbits.TRISB1 = 0; //SPI2 Clock
    475 TRISBbits.TRISB0 = 1; //SPI2 Data Input
    476
    477 //PORTC: all output
    478 PORTC = 0x00;
    479 LATC = 0x00;
    480 TRISC = 0x00;
    481
    482 //setup the remappable peripheral inputs:
    483 //Clear IOLOCK
    484 INTCONbits.GIE = 0;
    485 EECON2 = 0x55;
    486 EECON2 = 0xAA;
    487 PPSCONbits.IOLOCK = 0;
    488 RPINR21 = 0x03; //SPI2 Data Input -> RP3 ->RB0
    489 RPINR22 = 0x04; //SPI2 Clock Input -> RP4 ->RB1
    490 RPINR23 = 0x06; //SPI2 Slave Select -> RP6 ->RB3
    491 RPOR4 = 0x0A; //SPI2 Clock Output -> RP4 ->RB1
    492 RPOR5 = 0x09; //SPI2 Data Output -> RP5 ->RB2
    493 // Set IOLOCK
    494 EECON2 = 0x55;
    495 EECON2 = 0xAA;
    496 PPSCONbits.IOLOCK = 1;
    497 INTCONbits.GIE = 1;
    498
    499 //Timer0 OK for use, 8-bit prescale, 8- or 16-bit counter, sets TMR0IF
    500 //Timer1: enabling it locks pins RC0 and RC1 to a special-function input, cannot do that.
    501 //Timer2: 4-prescale, 4-bit post-scale, 8-bit counter&comparator, sets TMR2IF
    502 //Timer3: 3-bit prescale, 16-bit counter, allows cascading with TMR1 or TMR2
    503 //Timer4: 4-bit prescale, 8-bit count&compare, 4=bit postscale, sets TMR4IF
    504
    505 //setup Timer0 for keypad delay_ms: 4x downscale from Fosc/4 is 1MHz
    506 T0CON = 0x83; //Timer0 on, 16-bit mode, 16x prescale, on Fosc/4=4Mhz gives 1MHz= 1usec timer count
    507 INTCON2bits.TMR0IP = 1; //high priority interrupt
    508 INTCONbits.TMR0IE = 0; //for now, enabled on actual IR reception
    509
    510 //SPI2 Master to drive EEPROM and Display
    511 //LATBbits.LATB1 = 0;
    512 //TRISBbits.TRISB1 = 0; //SCK set as output
    513 //TRISBbits.TRISB0 = 1; //SDI set as input
    514 //TRISBbits.TRISB2 = 0; //SDO set as output
    515 SSP2STAT = 0x00; //power on state
    516 SSP2CON1 = 0x10; //power on state, synchronous enabled, clock idle low, clock=Fosc/4
    517 SSP2CON1bits.SSPEN = 1;
    518
    519 //Set-up HVLD module: mute audio when power-supply unexpectedly drops
    520 //Programmed HVLD value '1001' corresponds to 2.6V (range 2.47 - 2.73)
    521 //Take a small safety margin on that voltage level,
    522 //choosing it too low, can cause a too late audio mute.
    523 //(in time is as long as the audio opamps have reasonable supply voltage)
    524 HLVDCON = 0x79;
    525 PIR2bits.LVDIF = 0;
    526 IPR2bits.LVDIP = 1;
    527 PIE2bits.LVDIE = 0; //Enable only after power has stabelized
    528 }
    529
    530 /*************************************************************
    531 **********************MAIN*FUNCTIONS**************************
    532 *************************************************************/
    533 void main(void) {
    534
    535 unsigned char str[24];
    536
    537 PICinit();
    538 Delay_ms(1000);
    539 init1();
    540 Delay_ms(500);
    541
    542 while(1){
    543 display_oled_init(); //uses Multi-Font IC.
    544 Delay_ms(10); //clears itself!
    545
    546 Delay_ms(2500);
    547 Clear_OLED();
    548 Delay_ms(10);
    549
    550 OLED_JIS0208(0x4976, 4, 3); //Used to check address. Displays one kanji.
    551 Delay_ms(1000);
    552 Clear_OLED();
    553 Delay_ms(10);
    554
    555 OLED_String("Hello!", 0, 0, 1);
    556 OLED_String("This is a test", 0, 16, 2);
    557 OLED_String("Showing three fonts", 0, 32, 3);
    558 Delay_ms(3000);
    559 Clear_OLED();
    560 Delay_ms(10);
    561
    562 disp(); //displays tiny checkerboard pattern
    563 Delay_ms(1000);
    564 Clear_OLED();
    565 Delay_ms(10);
    566
    567 Image(NHD25664test); //Image does display
    568 Delay_ms(700);
    569 Clear_OLED();
    570 Delay_ms(10);
    571 }
    572 }
    « Last Edit: November 13, 2017, 01:16:45 AM by Kon-L »
    0
  • andres888

    Hi,

    Displays built-in IC controllers have limited functionalities comparing their own original version because they have some of their original pins wired to a certain configuration. You can guess such configuration by comparing the original controller pin-out and the display pin-out.
    Understanding the IC controller built-in configuration is the first step before coding the display initialization.
    You can find the display specs at https://newhavendisplay.com/content/specs/NHD-3.12-25664UMB3.pdf  and the original IC specs at http://www.displayfuture.com/Display/datasheet/controller/SSD1322.pdf .

    Anyway it's always good fun playing with displays.

    Good luck!

    0

Please sign in to leave a comment.