CBM font usable on LCD display

Put "i2cLcdUseCBMChar = 1" to the option.txt file.
You have to use the Chargen rom too
This commit is contained in:
gbouille 2018-12-18 08:23:53 +01:00
parent cb04179fc9
commit 8b3dc69bac
11 changed files with 78 additions and 28 deletions

View file

@ -94,6 +94,7 @@ GraphIEC = 1
//i2cLcdFlip = 1 // Rotate i2c LCD screen 180 degrees //i2cLcdFlip = 1 // Rotate i2c LCD screen 180 degrees
//i2cLcdOnContrast = 127 // Allows you to adjust the contrast on your i2c LCD screen //i2cLcdOnContrast = 127 // Allows you to adjust the contrast on your i2c LCD screen
//i2cScan = 1 // scan i2c bus and display addresses on 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 //QuickBoot = 0 // faster startup
//ShowOptions = 0 // display some options on startup screen //ShowOptions = 0 // display some options on startup screen

View file

@ -82,7 +82,7 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b
if (entryIndex < list->entries.size()) if (entryIndex < list->entries.size())
{ {
FileBrowser::BrowsableList::Entry* entry = &list->entries[entryIndex]; FileBrowser::BrowsableList::Entry* entry = &list->entries[entryIndex];
if (screen->IsMonocrome()) if (screen->IsLCD())
{ {
// pre-clear line on OLED // pre-clear line on OLED
memset(buffer1, ' ', columnsMax); memset(buffer1, ' ', columnsMax);
@ -114,9 +114,9 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b
int len = strlen(buffer2 + highlightScrollOffset); int len = strlen(buffer2 + highlightScrollOffset);
strncpy(buffer1, buffer2 + highlightScrollOffset, sizeof(buffer1)); 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) while (len < (int)columnsMax)
buffer1[len++] = ' '; buffer1[len++] = ' ';
buffer1[columnsMax] = 0; buffer1[columnsMax] = 0;
@ -524,7 +524,7 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM
if (screenLCD) if (screenLCD)
{ {
columns = screenLCD->Width() / 8; columns = screenLCD->Width() / 8;
rows = screenLCD->Height() / 16; rows = screenLCD->Height() / screenLCD->GetFontHeight();
positionX = 0; positionX = 0;
positionY = 0; positionY = 0;

View file

@ -24,6 +24,7 @@ static inline u8 ascii2petscii(u8 ch)
if (ch > 64 && ch < 91) ch += 128; if (ch > 64 && ch < 91) ch += 128;
else if (ch > 96 && ch < 123) ch -= 32; else if (ch > 96 && ch < 123) ch -= 32;
else if (ch > 192 && ch < 219) ch -= 128; else if (ch > 192 && ch < 219) ch -= 128;
else if (ch == 95) ch = 164; // to handle underscore
return ch; return ch;
} }
static inline u8 petscii2ascii(u8 ch) static inline u8 petscii2ascii(u8 ch)

View file

@ -19,12 +19,15 @@
#include "SSD1306.h" #include "SSD1306.h"
#include "debug.h" #include "debug.h"
#include <string.h> #include <string.h>
#include "Petscii.h"
extern "C" extern "C"
{ {
#include "xga_font_data.h" #include "xga_font_data.h"
} }
extern unsigned char* CBMFont;
SSD1306::SSD1306(int BSCMaster, u8 address, unsigned width, unsigned height, int flip, LCD_MODEL type) SSD1306::SSD1306(int BSCMaster, u8 address, unsigned width, unsigned height, int flip, LCD_MODEL type)
: BSCMaster(BSCMaster) : BSCMaster(BSCMaster)
, address(address) , 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) void SSD1306::RefreshTextRows(u32 start, u32 amountOfRows)
{ {
unsigned int i; unsigned int i;
start <<= 1; //start <<= 1;
amountOfRows <<= 1; //amountOfRows <<= 1;
for (i = start; i < start+amountOfRows; i++) for (i = start; i < start+amountOfRows; i++)
{ {
RefreshPage(i); RefreshPage(i);
@ -230,14 +233,14 @@ void SSD1306::SetVCOMDeselect(u8 value)
SendCommand( (value & 7) << 4 ); 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 // assumes 16 character width
int i; int i;
i = 0; i = 0;
while (str[i] && x < 16) while (str[i] && x < 16)
{ {
PlotCharacter(x++, y, str[i++], inverse); PlotCharacter(useCBMFont, petscii, x++, y, str[i++], inverse);
} }
} }
@ -268,15 +271,27 @@ 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; 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]; unsigned char a[8], 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(a, avpriv_vga16_font + (c * 16), inverse);
transpose8(b, avpriv_vga16_font + (c * 16) + 8, inverse); transpose8(b, avpriv_vga16_font + (c * 16) + 8, inverse);
memcpy(frame + (y * 256) + (x * 8), a, 8); memcpy(frame + (y * 256) + (x * 8), a, 8);
memcpy(frame + (y * 256) + (x * 8) + 128, b, 8); memcpy(frame + (y * 256) + (x * 8) + 128, b, 8);
} }
}
void SSD1306::PlotPixel(int x, int y, int c) void SSD1306::PlotPixel(int x, int y, int c)
{ {
switch (c) switch (c)

View file

@ -77,8 +77,8 @@ public:
// 128x64 0x3D or 0x3C (if SA0 is grounded) // 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); 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 PlotCharacter(bool useCBMFont, bool petscii, int x, int y, char ascii, bool inverse);
void PlotText(int x, int y, char* str, bool inverse); void PlotText(bool useCBMFont, bool petscii, int x, int y, char* str, bool inverse);
void InitHardware(); void InitHardware();
void DisplayOn(); void DisplayOn();

View file

@ -74,6 +74,9 @@ public:
virtual void SwapBuffers() = 0; virtual void SwapBuffers() = 0;
virtual void RefreshRows(u32 start, u32 amountOfRows) {} virtual void RefreshRows(u32 start, u32 amountOfRows) {}
virtual bool IsLCD() { return false; };
virtual bool UseCBMFont() { return false; };
bool IsMonocrome() const { return bpp == 1; } bool IsMonocrome() const { return bpp == 1; }
protected: protected:

View file

@ -23,7 +23,9 @@
#include "debug.h" #include "debug.h"
#include "ssd_logo.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; bpp = 1;
@ -38,6 +40,7 @@ void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int B
width = widthDesired; width = widthDesired;
height = heightDesired; height = heightDesired;
useCBMFont = luseCBMFont;
ssd1306 = new SSD1306(BSCMaster, LCDAddress, width, height, LCDFlip, LCDType); ssd1306 = new SSD1306(BSCMaster, LCDAddress, width, height, LCDFlip, LCDType);
ssd1306->ClearScreen(); ssd1306->ClearScreen();
@ -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) u32 ScreenLCD::PrintText(bool petscii, u32 x, u32 y, char *ptr, RGBA TxtColour, RGBA BkColour, bool measureOnly, u32* width, u32* height)
{ {
int len = 0; 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; return len;
} }
@ -111,6 +114,9 @@ u32 ScreenLCD::MeasureText(bool petscii, char *ptr, u32* width, u32* height)
u32 ScreenLCD::GetFontHeight() u32 ScreenLCD::GetFontHeight()
{ {
if (CBMFont && useCBMFont)
return 8;
else
return 16; return 16;
} }
@ -127,5 +133,20 @@ void ScreenLCD::SwapBuffers()
void ScreenLCD::RefreshRows(u32 start, u32 amountOfRows) void ScreenLCD::RefreshRows(u32 start, u32 amountOfRows)
{ {
if (ssd1306) if (ssd1306)
{
if (UseCBMFont())
ssd1306->RefreshTextRows(start, amountOfRows); ssd1306->RefreshTextRows(start, amountOfRows);
else
ssd1306->RefreshTextRows(start*2, amountOfRows*2);
}
}
bool ScreenLCD::IsLCD()
{
return true;
}
bool ScreenLCD::UseCBMFont()
{
return (CBMFont && useCBMFont);
} }

View file

@ -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 DrawRectangle(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour);
void Clear(RGBA colour); void Clear(RGBA colour);
@ -59,9 +59,11 @@ public:
void RefreshScreen(); void RefreshScreen();
void RefreshRows(u32 start, u32 amountOfRows); void RefreshRows(u32 start, u32 amountOfRows);
bool IsLCD();
bool UseCBMFont();
private: private:
SSD1306* ssd1306 = 0; SSD1306* ssd1306 = 0;
bool useCBMFont;
}; };
#endif #endif

