mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-09 13:07:03 +03:00
Add spectrum visualizer
This commit is contained in:
@@ -117,7 +117,7 @@ static void displayer_task(void *args) {
|
||||
if (displayer.state == DISPLAYER_IDLE) display->line(2, 0, DISPLAY_CLEAR | DISPLAY_UPDATE, displayer.string);
|
||||
vTaskSuspend(NULL);
|
||||
scroll_sleep = 0;
|
||||
display->clear();
|
||||
display->clear(true);
|
||||
display->line(1, DISPLAY_LEFT, DISPLAY_UPDATE, displayer.header);
|
||||
} else if (displayer.refresh) {
|
||||
// little trick when switching master while in IDLE and missing it
|
||||
|
||||
@@ -51,8 +51,9 @@ enum displayer_time_e { DISPLAYER_ELAPSED, DISPLAYER_REMAINING };
|
||||
// don't change anything there w/o changing all drivers init code
|
||||
extern struct display_s {
|
||||
int width, height;
|
||||
bool dirty;
|
||||
bool (*init)(char *config, char *welcome);
|
||||
void (*clear)(void);
|
||||
void (*clear)(bool full, ...);
|
||||
bool (*set_font)(int num, enum display_font_e font, int space);
|
||||
void (*on)(bool state);
|
||||
void (*brightness)(uint8_t level);
|
||||
@@ -60,8 +61,10 @@ extern struct display_s {
|
||||
bool (*line)(int num, int x, int attribute, char *text);
|
||||
int (*stretch)(int num, char *string, int max);
|
||||
void (*update)(void);
|
||||
void (*draw)(int x1, int y1, int x2, int y2, bool by_column, uint8_t *data);
|
||||
void (*draw_cbr)(uint8_t *data, int height); // height is the # of columns in data, as oppoosed to display height (0 = display height)
|
||||
void (*draw_raw)(int x1, int y1, int x2, int y2, bool by_column, bool MSb, uint8_t *data);
|
||||
void (*draw_cbr)(uint8_t *data, int width, int height); // width and height is the # of rows/columns in data, as opposed to display height (0 = display width, 0 = display height)
|
||||
void (*draw_line)(int x1, int y1, int x2, int y2);
|
||||
void (*draw_box)( int x1, int y1, int x2, int y2, bool fill);
|
||||
} *display;
|
||||
|
||||
void displayer_scroll(char *string, int speed);
|
||||
|
||||
@@ -38,25 +38,26 @@ static const char *TAG = "display";
|
||||
|
||||
// handlers
|
||||
static bool init(char *config, char *welcome);
|
||||
static void clear(void);
|
||||
static void clear(bool full, ...);
|
||||
static bool set_font(int num, enum display_font_e font, int space);
|
||||
static void text(enum display_font_e font, enum display_pos_e pos, int attribute, char *text, ...);
|
||||
static bool line(int num, int x, int attribute, char *text);
|
||||
static int stretch(int num, char *string, int max);
|
||||
static void draw_cbr(u8_t *data, int height);
|
||||
static void draw(int x1, int y1, int x2, int y2, bool by_column, u8_t *data);
|
||||
static void draw_cbr(u8_t *data, int width, int height);
|
||||
static void draw_raw(int x1, int y1, int x2, int y2, bool by_column, bool MSb, u8_t *data);
|
||||
static void draw_line(int x1, int y1, int x2, int y2);
|
||||
static void draw_box( int x1, int y1, int x2, int y2, bool fill);
|
||||
static void brightness(u8_t level);
|
||||
static void on(bool state);
|
||||
static void update(void);
|
||||
|
||||
// display structure for others to use
|
||||
struct display_s SSD13x6_display = { 0, 0,
|
||||
struct display_s SSD13x6_display = { 0, 0, true,
|
||||
init, clear, set_font, on, brightness,
|
||||
text, line, stretch, update, draw, draw_cbr, NULL };
|
||||
text, line, stretch, update, draw_raw, draw_cbr, draw_line, draw_box };
|
||||
|
||||
// SSD13x6 specific function
|
||||
static struct SSD13x6_Device Display;
|
||||
static SSD13x6_AddressMode AddressMode = AddressMode_Invalid;
|
||||
|
||||
static const unsigned char BitReverseTable256[] =
|
||||
{
|
||||
@@ -150,9 +151,24 @@ static bool init(char *config, char *welcome) {
|
||||
/****************************************************************************************
|
||||
*
|
||||
*/
|
||||
static void clear(void) {
|
||||
SSD13x6_Clear( &Display, SSD_COLOR_BLACK );
|
||||
SSD13x6_Update( &Display );
|
||||
static void clear(bool full, ...) {
|
||||
bool commit = true;
|
||||
|
||||
if (full) {
|
||||
SSD13x6_Clear( &Display, SSD_COLOR_BLACK );
|
||||
} else {
|
||||
va_list args;
|
||||
va_start(args, full);
|
||||
commit = va_arg(args, int);
|
||||
int x1 = va_arg(args, int), y1 = va_arg(args, int), x2 = va_arg(args, int), y2 = va_arg(args, int);
|
||||
if (x2 < 0) x2 = display->width - 1;
|
||||
if (y2 < 0) y2 = display->height - 1;
|
||||
SSD13x6_ClearWindow( &Display, x1, y1, x2, y2, SSD_COLOR_BLACK );
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
if (commit) update();
|
||||
else SSD13x6_display.dirty = true;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -209,12 +225,6 @@ static bool line(int num, int x, int attribute, char *text) {
|
||||
// counting 1..n
|
||||
num--;
|
||||
|
||||
// always horizontal mode for text display
|
||||
if (AddressMode != AddressMode_Horizontal) {
|
||||
AddressMode = AddressMode_Horizontal;
|
||||
SSD13x6_SetDisplayAddressMode( &Display, AddressMode );
|
||||
}
|
||||
|
||||
SSD13x6_SetFont( &Display, lines[num].font );
|
||||
if (attribute & DISPLAY_MONOSPACE) SSD13x6_FontForceMonospace( &Display, true );
|
||||
|
||||
@@ -237,7 +247,8 @@ static bool line(int num, int x, int attribute, char *text) {
|
||||
ESP_LOGD(TAG, "displaying %s line %u (x:%d, attr:%u)", text, num+1, x, attribute);
|
||||
|
||||
// update whole display if requested
|
||||
if (attribute & DISPLAY_UPDATE) SSD13x6_Update( &Display );
|
||||
if (attribute & DISPLAY_UPDATE) update();
|
||||
else SSD13x6_display.dirty = true;
|
||||
|
||||
return width + x < Display.Width;
|
||||
}
|
||||
@@ -278,13 +289,14 @@ static int stretch(int num, char *string, int max) {
|
||||
static void text(enum display_font_e font, enum display_pos_e pos, int attribute, char *text, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, text);
|
||||
TextAnchor Anchor = TextAnchor_Center;
|
||||
|
||||
if (attribute & DISPLAY_CLEAR) SSD13x6_Clear( &Display, SSD_COLOR_BLACK );
|
||||
|
||||
if (!text) return;
|
||||
|
||||
va_start(args, text);
|
||||
|
||||
switch(font) {
|
||||
case DISPLAY_FONT_LINE_1:
|
||||
SSD13x6_SetFont( &Display, &Font_line_1 );
|
||||
@@ -327,127 +339,82 @@ static void text(enum display_font_e font, enum display_pos_e pos, int attribute
|
||||
|
||||
ESP_LOGD(TAG, "SSDD13x6 displaying %s at %u with attribute %u", text, Anchor, attribute);
|
||||
|
||||
if (AddressMode != AddressMode_Horizontal) {
|
||||
AddressMode = AddressMode_Horizontal;
|
||||
SSD13x6_SetDisplayAddressMode( &Display, AddressMode );
|
||||
}
|
||||
|
||||
SSD13x6_FontDrawAnchoredString( &Display, Anchor, text, SSD_COLOR_WHITE );
|
||||
if (attribute & DISPLAY_UPDATE) SSD13x6_Update( &Display );
|
||||
if (attribute & DISPLAY_UPDATE) update();
|
||||
else SSD13x6_display.dirty = true;
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Process graphic display data from column-oriented bytes, MSbit first
|
||||
* Process graphic display data from column-oriented data (MSbit first)
|
||||
*/
|
||||
static void draw_cbr(u8_t *data, int height) {
|
||||
#ifndef FULL_REFRESH
|
||||
// force addressing mode by rows
|
||||
if (AddressMode != AddressMode_Horizontal) {
|
||||
AddressMode = AddressMode_Horizontal;
|
||||
SSD13x6_SetDisplayAddressMode( &Display, AddressMode );
|
||||
static void draw_cbr(u8_t *data, int width, int height) {
|
||||
if (!height) height = Display.Height;
|
||||
if (!width) width = Display.Width;
|
||||
|
||||
// need to do row/col swap and bit-reverse
|
||||
int rows = height / 8;
|
||||
for (int r = 0; r < rows; r++) {
|
||||
uint8_t *optr = Display.Framebuffer + r*Display.Width, *iptr = data + r;
|
||||
for (int c = width; --c >= 0;) {
|
||||
*optr++ = BitReverseTable256[*iptr];;
|
||||
iptr += rows;
|
||||
}
|
||||
}
|
||||
|
||||
// try to minimize I2C traffic which is very slow
|
||||
int rows = (height ? height : Display.Height) / 8;
|
||||
for (int r = 0; r < rows; r++) {
|
||||
uint8_t first = 0, last;
|
||||
uint8_t *optr = Display.Framebuffer + r*Display.Width, *iptr = data + r;
|
||||
|
||||
// row/col swap, frame buffer comparison and bit-reversing
|
||||
for (int c = 0; c < Display.Width; c++) {
|
||||
u8_t byte = BitReverseTable256[*iptr];
|
||||
if (byte != *optr) {
|
||||
if (!first) first = c + 1;
|
||||
last = c ;
|
||||
}
|
||||
*optr++ = byte;
|
||||
iptr += rows;
|
||||
}
|
||||
|
||||
// now update the display by "byte rows"
|
||||
if (first--) {
|
||||
SSD13x6_SetColumnAddress( &Display, first, last );
|
||||
SSD13x6_SetPageAddress( &Display, r, r);
|
||||
SSD13x6_WriteRawData( &Display, Display.Framebuffer + r*Display.Width + first, last - first + 1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!height) height = Display->Height;
|
||||
|
||||
SSD13x6_SetPageAddress( &Display, 0, height / 8 - 1);
|
||||
|
||||
// force addressing mode by columns (if we can)
|
||||
if (SSD13x6_GetCaps( &Display ) & CAPS_ADDRESS_VERTICAL) {
|
||||
// just copy data in frame buffer with bit-reverse
|
||||
for (int c = 0; c < Display.Width; c++)
|
||||
for (int r = 0; r < height / 8; r++)
|
||||
Display.Framebuffer[c*Display.Height/8 + r] = BitReverseTable256[data[c*height/8 +r]];
|
||||
|
||||
if (AddressMode != AddressMode_Vertical) {
|
||||
AddressMode = AddressMode_Vertical;
|
||||
SSD13x6_SetDisplayAddressMode( &Display, AddressMode );
|
||||
}
|
||||
} else {
|
||||
// need to do rwo/col swap and bit-reverse
|
||||
int rows = (height ? height : Display.Height) / 8;
|
||||
for (int r = 0; r < rows; r++) {
|
||||
uint8_t *optr = Display.Framebuffer + r*Display.Width, *iptr = data + r;
|
||||
for (int c = 0; c < Display.Width; c++) {
|
||||
*optr++ = BitReverseTable256[*iptr];;
|
||||
iptr += rows;
|
||||
}
|
||||
}
|
||||
ESP_LOGW(TAG, "Can't set addressing mode to vertical, swapping");
|
||||
}
|
||||
|
||||
SSD13x6_WriteRawData(&Display, Display.Framebuffer, Display.Width * Display.Height/8);
|
||||
#endif
|
||||
SSD13x6_display.dirty = true;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Process graphic display data MSBit first
|
||||
* WARNING: this has not been tested yet
|
||||
*/
|
||||
static void draw(int x1, int y1, int x2, int y2, bool by_column, u8_t *data) {
|
||||
|
||||
if (y1 % 8 || y2 % 8) {
|
||||
ESP_LOGW(TAG, "must write rows on byte boundaries (%u,%u) to (%u,%u)", x1, y1, x2, y2);
|
||||
return;
|
||||
}
|
||||
|
||||
static void draw_raw(int x1, int y1, int x2, int y2, bool by_column, bool MSb, u8_t *data) {
|
||||
// default end point to display size
|
||||
if (x2 == -1) x2 = Display.Width - 1;
|
||||
if (y2 == -1) y2 = Display.Height - 1;
|
||||
|
||||
// set addressing mode to match data
|
||||
if (by_column) {
|
||||
|
||||
if (AddressMode != AddressMode_Vertical) {
|
||||
AddressMode = AddressMode_Vertical;
|
||||
SSD13x6_SetDisplayAddressMode( &Display, AddressMode );
|
||||
}
|
||||
|
||||
// copy the window and do row/col exchange
|
||||
for (int r = y1/8; r <= y2/8; r++) {
|
||||
uint8_t *optr = Display.Framebuffer + r*Display.Width + x1, *iptr = data + r;
|
||||
for (int c = x1; c <= x2; c++) {
|
||||
*optr++ = *iptr;
|
||||
iptr += (y2-y1)/8 + 1;
|
||||
display->dirty = true;
|
||||
|
||||
// not a boundary draw
|
||||
if (y1 % 8 || y2 % 8 || x1 % 8 | x2 % 8) {
|
||||
ESP_LOGW(TAG, "can't write on non cols/rows boundaries for now");
|
||||
} else {
|
||||
// set addressing mode to match data
|
||||
if (by_column) {
|
||||
// copy the window and do row/col exchange
|
||||
for (int r = y1/8; r <= y2/8; r++) {
|
||||
uint8_t *optr = Display.Framebuffer + r*Display.Width + x1, *iptr = data + r;
|
||||
for (int c = x1; c <= x2; c++) {
|
||||
*optr++ = MSb ? BitReverseTable256[*iptr] : *iptr;
|
||||
iptr += (y2-y1)/8 + 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// just copy the window inside the frame buffer
|
||||
for (int r = y1/8; r <= y2/8; r++) {
|
||||
uint8_t *optr = Display.Framebuffer + r*Display.Width + x1, *iptr = data + r*(x2-x1+1);
|
||||
for (int c = x1; c <= x2; c++) *optr++ = *iptr++;
|
||||
}
|
||||
}
|
||||
|
||||
SSD13x6_SetColumnAddress( &Display, x1, x2);
|
||||
SSD13x6_SetPageAddress( &Display, y1/8, y2/8);
|
||||
SSD13x6_WriteRawData( &Display, data, (x2-x1 + 1) * ((y2-y1)/8 + 1));
|
||||
}
|
||||
} else {
|
||||
// just copy the window inside the frame buffer
|
||||
for (int r = y1/8; r <= y2/8; r++) {
|
||||
uint8_t *optr = Display.Framebuffer + r*Display.Width + x1, *iptr = data + r*(x2-x1+1);
|
||||
for (int c = x1; c <= x2; c++) *optr++ = *iptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Draw line
|
||||
*/
|
||||
static void draw_line( int x1, int y1, int x2, int y2) {
|
||||
SSD13x6_DrawLine( &Display, x1, y1, x2, y2, SSD_COLOR_WHITE );
|
||||
SSD13x6_display.dirty = true;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Draw Box
|
||||
*/
|
||||
static void draw_box( int x1, int y1, int x2, int y2, bool fill) {
|
||||
SSD13x6_DrawBox( &Display, x1, y1, x2, y2, SSD_COLOR_WHITE, fill );
|
||||
SSD13x6_display.dirty = true;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -470,7 +437,8 @@ static void on(bool state) {
|
||||
* Update
|
||||
*/
|
||||
static void update(void) {
|
||||
SSD13x6_Update( &Display );
|
||||
if (SSD13x6_display.dirty) SSD13x6_Update( &Display );
|
||||
SSD13x6_display.dirty = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "ssd13x6.h"
|
||||
|
||||
#define SHADOW_BUFFER
|
||||
|
||||
// used by both but different
|
||||
static uint8_t SSDCmd_Set_Display_Start_Line;
|
||||
static uint8_t SSDCmd_Set_Display_Offset;
|
||||
@@ -111,8 +113,32 @@ void SSD13x6_SetDisplayAddressMode( struct SSD13x6_Device* DeviceHandle, SSD13x6
|
||||
}
|
||||
|
||||
void SSD13x6_Update( struct SSD13x6_Device* DeviceHandle ) {
|
||||
#ifdef SHADOW_BUFFER
|
||||
// not sure the compiler does not have to redo all calculation in for loops, so local it is
|
||||
int width = DeviceHandle->Width, rows = DeviceHandle->Height / 8;
|
||||
uint8_t *optr = DeviceHandle->Shadowbuffer, *iptr = DeviceHandle->Framebuffer;
|
||||
|
||||
// by row, find first and last columns that have been updated
|
||||
for (int r = 0; r < rows; r++) {
|
||||
uint8_t first = 0, last;
|
||||
for (int c = 0; c < width; c++) {
|
||||
if (*iptr != *optr) {
|
||||
if (!first) first = c + 1;
|
||||
last = c ;
|
||||
}
|
||||
*optr++ = *iptr++;
|
||||
}
|
||||
|
||||
// now update the display by "byte rows"
|
||||
if (first--) {
|
||||
SSD13x6_SetColumnAddress( DeviceHandle, first, last );
|
||||
SSD13x6_SetPageAddress( DeviceHandle, r, r);
|
||||
SSD13x6_WriteData( DeviceHandle, DeviceHandle->Shadowbuffer + r*width + first, last - first + 1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (DeviceHandle->Model == SH1106) {
|
||||
// SH1106 requires a page-by-page update and ahs no end Page/Column
|
||||
// SH1106 requires a page-by-page update and has no end Page/Column
|
||||
for (int i = 0; i < DeviceHandle->Height / 8 ; i++) {
|
||||
SSD13x6_SetPageAddress( DeviceHandle, i, 0);
|
||||
SSD13x6_SetColumnAddress( DeviceHandle, 0, 0);
|
||||
@@ -124,6 +150,7 @@ void SSD13x6_Update( struct SSD13x6_Device* DeviceHandle ) {
|
||||
SSD13x6_SetPageAddress( DeviceHandle, 0, DeviceHandle->Height / 8 - 1);
|
||||
SSD13x6_WriteData( DeviceHandle, DeviceHandle->Framebuffer, DeviceHandle->FramebufferSize );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SSD13x6_WriteRawData( struct SSD13x6_Device* DeviceHandle, uint8_t* Data, size_t DataLength ) {
|
||||
@@ -214,6 +241,11 @@ static bool SSD13x6_Init( struct SSD13x6_Device* DeviceHandle, int Width, int He
|
||||
DeviceHandle->Width = Width;
|
||||
DeviceHandle->Height = Height;
|
||||
|
||||
#ifdef SHADOW_BUFFER
|
||||
DeviceHandle->Shadowbuffer = heap_caps_malloc( DeviceHandle->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
|
||||
memset( DeviceHandle->Shadowbuffer, 0xFF, DeviceHandle->FramebufferSize );
|
||||
#endif
|
||||
|
||||
SSD13x6_HWReset( DeviceHandle );
|
||||
SSD13x6_DisplayOff( DeviceHandle );
|
||||
|
||||
@@ -308,7 +340,11 @@ bool SSD13x6_Init_SPI( struct SSD13x6_Device* DeviceHandle, int Width, int Heigh
|
||||
DeviceHandle->CSPin = CSPin;
|
||||
|
||||
DeviceHandle->FramebufferSize = ( Width * Height ) / 8;
|
||||
#ifdef SHADOW_BUFFER
|
||||
DeviceHandle->Framebuffer = calloc( 1, DeviceHandle->FramebufferSize );
|
||||
#else
|
||||
DeviceHandle->Framebuffer = heap_caps_calloc( 1, DeviceHandle->FramebufferSize, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA );
|
||||
#endif
|
||||
NullCheck( DeviceHandle->Framebuffer, return false );
|
||||
|
||||
return SSD13x6_Init( DeviceHandle, Width, Height );
|
||||
|
||||
@@ -58,7 +58,7 @@ struct SSD13x6_Device {
|
||||
|
||||
enum { SSD1306, SSD1326, SH1106 } Model;
|
||||
uint8_t ReMap;
|
||||
uint8_t* Framebuffer;
|
||||
uint8_t* Framebuffer, *Shadowbuffer;
|
||||
int FramebufferSize;
|
||||
|
||||
WriteCommandProc WriteCommand;
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#include "ssd13x6.h"
|
||||
#include "ssd13x6_draw.h"
|
||||
|
||||
#undef NullCheck
|
||||
#define NullCheck(X,Y)
|
||||
|
||||
__attribute__( ( always_inline ) ) static inline bool IsPixelVisible( struct SSD13x6_Device* DeviceHandle, int x, int y ) {
|
||||
bool Result = (
|
||||
( x >= 0 ) &&
|
||||
@@ -75,7 +78,7 @@ void IRAM_ATTR SSD13x6_DrawHLine( struct SSD13x6_Device* DeviceHandle, int x, in
|
||||
NullCheck( DeviceHandle, return );
|
||||
NullCheck( DeviceHandle->Framebuffer, return );
|
||||
|
||||
for ( ; x <= XEnd; x++ ) {
|
||||
for ( ; x < XEnd; x++ ) {
|
||||
if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {
|
||||
SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color );
|
||||
} else {
|
||||
@@ -90,7 +93,7 @@ void IRAM_ATTR SSD13x6_DrawVLine( struct SSD13x6_Device* DeviceHandle, int x, in
|
||||
NullCheck( DeviceHandle, return );
|
||||
NullCheck( DeviceHandle->Framebuffer, return );
|
||||
|
||||
for ( ; y <= YEnd; y++ ) {
|
||||
for ( ; y < YEnd; y++ ) {
|
||||
if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {
|
||||
SSD13x6_DrawPixel( DeviceHandle, x, y, Color );
|
||||
} else {
|
||||
@@ -114,7 +117,7 @@ static inline void IRAM_ATTR DrawWideLine( struct SSD13x6_Device* DeviceHandle,
|
||||
|
||||
Error = ( dy * 2 ) - dx;
|
||||
|
||||
for ( ; x <= x1; x++ ) {
|
||||
for ( ; x < x1; x++ ) {
|
||||
if ( IsPixelVisible( DeviceHandle, x, y ) == true ) {
|
||||
SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color );
|
||||
}
|
||||
@@ -219,3 +222,32 @@ void SSD13x6_Clear( struct SSD13x6_Device* DeviceHandle, int Color ) {
|
||||
|
||||
memset( DeviceHandle->Framebuffer, Color, DeviceHandle->FramebufferSize );
|
||||
}
|
||||
|
||||
void SSD13x6_ClearWindow( struct SSD13x6_Device* DeviceHandle, int x1, int y1, int x2, int y2, int Color ) {
|
||||
NullCheck( DeviceHandle, return );
|
||||
NullCheck( DeviceHandle->Framebuffer, return );
|
||||
|
||||
/*
|
||||
int xr = ((x1 - 1) / 8) + 1 ) * 8;
|
||||
int xl = (x2 / 8) * 8;
|
||||
|
||||
for (int y = y1; y <= y2; y++) {
|
||||
for (int x = x1; x < xr; x++) SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color);
|
||||
if (xl > xr) memset( DeviceHandle->Framebuffer + (y / 8) * DeviceHandle->Width + xr, 0, xl - xr );
|
||||
for (int x = xl; x <= x2; x++) SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color);
|
||||
}
|
||||
|
||||
return;
|
||||
*/
|
||||
|
||||
// cheap optimization on boundaries
|
||||
if (x1 == 0 && x2 == DeviceHandle->Width - 1 && y1 % 8 == 0 && (y2 + 1) % 8 == 0) {
|
||||
memset( DeviceHandle->Framebuffer + (y1 / 8) * DeviceHandle->Width, 0, (y2 - y1 + 1) / 8 * DeviceHandle->Width );
|
||||
} else {
|
||||
for (int y = y1; y <= y2; y++) {
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
SSD13x6_DrawPixelFast( DeviceHandle, x, y, Color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ extern "C" {
|
||||
#define SSD_COLOR_XOR 2
|
||||
|
||||
void SSD13x6_Clear( struct SSD13x6_Device* DeviceHandle, int Color );
|
||||
void SSD13x6_ClearWindow( struct SSD13x6_Device* DeviceHandle, int x1, int y1, int x2, int y2, int Color );
|
||||
void SSD13x6_DrawPixel( struct SSD13x6_Device* DeviceHandle, int X, int Y, int Color );
|
||||
void SSD13x6_DrawPixelFast( struct SSD13x6_Device* DeviceHandle, int X, int Y, int Color );
|
||||
void SSD13x6_DrawHLine( struct SSD13x6_Device* DeviceHandle, int x, int y, int Width, int Color );
|
||||
|
||||
Reference in New Issue
Block a user