Hexiwear OLED Display Driver

Dependents:   Hexi_OLED_TextImage_Example Hexi_OLED_Text_Example Hexi_OLED_Image_Example security-console-app ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Hexi_OLED_SSD1351.cpp Source File

Hexi_OLED_SSD1351.cpp

00001 /** OLED Display Driver for Hexiwear
00002  *  This file contains OLED driver functionality for drawing images and text
00003  *
00004  * Redistribution and use in source and binary forms, with or without modification,
00005  * are permitted provided that the following conditions are met:
00006  *
00007  * Redistributions of source code must retain the above copyright notice, this list
00008  * of conditions and the following disclaimer.
00009  *
00010  * Redistributions in binary form must reproduce the above copyright notice, this
00011  * list of conditions and the following disclaimer in the documentation and/or
00012  * other materials provided with the distribution.
00013  *
00014  * Neither the name of NXP, nor the names of its
00015  * contributors may be used to endorse or promote products derived from this
00016  * software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00021  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00022  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00024  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00025  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00026  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00027  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  *
00029  * visit: http://www.mikroe.com and http://www.nxp.com
00030  *
00031  * get support at: http://www.mikroe.com/forum and https://community.nxp.com
00032  *
00033  * Project HEXIWEAR, 2015
00034  */
00035 
00036 #include "OLED_types.h"
00037 #include "OLED_info.h"
00038 #include "mbed.h"
00039 #include "Hexi_OLED_SSD1351.h"
00040 #include "OpenSans_Font.h"
00041    
00042 const init_cmd_t seq[] = {
00043     OLED_CMD_SET_CMD_LOCK,  CMD_BYTE,
00044     OLED_UNLOCK,            DATA_BYTE,
00045     OLED_CMD_SET_CMD_LOCK,  CMD_BYTE,
00046     OLED_ACC_TO_CMD_YES,    DATA_BYTE,
00047     OLED_CMD_DISPLAYOFF,    CMD_BYTE,
00048     OLED_CMD_SET_OSC_FREQ_AND_CLOCKDIV, CMD_BYTE,
00049     0xF1,                   DATA_BYTE,
00050     OLED_CMD_SET_MUX_RATIO, CMD_BYTE,
00051     0x5F,                   DATA_BYTE,
00052     OLED_CMD_SET_REMAP,     CMD_BYTE,
00053     OLED_REMAP_SETTINGS,    DATA_BYTE,
00054     OLED_CMD_SET_COLUMN,    CMD_BYTE,
00055     0x00,                   DATA_BYTE,
00056     0x5F,                   DATA_BYTE,
00057     OLED_CMD_SET_ROW,       CMD_BYTE,
00058     0x00,                   DATA_BYTE,
00059     0x5F,                   DATA_BYTE,
00060     OLED_CMD_STARTLINE,     CMD_BYTE,
00061     0x80,                   DATA_BYTE,
00062     OLED_CMD_DISPLAYOFFSET, CMD_BYTE,
00063     0x60,                   DATA_BYTE,
00064     OLED_CMD_PRECHARGE,     CMD_BYTE,
00065     0x32,                   CMD_BYTE,
00066     OLED_CMD_VCOMH,         CMD_BYTE,
00067     0x05,                   CMD_BYTE,
00068     OLED_CMD_NORMALDISPLAY, CMD_BYTE,
00069     OLED_CMD_CONTRASTABC,   CMD_BYTE,
00070     0x8A,                   DATA_BYTE,
00071     0x51,                   DATA_BYTE,
00072     0x8A,                   DATA_BYTE,
00073     OLED_CMD_CONTRASTMASTER, CMD_BYTE,
00074     0xCF,                   DATA_BYTE,
00075     OLED_CMD_SETVSL,        CMD_BYTE,
00076     0xA0,                   DATA_BYTE,
00077     0xB5,                   DATA_BYTE,
00078     0x55,                   DATA_BYTE,
00079     OLED_CMD_PRECHARGE2,    CMD_BYTE,
00080     0x01,                   DATA_BYTE,
00081     OLED_CMD_DISPLAYON,     CMD_BYTE
00082     };
00083 
00084 
00085     
00086 SSD1351::SSD1351(PinName mosiPin,PinName sclkPin,PinName pwrPin, PinName csPin,PinName rstPin, PinName dcPin): spi(mosiPin,NC,sclkPin) , power(pwrPin), cs(csPin),rst(rstPin),dc(dcPin) 
00087 {
00088 
00089     spi.frequency(8000000);
00090 
00091     
00092     dc =0;
00093     PowerOFF();
00094     wait_ms(1);
00095     rst = 0 ; 
00096     wait_ms(1);
00097     rst = 1 ;
00098     wait_ms(1);
00099     PowerON();
00100     
00101     currentChar_width  = 0,
00102     currentChar_height = 0;
00103     colorMask = COLOR_WHITE;
00104     
00105     oled_text_properties.alignParam = OLED_TEXT_ALIGN_CENTER;
00106     oled_text_properties.background = NULL;
00107     oled_text_properties.font       = OpenSans_10x15_Regular;
00108     oled_text_properties.fontColor  = COLOR_WHITE;
00109     SetTextProperties(&oled_text_properties);
00110         
00111     oled_dynamic_area.areaBuffer = NULL;
00112     oled_dynamic_area.height = 0;
00113     oled_dynamic_area.width = 0;
00114     oled_dynamic_area.xCrd = 0;
00115     oled_dynamic_area.yCrd = 0;
00116    
00117    
00118     for (int i=0;i<39;i++) 
00119     {
00120        SendCmd(seq[i].cmd, seq[i].type);
00121     }
00122 
00123 
00124 
00125 } 
00126 
00127 
00128 SSD1351::~SSD1351(void)
00129 {
00130   //TO_DO
00131   //Run Free and zero pointers. 
00132   
00133 }
00134 
00135 
00136 
00137  
00138 void SSD1351::SendCmd(uint32_t cmd,
00139                    uint8_t isFirst)
00140 {
00141   
00142   
00143   
00144   uint8_t
00145      txSize = 1,
00146      txBuf[4];
00147 
00148   memcpy((void*)txBuf, (void*)&cmd, txSize );
00149 
00150   if (isFirst )
00151   {
00152     dc = 0;   
00153   }
00154   else
00155   {
00156     dc = 1;
00157   }
00158   
00159     cs = 0;
00160     spi.write(*txBuf);
00161     cs  = 1; 
00162    
00163 }
00164 
00165 
00166 
00167 void SSD1351::SendData ( const uint8_t* dataToSend, 
00168                            uint32_t dataSize)
00169                             
00170 {
00171     
00172 
00173   uint16_t* arrayPtr = (uint16_t*)dataToSend;
00174 
00175   for( uint32_t i = 0; i < dataSize/2; i++ )
00176   {
00177       arrayPtr[i] &= colorMask;
00178   }
00179   
00180 
00181   SendCmd( OLED_CMD_WRITERAM, CMD_BYTE );
00182   
00183   /* sending data -> set DC pin */
00184   dc = 1;
00185   cs = 0 ;
00186 
00187   const uint8_t*
00188   /* traversing pointer */ 
00189   bufPtr = dataToSend;
00190 
00191 
00192   for ( uint32_t i = 0; i < dataSize; i++)
00193   {
00194       spi.write(*bufPtr);
00195       bufPtr += 1;
00196   }
00197   
00198   cs = 1;
00199  
00200 }
00201 
00202 
00203 oled_status_t SSD1351::DrawBox (
00204                             int8_t xCrd,
00205                             int8_t yCrd,
00206                             uint8_t width,
00207                             uint8_t height,
00208                             uint16_t color
00209                           )
00210 {
00211   
00212   oled_status_t status;  
00213   oled_dynamic_area_t boxArea;
00214 
00215   boxArea.xCrd   = xCrd;
00216   boxArea.yCrd   = yCrd;
00217   boxArea.width  = width;
00218   boxArea.height = height;
00219 
00220   uint32_t
00221     boxSize = width*height;
00222 
00223   SetDynamicArea( &boxArea );
00224 
00225   /* helper pointer */
00226   uint8_t*
00227     boxBuf = (uint8_t*)oled_dynamic_area.areaBuffer;
00228 
00229   if ( NULL == boxBuf )
00230   {
00231   
00232     return OLED_STATUS_ERROR;
00233   }
00234 
00235   /* check the bounds */ 
00236   if AreCoordsNotValid( xCrd, yCrd, width, height )
00237   {
00238     status = OLED_STATUS_INIT_ERROR;
00239   }
00240 
00241   else
00242   {
00243     /* fill the buffer with color */
00244 
00245     for ( uint16_t i = 0; i < boxSize; i++ )
00246     {
00247       boxBuf[ 2*i ]     = color >> 8;
00248       boxBuf[ 2*i + 1 ] = color;
00249     }
00250 
00251     /* set the locations */
00252 
00253     /* adjust for the offset */
00254     OLED_AdjustColumnOffset(xCrd);
00255     OLED_AdjustRowOffset(yCrd);
00256 
00257     SendCmd( OLED_CMD_SET_COLUMN, CMD_BYTE);   
00258     SendCmd( xCrd, DATA_BYTE );  
00259     SendCmd( xCrd + (width-1), DATA_BYTE );
00260     SendCmd( OLED_CMD_SET_ROW, CMD_BYTE );
00261     SendCmd( yCrd, DATA_BYTE );
00262     SendCmd( yCrd + (height-1), DATA_BYTE );
00263  
00264     /* fill the GRAM */
00265     SendData( (uint8_t*)boxBuf, boxSize*OLED_BYTES_PER_PIXEL );
00266     DestroyDynamicArea();
00267    
00268   }
00269 
00270   return status;
00271 }
00272 
00273 /**
00274  * fill the entire screen
00275  * @param  color color to fill with
00276  * @return status flag
00277  */
00278 void SSD1351::FillScreen( uint16_t color )
00279 {
00280   /* fill the screen buffer with color */
00281   for ( uint16_t i = 0; i < ( OLED_SCREEN_WIDTH * OLED_SCREEN_HEIGHT ); i++ )
00282   {
00283     screenBuf[ 2*i ]     = color >> 8;
00284     screenBuf[ 2*i + 1 ] = color;
00285   }
00286 
00287   /* set the locations */
00288   SetBorders( 0, 0, OLED_SCREEN_WIDTH, OLED_SCREEN_HEIGHT );
00289 
00290   /* fill GRAM */
00291   SendData( (uint8_t*)screenBuf, OLED_SCREEN_WIDTH * OLED_SCREEN_HEIGHT * OLED_BYTES_PER_PIXEL  );
00292 
00293 }
00294 
00295 
00296 
00297 oled_status_t SSD1351::DrawPixel (
00298                                int8_t xCrd,
00299                                int8_t yCrd,
00300                               uint16_t color
00301                             )
00302 {
00303   /* check the bounds */
00304   if AreCoordsNotValid( xCrd, yCrd, 1, 1 )
00305   {
00306     return OLED_STATUS_INIT_ERROR;
00307   }
00308 
00309   else
00310   {
00311     /* set directions */
00312     SetBorders( xCrd, yCrd, OLED_SCREEN_WIDTH, OLED_SCREEN_HEIGHT);
00313 
00314     uint16_t
00315       /* swap bytes */
00316       dot = color;
00317 
00318     OLED_SwapMe(dot);
00319 
00320     /* fill the GRAM */
00321     SendData( (uint8_t*)&dot, 2 );
00322     
00323     return OLED_STATUS_SUCCESS;
00324   }
00325 }
00326 
00327 
00328 oled_status_t SSD1351::DrawScreen (
00329                                    const uint8_t* image,
00330                                           int8_t xCrd,
00331                                           int8_t yCrd,
00332                                           uint8_t width,
00333                                           uint8_t height,
00334                                 oled_transition_t transition
00335                               )
00336 {
00337   oled_status_t
00338     status = OLED_STATUS_SUCCESS;
00339 
00340   if AreCoordsNotValid( xCrd, yCrd, width, height )
00341   {
00342     return OLED_STATUS_INIT_ERROR;
00343   }
00344 
00345   switch ( transition )
00346   {
00347     case OLED_TRANSITION_NONE:        {
00348                                         /* set the locations */
00349                                         SetBorders( xCrd, yCrd, width, height);
00350 
00351                                         /* fill the GRAM */
00352                                         SendData( (const uint8_t*)image, width * height * OLED_BYTES_PER_PIXEL );                                        
00353                                         break;
00354                                       }
00355 
00356     case OLED_TRANSITION_TOP_DOWN:    {
00357                                         TopDown( image, xCrd, yCrd, width, height );
00358                                         break;
00359                                       }
00360 
00361     case OLED_TRANSITION_DOWN_TOP:    {
00362                                         DownTop( image, xCrd, yCrd, width, height );
00363                                         break;
00364                                       }
00365 
00366     case OLED_TRANSITION_LEFT_RIGHT:  {
00367                                         LeftRight( image, xCrd, yCrd, width, height );
00368                                         break;
00369                                       }
00370 
00371     case OLED_TRANSITION_RIGHT_LEFT:  {
00372                                         RightLeft( image, xCrd, yCrd, width, height );
00373                                         break;
00374                                       }
00375 
00376     default: {}
00377   }
00378 
00379   return status;
00380 }
00381 
00382 
00383 oled_status_t SSD1351::SetFont(
00384                             const uint8_t* newFont,
00385                                   uint16_t newColor
00386                           )
00387 {
00388   /* save the new values in intern variables */
00389 
00390   selectedFont           = newFont;
00391   selectedFont_firstChar = newFont[2] | ( (uint16_t)newFont[3] << 8 );
00392   selectedFont_lastChar  = newFont[4] | ( (uint16_t)newFont[5] << 8 );
00393   selectedFont_height    = newFont[6];
00394   selectedFont_color     = newColor;
00395 
00396   OLED_SwapMe( selectedFont_color );
00397 
00398   return OLED_STATUS_SUCCESS;
00399 }
00400 
00401 
00402 void SSD1351::SetDynamicArea(oled_dynamic_area_t *dynamic_area)
00403 {
00404 
00405   if( NULL == oled_dynamic_area.areaBuffer )
00406   {
00407       oled_dynamic_area.areaBuffer = (oled_pixel_t)AllocateDynamicArea( dynamic_area->width * dynamic_area->height );
00408   }
00409   else if(
00410           ( dynamic_area->height != oled_dynamic_area.height ) ||
00411           ( dynamic_area->width != oled_dynamic_area.width )
00412          )
00413   {
00414     DestroyDynamicArea();
00415     oled_dynamic_area.areaBuffer = (oled_pixel_t)AllocateDynamicArea( dynamic_area->width * dynamic_area->height );
00416   }
00417 
00418   oled_dynamic_area.xCrd   = dynamic_area->xCrd;
00419   oled_dynamic_area.yCrd   = dynamic_area->yCrd;
00420   oled_dynamic_area.width  = dynamic_area->width;
00421   oled_dynamic_area.height = dynamic_area->height;
00422 }
00423 
00424 
00425 void SSD1351::DestroyDynamicArea()
00426 {
00427     if ( NULL != oled_dynamic_area.areaBuffer )
00428     {
00429         DestroyDynamicArea( oled_dynamic_area.areaBuffer );
00430         oled_dynamic_area.areaBuffer = NULL;
00431     }
00432 }
00433 
00434 
00435 void SSD1351::SetTextProperties(oled_text_properties_t *textProperties)
00436 {
00437   oled_text_properties.font       = textProperties->font;
00438   oled_text_properties.fontColor  = textProperties->fontColor;
00439   oled_text_properties.alignParam = textProperties->alignParam;
00440   oled_text_properties.background = textProperties->background;
00441 
00442   SetFont( oled_text_properties.font, oled_text_properties.fontColor );
00443 }
00444 
00445 void SSD1351::GetTextProperties(oled_text_properties_t *textProperties)
00446 {
00447   textProperties->font        = oled_text_properties.font;      
00448   textProperties->fontColor   = oled_text_properties.fontColor;  
00449   textProperties->alignParam  = oled_text_properties.alignParam;
00450   textProperties->background  = oled_text_properties.background;
00451 }
00452 
00453 uint8_t SSD1351::GetTextWidth(const uint8_t* text)
00454 {
00455     uint8_t chrCnt = 0;
00456     uint8_t text_width  = 0;
00457 
00458     while ( 0 != text[chrCnt] )
00459     {
00460         text_width += *( selectedFont + 8 + (uint16_t)( ( text[chrCnt++] - selectedFont_firstChar ) << 2 ) );
00461         /* make 1px space between chars */
00462         text_width++;
00463     }
00464     /* remove the final space */
00465     text_width--;
00466 
00467     return text_width;
00468 }
00469 
00470 
00471 
00472 uint8_t SSD1351::CharCount(uint8_t width, const uint8_t* font, const uint8_t* text, uint8_t length)
00473 {
00474     uint8_t chrCnt = 0;
00475     uint8_t text_width  = 0;
00476     uint16_t firstChar;
00477 
00478     firstChar = font[2] | ( (uint16_t)font[3] << 8 );
00479 
00480     while ( chrCnt < length )
00481     {
00482         text_width += *( font + 8 + (uint16_t)( ( text[chrCnt++] - firstChar ) << 2 ) );
00483         if(text_width > width)
00484         {
00485             chrCnt--;
00486             break;
00487         }
00488         /* make 1px space between chars */
00489         text_width++;
00490     }
00491 
00492     return chrCnt;
00493 }
00494 
00495 
00496 
00497 
00498 oled_status_t SSD1351::AddText( const uint8_t* text,int8_t xCrd, int8_t yCrd )
00499 {
00500     uint16_t
00501         chrCnt = 0;
00502         oled_pixel_t
00503         chrBuf = NULL;
00504 
00505     uint8_t
00506         currentChar_x = 0,
00507         currentChar_y = 0;
00508 
00509     uint8_t
00510         text_height = 0,
00511         text_width  = 0;
00512 
00513     text_width = GetTextWidth(text);
00514 
00515     /*
00516      * set default values, if necessary
00517      */
00518 
00519     text_height = selectedFont_height;
00520     oled_dynamic_area_t textArea;
00521 
00522     textArea.width  = text_width;
00523     textArea.height = text_height;
00524     textArea.xCrd = xCrd;
00525     textArea.yCrd = yCrd; 
00526     SetDynamicArea(&textArea);
00527 
00528     currentChar_y = ( oled_dynamic_area.height - text_height ) >> 1;
00529 
00530     switch ( oled_text_properties.alignParam & OLED_TEXT_HALIGN_MASK )
00531     {
00532         case OLED_TEXT_ALIGN_LEFT:
00533         {
00534             currentChar_x = 0;
00535             break;
00536         }
00537 
00538         case OLED_TEXT_ALIGN_RIGHT:
00539         {
00540             currentChar_x = ( oled_dynamic_area.width - text_width );
00541             break;
00542         }
00543 
00544         case OLED_TEXT_ALIGN_CENTER:
00545         {
00546             currentChar_x += ( oled_dynamic_area.width - text_width ) >> 1 ;
00547             break;
00548         }
00549 
00550         case OLED_TEXT_ALIGN_NONE:
00551         {
00552             break;
00553         }
00554 
00555         default: {}
00556     }
00557 
00558     if ( CreateTextBackground() != OLED_STATUS_SUCCESS )
00559     {
00560         return OLED_STATUS_ERROR;
00561     }
00562 
00563     /*
00564     * write the characters into designated space, one by one
00565     */
00566 
00567     chrCnt = 0;
00568     while ( 0 != text[chrCnt] )
00569     {
00570         WriteCharToBuf( text[chrCnt++], &chrBuf );
00571 
00572         if ( NULL == chrBuf )
00573         {
00574           return OLED_STATUS_INIT_ERROR;
00575         }
00576 
00577         else
00578         {
00579           if  (
00580                         ( ( currentChar_x + currentChar_width )  > oled_dynamic_area.width )
00581                     ||  ( ( currentChar_y + currentChar_height ) > oled_dynamic_area.height )
00582               )
00583           {
00584             DestroyDynamicArea( chrBuf );
00585             chrBuf = NULL;
00586             return OLED_STATUS_ERROR;
00587           }
00588 
00589           /* copy data */
00590           oled_pixel_t
00591               copyAddr = oled_dynamic_area.areaBuffer + ( currentChar_y * oled_dynamic_area.width + currentChar_x );
00592               
00593           AddCharToTextArea( chrBuf, currentChar_width, currentChar_height, copyAddr, oled_dynamic_area.width );
00594 
00595           currentChar_x += ( currentChar_width+1 );
00596           currentChar_y += 0;
00597 
00598           DestroyDynamicArea( chrBuf );
00599           chrBuf = NULL;
00600         }
00601     }
00602 
00603     UpdateBuffer(
00604                                         oled_dynamic_area.xCrd,
00605                                         oled_dynamic_area.yCrd,
00606                                         oled_dynamic_area.width,
00607                                         oled_dynamic_area.height,
00608                                         (const uint8_t*)oled_dynamic_area.areaBuffer
00609                                     );
00610 
00611     return OLED_STATUS_SUCCESS;
00612 }
00613 
00614 
00615 oled_status_t SSD1351::AddText( const uint8_t* text)
00616 {
00617     uint16_t
00618         chrCnt = 0;
00619         oled_pixel_t
00620         chrBuf = NULL;
00621 
00622     uint8_t
00623         currentChar_x = 0,
00624         currentChar_y = 0;
00625 
00626     uint8_t
00627         text_height = 0,
00628         text_width  = 0;
00629 
00630     text_width = GetTextWidth(text);
00631 
00632     /**
00633      * set default values, if necessary
00634      */
00635 
00636     text_height = selectedFont_height;
00637   
00638     /* Disable this for now.Generated Fontwidth supposedly a lot wider than it really is*/
00639     #if 0
00640    if  (( oled_dynamic_area.width  < text_width )||( oled_dynamic_area.height < text_height ))
00641    {
00642         oled_dynamic_area_t textArea;
00643         textArea.width  = text_width;
00644         textArea.height = text_height;
00645         SetDynamicArea(&textArea);
00646    }
00647    #endif 
00648   
00649     currentChar_y = ( oled_dynamic_area.height - text_height ) >> 1;
00650 
00651     switch ( oled_text_properties.alignParam & OLED_TEXT_HALIGN_MASK )
00652     {
00653         case OLED_TEXT_ALIGN_LEFT:
00654         {
00655             currentChar_x = 0;
00656             break;
00657         }
00658 
00659         case OLED_TEXT_ALIGN_RIGHT:
00660         {
00661             currentChar_x = ( oled_dynamic_area.width - text_width );
00662             break;
00663         }
00664 
00665         case OLED_TEXT_ALIGN_CENTER:
00666         {
00667             currentChar_x += ( oled_dynamic_area.width - text_width ) >> 1 ;
00668             break;
00669         }
00670 
00671         case OLED_TEXT_ALIGN_NONE:
00672         {
00673             break;
00674         }
00675 
00676         default: {}
00677     }
00678 
00679     if ( CreateTextBackground() != OLED_STATUS_SUCCESS )
00680     {
00681         return OLED_STATUS_ERROR;
00682     }
00683 
00684     /**
00685     * write the characters into designated space, one by one
00686     */
00687 
00688     chrCnt = 0;
00689     while ( 0 != text[chrCnt] )
00690     {
00691         WriteCharToBuf( text[chrCnt++], &chrBuf );
00692 
00693         if ( NULL == chrBuf )
00694         {
00695           return OLED_STATUS_INIT_ERROR;
00696         }
00697 
00698         else
00699         {
00700           if  (
00701                         ( ( currentChar_x + currentChar_width )  > oled_dynamic_area.width )
00702                     ||  ( ( currentChar_y + currentChar_height ) > oled_dynamic_area.height )
00703               )
00704           {
00705             DestroyDynamicArea( chrBuf );
00706             chrBuf = NULL;
00707             return OLED_STATUS_ERROR;
00708           }
00709 
00710           /* copy data */ 
00711           oled_pixel_t
00712               copyAddr = oled_dynamic_area.areaBuffer + ( currentChar_y * oled_dynamic_area.width + currentChar_x );
00713               
00714           AddCharToTextArea( chrBuf, currentChar_width, currentChar_height, copyAddr, oled_dynamic_area.width );
00715 
00716           currentChar_x += ( currentChar_width+1 );
00717           currentChar_y += 0;
00718 
00719           DestroyDynamicArea( chrBuf );
00720           chrBuf = NULL;
00721         }
00722     }
00723 
00724     UpdateBuffer(
00725                                         oled_dynamic_area.xCrd,
00726                                         oled_dynamic_area.yCrd,
00727                                         oled_dynamic_area.width,
00728                                         oled_dynamic_area.height,
00729                                         (const uint8_t*)oled_dynamic_area.areaBuffer
00730                                     );
00731 
00732     return OLED_STATUS_SUCCESS;
00733 }
00734 
00735 
00736 
00737 oled_status_t SSD1351::DrawText( const uint8_t* text)
00738 {
00739 
00740   if ( NULL == text )
00741   {
00742     return OLED_STATUS_ERROR;
00743   }
00744 
00745   AddText(text);
00746   /* set the locations */
00747   SetBorders( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height );
00748   /* fill the GRAM */
00749   SendData( (const uint8_t*)oled_dynamic_area.areaBuffer, oled_dynamic_area.width * oled_dynamic_area.height * OLED_BYTES_PER_PIXEL );
00750 
00751   //free( currentTextAreaImage );
00752   return OLED_STATUS_SUCCESS;
00753 }
00754 
00755 
00756 void SSD1351::GetImageDimensions(uint8_t *width, uint8_t *height, const uint8_t* image)
00757 {
00758   *height = image[2] + (image[3] << 8);
00759   *width  = image[4] + (image[5] << 8);
00760 }
00761 
00762 
00763 oled_status_t SSD1351::AddImage ( const uint8_t* image )
00764 {
00765   oled_status_t
00766     status = OLED_STATUS_SUCCESS;
00767 
00768   /* check the bounds */
00769   if AreCoordsNotValid( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height )
00770   {
00771     status = OLED_STATUS_INIT_ERROR;
00772   }
00773 
00774   else
00775   {
00776     Swap( (oled_pixel_t)oled_dynamic_area.areaBuffer, BMP_SkipHeader(image), oled_dynamic_area.width*oled_dynamic_area.height );
00777 
00778     /* update the main screen buffer */
00779     UpdateBuffer( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height, (const uint8_t *)oled_dynamic_area.areaBuffer );
00780   }
00781 
00782   return status;
00783 }
00784 
00785 
00786 oled_status_t SSD1351::AddImage ( const uint8_t* image, int8_t xCrd, int8_t yCrd )
00787 {
00788   oled_status_t
00789     status = OLED_STATUS_SUCCESS;
00790 
00791   oled_dynamic_area_t  image_dynamicArea;
00792 
00793   image_dynamicArea.xCrd = xCrd;
00794   image_dynamicArea.yCrd = yCrd;
00795 
00796   GetImageDimensions(&image_dynamicArea.width, &image_dynamicArea.height, image);
00797   SetDynamicArea(&image_dynamicArea);
00798 
00799   /* check the bounds */
00800   if AreCoordsNotValid( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height )
00801   {
00802     status = OLED_STATUS_INIT_ERROR;
00803   }
00804 
00805   else
00806   {
00807     Swap( (oled_pixel_t)oled_dynamic_area.areaBuffer, BMP_SkipHeader(image), oled_dynamic_area.width*oled_dynamic_area.height );
00808 
00809     /* update the main screen buffer */
00810     UpdateBuffer( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height, (const uint8_t *)oled_dynamic_area.areaBuffer );
00811   }
00812 
00813   return status;
00814 }
00815 
00816 
00817 
00818 oled_status_t SSD1351::DrawImage ( const uint8_t* image )
00819 {
00820   
00821   oled_status_t
00822     status = OLED_STATUS_SUCCESS;
00823 
00824   status = AddImage( image );
00825 
00826   /* set the locations */
00827   SetBorders( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height );
00828 
00829   /* fill the GRAM */
00830   SendData( (const uint8_t*)oled_dynamic_area.areaBuffer, oled_dynamic_area.width * oled_dynamic_area.height * OLED_BYTES_PER_PIXEL );
00831 
00832 
00833   return status;
00834 }
00835 
00836 oled_status_t SSD1351::DrawImage ( const uint8_t* image, int8_t xCrd, int8_t yCrd  )
00837 {
00838   
00839   oled_status_t
00840     status = OLED_STATUS_SUCCESS;
00841 
00842   status = AddImage( image,xCrd,yCrd);
00843 
00844   /* set the locations */
00845   SetBorders( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height );
00846 
00847   /* fill the GRAM */
00848   SendData( (const uint8_t*)oled_dynamic_area.areaBuffer, oled_dynamic_area.width * oled_dynamic_area.height * OLED_BYTES_PER_PIXEL );
00849 
00850 
00851   return status;
00852 }
00853 
00854 
00855 
00856 void SSD1351::DimScreenON()
00857 {
00858     for ( int i = 0; i < 16; i++ )
00859     {
00860         SendCmd( OLED_CMD_CONTRASTMASTER, CMD_BYTE );
00861         SendCmd( 0xC0 | (0xF-i), DATA_BYTE );
00862         wait_ms(20);
00863         // OSA_TimeDelay( 20 );
00864     }
00865 }
00866 
00867 
00868 void SSD1351::DimScreenOFF()
00869 {
00870   SendCmd( OLED_CMD_CONTRASTMASTER, CMD_BYTE );
00871   SendCmd( 0xC0 | 0xF, DATA_BYTE );
00872 }
00873 
00874 
00875 
00876 void SSD1351::Swap(
00877                     oled_pixel_t imgDst,
00878                   const uint8_t* imgSrc,
00879                         uint16_t imgSize
00880                 )
00881 {
00882   for ( int var = 0; var < imgSize; var++ )
00883   {
00884     *imgDst = *imgSrc << 8;
00885     imgSrc++;
00886     *imgDst |= *imgSrc;
00887     imgDst++;
00888     imgSrc++;
00889   }
00890 }
00891 
00892 
00893 void SSD1351::PowerON()
00894 {
00895   power = 1;
00896 }
00897 
00898 void SSD1351::PowerOFF()
00899 {
00900   power = 0;
00901 }
00902 
00903 
00904 
00905  /* Formerly Known as GuiDriver_UpdateScreen */
00906 void SSD1351::UpdateBuffer (
00907                                 int8_t xCrd,
00908                                 int8_t yCrd,
00909                                 uint8_t width,
00910                                 uint8_t height,
00911                                 const uint8_t* image
00912                               )
00913 {
00914   /* copy data */
00915   oled_pixel_t
00916     copyAddr = (oled_pixel_t)screenBuf + ( yCrd*OLED_SCREEN_WIDTH + xCrd );
00917 
00918   for ( uint8_t i = 0; i < height; i++ )
00919   {
00920     memcpy( (void*)copyAddr, (void*)image, width*OLED_BYTES_PER_PIXEL );
00921     copyAddr += OLED_SCREEN_WIDTH;
00922     image    += width*OLED_BYTES_PER_PIXEL;
00923   }
00924 } 
00925 
00926 
00927 oled_status_t SSD1351::Label ( const uint8_t* text,int8_t xCrd, int8_t yCrd )
00928 {
00929 
00930   if ( NULL == text )
00931   {
00932     return OLED_STATUS_ERROR;
00933   }
00934 
00935   AddText(text,xCrd,yCrd);
00936 
00937   /* set the locations */
00938   SetBorders( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height );
00939 
00940   /* fill the GRAM */
00941   SendData( (const uint8_t*)oled_dynamic_area.areaBuffer, oled_dynamic_area.width * oled_dynamic_area.height * OLED_BYTES_PER_PIXEL );
00942 
00943   //free( currentTextAreaImage );
00944   return OLED_STATUS_SUCCESS;
00945 }
00946 
00947 
00948 oled_status_t SSD1351::TextBox(const uint8_t* text, int8_t xCrd, int8_t yCrd,uint8_t width,uint8_t height)
00949 {
00950 
00951   if ( NULL == text )
00952   {
00953     return OLED_STATUS_ERROR;
00954   }
00955 
00956   oled_dynamic_area_t textArea;
00957   textArea.width  = width;
00958   textArea.height = height;
00959   textArea.xCrd = xCrd;
00960   textArea.yCrd = yCrd; 
00961 
00962   SetDynamicArea(&textArea);
00963   DrawText(text);
00964 
00965   return OLED_STATUS_SUCCESS;
00966 
00967 }
00968 
00969 
00970 /* Internal Functions */
00971 
00972 /**
00973  * [transpose description]
00974  * @param transImage  Transposed Image    
00975  * @param image       Source Image  
00976  * @param width       Width to Transpose
00977  * @param height      Height to Transpose 
00978  */
00979 void SSD1351::Transpose(
00980                              oled_pixel_t transImage,
00981                        const oled_pixel_t image,
00982                                   uint8_t width,
00983                                   uint8_t height
00984                      )
00985 {
00986   for ( uint8_t i = 0; i < height; i++ )
00987   {
00988     for ( uint8_t j = 0; j < width ; j++ )
00989     {
00990       transImage[ j*height + i ] = image[ i*width + j ];
00991     }
00992   }
00993 }
00994 
00995 
00996 
00997 /**
00998  * TopDown Transition Effect for Image
00999  * @param  image  image to be transitioned
01000  * @param  xCrd   x coordinate of image
01001  * @param  yCrd   y coordinate of image
01002  * @param  width  width of image
01003  * @param  height height of image
01004  * @return        status flag
01005  */
01006 oled_status_t SSD1351::TopDown(
01007                                 const uint8_t* image,
01008                                        int8_t xCrd,
01009                                        int8_t yCrd,
01010                                        uint8_t width,
01011                                        uint8_t height
01012                             )
01013 {
01014   uint16_t
01015     transStep = OLED_TRANSITION_STEP;
01016 
01017   uint16_t
01018     partImgSize = width*transStep;
01019 
01020   oled_status_t
01021     status = OLED_STATUS_SUCCESS;
01022 
01023   uint8_t*
01024     partImgPtr = (uint8_t*)image + ( height - transStep ) * ( width * OLED_BYTES_PER_PIXEL );
01025 
01026   /**
01027    * set locations
01028    */
01029 
01030   while (1)
01031   {
01032     SetBorders( xCrd, yCrd, width, height );
01033 
01034     if ( partImgSize > width*height )
01035     {
01036         SendData( (const uint8_t*)image, width*height*OLED_BYTES_PER_PIXEL );
01037         break;
01038     }
01039     else
01040     {
01041         SendData( (const uint8_t*)partImgPtr, partImgSize * OLED_BYTES_PER_PIXEL );
01042     }
01043 
01044 
01045     /**
01046      * update variables
01047      */
01048 
01049     partImgPtr  -= ( width * transStep ) * OLED_BYTES_PER_PIXEL;
01050     partImgSize += ( width * transStep );
01051     transStep++;
01052   }
01053 
01054   return status;
01055 }
01056 
01057 /**
01058  * DownTop Transition Effect for Image
01059  * @param  image  image to be transitioned
01060  * @param  xCrd   x coordinate of image
01061  * @param  yCrd   y coordinate of image
01062  * @param  width  width of image
01063  * @param  height height of image
01064  * @return        status flag
01065  */
01066 
01067 oled_status_t SSD1351::DownTop(
01068                                 const uint8_t* image,
01069                                       int8_t xCrd,
01070                                       int8_t yCrd,
01071                                       uint8_t width,
01072                                       uint8_t height
01073                             )
01074 {
01075   uint16_t
01076     transStep = OLED_TRANSITION_STEP;
01077 
01078   uint16_t
01079     partImgSize = width*transStep;
01080 
01081   oled_status_t
01082     status = OLED_STATUS_SUCCESS;
01083 
01084   uint8_t*
01085     partImgPtr = (uint8_t*)image;
01086 
01087   uint8_t
01088     yCrd_moving = ( yCrd + height ) - 1;
01089 
01090   /**
01091    * set locations
01092    */
01093 
01094   while (1)
01095   {
01096     if  (
01097              ( partImgSize > OLED_SCREEN_SIZE )
01098           ||        ( yCrd_moving < yCrd )
01099         )
01100     {
01101       /* draw full image */
01102       SetBorders( xCrd, yCrd, width, height );
01103       SendData( (const uint8_t*)image, width * height * OLED_BYTES_PER_PIXEL );
01104       break;
01105     }
01106 
01107     else
01108     {
01109       SetBorders( xCrd, yCrd_moving, width, ( yCrd + height ) - yCrd_moving );
01110       SendData( (const uint8_t*)partImgPtr, partImgSize * OLED_BYTES_PER_PIXEL );
01111     }
01112 
01113     /**
01114      * update variables
01115      */
01116 
01117     yCrd_moving -= transStep;
01118     partImgSize += ( width * transStep );
01119     transStep++;
01120   }
01121 
01122   return status;
01123 }
01124 
01125 
01126 /**
01127  * LeftRight Transition Effect for Image
01128  * @param  image  image to be transitioned
01129  * @param  xCrd   x coordinate of image
01130  * @param  yCrd   y coordinate of image
01131  * @param  width  width of image
01132  * @param  height height of image
01133  * @return        status flag
01134  */
01135 
01136 oled_status_t SSD1351::LeftRight(
01137                                  const uint8_t* image,
01138                                         int8_t xCrd,
01139                                         int8_t yCrd,
01140                                         uint8_t width,
01141                                         uint8_t height
01142                               )
01143 {
01144   oled_status_t
01145     status = OLED_STATUS_SUCCESS;
01146 
01147   oled_dynamic_area_t
01148       transImageArea =
01149       {
01150           .xCrd = 0,
01151           .yCrd = 0,
01152 
01153           .width = 96,
01154           .height= 96
01155       };
01156 
01157   SetDynamicArea( &transImageArea );
01158 
01159   /* helper pointer */
01160   oled_pixel_t
01161     transImage = (oled_pixel_t)oled_dynamic_area.areaBuffer;
01162 
01163   if ( NULL == transImage )
01164   {
01165     return OLED_STATUS_INIT_ERROR;
01166   }
01167 
01168   Transpose( transImage,(oled_pixel_t)image, width, height );
01169 
01170   SendCmd( OLED_CMD_SET_REMAP, CMD_BYTE );
01171   SendCmd( OLED_REMAP_SETTINGS | REMAP_VERTICAL_INCREMENT, DATA_BYTE );
01172  
01173   uint16_t
01174     transStep = OLED_TRANSITION_STEP;
01175 
01176   uint16_t
01177     partImgSize = height*transStep;
01178 
01179   uint8_t*
01180     partImgPtr = (uint8_t*)transImage + ( width - transStep ) * ( height * OLED_BYTES_PER_PIXEL );
01181 
01182   /**
01183    * set locations
01184    */
01185 
01186   while (1)
01187   {
01188     SetBorders( xCrd, yCrd, width, height );
01189 
01190     if ( partImgSize > width*height )
01191     {
01192       SendData((const uint8_t*)transImage, width * height * OLED_BYTES_PER_PIXEL );
01193       break;
01194     }
01195     else
01196     {
01197       SendData( (const uint8_t*)partImgPtr, partImgSize * OLED_BYTES_PER_PIXEL );
01198     }
01199 
01200 
01201     partImgPtr  -= ( transStep * height ) * OLED_BYTES_PER_PIXEL;
01202     partImgSize += ( transStep * height );
01203     transStep++;
01204     
01205   }
01206    
01207     SendCmd( OLED_CMD_SET_REMAP, CMD_BYTE );
01208     SendCmd( OLED_REMAP_SETTINGS, DATA_BYTE );
01209     DestroyDynamicArea();
01210     return status;
01211 }
01212 
01213 
01214 /**
01215  * RightLeft Transition Effect for Image
01216  * @param  image  image to be transitioned
01217  * @param  xCrd   x coordinate of image
01218  * @param  yCrd   y coordinate of image
01219  * @param  width  width of image
01220  * @param  height height of image
01221  * @return        status flag
01222  */
01223 oled_status_t SSD1351::RightLeft(
01224                                  const uint8_t* image,
01225                                         int8_t xCrd,
01226                                         int8_t yCrd,
01227                                         uint8_t width,
01228                                         uint8_t height
01229                               )
01230 {
01231   oled_dynamic_area_t
01232       transImageArea =
01233       {
01234           .xCrd = 0,
01235           .yCrd = 0,
01236 
01237           .width = 96,
01238           .height= 96
01239       };
01240 
01241   SetDynamicArea( &transImageArea );
01242 
01243   /* helper pointer */
01244   oled_pixel_t
01245     transImage = oled_dynamic_area.areaBuffer;
01246 
01247   if ( NULL == transImage )
01248   {
01249     return OLED_STATUS_INIT_ERROR;
01250   }
01251 
01252   Transpose(transImage, (oled_pixel_t)image, width, height );
01253 
01254   SendCmd( OLED_CMD_SET_REMAP, CMD_BYTE );
01255   SendCmd( OLED_REMAP_SETTINGS | REMAP_VERTICAL_INCREMENT, DATA_BYTE );
01256 
01257 
01258   uint16_t
01259     transStep = OLED_TRANSITION_STEP;
01260 
01261   uint16_t
01262     partImgSize = height * transStep;
01263 
01264   uint8_t*
01265     partImgPtr = (uint8_t*)transImage;
01266 
01267   uint8_t
01268     xCrd_moving = ( xCrd + width ) - 1;
01269 
01270   /** set locations */
01271 
01272   while (1)
01273   {
01274     if  (( partImgSize > width*height )|| ( xCrd_moving < xCrd ))       
01275     {
01276        SetBorders( xCrd, yCrd, width, height );
01277        SendData( (const uint8_t*)transImage, height * width * OLED_BYTES_PER_PIXEL );
01278        break;
01279     }
01280     else
01281     {
01282        SetBorders( xCrd_moving, yCrd, ( xCrd + width ) - xCrd_moving, height );
01283        SendData( (const uint8_t*)partImgPtr, partImgSize * OLED_BYTES_PER_PIXEL );
01284     }
01285 
01286     /** update variables*/
01287 
01288     xCrd_moving -= transStep;
01289     partImgSize += ( height * transStep );
01290     transStep++;
01291   }
01292 
01293   SendCmd( OLED_CMD_SET_REMAP, CMD_BYTE );
01294   SendCmd( OLED_REMAP_SETTINGS, DATA_BYTE );
01295 
01296   DestroyDynamicArea();
01297 
01298   return OLED_STATUS_SUCCESS;
01299 }
01300 
01301 
01302 /**
01303  * [setDirection description]
01304  * @param  self [description]
01305  * @param  xCrd [description]
01306  * @param  yCrd [description]
01307  * @return      [description]
01308  */
01309 void SSD1351::SetBorders(
01310                         int8_t xCrd,
01311                         int8_t yCrd,
01312                         uint8_t width,
01313                         uint8_t height
01314                       )
01315 {
01316   
01317   /* adjust for the offset*/
01318   OLED_AdjustColumnOffset(xCrd);
01319   OLED_AdjustRowOffset(yCrd);
01320 
01321   SendCmd( OLED_CMD_SET_COLUMN, CMD_BYTE );
01322   SendCmd( xCrd, DATA_BYTE );
01323   SendCmd( xCrd + (width-1), DATA_BYTE );
01324   SendCmd( OLED_CMD_SET_ROW, CMD_BYTE );
01325   SendCmd( yCrd, DATA_BYTE );
01326   SendCmd( yCrd + (height-1), DATA_BYTE );
01327   
01328 }
01329 
01330 /**
01331  * create the buffer for a partial image
01332  * @param  imgBuf [description]
01333  * @param  width  [description]
01334  * @param  height [description]
01335  * @return        [description]
01336  */
01337 oled_status_t SSD1351::CreateTextBackground()
01338 {
01339   uint8_t
01340     xCrd   = oled_dynamic_area.xCrd,
01341     yCrd   = oled_dynamic_area.yCrd,
01342     width  = oled_dynamic_area.width,
01343     height = oled_dynamic_area.height;
01344 
01345   oled_pixel_t
01346     imgBuf = oled_dynamic_area.areaBuffer,
01347     copyAddr;
01348 
01349   const uint8_t*
01350     background = oled_text_properties.background;
01351 
01352   /* copy data */
01353 
01354   if  (
01355             ( NULL == imgBuf )
01356         ||  ( ( xCrd + width )  > OLED_SCREEN_WIDTH )
01357         ||  ( ( yCrd + height ) > OLED_SCREEN_HEIGHT )
01358       )
01359   {
01360     return OLED_STATUS_INIT_ERROR;
01361   }
01362 
01363   if ( NULL == background )
01364   {
01365     for ( uint8_t i = 0; i < height; i++ )
01366     {
01367       memset( (void*)imgBuf, 0, width*OLED_BYTES_PER_PIXEL );
01368       imgBuf   += width;
01369     }
01370   }
01371 
01372   else
01373   {
01374     copyAddr = (oled_pixel_t)( BMP_SkipHeader( background ) ) + ( yCrd*OLED_SCREEN_WIDTH + xCrd );
01375     for ( uint8_t i = 0; i < height; i++ )
01376     {
01377       Swap( (oled_pixel_t)imgBuf, (const uint8_t*)copyAddr, width );
01378       imgBuf   += width;
01379       copyAddr += OLED_SCREEN_WIDTH;
01380     }
01381   }
01382 
01383   return OLED_STATUS_SUCCESS;
01384 }
01385 
01386 
01387 /**
01388  * Write the character to Buffer
01389  * @param charToWrite character to be written
01390  * @param chrBuf      given pointer for buffer for the character
01391  */
01392 void SSD1351::WriteCharToBuf(
01393                             uint16_t charToWrite,
01394                             oled_pixel_t* chrBuf
01395                           )
01396 {
01397   uint8_t
01398     foo = 0,
01399     mask;
01400 
01401   const uint8_t*
01402     pChTable = selectedFont + 8 + (uint16_t)( ( charToWrite - selectedFont_firstChar ) << 2 );
01403 
01404   currentChar_width  = *pChTable,
01405   currentChar_height = selectedFont_height;
01406 
01407   uint32_t
01408     offset =      (uint32_t)pChTable[1]
01409               | ( (uint32_t)pChTable[2] << 8 )
01410               | ( (uint32_t)pChTable[3] << 16 );
01411 
01412   const uint8_t*
01413     pChBitMap = selectedFont + offset;
01414 
01415   /* allocate space for char image */
01416   *chrBuf = (oled_pixel_t)AllocateDynamicArea( currentChar_height * currentChar_width );
01417 
01418   if ( NULL == *chrBuf )
01419   {
01420     return;
01421   }
01422 
01423   for ( uint8_t yCnt = 0; yCnt < currentChar_height; yCnt++ )
01424   {
01425     mask = 0;
01426 
01427     for ( uint8_t xCnt = 0; xCnt < currentChar_width; xCnt++ )
01428     {
01429       if ( 0 == mask )
01430       {
01431         mask = 1;
01432         foo  = *pChBitMap++;
01433       }
01434 
01435       if ( 0 != ( foo & mask ) )
01436       {
01437         *( *chrBuf + yCnt*currentChar_width + xCnt ) = selectedFont_color;
01438       }
01439 
01440        else
01441        {
01442            *( *chrBuf + yCnt*currentChar_width + xCnt ) = 0;
01443        }
01444 
01445       mask <<= 1;
01446     }
01447   }
01448 }
01449 
01450 
01451 /**
01452  * Add subimage/character to the active image buffer
01453  * @param  xOffset offset for the x-coordinate
01454  * @param  yOffset offset for the y-coordinate
01455  * @param  width   desired width
01456  * @param  height  desired height
01457  * @return         status flag
01458  */
01459 oled_status_t SSD1351::AddCharToTextArea(
01460                                         oled_pixel_t chrPtr,
01461                                              uint8_t chrWidth,
01462                                              uint8_t chrHeight,
01463                                         oled_pixel_t copyAddr,
01464                                              uint8_t imgWidth
01465                                       )
01466 {
01467   if ( NULL == copyAddr )
01468   {
01469     return OLED_STATUS_INIT_ERROR;
01470   }
01471 
01472   for ( uint8_t i = 0; i < chrHeight; i++ )
01473   {
01474     for ( uint8_t j = 0; j < chrWidth; j++ )
01475     {
01476       if ( 0 != chrPtr[j] )
01477       {
01478           copyAddr[j] = chrPtr[j];
01479       }
01480     }
01481     copyAddr += imgWidth;
01482     chrPtr   += chrWidth;
01483   }
01484   return OLED_STATUS_SUCCESS;
01485 }
01486 
01487 
01488 /**
01489  * Allocate memory for the desired image/character
01490  * @param area desired area dimensions
01491  */
01492 void* SSD1351::AllocateDynamicArea( uint32_t area )
01493 {
01494   void*
01495       ptr = malloc( area * OLED_BYTES_PER_PIXEL );
01496 
01497   if ( NULL == ptr )
01498   {
01499       return NULL;
01500   }
01501 
01502   return ptr;
01503 }
01504 
01505 
01506 /**
01507  * Deallocate current area
01508  * @param area pointer to current area
01509  */
01510 oled_status_t SSD1351::DestroyDynamicArea( void* ptr )
01511 {
01512   if ( NULL == ptr )
01513   {
01514       return OLED_STATUS_INIT_ERROR;
01515   }
01516 
01517    free(ptr); 
01518 
01519    return OLED_STATUS_SUCCESS; 
01520 }