Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Hexi_OLED_TextImage_Example Hexi_OLED_Text_Example Hexi_OLED_Image_Example security-console-app ... more
Diff: OLED_driver.cpp
- Revision:
- 0:06f42dd3eab3
diff -r 000000000000 -r 06f42dd3eab3 OLED_driver.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/OLED_driver.cpp Wed Aug 17 22:08:40 2016 +0000
@@ -0,0 +1,1348 @@
+#include "OLED_types.h"
+#include "OLED_info.h"
+#include "mbed.h"
+#include "OLED_driver.h"
+#include "OLED_fonts.h"
+
+
+/* oled_init arrays*/
+const uint32_t oled_init_cmd[] = {
+ OLED_CMD_SET_CMD_LOCK,
+ OLED_UNLOCK,
+ OLED_CMD_SET_CMD_LOCK,
+ OLED_ACC_TO_CMD_YES,
+ OLED_CMD_DISPLAYOFF,
+ OLED_CMD_SET_OSC_FREQ_AND_CLOCKDIV,
+ 0xF1,
+ OLED_CMD_SET_MUX_RATIO,
+ 0x5F,
+ OLED_CMD_SET_REMAP,
+ OLED_REMAP_SETTINGS,
+ OLED_CMD_SET_COLUMN,
+ 0x00,
+ 0x5F,
+ OLED_CMD_SET_ROW,
+ 0x00,
+ 0x5F,
+ OLED_CMD_STARTLINE,
+ 0x80,
+ OLED_CMD_DISPLAYOFFSET,
+ 0x60,
+ OLED_CMD_PRECHARGE,
+ 0x32,
+ OLED_CMD_VCOMH,
+ 0x05,
+ OLED_CMD_NORMALDISPLAY,
+ OLED_CMD_CONTRASTABC,
+ 0x8A,
+ 0x51,
+ 0x8A,
+ OLED_CMD_CONTRASTMASTER,
+ 0xCF,
+ OLED_CMD_SETVSL,
+ 0xA0,
+ 0xB5,
+ 0x55,
+ OLED_CMD_PRECHARGE2,
+ 0x01,
+ OLED_CMD_DISPLAYON };
+
+
+const uint8_t oled_init_isFirst[] = {
+ FIRST_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ FIRST_BYTE,
+ FIRST_BYTE,
+ FIRST_BYTE,
+ FIRST_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ OTHER_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ OTHER_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE,
+ OTHER_BYTE,
+ FIRST_BYTE};
+
+
+
+
+OLED::OLED(PinName mosi,PinName sclk,PinName pwr, PinName cs,PinName rst, PinName dc): oled_SPI(mosi,NC,sclk) , oled_POWER(pwr), oled_CS(cs),oled_RST(rst),oled_DC(dc)
+{
+
+ oled_SPI.frequency(8000000);
+
+
+ oled_DC =0;
+ OLED_PowerOFF();
+ wait_ms(1);
+ oled_RST = 0 ;
+ wait_ms(1);
+ oled_RST = 1 ;
+ wait_ms(1);
+ OLED_PowerON();
+
+ isFontInitialized = 0 ;
+ currentChar_width = 0,
+ currentChar_height = 0;
+ colorMask = COLOR_WHITE;
+
+ oled_text_properties.alignParam = OLED_TEXT_ALIGN_CENTER;
+ oled_text_properties.background = NULL;
+ oled_text_properties.font = oledFont_Tahoma_8_Regular;
+ oled_text_properties.fontColor = COLOR_RED;
+
+ oled_dynamic_area.areaBuffer = NULL;
+ oled_dynamic_area.height = 0;
+ oled_dynamic_area.width = 0;
+
+
+
+ for (int i=0;i<39;i++)
+ {
+ OLED_SendCmd(oled_init_cmd[i],oled_init_isFirst[i]);
+ }
+
+
+
+}
+
+
+OLED::~OLED(void)
+{
+
+ //Run Free and zero pointers.
+}
+
+
+
+
+void OLED::OLED_SendCmd(uint32_t cmd,
+ uint8_t isFirst)
+{
+
+
+
+ uint8_t
+ txSize = 1,
+ txBuf[4];
+
+ memcpy((void*)txBuf, (void*)&cmd, txSize );
+
+ if (isFirst )
+ {
+ oled_DC = 0;
+ }
+ else
+ {
+ oled_DC = 1;
+ }
+
+ oled_CS = 0;
+ oled_SPI.write(*txBuf);
+ oled_CS = 1;
+
+}
+
+
+
+void OLED::OLED_SendData ( const uint8_t* dataToSend,
+ uint32_t dataSize)
+
+{
+
+
+ uint16_t* arrayPtr = (uint16_t*)dataToSend;
+
+ for( uint32_t i = 0; i < dataSize/2; i++ )
+ {
+ arrayPtr[i] &= colorMask;
+ }
+
+
+ this->OLED_SendCmd( OLED_CMD_WRITERAM, FIRST_BYTE );
+
+
+ // sending data -> set DC pin
+
+ oled_DC = 1;
+ oled_CS = 0 ;
+
+
+ const uint8_t*
+ // traversing pointer
+ bufPtr = dataToSend;
+
+
+ for ( uint32_t i = 0; i < dataSize; i++)
+ {
+ oled_SPI.write(*bufPtr);
+ bufPtr += 1;
+ }
+
+
+ oled_CS = 1;
+
+}
+
+
+oled_status_t OLED::OLED_DrawBox (
+ uint16_t xCrd,
+ uint16_t yCrd,
+ uint16_t width,
+ uint16_t height,
+ uint16_t color
+ )
+{
+
+ oled_status_t status;
+ oled_dynamic_area_t boxArea;
+
+ boxArea.xCrd = xCrd;
+ boxArea.yCrd = yCrd;
+ boxArea.width = width;
+ boxArea.height = height;
+
+ uint32_t
+ boxSize = width*height;
+
+ OLED_SetDynamicArea( &boxArea );
+
+ // helper pointer
+ uint8_t*
+ boxBuf = (uint8_t*)oled_dynamic_area.areaBuffer;
+
+ if ( NULL == boxBuf )
+ {
+
+ return OLED_STATUS_ERROR;
+ }
+
+ // check the bounds
+ if AreCoordsNotValid( xCrd, yCrd, width, height )
+ {
+ status = OLED_STATUS_INIT_ERROR;
+ }
+
+ else
+ {
+ /** fill the buffer with color */
+
+ for ( uint16_t i = 0; i < boxSize; i++ )
+ {
+ boxBuf[ 2*i ] = color >> 8;
+ boxBuf[ 2*i + 1 ] = color;
+ }
+
+ /** set the locations */
+
+ // adjust for the offset
+ OLED_AdjustColumnOffset(xCrd);
+ OLED_AdjustRowOffset(yCrd);
+
+ OLED_SendCmd( OLED_CMD_SET_COLUMN, FIRST_BYTE);
+ OLED_SendCmd( xCrd, OTHER_BYTE );
+ OLED_SendCmd( xCrd + (width-1), OTHER_BYTE );
+ OLED_SendCmd( OLED_CMD_SET_ROW, FIRST_BYTE );
+ OLED_SendCmd( yCrd, OTHER_BYTE );
+ OLED_SendCmd( yCrd + (height-1), OTHER_BYTE );
+
+
+ // fill the GRAM
+ OLED_SendData( (uint8_t*)boxBuf, boxSize*OLED_BYTES_PER_PIXEL );
+
+ OLED_DestroyDynamicArea();
+
+ }
+
+ return status;
+}
+
+/**
+ * fill the entire screen
+ * @param color color to fill with
+ * @return status flag
+ */
+void OLED::OLED_FillScreen( uint16_t color )
+{
+ /** fill the screen buffer with color */
+ for ( uint16_t i = 0; i < ( OLED_SCREEN_WIDTH * OLED_SCREEN_HEIGHT ); i++ )
+ {
+ screenBuf[ 2*i ] = color >> 8;
+ screenBuf[ 2*i + 1 ] = color;
+ }
+
+ /** set the locations */
+ SetBorders( 0, 0, OLED_SCREEN_WIDTH, OLED_SCREEN_HEIGHT );
+
+ /** fill GRAM */
+ OLED_SendData( (uint8_t*)screenBuf, OLED_SCREEN_WIDTH * OLED_SCREEN_HEIGHT * OLED_BYTES_PER_PIXEL );
+
+}
+
+
+
+oled_status_t OLED::OLED_DrawPixel (
+ int16_t xCrd,
+ int16_t yCrd,
+ uint16_t color
+ )
+{
+ // check the bounds
+ if AreCoordsNotValid( xCrd, yCrd, 1, 1 )
+ {
+ return OLED_STATUS_INIT_ERROR;
+ }
+
+ else
+ {
+ // set directions
+ SetBorders( xCrd, yCrd, OLED_SCREEN_WIDTH, OLED_SCREEN_HEIGHT);
+
+ uint16_t
+ // swap bytes
+ dot = color;
+
+ OLED_SwapMe(dot);
+
+ // fill the GRAM
+ OLED_SendData( (uint8_t*)&dot, 2 );
+
+ return OLED_STATUS_SUCCESS;
+ }
+}
+
+
+oled_status_t OLED::OLED_DrawScreen (
+ const uint8_t* image,
+ uint8_t xCrd,
+ uint8_t yCrd,
+ uint8_t width,
+ uint8_t height,
+ oled_transition_t transition
+ )
+{
+ oled_status_t
+ status = OLED_STATUS_SUCCESS;
+
+ if AreCoordsNotValid( xCrd, yCrd, width, height )
+ {
+ return OLED_STATUS_INIT_ERROR;
+ }
+
+ switch ( transition )
+ {
+ case OLED_TRANSITION_NONE: {
+ /** set the locations */
+ SetBorders( xCrd, yCrd, width, height);
+
+ // fill the GRAM
+ OLED_SendData( (const uint8_t*)image, width * height * OLED_BYTES_PER_PIXEL );
+ break;
+ }
+
+ case OLED_TRANSITION_TOP_DOWN: {
+ TopDown( image, xCrd, yCrd, width, height );
+ break;
+ }
+
+ case OLED_TRANSITION_DOWN_TOP: {
+ DownTop( image, xCrd, yCrd, width, height );
+ break;
+ }
+
+ case OLED_TRANSITION_LEFT_RIGHT: {
+ LeftRight( image, xCrd, yCrd, width, height );
+ break;
+ }
+
+ case OLED_TRANSITION_RIGHT_LEFT: {
+ RightLeft( image, xCrd, yCrd, width, height );
+ break;
+ }
+
+ default: {}
+ }
+
+ return status;
+}
+
+
+oled_status_t OLED::OLED_SetFont(
+ const uint8_t* newFont,
+ uint16_t newColor
+ )
+{
+ /** save the new values in intern variables */
+
+ selectedFont = newFont;
+ // selectedFont_firstChar = newFont[2] + (newFont[3] << 8);
+ selectedFont_firstChar = newFont[2] | ( (uint16_t)newFont[3] << 8 );
+ // selectedFont_lastChar = newFont[4] + (newFont[5] << 8);
+ selectedFont_lastChar = newFont[4] | ( (uint16_t)newFont[5] << 8 );
+ selectedFont_height = newFont[6];
+ selectedFont_color = newColor;
+
+ OLED_SwapMe( selectedFont_color );
+
+ isFontInitialized = 1;
+ return OLED_STATUS_SUCCESS;
+}
+
+
+void OLED::OLED_SetDynamicArea(oled_dynamic_area_t *dynamic_area)
+{
+
+ if( NULL == oled_dynamic_area.areaBuffer )
+ {
+ oled_dynamic_area.areaBuffer = (oled_pixel_t)AllocateDynamicArea( dynamic_area->width * dynamic_area->height );
+ }
+ else if(
+ ( dynamic_area->height != oled_dynamic_area.height ) ||
+ ( dynamic_area->width != oled_dynamic_area.width )
+ )
+ {
+ OLED_DestroyDynamicArea();
+ oled_dynamic_area.areaBuffer = (oled_pixel_t)AllocateDynamicArea( dynamic_area->width * dynamic_area->height );
+ }
+
+ oled_dynamic_area.xCrd = dynamic_area->xCrd;
+ oled_dynamic_area.yCrd = dynamic_area->yCrd;
+ oled_dynamic_area.width = dynamic_area->width;
+ oled_dynamic_area.height = dynamic_area->height;
+}
+
+
+void OLED::OLED_DestroyDynamicArea()
+{
+ if ( NULL != oled_dynamic_area.areaBuffer )
+ {
+ DestroyDynamicArea( oled_dynamic_area.areaBuffer );
+ oled_dynamic_area.areaBuffer = NULL;
+ }
+}
+
+
+void OLED::OLED_SetTextProperties(oled_text_properties_t *textProperties)
+{
+ oled_text_properties.font = textProperties->font;
+ oled_text_properties.fontColor = textProperties->fontColor;
+ oled_text_properties.alignParam = textProperties->alignParam;
+ oled_text_properties.background = textProperties->background;
+
+ OLED_SetFont( oled_text_properties.font, oled_text_properties.fontColor );
+}
+
+
+
+
+uint8_t OLED::OLED_GetTextWidth(const uint8_t* text)
+{
+ uint8_t chrCnt = 0;
+ uint8_t text_width = 0;
+
+ while ( 0 != text[chrCnt] )
+ {
+ text_width += *( selectedFont + 8 + (uint16_t)( ( text[chrCnt++] - selectedFont_firstChar ) << 2 ) );
+ // make 1px space between chars
+ text_width++;
+ }
+ // remove the final space
+ text_width--;
+
+ return text_width;
+}
+
+
+
+uint8_t OLED::OLED_CharCount(uint8_t width, const uint8_t* font, const uint8_t* text, uint8_t length)
+{
+ uint8_t chrCnt = 0;
+ uint8_t text_width = 0;
+ uint16_t firstChar;
+
+ firstChar = font[2] | ( (uint16_t)font[3] << 8 );
+
+ while ( chrCnt < length )
+ {
+ text_width += *( font + 8 + (uint16_t)( ( text[chrCnt++] - firstChar ) << 2 ) );
+ if(text_width > width)
+ {
+ chrCnt--;
+ break;
+ }
+ // make 1px space between chars
+ text_width++;
+ }
+
+ return chrCnt;
+}
+
+
+oled_status_t OLED::OLED_AddText( const uint8_t* text )
+{
+ uint16_t
+ chrCnt = 0;
+ oled_pixel_t
+ chrBuf = NULL;
+
+ uint8_t
+ currentChar_x = 0,
+ currentChar_y = 0;
+
+ uint8_t
+ text_height = 0,
+ text_width = 0;
+
+ text_width = OLED_GetTextWidth(text);
+
+ /**
+ * set default values, if necessary
+ */
+
+ text_height = selectedFont_height;
+
+ if (( oled_dynamic_area.width < text_width )||( oled_dynamic_area.height < text_height ))
+ {
+ oled_dynamic_area_t
+ textArea;
+
+ textArea.width = text_width;
+ textArea.height = text_height;
+ OLED_SetDynamicArea( &textArea );
+ }
+
+ // oled_dynamic_area.width = text_width;
+ // oled_dynamic_area.height = text_height;
+ // // malloc new text space
+ // OLED_DestroyDynamicArea();
+ // oled_dynamic_area.areaBuffer = (oled_pixel_t)AllocateDynamicArea( oled_dynamic_area.width * oled_dynamic_area.height );
+
+ // if ( NULL == oled_dynamic_area.areaBuffer )
+ // {
+ // return OLED_STATUS_INIT_ERROR;
+ // }
+
+ currentChar_y = ( oled_dynamic_area.height - text_height ) >> 1;
+
+ switch ( oled_text_properties.alignParam & OLED_TEXT_HALIGN_MASK )
+ {
+ case OLED_TEXT_ALIGN_LEFT:
+ {
+ currentChar_x = 0;
+ break;
+ }
+
+ case OLED_TEXT_ALIGN_RIGHT:
+ {
+ currentChar_x = ( oled_dynamic_area.width - text_width );
+ break;
+ }
+
+ case OLED_TEXT_ALIGN_CENTER:
+ {
+ currentChar_x += ( oled_dynamic_area.width - text_width ) >> 1 ;
+ break;
+ }
+
+ case OLED_TEXT_ALIGN_NONE:
+ {
+ break;
+ }
+
+ default: {}
+ }
+
+ if ( CreateTextBackground() != OLED_STATUS_SUCCESS )
+ {
+ return OLED_STATUS_ERROR;
+ }
+
+ /**
+ * write the characters into designated space, one by one
+ */
+
+ chrCnt = 0;
+ while ( 0 != text[chrCnt] )
+ {
+ WriteCharToBuf( text[chrCnt++], &chrBuf );
+
+ if ( NULL == chrBuf )
+ {
+ return OLED_STATUS_INIT_ERROR;
+ }
+
+ else
+ {
+ if (
+ ( ( currentChar_x + currentChar_width ) > oled_dynamic_area.width )
+ || ( ( currentChar_y + currentChar_height ) > oled_dynamic_area.height )
+ )
+ {
+ DestroyDynamicArea( chrBuf );
+ chrBuf = NULL;
+ return OLED_STATUS_ERROR;
+ }
+
+ // copy data
+ oled_pixel_t
+ copyAddr = oled_dynamic_area.areaBuffer + ( currentChar_y * oled_dynamic_area.width + currentChar_x );
+
+ AddCharToTextArea( chrBuf, currentChar_width, currentChar_height, copyAddr, oled_dynamic_area.width );
+
+ currentChar_x += ( currentChar_width+1 );
+ currentChar_y += 0;
+
+ DestroyDynamicArea( chrBuf );
+ chrBuf = NULL;
+ }
+ }
+
+ OLED_UpdateBuffer(
+ oled_dynamic_area.xCrd,
+ oled_dynamic_area.yCrd,
+ oled_dynamic_area.width,
+ oled_dynamic_area.height,
+ (const uint8_t*)oled_dynamic_area.areaBuffer
+ );
+
+ return OLED_STATUS_SUCCESS;
+}
+
+
+
+
+oled_status_t OLED::OLED_DrawText ( const uint8_t* text )
+{
+
+ if ( NULL == text )
+ {
+ return OLED_STATUS_ERROR;
+ }
+
+ OLED_AddText( text );
+
+ // set the locations
+ SetBorders( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height );
+
+ // fill the GRAM
+ OLED_SendData( (const uint8_t*)oled_dynamic_area.areaBuffer, oled_dynamic_area.width * oled_dynamic_area.height * OLED_BYTES_PER_PIXEL );
+
+
+// free( currentTextAreaImage );
+ return OLED_STATUS_SUCCESS;
+}
+
+
+void OLED::OLED_GetImageDimensions(uint8_t *width, uint8_t *height, const uint8_t* image)
+{
+ *height = image[2] + (image[3] << 8);
+ *width = image[4] + (image[5] << 8);
+}
+
+
+
+oled_status_t OLED::OLED_AddImage ( const uint8_t* image )
+{
+ oled_status_t
+ status = OLED_STATUS_SUCCESS;
+
+ // check the bounds
+ if AreCoordsNotValid( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height )
+ {
+ status = OLED_STATUS_INIT_ERROR;
+ }
+
+ else
+ {
+ OLED_Swap( (oled_pixel_t)oled_dynamic_area.areaBuffer, BMP_SkipHeader(image), oled_dynamic_area.width*oled_dynamic_area.height );
+
+ // update the main screen buffer
+ OLED_UpdateBuffer( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height, (const uint8_t *)oled_dynamic_area.areaBuffer );
+ }
+
+ return status;
+}
+
+
+
+oled_status_t OLED::OLED_DrawImage ( const uint8_t* image )
+{
+
+ oled_status_t
+ status = OLED_STATUS_SUCCESS;
+
+ status = OLED_AddImage( image );
+
+ // set the locations
+ SetBorders( oled_dynamic_area.xCrd, oled_dynamic_area.yCrd, oled_dynamic_area.width, oled_dynamic_area.height );
+
+ // fill the GRAM
+ OLED_SendData( (const uint8_t*)oled_dynamic_area.areaBuffer, oled_dynamic_area.width * oled_dynamic_area.height * OLED_BYTES_PER_PIXEL );
+
+
+ return status;
+}
+
+
+
+void OLED::OLED_DimScreenON()
+{
+ for ( int i = 0; i < 16; i++ )
+ {
+ OLED_SendCmd( OLED_CMD_CONTRASTMASTER, FIRST_BYTE );
+ OLED_SendCmd( 0xC0 | (0xF-i), OTHER_BYTE );
+ wait_ms(20);
+ //OSA_TimeDelay( 20 );
+ }
+}
+
+
+void OLED::OLED_DimScreenOFF()
+{
+ OLED_SendCmd( OLED_CMD_CONTRASTMASTER, FIRST_BYTE );
+ OLED_SendCmd( 0xC0 | 0xF, OTHER_BYTE );
+}
+
+
+
+void OLED::OLED_Swap(
+ oled_pixel_t imgDst,
+ const uint8_t* imgSrc,
+ uint16_t imgSize
+ )
+{
+ for ( int var = 0; var < imgSize; var++ )
+ {
+ *imgDst = *imgSrc << 8;
+ imgSrc++;
+ *imgDst |= *imgSrc;
+ imgDst++;
+ imgSrc++;
+ }
+}
+
+
+void OLED::OLED_PowerON()
+{
+ oled_POWER = 1;
+}
+
+void OLED::OLED_PowerOFF()
+{
+ oled_POWER = 0;
+}
+
+
+
+ //Formerly Known as GuiDriver_UpdateScreen
+void OLED::OLED_UpdateBuffer (
+ uint8_t xCrd,
+ uint8_t yCrd,
+ uint8_t width,
+ uint8_t height,
+ const uint8_t* image
+ )
+{
+ // copy data
+ oled_pixel_t
+ copyAddr = (oled_pixel_t)screenBuf + ( yCrd*OLED_SCREEN_WIDTH + xCrd );
+
+ for ( uint8_t i = 0; i < height; i++ )
+ {
+ memcpy( (void*)copyAddr, (void*)image, width*OLED_BYTES_PER_PIXEL );
+ copyAddr += OLED_SCREEN_WIDTH;
+ image += width*OLED_BYTES_PER_PIXEL;
+ }
+}
+
+/* Internal Functions */
+
+/**
+ * [transpose description]
+ * @param transImage Transposed Image
+ * @param image Source Image
+ * @param width Width to Transpose
+ * @param height Height to Transpose
+ */
+void OLED::Transpose(
+ oled_pixel_t transImage,
+ const oled_pixel_t image,
+ uint8_t width,
+ uint8_t height
+ )
+{
+ for ( uint8_t i = 0; i < height; i++ )
+ {
+ for ( uint8_t j = 0; j < width ; j++ )
+ {
+ transImage[ j*height + i ] = image[ i*width + j ];
+ }
+ }
+}
+
+
+
+/**
+ * TopDown Transition Effect for Image
+ * @param image image to be transitioned
+ * @param xCrd x coordinate of image
+ * @param yCrd y coordinate of image
+ * @param width width of image
+ * @param height height of image
+ * @return status flag
+ */
+oled_status_t OLED::TopDown(
+ const uint8_t* image,
+ uint8_t xCrd,
+ uint8_t yCrd,
+ uint8_t width,
+ uint8_t height
+ )
+{
+ uint16_t
+ transStep = OLED_TRANSITION_STEP;
+
+ uint16_t
+ partImgSize = width*transStep;
+
+ oled_status_t
+ status = OLED_STATUS_SUCCESS;
+
+ uint8_t*
+ partImgPtr = (uint8_t*)image + ( height - transStep ) * ( width * OLED_BYTES_PER_PIXEL );
+
+ /**
+ * set locations
+ */
+
+ while (1)
+ {
+ SetBorders( xCrd, yCrd, width, height );
+
+ if ( partImgSize > width*height )
+ {
+ OLED_SendData( (const uint8_t*)image, width*height*OLED_BYTES_PER_PIXEL );
+ break;
+ }
+ else
+ {
+ OLED_SendData( (const uint8_t*)partImgPtr, partImgSize * OLED_BYTES_PER_PIXEL );
+ }
+
+
+ /**
+ * update variables
+ */
+
+ partImgPtr -= ( width * transStep ) * OLED_BYTES_PER_PIXEL;
+ partImgSize += ( width * transStep );
+ transStep++;
+ }
+
+ return status;
+}
+
+/**
+ * DownTop Transition Effect for Image
+ * @param image image to be transitioned
+ * @param xCrd x coordinate of image
+ * @param yCrd y coordinate of image
+ * @param width width of image
+ * @param height height of image
+ * @return status flag
+ */
+
+oled_status_t OLED::DownTop(
+ const uint8_t* image,
+ uint8_t xCrd,
+ uint8_t yCrd,
+ uint8_t width,
+ uint8_t height
+ )
+{
+ uint16_t
+ transStep = OLED_TRANSITION_STEP;
+
+ uint16_t
+ partImgSize = width*transStep;
+
+ oled_status_t
+ status = OLED_STATUS_SUCCESS;
+
+ uint8_t*
+ partImgPtr = (uint8_t*)image;
+
+ uint8_t
+ yCrd_moving = ( yCrd + height ) - 1;
+
+ /**
+ * set locations
+ */
+
+ while (1)
+ {
+ if (
+ ( partImgSize > OLED_SCREEN_SIZE )
+ || ( yCrd_moving < yCrd )
+ )
+ {
+ // draw full image
+ SetBorders( xCrd, yCrd, width, height );
+ OLED_SendData( (const uint8_t*)image, width * height * OLED_BYTES_PER_PIXEL );
+ break;
+ }
+
+ else
+ {
+ SetBorders( xCrd, yCrd_moving, width, ( yCrd + height ) - yCrd_moving );
+ OLED_SendData( (const uint8_t*)partImgPtr, partImgSize * OLED_BYTES_PER_PIXEL );
+ }
+
+ /**
+ * update variables
+ */
+
+ yCrd_moving -= transStep;
+ partImgSize += ( width * transStep );
+ transStep++;
+ }
+
+ return status;
+}
+
+
+/**
+ * LeftRight Transition Effect for Image
+ * @param image image to be transitioned
+ * @param xCrd x coordinate of image
+ * @param yCrd y coordinate of image
+ * @param width width of image
+ * @param height height of image
+ * @return status flag
+ */
+
+oled_status_t OLED::LeftRight(
+ const uint8_t* image,
+ uint8_t xCrd,
+ uint8_t yCrd,
+ uint8_t width,
+ uint8_t height
+ )
+{
+ oled_status_t
+ status = OLED_STATUS_SUCCESS;
+
+ oled_dynamic_area_t
+ transImageArea =
+ {
+ .xCrd = 0,
+ .yCrd = 0,
+
+ .width = 96,
+ .height= 96
+ };
+
+ OLED_SetDynamicArea( &transImageArea );
+
+ // helper pointer
+ oled_pixel_t
+ transImage = (oled_pixel_t)oled_dynamic_area.areaBuffer;
+
+ if ( NULL == transImage )
+ {
+ return OLED_STATUS_INIT_ERROR;
+ }
+
+ Transpose( (oled_pixel_t)transImage, (const oled_pixel_t)image, width, height );
+
+ OLED_SendCmd( OLED_CMD_SET_REMAP, FIRST_BYTE );
+ OLED_SendCmd( OLED_REMAP_SETTINGS | REMAP_VERTICAL_INCREMENT, OTHER_BYTE );
+
+ uint16_t
+ transStep = OLED_TRANSITION_STEP;
+
+ uint16_t
+ partImgSize = height*transStep;
+
+ uint8_t*
+ partImgPtr = (uint8_t*)transImage + ( width - transStep ) * ( height * OLED_BYTES_PER_PIXEL );
+
+ /**
+ * set locations
+ */
+
+ while (1)
+ {
+ SetBorders( xCrd, yCrd, width, height );
+
+ if ( partImgSize > width*height )
+ {
+ OLED_SendData((const uint8_t*)transImage, width * height * OLED_BYTES_PER_PIXEL );
+ break;
+ }
+ else
+ {
+ OLED_SendData( (const uint8_t*)partImgPtr, partImgSize * OLED_BYTES_PER_PIXEL );
+ }
+
+
+ partImgPtr -= ( transStep * height ) * OLED_BYTES_PER_PIXEL;
+ partImgSize += ( transStep * height );
+ transStep++;
+
+ }
+
+ OLED_SendCmd( OLED_CMD_SET_REMAP, FIRST_BYTE );
+ OLED_SendCmd( OLED_REMAP_SETTINGS, OTHER_BYTE );
+
+ OLED_DestroyDynamicArea();
+ return status;
+}
+
+
+/**
+ * RightLeft Transition Effect for Image
+ * @param image image to be transitioned
+ * @param xCrd x coordinate of image
+ * @param yCrd y coordinate of image
+ * @param width width of image
+ * @param height height of image
+ * @return status flag
+ */
+oled_status_t OLED::RightLeft(
+ const uint8_t* image,
+ uint8_t xCrd,
+ uint8_t yCrd,
+ uint8_t width,
+ uint8_t height
+ )
+{
+ oled_dynamic_area_t
+ transImageArea =
+ {
+ .xCrd = 0,
+ .yCrd = 0,
+
+ .width = 96,
+ .height= 96
+ };
+
+ OLED_SetDynamicArea( &transImageArea );
+
+ // helper pointer
+ oled_pixel_t
+ transImage = oled_dynamic_area.areaBuffer;
+
+ if ( NULL == transImage )
+ {
+ return OLED_STATUS_INIT_ERROR;
+ }
+
+ Transpose( (oled_pixel_t)transImage, (const oled_pixel_t)image, width, height );
+
+ OLED_SendCmd( OLED_CMD_SET_REMAP, FIRST_BYTE );
+ OLED_SendCmd( OLED_REMAP_SETTINGS | REMAP_VERTICAL_INCREMENT, OTHER_BYTE );
+
+
+ uint16_t
+ transStep = OLED_TRANSITION_STEP;
+
+ uint16_t
+ partImgSize = height * transStep;
+
+ uint8_t*
+ partImgPtr = (uint8_t*)transImage;
+
+ uint8_t
+ xCrd_moving = ( xCrd + width ) - 1;
+
+ /** set locations */
+
+ while (1)
+ {
+ if (( partImgSize > width*height )|| ( xCrd_moving < xCrd ))
+ {
+ SetBorders( xCrd, yCrd, width, height );
+ OLED_SendData( (const uint8_t*)transImage, height * width * OLED_BYTES_PER_PIXEL );
+ break;
+ }
+ else
+ {
+ SetBorders( xCrd_moving, yCrd, ( xCrd + width ) - xCrd_moving, height );
+ OLED_SendData( (const uint8_t*)partImgPtr, partImgSize * OLED_BYTES_PER_PIXEL );
+ }
+
+ /** update variables*/
+
+ xCrd_moving -= transStep;
+ partImgSize += ( height * transStep );
+ transStep++;
+ }
+
+ OLED_SendCmd( OLED_CMD_SET_REMAP, FIRST_BYTE );
+ OLED_SendCmd( OLED_REMAP_SETTINGS, OTHER_BYTE );
+
+ OLED_DestroyDynamicArea();
+
+ return OLED_STATUS_SUCCESS;
+}
+
+
+/**
+ * [setDirection description]
+ * @param self [description]
+ * @param xCrd [description]
+ * @param yCrd [description]
+ * @return [description]
+ */
+void OLED::SetBorders(
+ uint8_t xCrd,
+ uint8_t yCrd,
+ uint8_t width,
+ uint8_t height
+ )
+{
+
+ // adjust for the offset
+ OLED_AdjustColumnOffset(xCrd);
+ OLED_AdjustRowOffset(yCrd);
+
+ OLED_SendCmd( OLED_CMD_SET_COLUMN, FIRST_BYTE );
+ OLED_SendCmd( xCrd, OTHER_BYTE );
+ OLED_SendCmd( xCrd + (width-1), OTHER_BYTE );
+ OLED_SendCmd( OLED_CMD_SET_ROW, FIRST_BYTE );
+ OLED_SendCmd( yCrd, OTHER_BYTE );
+ OLED_SendCmd( yCrd + (height-1), OTHER_BYTE );
+
+}
+
+/**
+ * create the buffer for a partial image
+ * @param imgBuf [description]
+ * @param width [description]
+ * @param height [description]
+ * @return [description]
+ */
+oled_status_t OLED::CreateTextBackground()
+{
+ uint8_t
+ xCrd = oled_dynamic_area.xCrd,
+ yCrd = oled_dynamic_area.yCrd,
+ width = oled_dynamic_area.width,
+ height = oled_dynamic_area.height;
+
+ oled_pixel_t
+ imgBuf = oled_dynamic_area.areaBuffer,
+ copyAddr;
+
+ const uint8_t*
+ background = oled_text_properties.background;
+
+ /** copy data */
+
+ if (
+ ( NULL == imgBuf )
+ || ( ( xCrd + width ) > OLED_SCREEN_WIDTH )
+ || ( ( yCrd + height ) > OLED_SCREEN_HEIGHT )
+ )
+ {
+ return OLED_STATUS_INIT_ERROR;
+ }
+
+ if ( NULL == background )
+ {
+ for ( uint8_t i = 0; i < height; i++ )
+ {
+ memset( (void*)imgBuf, 0, width*OLED_BYTES_PER_PIXEL );
+ imgBuf += width;
+ }
+ }
+
+ else
+ {
+ copyAddr = (oled_pixel_t)( BMP_SkipHeader( background ) ) + ( yCrd*OLED_SCREEN_WIDTH + xCrd );
+ for ( uint8_t i = 0; i < height; i++ )
+ {
+ OLED_Swap( (oled_pixel_t)imgBuf, (const uint8_t*)copyAddr, width );
+ imgBuf += width;
+ copyAddr += OLED_SCREEN_WIDTH;
+ }
+ }
+
+ return OLED_STATUS_SUCCESS;
+}
+
+
+/**
+ * Write the character to Buffer
+ * @param charToWrite character to be written
+ * @param chrBuf given pointer for buffer for the character
+ */
+void OLED::WriteCharToBuf(
+ uint16_t charToWrite,
+ oled_pixel_t* chrBuf
+ )
+{
+ uint8_t
+ foo = 0,
+ mask;
+
+ const uint8_t*
+ pChTable = selectedFont + 8 + (uint16_t)( ( charToWrite - selectedFont_firstChar ) << 2 );
+
+ currentChar_width = *pChTable,
+ currentChar_height = selectedFont_height;
+
+ uint32_t
+ offset = (uint32_t)pChTable[1]
+ | ( (uint32_t)pChTable[2] << 8 )
+ | ( (uint32_t)pChTable[3] << 16 );
+
+ const uint8_t*
+ pChBitMap = selectedFont + offset;
+
+ if ( 0 == isFontInitialized )
+ {
+ // default font
+ OLED_SetFont( oledFont_Tahoma_8_Regular, COLOR_WHITE );
+ }
+
+ // allocate space for char image
+ *chrBuf = (oled_pixel_t)AllocateDynamicArea( currentChar_height * currentChar_width );
+
+ if ( NULL == *chrBuf )
+ {
+ return;
+ }
+
+ for ( uint8_t yCnt = 0; yCnt < currentChar_height; yCnt++ )
+ {
+ mask = 0;
+
+ for ( uint8_t xCnt = 0; xCnt < currentChar_width; xCnt++ )
+ {
+ if ( 0 == mask )
+ {
+ mask = 1;
+ foo = *pChBitMap++;
+ }
+
+ if ( 0 != ( foo & mask ) )
+ {
+ *( *chrBuf + yCnt*currentChar_width + xCnt ) = selectedFont_color;
+ }
+
+ else
+ {
+ *( *chrBuf + yCnt*currentChar_width + xCnt ) = 0;
+ }
+
+ mask <<= 1;
+ }
+ }
+}
+
+
+
+/**
+ * Add subimage/character to the active image buffer
+ * @param xOffset offset for the x-coordinate
+ * @param yOffset offset for the y-coordinate
+ * @param width desired width
+ * @param height desired height
+ * @return status flag
+ */
+oled_status_t OLED::AddCharToTextArea(
+ oled_pixel_t chrPtr,
+ uint8_t chrWidth,
+ uint8_t chrHeight,
+ oled_pixel_t copyAddr,
+ uint8_t imgWidth
+ )
+{
+ if ( NULL == copyAddr )
+ {
+ return OLED_STATUS_INIT_ERROR;
+ }
+
+ for ( uint8_t i = 0; i < chrHeight; i++ )
+ {
+ for ( uint8_t j = 0; j < chrWidth; j++ )
+ {
+ if ( 0 != chrPtr[j] )
+ {
+ copyAddr[j] = chrPtr[j];
+ }
+ }
+ copyAddr += imgWidth;
+ chrPtr += chrWidth;
+ }
+ return OLED_STATUS_SUCCESS;
+}
+
+
+/**
+ * Allocate memory for the desired image/character
+ * @param area desired area dimensions
+ */
+void* OLED::AllocateDynamicArea( uint32_t area )
+{
+ void*
+ ptr = malloc( area * OLED_BYTES_PER_PIXEL );
+
+ if ( NULL == ptr )
+ {
+ return NULL;
+ }
+
+ return ptr;
+}
+
+
+/**
+ * Deallocate current area
+ * @param area pointer to current area
+ */
+oled_status_t OLED::DestroyDynamicArea( void* ptr )
+{
+ if ( NULL == ptr )
+ {
+ return OLED_STATUS_INIT_ERROR;
+ }
+
+ free(ptr);
+
+ return OLED_STATUS_SUCCESS;
+}
+
+
+
+
+
+