View file

@ -117,6 +117,7 @@ u16 pc;
unsigned int screenWidth = 1024; unsigned int screenWidth = 1024;
unsigned int screenHeight = 768; unsigned int screenHeight = 768;
int i2cLcdUseCBMChar = 0;
const char* termainalTextRed = "\E[31m"; const char* termainalTextRed = "\E[31m";
const char* termainalTextNormal = "\E[0m"; const char* termainalTextNormal = "\E[0m";
@ -250,6 +251,7 @@ void InitialiseLCD()
int i2cLcdOnContrast = options.I2CLcdOnContrast(); int i2cLcdOnContrast = options.I2CLcdOnContrast();
int i2cLcdDimContrast = options.I2CLcdDimContrast(); int i2cLcdDimContrast = options.I2CLcdDimContrast();
int i2cLcdDimTime = options.I2CLcdDimTime(); int i2cLcdDimTime = options.I2CLcdDimTime();
i2cLcdUseCBMChar = options.I2cLcdUseCBMChar();
LCD_MODEL i2cLcdModel = options.I2CLcdModel(); LCD_MODEL i2cLcdModel = options.I2CLcdModel();
if (i2cLcdModel) if (i2cLcdModel)
@ -259,7 +261,7 @@ void InitialiseLCD()
if (i2cLcdModel == LCD_1306_128x32) if (i2cLcdModel == LCD_1306_128x32)
height = 32; height = 32;
screenLCD = new ScreenLCD(); 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->SetContrast(i2cLcdOnContrast);
screenLCD->ClearInit(0); // sh1106 needs this screenLCD->ClearInit(0); // sh1106 needs this
@ -268,7 +270,7 @@ void InitialiseLCD()
{ {
screenLCD->PlotRawImage(logo_ssd_1541ii, 0, 0, width, height); screenLCD->PlotRawImage(logo_ssd_1541ii, 0, 0, width, height);
snprintf(tempBuffer, tempBufferSize, "Pi1541 V%d.%02d", versionMajor, versionMinor); 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; logo_done = true;
} }
else if (( height == 64) && (strcasecmp(options.GetLcdLogoName(), "1541classic") == 0) ) else if (( height == 64) && (strcasecmp(options.GetLcdLogoName(), "1541classic") == 0) )
@ -297,7 +299,7 @@ void InitialiseLCD()
snprintf(tempBuffer, tempBufferSize, "Pi1541 V%d.%02d", versionMajor, versionMinor); snprintf(tempBuffer, tempBufferSize, "Pi1541 V%d.%02d", versionMajor, versionMinor);
int x = (width - 8*strlen(tempBuffer) ) /2; int x = (width - 8*strlen(tempBuffer) ) /2;
int y = (height-16)/2; int y = (height-16)/2;
screenLCD->PrintText(0, x, y, tempBuffer, 0x0); screenLCD->PrintText(false, x, y, tempBuffer, 0x0);
} }
screenLCD->RefreshScreen(); screenLCD->RefreshScreen();
} }
@ -1343,6 +1345,8 @@ void DisplayOptions(int y_pos)
screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
snprintf(tempBuffer, tempBufferSize, "AutoBaseName = %s\r\n", options.GetAutoBaseName()); snprintf(tempBuffer, tempBufferSize, "AutoBaseName = %s\r\n", options.GetAutoBaseName());
screen.PrintText(false, 0, y_pos += 16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); 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) void DisplayI2CScan(int y_pos)

