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 );
- }
|