| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 | /** * Copyright (c) 2017-2018 Tara Keeling *  * This software is released under the MIT License. * https://opensource.org/licenses/MIT */#include <stdio.h>#include <string.h>#include <stdint.h>#include <stdbool.h>#include <stdlib.h>#include <math.h>#include <esp_attr.h>#include "ssd1306.h"#include "ssd1306_draw.h"__attribute__( ( always_inline ) ) static inline bool IsPixelVisible( struct SSD1306_Device* DeviceHandle, int x, int y )  {    bool Result = (        ( x >= 0 ) &&        ( x < DeviceHandle->Width ) &&        ( y >= 0 ) &&        ( y < DeviceHandle->Height )    ) ? true : false;#if CONFIG_SSD1306_CLIPDEBUG > 0    if ( Result == false ) {        ClipDebug( x, y );    }#endif    return Result;}__attribute__( ( always_inline ) ) static inline void SwapInt( int* a, int* b ) {    int Temp = *b;    *b = *a;    *a = Temp;}inline void IRAM_ATTR SSD1306_DrawPixelFast( struct SSD1306_Device* DeviceHandle, int X, int Y, int Color ) {    uint32_t YBit = ( Y & 0x07 );    uint8_t* FBOffset = NULL;    /*      * We only need to modify the Y coordinate since the pitch     * of the screen is the same as the width.     * Dividing Y by 8 gives us which row the pixel is in but not     * the bit position.     */    Y>>= 3;    FBOffset = DeviceHandle->Framebuffer + ( ( Y * DeviceHandle->Width ) + X );    if ( Color == SSD_COLOR_XOR ) {        *FBOffset ^= BIT( YBit );    } else {        *FBOffset = ( Color == SSD_COLOR_WHITE ) ? *FBOffset | BIT( YBit ) : *FBOffset & ~BIT( YBit );    }}void IRAM_ATTR SSD1306_DrawPixel( struct SSD1306_Device* DeviceHandle, int x, int y, int Color ) {    NullCheck( DeviceHandle, return );    if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {        SSD1306_DrawPixelFast( DeviceHandle, x, y, Color );    }}void IRAM_ATTR SSD1306_DrawHLine( struct SSD1306_Device* DeviceHandle, int x, int y, int Width, int Color ) {    int XEnd = x + Width;    NullCheck( DeviceHandle, return );    NullCheck( DeviceHandle->Framebuffer, return );    for ( ; x <= XEnd; x++ ) {        if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {            SSD1306_DrawPixelFast( DeviceHandle, x, y, Color );        } else {            break;        }    }}void IRAM_ATTR SSD1306_DrawVLine( struct SSD1306_Device* DeviceHandle, int x, int y, int Height, int Color ) {    int YEnd = y + Height;    NullCheck( DeviceHandle, return );    NullCheck( DeviceHandle->Framebuffer, return );    for ( ; y <= YEnd; y++ ) {        if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {            SSD1306_DrawPixel( DeviceHandle, x, y, Color );        } else {            break;        }    }}static inline void IRAM_ATTR DrawWideLine( struct SSD1306_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) {    int dx = ( x1 - x0 );    int dy = ( y1 - y0 );    int Error = 0;    int Incr = 1;    int x = x0;    int y = y0;    if ( dy < 0 ) {        Incr = -1;        dy = -dy;    }    Error = ( dy * 2 ) - dx;    for ( ; x <= x1; x++ ) {        if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {            SSD1306_DrawPixelFast( DeviceHandle, x, y, Color );        }        if ( Error > 0 ) {            Error-= ( dx * 2 );            y+= Incr;        }        Error+= ( dy * 2 );    }}static inline void IRAM_ATTR DrawTallLine( struct SSD1306_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) {    int dx = ( x1 - x0 );    int dy = ( y1 - y0 );    int Error = 0;    int Incr = 1;    int x = x0;    int y = y0;    if ( dx < 0 ) {        Incr = -1;        dx = -dx;    }    Error = ( dx * 2 ) - dy;    for ( ; y < y1; y++ ) {        if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {            SSD1306_DrawPixelFast( DeviceHandle, x, y, Color );        }        if ( Error > 0 ) {            Error-= ( dy * 2 );            x+= Incr;        }        Error+= ( dx * 2 );    }}void IRAM_ATTR SSD1306_DrawLine( struct SSD1306_Device* DeviceHandle, int x0, int y0, int x1, int y1, int Color ) {    NullCheck( DeviceHandle, return );    NullCheck( DeviceHandle->Framebuffer, return );    if ( x0 == x1 ) {        SSD1306_DrawVLine( DeviceHandle, x0, y0, ( y1 - y0 ), Color );    } else if ( y0 == y1 ) {        SSD1306_DrawHLine( DeviceHandle, x0, y0, ( x1 - x0 ), Color );    } else {        if ( abs( x1 - x0 ) > abs( y1 - y0 ) ) {            /* Wide ( run > rise ) */            if ( x0 > x1 ) {                SwapInt( &x0, &x1 );                SwapInt( &y0, &y1 );            }            DrawWideLine( DeviceHandle, x0, y0, x1, y1, Color );        } else {            /* Tall ( rise > run ) */            if ( y0 > y1 ) {                SwapInt( &y0, &y1 );                SwapInt( &x0, &x1 );            }            DrawTallLine( DeviceHandle, x0, y0, x1, y1, Color );        }    }}void IRAM_ATTR SSD1306_DrawBox( struct SSD1306_Device* DeviceHandle, int x1, int y1, int x2, int y2, int Color, bool Fill ) {    int Width = ( x2 - x1 );    int Height = ( y2 - y1 );    NullCheck( DeviceHandle, return );    NullCheck( DeviceHandle->Framebuffer, return );    if ( Fill == false ) {        /* Top side */        SSD1306_DrawHLine( DeviceHandle, x1, y1, Width, Color );        /* Bottom side */        SSD1306_DrawHLine( DeviceHandle, x1, y1 + Height, Width, Color );        /* Left side */        SSD1306_DrawVLine( DeviceHandle, x1, y1, Height, Color );        /* Right side */        SSD1306_DrawVLine( DeviceHandle, x1 + Width, y1, Height, Color );    } else {        /* Fill the box by drawing horizontal lines */        for ( ; y1 <= y2; y1++ ) {            SSD1306_DrawHLine( DeviceHandle, x1, y1, Width, Color );        }    }}void SSD1306_Clear( struct SSD1306_Device* DeviceHandle, int Color ) {    NullCheck( DeviceHandle, return );    NullCheck( DeviceHandle->Framebuffer, return );    memset( DeviceHandle->Framebuffer, Color, DeviceHandle->FramebufferSize );}
 |