View file

@ -148,6 +148,7 @@ Options::Options(void)
, i2cLcdFlip(0) , i2cLcdFlip(0)
, i2cLcdOnContrast(127) , i2cLcdOnContrast(127)
, i2cLcdModel(LCD_UNKNOWN) , i2cLcdModel(LCD_UNKNOWN)
, i2cLcdUseCBMChar(0)
, scrollHighlightRate(0.125f) , scrollHighlightRate(0.125f)
, keyboardBrowseLCDScreen(0) , keyboardBrowseLCDScreen(0)
, buttonEnter(1) , buttonEnter(1)
@ -235,6 +236,7 @@ void Options::Process(char* buffer)
ELSE_CHECK_DECIMAL_OPTION(i2cLcdOnContrast) ELSE_CHECK_DECIMAL_OPTION(i2cLcdOnContrast)
ELSE_CHECK_DECIMAL_OPTION(i2cLcdDimContrast) ELSE_CHECK_DECIMAL_OPTION(i2cLcdDimContrast)
ELSE_CHECK_DECIMAL_OPTION(i2cLcdDimTime) ELSE_CHECK_DECIMAL_OPTION(i2cLcdDimTime)
ELSE_CHECK_DECIMAL_OPTION(i2cLcdUseCBMChar)
ELSE_CHECK_FLOAT_OPTION(scrollHighlightRate) ELSE_CHECK_FLOAT_OPTION(scrollHighlightRate)
ELSE_CHECK_DECIMAL_OPTION(keyboardBrowseLCDScreen) ELSE_CHECK_DECIMAL_OPTION(keyboardBrowseLCDScreen)
ELSE_CHECK_DECIMAL_OPTION(buttonEnter) ELSE_CHECK_DECIMAL_OPTION(buttonEnter)

