Add spectrum visualizer

This commit is contained in:
philippe44
2020-02-16 22:56:08 -08:00
parent 11f2b0a563
commit ed224f6b71
19 changed files with 737 additions and 272 deletions

View File

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

View File

@@ -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;

View File

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

View File

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