From 3242a517b33d91b2eb3a11f7c4af59a4b6e83e1a Mon Sep 17 00:00:00 2001 From: penfold42 Date: Fri, 22 Jun 2018 09:31:13 +1000 Subject: [PATCH 1/4] Ground work for sh1106 and brightness controls - just options parsing --- src/SSD1306.cpp | 3 ++- src/SSD1306.h | 3 ++- src/ScreenLCD.cpp | 4 ++-- src/ScreenLCD.h | 2 +- src/main.cpp | 10 +++++++++- src/options.h | 6 ++++++ 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/SSD1306.cpp b/src/SSD1306.cpp index 40377a0..688b6b5 100644 --- a/src/SSD1306.cpp +++ b/src/SSD1306.cpp @@ -57,9 +57,10 @@ extern "C" unsigned char frame[SSD1306_128x64_BYTES]; -SSD1306::SSD1306(int BSCMaster, u8 address, int flip) +SSD1306::SSD1306(int BSCMaster, u8 address, int flip, int type) : BSCMaster(BSCMaster) , address(address) + , type(type) { RPI_I2CInit(BSCMaster, 1); diff --git a/src/SSD1306.h b/src/SSD1306.h index 165d72f..c69fce5 100644 --- a/src/SSD1306.h +++ b/src/SSD1306.h @@ -72,7 +72,7 @@ class SSD1306 public: // 128x32 0x3C // 128x64 0x3D or 0x3C (if SA0 is grounded) - SSD1306(int BSCMaster = 1, u8 address = 0x3C, int flip = 0); + SSD1306(int BSCMaster = 1, u8 address = 0x3C, int flip = 0, int type=1306); void PlotCharacter(int x, int y, char ascii, bool inverse); void Plottext(int x, int y, char* str, bool inverse); @@ -96,5 +96,6 @@ protected: int BSCMaster; u8 address; + int type; }; #endif diff --git a/src/ScreenLCD.cpp b/src/ScreenLCD.cpp index 89b215b..998c1ed 100644 --- a/src/ScreenLCD.cpp +++ b/src/ScreenLCD.cpp @@ -22,7 +22,7 @@ #include #include "debug.h" -void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip) +void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip, int LCDType) { bpp = 1; @@ -38,7 +38,7 @@ void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int B width = widthDesired; height = heightDesired; - ssd1306 = new SSD1306(BSCMaster, LCDAddress, LCDFlip); + ssd1306 = new SSD1306(BSCMaster, LCDAddress, LCDFlip, LCDType); ssd1306->DisplayOn(); ssd1306->Plottext(5, 1, "Pi1541", false); ssd1306->RefreshScreen(); diff --git a/src/ScreenLCD.h b/src/ScreenLCD.h index 4a17572..ee77614 100644 --- a/src/ScreenLCD.h +++ b/src/ScreenLCD.h @@ -32,7 +32,7 @@ public: { } - void Open(u32 width, u32 height, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip); + void Open(u32 width, u32 height, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip, int 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 b187627..c797c41 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1167,10 +1167,18 @@ extern "C" int i2cBusMaster = options.I2CBusMaster(); int i2cLcdAddress = options.I2CLcdAddress(); int i2cLcdFlip = options.I2CLcdFlip(); + int i2cLcdOnBright = options.I2CLcdOnBright(); + int i2cLcdDimBright = options.I2CLcdDimBright(); + int i2cLcdDimTime = options.I2CLcdDimTime(); if (strcasecmp(options.GetLCDName(), "ssd1306_128x64") == 0) { screenLCD = new ScreenLCD(); - screenLCD->Open(128, 64, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip); + screenLCD->Open(128, 64, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip, 1306); + } + else if (strcasecmp(options.GetLCDName(), "sh1106_128x64") == 0) + { + screenLCD = new ScreenLCD(); + screenLCD->Open(128, 64, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip, 1106); } else { diff --git a/src/options.h b/src/options.h index 283d773..bf8fd36 100644 --- a/src/options.h +++ b/src/options.h @@ -71,6 +71,9 @@ public: inline unsigned int I2CBusMaster() const { return i2cBusMaster; } inline unsigned int I2CLcdAddress() const { return i2cLcdAddress; } inline unsigned int I2CLcdFlip() const { return i2cLcdFlip; } + inline unsigned int I2CLcdOnBright() const { return i2cLcdOnBright; } + inline unsigned int I2CLcdDimBright() const { return i2cLcdDimBright; } + inline unsigned int I2CLcdDimTime() const { return i2cLcdDimTime; } // Page up and down will jump a different amount based on the maximum number rows displayed. // Perhaps we should use some keyboard modifier to the the other screen? @@ -105,6 +108,9 @@ private: unsigned int i2cBusMaster; unsigned int i2cLcdAddress; unsigned int i2cLcdFlip; + unsigned int i2cLcdOnBright; + unsigned int i2cLcdDimBright; + unsigned int i2cLcdDimTime; unsigned int keyboardBrowseLCDScreen; From bd8a31604c71f2cc3b5a4218cd374e916c85519d Mon Sep 17 00:00:00 2001 From: penfold42 Date: Fri, 22 Jun 2018 22:32:54 +1000 Subject: [PATCH 2/4] Added SetContrast functions --- src/SSD1306.cpp | 6 ++++++ src/SSD1306.h | 1 + src/ScreenLCD.cpp | 5 +++++ src/ScreenLCD.h | 2 ++ src/main.cpp | 9 ++++++--- src/options.cpp | 3 +++ src/options.h | 8 ++++---- 7 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/SSD1306.cpp b/src/SSD1306.cpp index 688b6b5..e43a09c 100644 --- a/src/SSD1306.cpp +++ b/src/SSD1306.cpp @@ -222,6 +222,12 @@ void SSD1306::DisplayOff() SendCommand(SSD1306_CMD_DISPLAY_OFF); } +void SSD1306::SetContrast(u8 value) +{ + SendCommand(SSD1306_CMD_SET_CONTRAST_CONTROL); + SendCommand(value); +} + void SSD1306::Plottext(int x, int y, char* str, bool inverse) { int i; diff --git a/src/SSD1306.h b/src/SSD1306.h index c69fce5..b34dae6 100644 --- a/src/SSD1306.h +++ b/src/SSD1306.h @@ -79,6 +79,7 @@ public: void DisplayOn(); void DisplayOff(); + void SetContrast(u8 value); void ClearScreen(); void RefreshScreen(); diff --git a/src/ScreenLCD.cpp b/src/ScreenLCD.cpp index 998c1ed..56fa10d 100644 --- a/src/ScreenLCD.cpp +++ b/src/ScreenLCD.cpp @@ -60,6 +60,11 @@ void ScreenLCD::Clear(RGBA colour) ssd1306->ClearScreen(); } +void ScreenLCD::SetContrast(u8 value) +{ + ssd1306->SetContrast(value); +} + void ScreenLCD::WriteChar(bool petscii, u32 x, u32 y, unsigned char c, RGBA colour) { if (opened) diff --git a/src/ScreenLCD.h b/src/ScreenLCD.h index ee77614..d3c1dd6 100644 --- a/src/ScreenLCD.h +++ b/src/ScreenLCD.h @@ -37,6 +37,8 @@ public: void ClearArea(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour); void Clear(RGBA colour); + void SetContrast(u8 value); + void ScrollArea(u32 x1, u32 y1, u32 x2, u32 y2); void WriteChar(bool petscii, u32 x, u32 y, unsigned char c, RGBA colour); diff --git a/src/main.cpp b/src/main.cpp index c797c41..3166a75 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -496,7 +496,8 @@ void UpdateScreen() if (screenLCD) { screenLCD->PrintText(false, 0, 0, tempBuffer, RGBA(0xff, 0xff, 0xff, 0xff), RGBA(0xff, 0xff, 0xff, 0xff)); - screenLCD->RefreshRows(0, 2); //SwapBuffers(); +// screenLCD->SetContrast(3*track); + screenLCD->RefreshRows(0, 2); } } @@ -1167,18 +1168,20 @@ extern "C" int i2cBusMaster = options.I2CBusMaster(); int i2cLcdAddress = options.I2CLcdAddress(); int i2cLcdFlip = options.I2CLcdFlip(); - int i2cLcdOnBright = options.I2CLcdOnBright(); - int i2cLcdDimBright = options.I2CLcdDimBright(); + int i2cLcdOnContrast = options.I2CLcdOnContrast(); + int i2cLcdDimContrast = options.I2CLcdDimContrast(); int i2cLcdDimTime = options.I2CLcdDimTime(); if (strcasecmp(options.GetLCDName(), "ssd1306_128x64") == 0) { screenLCD = new ScreenLCD(); screenLCD->Open(128, 64, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip, 1306); + screenLCD->SetContrast(i2cLcdOnContrast); } else if (strcasecmp(options.GetLCDName(), "sh1106_128x64") == 0) { screenLCD = new ScreenLCD(); screenLCD->Open(128, 64, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip, 1106); + screenLCD->SetContrast(i2cLcdOnContrast); } else { diff --git a/src/options.cpp b/src/options.cpp index 97c5a9c..b8c0f25 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -206,6 +206,9 @@ void Options::Process(char* buffer) ELSE_CHECK_DECIMAL_OPTION(i2cBusMaster) ELSE_CHECK_DECIMAL_OPTION(i2cLcdAddress) ELSE_CHECK_DECIMAL_OPTION(i2cLcdFlip) + ELSE_CHECK_DECIMAL_OPTION(i2cLcdOnContrast) + ELSE_CHECK_DECIMAL_OPTION(i2cLcdDimContrast) + ELSE_CHECK_DECIMAL_OPTION(i2cLcdDimTime) ELSE_CHECK_DECIMAL_OPTION(keyboardBrowseLCDScreen) else if ((strcasecmp(pOption, "StarFileName") == 0)) { diff --git a/src/options.h b/src/options.h index bf8fd36..36e9400 100644 --- a/src/options.h +++ b/src/options.h @@ -71,8 +71,8 @@ public: inline unsigned int I2CBusMaster() const { return i2cBusMaster; } inline unsigned int I2CLcdAddress() const { return i2cLcdAddress; } inline unsigned int I2CLcdFlip() const { return i2cLcdFlip; } - inline unsigned int I2CLcdOnBright() const { return i2cLcdOnBright; } - inline unsigned int I2CLcdDimBright() const { return i2cLcdDimBright; } + inline unsigned int I2CLcdOnContrast() const { return i2cLcdOnContrast; } + inline unsigned int I2CLcdDimContrast() const { return i2cLcdDimContrast; } inline unsigned int I2CLcdDimTime() const { return i2cLcdDimTime; } // Page up and down will jump a different amount based on the maximum number rows displayed. @@ -108,8 +108,8 @@ private: unsigned int i2cBusMaster; unsigned int i2cLcdAddress; unsigned int i2cLcdFlip; - unsigned int i2cLcdOnBright; - unsigned int i2cLcdDimBright; + unsigned int i2cLcdOnContrast = 127; + unsigned int i2cLcdDimContrast; unsigned int i2cLcdDimTime; unsigned int keyboardBrowseLCDScreen; From f0e90cf3856bda2789df95a2b16638ad3568ed16 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Sat, 23 Jun 2018 12:52:54 +1000 Subject: [PATCH 3/4] Also change VCOMDeselect when changing contrast --- src/SSD1306.cpp | 51 ++++++++++++++++++++++++++++--------------------- src/SSD1306.h | 1 + src/main.cpp | 2 +- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/SSD1306.cpp b/src/SSD1306.cpp index e43a09c..ec27e45 100644 --- a/src/SSD1306.cpp +++ b/src/SSD1306.cpp @@ -28,6 +28,7 @@ extern "C" #define SSD1306_CMD_SET_MEMORY_ADDRESSING_MODE 0x20 +#define SSD1306_CMD_SET_COLUMN_ADDRESS 0x21 #define SSD1306_CMD_SET_PAGE_ADDRESS 0x22 #define SSD1306_CMD_DEACTIVATE_SCROLL 0x2E #define SSD1306_CMD_ACTIVATE_SCROLL 0x2F @@ -65,24 +66,24 @@ SSD1306::SSD1306(int BSCMaster, u8 address, int flip, int type) RPI_I2CInit(BSCMaster, 1); // SSD1306 data sheet configuration flow - SendCommand(SSD1306_CMD_DISPLAY_OFF); - SendCommand(SSD1306_CMD_MULTIPLEX_RATIO); + SendCommand(SSD1306_CMD_DISPLAY_OFF); // 0xAE + SendCommand(SSD1306_CMD_MULTIPLEX_RATIO); // 0xA8 SendCommand(0x3F); // SSD1306_LCDHEIGHT - 1 - SendCommand(SSD1306_CMD_SET_DISPLAY_OFFSET); + SendCommand(SSD1306_CMD_SET_DISPLAY_OFFSET); // 0xD3 Vertical scroll position SendCommand(0x00); // no Offset - SendCommand(SSD1306_CMD_SET_START_LINE | 0x0); + SendCommand(SSD1306_CMD_SET_START_LINE | 0x0); // 0x40 if (flip) { SendCommand(0xA0); // No Segment Re-Map SendCommand(0xC0); // No COM Output Scan Direction } else { - SendCommand(0xA1); // Set Segment Re-Map - SendCommand(0xC8); // Set COM Output Scan Direction + SendCommand(0xA1); // Set Segment Re-Map (horizontal flip) + SendCommand(0xC8); // Set COM Output Scan Direction (vertical flip) } - SendCommand(SSD1306_CMD_SET_COM_PINS); // Layout and direction + SendCommand(SSD1306_CMD_SET_COM_PINS); // 0xDA Layout and direction SendCommand(0x12); SendCommand(SSD1306_CMD_SET_CONTRAST_CONTROL); @@ -90,11 +91,12 @@ SSD1306::SSD1306(int BSCMaster, u8 address, int flip, int type) SendCommand(SSD1306_CMD_ENTIRE_DISPLAY_ON); - SendCommand(SSD1306_CMD_NORMAL_DISPLAY); - SendCommand(0xD5); - SendCommand(0x80); + SendCommand(SSD1306_CMD_NORMAL_DISPLAY); // 0xA6 = non inverted - SendCommand(SSD1306_CMD_SET_PRE_CHARGE_PERIOD); +// SendCommand(0xD5); // CLOCK_DIVIDER_FREQ +// SendCommand(0x80); // 7:4 oscillator f, 3:0 divider + + SendCommand(SSD1306_CMD_SET_PRE_CHARGE_PERIOD); // 0xD9 SendCommand(0xF1); SendCommand(SSD1306_CMD_SET_VCOMH_DESELECT_LEVEL); @@ -106,25 +108,23 @@ SSD1306::SSD1306(int BSCMaster, u8 address, int flip, int type) SendCommand(SSD1306_ENABLE_CHARGE_PUMP); // Enable charge pump regulator SendCommand(0x14); // external = 0x10 internal = 0x14 - - - +/* +// only for page mode addressing SendCommand(0x00); // Set Lower Column Start Address - SendCommand(0x10); // Set Higher Column Start Address - SendCommand(0xB0); // Set Page Start Address for Page Addressing Mode +*/ SendCommand(SSD1306_CMD_SET_MEMORY_ADDRESSING_MODE); // Set Memory Addressing Mode SendCommand(0x00); // 00 - Horizontal Addressing Mode - SendCommand(0x21); // Set Column Address (only for horizontal or vertical mode) - SendCommand(0x00); - SendCommand(0x7F); + SendCommand(SSD1306_CMD_SET_COLUMN_ADDRESS); // 0x21 Set Column Address (only for horizontal or vertical mode) + SendCommand(0x00); // start 0 + SendCommand(0x7F); // end 127 - SendCommand(SSD1306_CMD_SET_PAGE_ADDRESS); - SendCommand(0x00); - SendCommand(0x07); + SendCommand(SSD1306_CMD_SET_PAGE_ADDRESS); // 0x22 + SendCommand(0x00); // start 0 + SendCommand(0x07); // end 7 (so 8 vertical bytes == 64 row display) SendCommand(SSD1306_CMD_DEACTIVATE_SCROLL); } @@ -226,6 +226,13 @@ void SSD1306::SetContrast(u8 value) { SendCommand(SSD1306_CMD_SET_CONTRAST_CONTROL); SendCommand(value); + SetVCOMDeselect( value >> 5); +} + +void SSD1306::SetVCOMDeselect(u8 value) +{ + SendCommand(SSD1306_CMD_SET_VCOMH_DESELECT_LEVEL); + SendCommand( (value & 7) << 4 ); } void SSD1306::Plottext(int x, int y, char* str, bool inverse) diff --git a/src/SSD1306.h b/src/SSD1306.h index b34dae6..6ba445b 100644 --- a/src/SSD1306.h +++ b/src/SSD1306.h @@ -80,6 +80,7 @@ public: void DisplayOn(); void DisplayOff(); void SetContrast(u8 value); + void SetVCOMDeselect(u8 value); void ClearScreen(); void RefreshScreen(); diff --git a/src/main.cpp b/src/main.cpp index 3166a75..5af771d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -496,7 +496,7 @@ void UpdateScreen() if (screenLCD) { screenLCD->PrintText(false, 0, 0, tempBuffer, RGBA(0xff, 0xff, 0xff, 0xff), RGBA(0xff, 0xff, 0xff, 0xff)); -// screenLCD->SetContrast(3*track); +// screenLCD->SetContrast(255.0/79.0*track); screenLCD->RefreshRows(0, 2); } From 8f67aef459fa6ade5a5327d5fc90cc3bc07348a3 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Sat, 23 Jun 2018 13:58:05 +1000 Subject: [PATCH 4/4] Add LCD contrast control i2cLcdOnContrast = 127 // (0..255) UNTESTED sh1106 support LCDName = sh1106_128x64 --- src/SSD1306.cpp | 31 +++++++++++++++++++++++-------- src/SSD1306.h | 1 + src/main.cpp | 2 ++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/SSD1306.cpp b/src/SSD1306.cpp index ec27e45..3f65688 100644 --- a/src/SSD1306.cpp +++ b/src/SSD1306.cpp @@ -108,8 +108,7 @@ SSD1306::SSD1306(int BSCMaster, u8 address, int flip, int type) SendCommand(SSD1306_ENABLE_CHARGE_PUMP); // Enable charge pump regulator SendCommand(0x14); // external = 0x10 internal = 0x14 -/* -// only for page mode addressing +/* only for page mode addressing? so can be deleted SendCommand(0x00); // Set Lower Column Start Address SendCommand(0x10); // Set Higher Column Start Address SendCommand(0xB0); // Set Page Start Address for Page Addressing Mode @@ -118,6 +117,9 @@ SSD1306::SSD1306(int BSCMaster, u8 address, int flip, int type) SendCommand(SSD1306_CMD_SET_MEMORY_ADDRESSING_MODE); // Set Memory Addressing Mode SendCommand(0x00); // 00 - Horizontal Addressing Mode + Home(); + +/* replaced by Home SendCommand(SSD1306_CMD_SET_COLUMN_ADDRESS); // 0x21 Set Column Address (only for horizontal or vertical mode) SendCommand(0x00); // start 0 SendCommand(0x7F); // end 127 @@ -125,6 +127,7 @@ SSD1306::SSD1306(int BSCMaster, u8 address, int flip, int type) SendCommand(SSD1306_CMD_SET_PAGE_ADDRESS); // 0x22 SendCommand(0x00); // start 0 SendCommand(0x07); // end 7 (so 8 vertical bytes == 64 row display) +*/ SendCommand(SSD1306_CMD_DEACTIVATE_SCROLL); } @@ -151,12 +154,7 @@ void SSD1306::SendData(u8 data) void SSD1306::Home() { - SendCommand(0x21); // column range - SendCommand(0x00); // set start to 0 - SendCommand(0x7F); // set end to 0x7F - SendCommand(0x22); // row range - SendCommand(0x00); // set start to 0 - SendCommand(0x07); // set end to 0x07 + MoveCursorByte(0, 0); } void SSD1306::MoveCursorByte(u8 row, u8 col) @@ -164,12 +162,18 @@ void SSD1306::MoveCursorByte(u8 row, u8 col) if (col > 127) { col = 127; } if (row > 7) { row = 7; } + if (type == 1106) + SetDisplayWindow(col+2, 129, row, 7); // sh1106 has 132x64 ram, display is centreed + else + SetDisplayWindow(col+0, 127, row, 7); +/* SendCommand(0x21); // set column SendCommand(col); // start = col SendCommand(0x7F); // end = col max SendCommand(0x22); // set row SendCommand(row); // start = row SendCommand(0x07); // end = row max +*/ } void SSD1306::MoveCursorCharacter(u8 row, u8 col) @@ -235,6 +239,17 @@ void SSD1306::SetVCOMDeselect(u8 value) SendCommand( (value & 7) << 4 ); } +void SSD1306::SetDisplayWindow(u8 x1, u8 x2, u8 y1, u8 y2) +{ + SendCommand(SSD1306_CMD_SET_COLUMN_ADDRESS); // 0x21 Set Column Address (only for horizontal or vertical mode) + SendCommand(x1); // start 0 + SendCommand(x2); // end 127 + + SendCommand(SSD1306_CMD_SET_PAGE_ADDRESS); // 0x22 + SendCommand(y1); // start 0 + SendCommand(y2); // end 7 (so 8 vertical bytes == 64 row display) +} + void SSD1306::Plottext(int x, int y, char* str, bool inverse) { int i; diff --git a/src/SSD1306.h b/src/SSD1306.h index 6ba445b..9bad2c4 100644 --- a/src/SSD1306.h +++ b/src/SSD1306.h @@ -85,6 +85,7 @@ public: void ClearScreen(); void RefreshScreen(); void RefreshRows(u8 start, u8 amountOfRows); + void SetDisplayWindow(u8 x1, u8 y1, u8 x2, u8 y2); protected: void SendCommand(u8 command); diff --git a/src/main.cpp b/src/main.cpp index 5af771d..d9b5b85 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1028,6 +1028,8 @@ static void CheckOptions() screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); snprintf(tempBuffer, tempBufferSize, "i2cLcdFlip = %d\r\n", options.I2CLcdFlip()); screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); + snprintf(tempBuffer, tempBufferSize, "LCDName = %s\r\n", options.GetLCDName()); + screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); IEC_Bus::WaitMicroSeconds(5 * 1000000); }