View file

@ -75,7 +75,6 @@ public:
inline unsigned int LowercaseBrowseModeFilenames() const { return lowercaseBrowseModeFilenames; } inline unsigned int LowercaseBrowseModeFilenames() const { return lowercaseBrowseModeFilenames; }
inline unsigned int ScreenWidth() const { return screenWidth; } inline unsigned int ScreenWidth() const { return screenWidth; }
inline unsigned int ScreenHeight() const { return screenHeight; } inline unsigned int ScreenHeight() const { return screenHeight; }
@ -86,6 +85,7 @@ public:
inline unsigned int I2CLcdOnContrast() const { return i2cLcdOnContrast; } inline unsigned int I2CLcdOnContrast() const { return i2cLcdOnContrast; }
inline unsigned int I2CLcdDimContrast() const { return i2cLcdDimContrast; } inline unsigned int I2CLcdDimContrast() const { return i2cLcdDimContrast; }
inline unsigned int I2CLcdDimTime() const { return i2cLcdDimTime; } inline unsigned int I2CLcdDimTime() const { return i2cLcdDimTime; }
inline unsigned int I2cLcdUseCBMChar() const { return i2cLcdUseCBMChar; }
inline LCD_MODEL I2CLcdModel() const { return i2cLcdModel; } inline LCD_MODEL I2CLcdModel() const { return i2cLcdModel; }
inline const char* GetLcdLogoName() const { return LcdLogoName; } inline const char* GetLcdLogoName() const { return LcdLogoName; }
@ -141,6 +141,7 @@ private:
unsigned int i2cLcdOnContrast; unsigned int i2cLcdOnContrast;
unsigned int i2cLcdDimContrast; unsigned int i2cLcdDimContrast;
unsigned int i2cLcdDimTime; unsigned int i2cLcdDimTime;
unsigned int i2cLcdUseCBMChar;
LCD_MODEL i2cLcdModel = LCD_UNKNOWN; LCD_MODEL i2cLcdModel = LCD_UNKNOWN;
float scrollHighlightRate; float scrollHighlightRate;