diff --git a/src/SSD1306.cpp b/src/SSD1306.cpp index 8f20f1a..9e6728a 100644 --- a/src/SSD1306.cpp +++ b/src/SSD1306.cpp @@ -27,12 +27,14 @@ extern "C" unsigned char frame[SSD1306_128x64_BYTES]; -SSD1306::SSD1306(int BSCMaster, u8 address, int flip, int type) +SSD1306::SSD1306(int BSCMaster, u8 address, unsigned width, unsigned height, int flip, LCD_MODEL type) : BSCMaster(BSCMaster) , address(address) , type(type) , flip(flip) , contrast(127) + , width(width) + , height(height) { RPI_I2CInit(BSCMaster, 1); @@ -45,7 +47,7 @@ void SSD1306::InitHardware() SendCommand(SSD1306_CMD_DISPLAY_OFF); // 0xAE SendCommand(SSD1306_CMD_MULTIPLEX_RATIO); // 0xA8 - SendCommand(0x3F); // SSD1306_LCDHEIGHT - 1 + SendCommand(height-1); // SSD1306_LCDHEIGHT - 1 SendCommand(SSD1306_CMD_SET_DISPLAY_OFFSET); // 0xD3 Vertical scroll position SendCommand(0x00); // no Offset @@ -61,7 +63,10 @@ void SSD1306::InitHardware() } SendCommand(SSD1306_CMD_SET_COM_PINS); // 0xDA Layout and direction - SendCommand(0x12); + if (type == LCD_1306_128x32) + SendCommand(0x02); + else + SendCommand(0x12); SetContrast(GetContrast()); @@ -86,7 +91,7 @@ void SSD1306::InitHardware() Home(); - if (type != 1106) + if (type != LCD_1106_128x64) SendCommand(SSD1306_CMD_DEACTIVATE_SCROLL); // 0x2E } @@ -115,23 +120,23 @@ void SSD1306::Home() MoveCursorByte(0, 0); } -void SSD1306::MoveCursorByte(u8 row, u8 col) +void SSD1306::MoveCursorByte(u8 page, u8 col) { - if (col > 127) { col = 127; } - if (row > 7) { row = 7; } + if (col > width-1) { col = width-1; } + if (page > height/8-1) { page = height/8-1; } - if (type == 1106) + if (type == LCD_1106_128x64) col += 2; // sh1106 uses columns 2..129 - SendCommand(SSD1306_CMD_SET_PAGE | row); // 0xB0 page address + SendCommand(SSD1306_CMD_SET_PAGE | page); // 0xB0 page address SendCommand(SSD1306_CMD_SET_COLUMN_LOW | (col & 0xf)); // 0x00 column address lower bits SendCommand(SSD1306_CMD_SET_COLUMN_HIGH | (col >> 4)); // 0x10 column address upper bits } void SSD1306::RefreshScreen() { - int i; - for (i = 0; i < 8; i++) + unsigned i; + for (i = 0; i < height/8; i++) { RefreshPage(i); } @@ -151,9 +156,19 @@ void SSD1306::RefreshRows(u32 start, u32 amountOfRows) void SSD1306::RefreshPage(u32 page) { + if (page >= height/8) + return; + + // x32 displays use lower half (pages 2 and 3) + if (type == LCD_1306_128x32) + { + page = page+4; // 0,1,2,3 -> 4,5,6,7 + page = page%4; // and wrap it so 4,5 -> 0,1 + } + int i; - int start = page*128; - int end = page*128 + 128; + int start = page*width; + int end = start + width; MoveCursorByte(page, 0); for (i = start; i < end; i++) @@ -183,7 +198,7 @@ void SSD1306::SetContrast(u8 value) contrast = value; SendCommand(SSD1306_CMD_SET_CONTRAST_CONTROL); SendCommand(value); - if (type == 1306) + if (type != LCD_1106_128x64) // dont fiddle vcomdeselect on 1106 displays SetVCOMDeselect( value >> 8); } diff --git a/src/SSD1306.h b/src/SSD1306.h index f1ea8d9..6ab245f 100644 --- a/src/SSD1306.h +++ b/src/SSD1306.h @@ -76,7 +76,7 @@ class SSD1306 public: // 128x32 0x3C // 128x64 0x3D or 0x3C (if SA0 is grounded) - SSD1306(int BSCMaster = 1, u8 address = 0x3C, int flip = 0, int type=1306); + SSD1306(int BSCMaster = 1, u8 address = 0x3C, unsigned width = 128, unsigned height = 64, int flip = 0, LCD_MODEL type=LCD_UNKNOWN); void PlotCharacter(int x, int y, char ascii, bool inverse); void PlotText(int x, int y, char* str, bool inverse); @@ -110,6 +110,8 @@ protected: int type; int flip; int contrast; + unsigned width; + unsigned height; }; #endif diff --git a/src/ScreenLCD.cpp b/src/ScreenLCD.cpp index bde0a30..591422c 100644 --- a/src/ScreenLCD.cpp +++ b/src/ScreenLCD.cpp @@ -23,14 +23,14 @@ #include "debug.h" #include "ssd_logo.h" -void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip, int LCDType) +void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip, LCD_MODEL LCDType) { bpp = 1; if (widthDesired < 128) widthDesired = 128; - if (heightDesired < 64) - heightDesired = 64; + if (heightDesired < 32) + heightDesired = 32; if (widthDesired > 128) widthDesired = 128; if (heightDesired > 64) @@ -39,7 +39,7 @@ void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int B width = widthDesired; height = heightDesired; - ssd1306 = new SSD1306(BSCMaster, LCDAddress, LCDFlip, LCDType); + ssd1306 = new SSD1306(BSCMaster, LCDAddress, width, height, LCDFlip, LCDType); ssd1306->ClearScreen(); ssd1306->RefreshScreen(); ssd1306->DisplayOn(); diff --git a/src/ScreenLCD.h b/src/ScreenLCD.h index dc68275..b81d114 100644 --- a/src/ScreenLCD.h +++ b/src/ScreenLCD.h @@ -21,6 +21,7 @@ #include "ScreenBase.h" #include "SSD1306.h" +#include "options.h" class ScreenLCD : public ScreenBase { @@ -32,7 +33,7 @@ public: { } - void Open(u32 width, u32 height, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip, int LCDType); + void Open(u32 width, u32 height, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip, LCD_MODEL LCDType); void ClearArea(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour); void Clear(RGBA colour); diff --git a/src/main.cpp b/src/main.cpp index ad9bcd8..5e34d83 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -365,26 +365,30 @@ void InitialiseLCD() int i2cLcdOnContrast = options.I2CLcdOnContrast(); int i2cLcdDimContrast = options.I2CLcdDimContrast(); int i2cLcdDimTime = options.I2CLcdDimTime(); - int i2cLcdModel = options.I2CLcdModel(); + LCD_MODEL i2cLcdModel = options.I2CLcdModel(); if (i2cLcdModel) { + int width = 128; + int height = 64; + if (i2cLcdModel == LCD_1306_128x32) + height = 32; screenLCD = new ScreenLCD(); - screenLCD->Open(128, 64, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip, i2cLcdModel); + screenLCD->Open(width, height, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip, i2cLcdModel); screenLCD->SetContrast(i2cLcdOnContrast); screenLCD->ClearInit(0); // sh1106 needs this bool logo_done = false; - if (strcasecmp(options.GetLcdLogoName(), "1541ii") == 0) + if ( (height == 64) && (strcasecmp(options.GetLcdLogoName(), "1541ii") == 0) ) { - screenLCD->PlotRawImage(logo_ssd_1541ii, 0, 0, 128, 64); + screenLCD->PlotRawImage(logo_ssd_1541ii, 0, 0, width, height); snprintf(tempBuffer, tempBufferSize, "Pi1541 V%d.%02d", versionMajor, versionMinor); screenLCD->PrintText(0, 16, 0, tempBuffer, 0xffffffff); logo_done = true; } - else if (strcasecmp(options.GetLcdLogoName(), "1541classic") == 0) + else if (( height == 64) && (strcasecmp(options.GetLcdLogoName(), "1541classic") == 0) ) { - screenLCD->PlotRawImage(logo_ssd_1541classic, 0, 0, 128, 64); + screenLCD->PlotRawImage(logo_ssd_1541classic, 0, 0, width, height); logo_done = true; } else if (f_stat(options.GetLcdLogoName(), &filLcdIcon) == FR_OK && filLcdIcon.fsize <= LCD_LOGO_MAX_SIZE) @@ -398,7 +402,7 @@ void InitialiseLCD() u32 bytesRead; f_read(&fp, LcdLogoFile, LCD_LOGO_MAX_SIZE, &bytesRead); f_close(&fp); - screenLCD->PlotRawImage(LcdLogoFile, 0, 0, 128, 64); + screenLCD->PlotRawImage(LcdLogoFile, 0, 0, width, height); logo_done = true; } } @@ -406,8 +410,8 @@ void InitialiseLCD() if (!logo_done) { snprintf(tempBuffer, tempBufferSize, "Pi1541 V%d.%02d", versionMajor, versionMinor); - int x = (128 - 8*strlen(tempBuffer) ) /2; - int y = (64-16)/2; + int x = (width - 8*strlen(tempBuffer) ) /2; + int y = (height-16)/2; screenLCD->PrintText(0, x, y, tempBuffer, 0x0); } screenLCD->RefreshScreen(); diff --git a/src/options.cpp b/src/options.cpp index 5fa487e..62550b2 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -145,7 +145,7 @@ Options::Options(void) , i2cScan(0) , i2cLcdFlip(0) , i2cLcdOnContrast(127) - , i2cLcdModel(0) + , i2cLcdModel(LCD_UNKNOWN) , scrollHighlightRate(0.125f) , keyboardBrowseLCDScreen(0) { @@ -241,9 +241,11 @@ void Options::Process(char* buffer) { strncpy(LCDName, pValue, 255); if (strcasecmp(pValue, "ssd1306_128x64") == 0) - i2cLcdModel = 1306; + i2cLcdModel = LCD_1306_128x64; + else if (strcasecmp(pValue, "ssd1306_128x32") == 0) + i2cLcdModel = LCD_1306_128x32; else if (strcasecmp(pValue, "sh1106_128x64") == 0) - i2cLcdModel = 1106; + i2cLcdModel = LCD_1106_128x64; } else if ((strcasecmp(pOption, "ROM") == 0) || (strcasecmp(pOption, "ROM1") == 0)) diff --git a/src/options.h b/src/options.h index 22a8931..24dd1e9 100644 --- a/src/options.h +++ b/src/options.h @@ -19,6 +19,8 @@ #ifndef OPTIONS_H #define OPTIONS_H +#include "types.h" + class TextParser { public: @@ -77,7 +79,7 @@ public: inline unsigned int I2CLcdOnContrast() const { return i2cLcdOnContrast; } inline unsigned int I2CLcdDimContrast() const { return i2cLcdDimContrast; } inline unsigned int I2CLcdDimTime() const { return i2cLcdDimTime; } - inline unsigned int I2CLcdModel() const { return i2cLcdModel; } + inline LCD_MODEL I2CLcdModel() const { return i2cLcdModel; } inline const char* GetLcdLogoName() const { return LcdLogoName; } @@ -123,7 +125,8 @@ private: unsigned int i2cLcdOnContrast; unsigned int i2cLcdDimContrast; unsigned int i2cLcdDimTime; - unsigned int i2cLcdModel; +// unsigned int i2cLcdModel; + LCD_MODEL i2cLcdModel = LCD_UNKNOWN; float scrollHighlightRate; diff --git a/src/stb_image.h b/src/stb_image.h index a056138..dc83749 100644 --- a/src/stb_image.h +++ b/src/stb_image.h @@ -892,12 +892,14 @@ static int stbi__mad3sizes_valid(int a, int b, int c, int add) stbi__addsizes_valid(a*b*c, add); } +#ifndef STBI_NO_LINEAR // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) { return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); } +#endif // mallocs with size overflow checking static void *stbi__malloc_mad2(int a, int b, int add) @@ -912,11 +914,13 @@ static void *stbi__malloc_mad3(int a, int b, int c, int add) return stbi__malloc(a*b*c + add); } +#ifndef STBI_NO_LINEAR static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) { if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; return stbi__malloc(a*b*c*d + add); } +#endif // stbi__err - error // stbi__errpf - error returning pointer to float diff --git a/src/types.h b/src/types.h index 253092b..22aa7dc 100644 --- a/src/types.h +++ b/src/types.h @@ -9,5 +9,11 @@ typedef unsigned long long u64; typedef signed long long s64; +typedef enum { + LCD_UNKNOWN, + LCD_1306_128x64, + LCD_1306_128x32, + LCD_1106_128x64, +} LCD_MODEL; #endif