diff --git a/options.txt b/options.txt index 4cd4a10..607a10f 100644 --- a/options.txt +++ b/options.txt @@ -94,6 +94,7 @@ GraphIEC = 1 //i2cLcdFlip = 1 // Rotate i2c LCD screen 180 degrees //i2cLcdOnContrast = 127 // Allows you to adjust the contrast on your i2c LCD screen //i2cScan = 1 // scan i2c bus and display addresses on screen +//i2cLcdUseCBMChar = 0 // set it to 1 to use CBM font on LCD. Small but fun ! //QuickBoot = 0 // faster startup //ShowOptions = 0 // display some options on startup screen diff --git a/src/FileBrowser.cpp b/src/FileBrowser.cpp index 6aee13b..b6036f0 100644 --- a/src/FileBrowser.cpp +++ b/src/FileBrowser.cpp @@ -82,7 +82,7 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b if (entryIndex < list->entries.size()) { FileBrowser::BrowsableList::Entry* entry = &list->entries[entryIndex]; - if (screen->IsMonocrome()) + if (screen->IsLCD()) { // pre-clear line on OLED memset(buffer1, ' ', columnsMax); @@ -114,9 +114,9 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b int len = strlen(buffer2 + highlightScrollOffset); strncpy(buffer1, buffer2 + highlightScrollOffset, sizeof(buffer1)); - if (!screen->IsMonocrome()) + if (!screen->IsLCD()) { - // space pad the remainder of the line (but not on OLED==monochrome) + // space pad the remainder of the line (but not on OLED) while (len < (int)columnsMax) buffer1[len++] = ' '; buffer1[columnsMax] = 0; @@ -524,7 +524,7 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM if (screenLCD) { columns = screenLCD->Width() / 8; - rows = screenLCD->Height() / 16; + rows = screenLCD->Height() / screenLCD->GetFontHeight(); positionX = 0; positionY = 0; diff --git a/src/Petscii.h b/src/Petscii.h index f780896..bbda95d 100644 --- a/src/Petscii.h +++ b/src/Petscii.h @@ -24,6 +24,7 @@ static inline u8 ascii2petscii(u8 ch) if (ch > 64 && ch < 91) ch += 128; else if (ch > 96 && ch < 123) ch -= 32; else if (ch > 192 && ch < 219) ch -= 128; + else if (ch == 95) ch = 164; // to handle underscore return ch; } static inline u8 petscii2ascii(u8 ch) diff --git a/src/SSD1306.cpp b/src/SSD1306.cpp index 68ea99d..c96fc33 100644 --- a/src/SSD1306.cpp +++ b/src/SSD1306.cpp @@ -19,12 +19,15 @@ #include "SSD1306.h" #include "debug.h" #include +#include "Petscii.h" extern "C" { #include "xga_font_data.h" } +extern unsigned char* CBMFont; + SSD1306::SSD1306(int BSCMaster, u8 address, unsigned width, unsigned height, int flip, LCD_MODEL type) : BSCMaster(BSCMaster) , address(address) @@ -142,13 +145,13 @@ void SSD1306::RefreshScreen() } } -// assumes a text row is 16 bit high +// assumes a text row is 8 bit high void SSD1306::RefreshTextRows(u32 start, u32 amountOfRows) { unsigned int i; - start <<= 1; - amountOfRows <<= 1; + //start <<= 1; + //amountOfRows <<= 1; for (i = start; i < start+amountOfRows; i++) { RefreshPage(i); @@ -230,14 +233,14 @@ void SSD1306::SetVCOMDeselect(u8 value) SendCommand( (value & 7) << 4 ); } -void SSD1306::PlotText(int x, int y, char* str, bool inverse) +void SSD1306::PlotText(bool useCBMFont, bool petscii, int x, int y, char* str, bool inverse) { // assumes 16 character width int i; i = 0; while (str[i] && x < 16) { - PlotCharacter(x++, y, str[i++], inverse); + PlotCharacter(useCBMFont, petscii, x++, y, str[i++], inverse); } } @@ -268,13 +271,25 @@ void transpose8(unsigned char* B, const unsigned char* A, bool inverse) B[4] = y >> 24; B[5] = y >> 16; B[6] = y >> 8; B[7] = y; } -void SSD1306::PlotCharacter(int x, int y, char c, bool inverse) +void SSD1306::PlotCharacter(bool useCBMFont, bool petscii, int x, int y, char c, bool inverse) { unsigned char a[8], b[8]; - transpose8(a, avpriv_vga16_font + (c * 16), inverse); - transpose8(b, avpriv_vga16_font + (c * 16) + 8, inverse); - memcpy(frame + (y * 256) + (x * 8), a, 8); - memcpy(frame + (y * 256) + (x * 8) + 128, b, 8); + if (useCBMFont && CBMFont) + { + if (! petscii) + c = ascii2petscii(c); + c = petscii2screen(c); + transpose8(a, CBMFont + ((c+256) * 8), inverse); // 256 byte shift to use the maj/min bank + memcpy(frame + (y * 128) + (x * 8), a, 8); + } + else + { + transpose8(a, avpriv_vga16_font + (c * 16), inverse); + transpose8(b, avpriv_vga16_font + (c * 16) + 8, inverse); + memcpy(frame + (y * 256) + (x * 8), a, 8); + memcpy(frame + (y * 256) + (x * 8) + 128, b, 8); + } + } void SSD1306::PlotPixel(int x, int y, int c) diff --git a/src/SSD1306.h b/src/SSD1306.h index 92c5473..b1ffb62 100644 --- a/src/SSD1306.h +++ b/src/SSD1306.h @@ -77,8 +77,8 @@ public: // 128x64 0x3D or 0x3C (if SA0 is grounded) 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); + void PlotCharacter(bool useCBMFont, bool petscii, int x, int y, char ascii, bool inverse); + void PlotText(bool useCBMFont, bool petscii, int x, int y, char* str, bool inverse); void InitHardware(); void DisplayOn(); diff --git a/src/ScreenBase.h b/src/ScreenBase.h index b98440f..4ebb07f 100644 --- a/src/ScreenBase.h +++ b/src/ScreenBase.h @@ -74,6 +74,9 @@ public: virtual void SwapBuffers() = 0; virtual void RefreshRows(u32 start, u32 amountOfRows) {} + virtual bool IsLCD() { return false; }; + virtual bool UseCBMFont() { return false; }; + bool IsMonocrome() const { return bpp == 1; } protected: diff --git a/src/ScreenLCD.cpp b/src/ScreenLCD.cpp index ac599a8..32a4659 100644 --- a/src/ScreenLCD.cpp +++ b/src/ScreenLCD.cpp @@ -23,7 +23,9 @@ #include "debug.h" #include "ssd_logo.h" -void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip, LCD_MODEL LCDType) +extern unsigned char* CBMFont; + +void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip, LCD_MODEL LCDType, bool luseCBMFont) { bpp = 1; @@ -38,7 +40,8 @@ void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int B width = widthDesired; height = heightDesired; - + useCBMFont = luseCBMFont; + ssd1306 = new SSD1306(BSCMaster, LCDAddress, width, height, LCDFlip, LCDType); ssd1306->ClearScreen(); ssd1306->RefreshScreen(); @@ -100,7 +103,7 @@ void ScreenLCD::PlotRawImage(const u8* image, int x, int y, int w, int h) u32 ScreenLCD::PrintText(bool petscii, u32 x, u32 y, char *ptr, RGBA TxtColour, RGBA BkColour, bool measureOnly, u32* width, u32* height) { int len = 0; - ssd1306->PlotText(x >> 3, y >> 4, ptr, (BkColour & 0xffffff) != 0); + ssd1306->PlotText(UseCBMFont(), petscii, x >> 3, y >> 4, ptr, (BkColour & 0xffffff) != 0); return len; } @@ -111,7 +114,10 @@ u32 ScreenLCD::MeasureText(bool petscii, char *ptr, u32* width, u32* height) u32 ScreenLCD::GetFontHeight() { - return 16; + if (CBMFont && useCBMFont) + return 8; + else + return 16; } void ScreenLCD::RefreshScreen() @@ -127,5 +133,20 @@ void ScreenLCD::SwapBuffers() void ScreenLCD::RefreshRows(u32 start, u32 amountOfRows) { if (ssd1306) + { + if (UseCBMFont()) ssd1306->RefreshTextRows(start, amountOfRows); + else + ssd1306->RefreshTextRows(start*2, amountOfRows*2); + } } + +bool ScreenLCD::IsLCD() +{ + return true; +} + +bool ScreenLCD::UseCBMFont() +{ + return (CBMFont && useCBMFont); +} \ No newline at end of file diff --git a/src/ScreenLCD.h b/src/ScreenLCD.h index fd77137..6b3dbbc 100644 --- a/src/ScreenLCD.h +++ b/src/ScreenLCD.h @@ -33,7 +33,7 @@ public: { } - void Open(u32 width, u32 height, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip, LCD_MODEL LCDType); + void Open(u32 width, u32 height, u32 colourDepth, int BSCMaster, int LCDAddress, int LCDFlip, LCD_MODEL LCDType, bool luseCBMFont); void DrawRectangle(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour); void Clear(RGBA colour); @@ -59,9 +59,11 @@ public: void RefreshScreen(); void RefreshRows(u32 start, u32 amountOfRows); - + bool IsLCD(); + bool UseCBMFont(); private: SSD1306* ssd1306 = 0; + bool useCBMFont; }; #endif diff --git a/src/main.cpp b/src/main.cpp index def4e72..b662c37 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -117,6 +117,7 @@ u16 pc; unsigned int screenWidth = 1024; unsigned int screenHeight = 768; +int i2cLcdUseCBMChar = 0; const char* termainalTextRed = "\E[31m"; const char* termainalTextNormal = "\E[0m"; @@ -250,6 +251,7 @@ void InitialiseLCD() int i2cLcdOnContrast = options.I2CLcdOnContrast(); int i2cLcdDimContrast = options.I2CLcdDimContrast(); int i2cLcdDimTime = options.I2CLcdDimTime(); + i2cLcdUseCBMChar = options.I2cLcdUseCBMChar(); LCD_MODEL i2cLcdModel = options.I2CLcdModel(); if (i2cLcdModel) @@ -259,7 +261,7 @@ void InitialiseLCD() if (i2cLcdModel == LCD_1306_128x32) height = 32; screenLCD = new ScreenLCD(); - screenLCD->Open(width, height, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip, i2cLcdModel); + screenLCD->Open(width, height, 1, i2cBusMaster, i2cLcdAddress, i2cLcdFlip, i2cLcdModel, i2cLcdUseCBMChar); screenLCD->SetContrast(i2cLcdOnContrast); screenLCD->ClearInit(0); // sh1106 needs this @@ -268,7 +270,7 @@ void InitialiseLCD() { 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); + screenLCD->PrintText(false, 16, 0, tempBuffer, 0xffffffff); logo_done = true; } else if (( height == 64) && (strcasecmp(options.GetLcdLogoName(), "1541classic") == 0) ) @@ -297,7 +299,7 @@ void InitialiseLCD() snprintf(tempBuffer, tempBufferSize, "Pi1541 V%d.%02d", versionMajor, versionMinor); int x = (width - 8*strlen(tempBuffer) ) /2; int y = (height-16)/2; - screenLCD->PrintText(0, x, y, tempBuffer, 0x0); + screenLCD->PrintText(false, x, y, tempBuffer, 0x0); } screenLCD->RefreshScreen(); } @@ -345,7 +347,7 @@ void UpdateScreen() int top, top2, top3; int bottom; int graphX = 0; - //bool refreshUartStatusDisplay; + //bool refreshUartStatusDisplay; top = screenHeight - height / 2; bottom = screenHeight - 1; @@ -1051,7 +1053,7 @@ void emulator() m_IEC_Commands.SetAutoBootFB128(options.AutoBootFB128()); m_IEC_Commands.Set128BootSectorName(options.Get128BootSectorName()); - m_IEC_Commands.SetLowercaseBrowseModeFilenames(options.LowercaseBrowseModeFilenames()); + m_IEC_Commands.SetLowercaseBrowseModeFilenames(options.LowercaseBrowseModeFilenames()); emulating = IEC_COMMANDS; @@ -1343,6 +1345,8 @@ void DisplayOptions(int y_pos) screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); snprintf(tempBuffer, tempBufferSize, "AutoBaseName = %s\r\n", options.GetAutoBaseName()); screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); + snprintf(tempBuffer, tempBufferSize, "I2cLcdUseCBMChar = %d\r\n", i2cLcdUseCBMChar); + screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); } void DisplayI2CScan(int y_pos) diff --git a/src/options.cpp b/src/options.cpp index 0d3af35..2eaf7d3 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -148,6 +148,7 @@ Options::Options(void) , i2cLcdFlip(0) , i2cLcdOnContrast(127) , i2cLcdModel(LCD_UNKNOWN) + , i2cLcdUseCBMChar(0) , scrollHighlightRate(0.125f) , keyboardBrowseLCDScreen(0) , buttonEnter(1) @@ -235,6 +236,7 @@ void Options::Process(char* buffer) ELSE_CHECK_DECIMAL_OPTION(i2cLcdOnContrast) ELSE_CHECK_DECIMAL_OPTION(i2cLcdDimContrast) ELSE_CHECK_DECIMAL_OPTION(i2cLcdDimTime) + ELSE_CHECK_DECIMAL_OPTION(i2cLcdUseCBMChar) ELSE_CHECK_FLOAT_OPTION(scrollHighlightRate) ELSE_CHECK_DECIMAL_OPTION(keyboardBrowseLCDScreen) ELSE_CHECK_DECIMAL_OPTION(buttonEnter) diff --git a/src/options.h b/src/options.h index 8a11bee..5001dc2 100644 --- a/src/options.h +++ b/src/options.h @@ -75,7 +75,6 @@ public: inline unsigned int LowercaseBrowseModeFilenames() const { return lowercaseBrowseModeFilenames; } - inline unsigned int ScreenWidth() const { return screenWidth; } inline unsigned int ScreenHeight() const { return screenHeight; } @@ -86,6 +85,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 I2cLcdUseCBMChar() const { return i2cLcdUseCBMChar; } inline LCD_MODEL I2CLcdModel() const { return i2cLcdModel; } inline const char* GetLcdLogoName() const { return LcdLogoName; } @@ -141,6 +141,7 @@ private: unsigned int i2cLcdOnContrast; unsigned int i2cLcdDimContrast; unsigned int i2cLcdDimTime; + unsigned int i2cLcdUseCBMChar; LCD_MODEL i2cLcdModel = LCD_UNKNOWN; float scrollHighlightRate;