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
OLED_driver.cpp
- Committer:
- khuang
- Date:
- 2016-08-17
- Revision:
- 0:06f42dd3eab3
File content as of revision 0:06f42dd3eab3:
#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;
}