Merge pull request #60 from penfold42/i2cdelta

Oled display optimisations and small things
This commit is contained in:
Stephen White 2018-08-04 17:16:53 +10:00 committed by GitHub
commit 2819392170
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 95 additions and 41 deletions

View file

@ -318,6 +318,8 @@ void DiskCaddy::ShowSelectedImage(u32 index)
const char* name = image->GetName(); const char* name = image->GetName();
if (name) if (name)
{ {
memset(buffer, ' ', screenLCD->Width()/screenLCD->GetFontWidth());
screenLCD->PrintText(false, x, y, buffer, BkColour, BkColour);
snprintf(buffer, 256, "%d %s", caddyIndex + 1, name); snprintf(buffer, 256, "%d %s", caddyIndex + 1, name);
screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), caddyIndex == index ? RGBA(0xff, 0xff, 0xff, 0xff) : BkColour); screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), caddyIndex == index ? RGBA(0xff, 0xff, 0xff, 0xff) : BkColour);
y += LCDFONTHEIGHT; y += LCDFONTHEIGHT;

View file

@ -81,6 +81,10 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b
FileBrowser::BrowsableList::Entry* entry = &list->entries[entryIndex]; FileBrowser::BrowsableList::Entry* entry = &list->entries[entryIndex];
if (screen->IsMonocrome()) if (screen->IsMonocrome())
{ {
// pre-clear line on OLED
memset(buffer1, ' ', columnsMax);
screen->PrintText(false, x, y, buffer1, BkColour, BkColour);
if (entry->filImage.fattrib & AM_DIR) if (entry->filImage.fattrib & AM_DIR)
{ {
snprintf(buffer2, 256, "[%s]", entry->filImage.fname); snprintf(buffer2, 256, "[%s]", entry->filImage.fname);
@ -106,9 +110,14 @@ 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())
{
// space pad the remainder of the line (but not on OLED==monochrome)
while (len < (int)columnsMax) while (len < (int)columnsMax)
buffer1[len++] = ' '; buffer1[len++] = ' ';
buffer1[columnsMax] = 0; buffer1[columnsMax] = 0;
}
if (selected) if (selected)
{ {
@ -140,7 +149,7 @@ void FileBrowser::BrowsableListView::RefreshLine(u32 entryIndex, u32 x, u32 y, b
} }
} }
} }
else else // line is blank, write spaces
{ {
memset(buffer1, ' ', columnsMax); memset(buffer1, ' ', columnsMax);
screen->PrintText(false, x, y, buffer1, BkColour, BkColour); screen->PrintText(false, x, y, buffer1, BkColour, BkColour);
@ -548,6 +557,7 @@ void FileBrowser::RefreshFolderEntries()
f_closedir(&dir); f_closedir(&dir);
strcpy(entry.filImage.fname, ".."); strcpy(entry.filImage.fname, "..");
entry.filImage.fattrib |= AM_DIR;
entry.filIcon.fname[0] = 0; entry.filIcon.fname[0] = 0;
folder.entries.push_back(entry); folder.entries.push_back(entry);

View file

@ -23,6 +23,7 @@
extern "C" extern "C"
{ {
#include "rpi-aux.h" #include "rpi-aux.h"
extern void reboot_now(void);
} }
// If disk swaps can be done via multiple cores then directDiskSwapRequest needs to be volatile. WARNING: volatile acesses can be very expensive. // If disk swaps can be done via multiple cores then directDiskSwapRequest needs to be volatile. WARNING: volatile acesses can be very expensive.
@ -152,6 +153,9 @@ bool InputMappings::CheckKeyboardBrowseMode()
keyboardFlags = 0; keyboardFlags = 0;
if (keyboard->KeyHeld(KEY_DELETE) && keyboard->KeyLCtrlAlt() )
reboot_now();
if (keyboard->KeyHeld(KEY_ESC)) if (keyboard->KeyHeld(KEY_ESC))
SetKeyboardFlag(ESC_FLAG); SetKeyboardFlag(ESC_FLAG);
else if (keyboard->KeyHeld(KEY_ENTER)) else if (keyboard->KeyHeld(KEY_ENTER))
@ -245,6 +249,10 @@ void InputMappings::CheckKeyboardEmulationMode(unsigned numberOfImages, unsigned
keyboardFlags = 0; keyboardFlags = 0;
if (keyboard->CheckChanged()) if (keyboard->CheckChanged())
{ {
if (keyboard->KeyHeld(KEY_DELETE) && keyboard->KeyLCtrlAlt() )
reboot_now();
if (keyboard->KeyHeld(KEY_ESC)) if (keyboard->KeyHeld(KEY_ESC))
SetKeyboardFlag(ESC_FLAG); SetKeyboardFlag(ESC_FLAG);
else if (keyboard->KeyHeld(KEY_PAGEUP)) else if (keyboard->KeyHeld(KEY_PAGEUP))

View file

@ -340,17 +340,14 @@ public:
u64 mask = 1ULL << (rawKey & 0x3f); u64 mask = 1ULL << (rawKey & 0x3f);
return (keyStatus[keyStatusIndex] & mask); return (keyStatus[keyStatusIndex] & mask);
} }
inline bool KeyAnyHeld() inline bool KeyAnyHeld()
{ { return (keyStatus[0] | keyStatus[1]); }
return (keyStatus[0] | keyStatus[1]);
} inline bool KeyEitherAlt() { return (modifier & (KEY_MOD_LALT | KEY_MOD_RALT) ); }
inline bool KeyEitherAlt()
{ inline bool KeyNoModifiers() { return (!modifier ); }
return (modifier & (KEY_MOD_LALT | KEY_MOD_RALT) );
} inline bool KeyLCtrlAlt() { return (modifier == (KEY_MOD_LALT | KEY_MOD_LCTRL) ); }
inline bool KeyNoModifiers()
{
return (!modifier );
}
}; };
#endif #endif

View file

@ -25,8 +25,6 @@ extern "C"
#include "xga_font_data.h" #include "xga_font_data.h"
} }
unsigned char frame[SSD1306_128x64_BYTES];
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)
@ -36,8 +34,10 @@ SSD1306::SSD1306(int BSCMaster, u8 address, unsigned width, unsigned height, int
, width(width) , width(width)
, height(height) , height(height)
{ {
sizeof_frame = width*height/8;
frame = (unsigned char *)malloc(sizeof_frame);
oldFrame = (unsigned char *)malloc(sizeof_frame);
RPI_I2CInit(BSCMaster, 1); RPI_I2CInit(BSCMaster, 1);
InitHardware(); InitHardware();
} }
@ -117,10 +117,10 @@ void SSD1306::SendData(u8 data)
void SSD1306::Home() void SSD1306::Home()
{ {
MoveCursorByte(0, 0); SetDataPointer(0, 0);
} }
void SSD1306::MoveCursorByte(u8 page, u8 col) void SSD1306::SetDataPointer(u8 page, u8 col)
{ {
if (col > width-1) { col = width-1; } if (col > width-1) { col = width-1; }
if (page > height/8-1) { page = height/8-1; } if (page > height/8-1) { page = height/8-1; }
@ -142,7 +142,8 @@ void SSD1306::RefreshScreen()
} }
} }
void SSD1306::RefreshRows(u32 start, u32 amountOfRows) // assumes a text row is 16 bit high
void SSD1306::RefreshTextRows(u32 start, u32 amountOfRows)
{ {
unsigned int i; unsigned int i;
@ -154,6 +155,10 @@ void SSD1306::RefreshRows(u32 start, u32 amountOfRows)
} }
} }
// Some very basic optimisation is implemented.
// it scans the page to work out the first (new_start) and last (new_end) changed bytes
// Only update that window on the OLED
// If someone is keen, a smarter algorithm could work out a series of ranges to update
void SSD1306::RefreshPage(u32 page) void SSD1306::RefreshPage(u32 page)
{ {
if (page >= height/8) if (page >= height/8)
@ -170,16 +175,33 @@ void SSD1306::RefreshPage(u32 page)
int start = page*width; int start = page*width;
int end = start + width; int end = start + width;
MoveCursorByte(page, 0); int new_start = -1;
int new_end = -1;
for (i = start; i < end; i++) for (i = start; i < end; i++)
{
if (oldFrame[i] ^ frame[i])
{
if (new_start == -1)
new_start = i;
new_end = i;
}
}
if (new_start >= 0)
{
SetDataPointer(page, new_start-start);
for (i = new_start; i <= new_end; i++)
{ {
SendData(frame[i]); SendData(frame[i]);
oldFrame[i] = frame[i];
}
} }
} }
void SSD1306::ClearScreen() void SSD1306::ClearScreen()
{ {
memset(frame, 0, sizeof(frame)); memset(frame, 0, sizeof_frame);
memset(oldFrame, 0xff, sizeof_frame); // to force update
RefreshScreen(); RefreshScreen();
} }
@ -210,6 +232,7 @@ void SSD1306::SetVCOMDeselect(u8 value)
void SSD1306::PlotText(int x, int y, char* str, bool inverse) void SSD1306::PlotText(int x, int y, char* str, bool inverse)
{ {
// assumes 16 character width
int i; int i;
i = 0; i = 0;
while (str[i] && x < 16) while (str[i] && x < 16)
@ -258,9 +281,9 @@ void SSD1306::PlotPixel(int x, int y, int c)
{ {
switch (c) switch (c)
{ {
case 1: frame[x+ (y/8)*SSD1306_LCDWIDTH] |= (1 << (y&7)); break; case 1: frame[x+ (y/8)*width] |= (1 << (y&7)); break;
case 0: frame[x+ (y/8)*SSD1306_LCDWIDTH] &= ~(1 << (y&7)); break; case 0: frame[x+ (y/8)*width] &= ~(1 << (y&7)); break;
case -1: frame[x+ (y/8)*SSD1306_LCDWIDTH] ^= (1 << (y&7)); break; case -1: frame[x+ (y/8)*width] ^= (1 << (y&7)); break;
} }
} }

View file

@ -18,6 +18,8 @@
#ifndef SSD1306_H #ifndef SSD1306_H
#define SSD1306_H #define SSD1306_H
#include <stdlib.h>
#include "types.h" #include "types.h"
extern "C" extern "C"
{ {
@ -66,10 +68,7 @@ extern "C"
//0000000 | 0 //0000000 | 0
//________________________________________________________ //________________________________________________________
#define SSD1306_LCDWIDTH 128 #define SSD1306_128x64_BYTES ((128 * 64) / 8)
#define SSD1306_LCDHEIGHT 64
#define SSD1306_128x64_BYTES ((SSD1306_LCDWIDTH * SSD1306_LCDHEIGHT) / 8)
class SSD1306 class SSD1306
{ {
@ -91,7 +90,7 @@ public:
void ClearScreen(); void ClearScreen();
void RefreshScreen(); void RefreshScreen();
void RefreshPage(u32 page); void RefreshPage(u32 page);
void RefreshRows(u32 start, u32 amountOfRows); void RefreshTextRows(u32 start, u32 amountOfRows);
void SetDisplayWindow(u8 x1, u8 y1, u8 x2, u8 y2); void SetDisplayWindow(u8 x1, u8 y1, u8 x2, u8 y2);
void PlotPixel(int x, int y, int c); void PlotPixel(int x, int y, int c);
void PlotImage(const unsigned char * source); void PlotImage(const unsigned char * source);
@ -101,9 +100,13 @@ protected:
void SendData(u8 data); void SendData(u8 data);
void Home(); void Home();
void MoveCursorByte(u8 row, u8 col); void SetDataPointer(u8 row, u8 col);
unsigned char frame[SSD1306_128x64_BYTES]; // unsigned char frame[SSD1306_128x64_BYTES];
// unsigned char oldFrame[SSD1306_128x64_BYTES];
unsigned char * frame;
unsigned char * oldFrame;
unsigned sizeof_frame;
int BSCMaster; int BSCMaster;
u8 address; u8 address;

View file

@ -127,5 +127,5 @@ void ScreenLCD::SwapBuffers()
void ScreenLCD::RefreshRows(u32 start, u32 amountOfRows) void ScreenLCD::RefreshRows(u32 start, u32 amountOfRows)
{ {
if (ssd1306) if (ssd1306)
ssd1306->RefreshRows(start, amountOfRows); ssd1306->RefreshTextRows(start, amountOfRows);
} }

View file

@ -441,9 +441,9 @@ void UpdateScreen()
u32 textColour = COLOUR_BLACK; u32 textColour = COLOUR_BLACK;
u32 bgColour = COLOUR_WHITE; u32 bgColour = COLOUR_WHITE;
RGBA atnColour = COLOUR_YELLOW;
RGBA dataColour = COLOUR_GREEN; RGBA dataColour = COLOUR_GREEN;
RGBA clockColour = COLOUR_CYAN; RGBA clockColour = COLOUR_CYAN;
RGBA atnColour = COLOUR_YELLOW;
RGBA BkColour = FileBrowser::Colour(VIC2_COLOUR_INDEX_BLUE); RGBA BkColour = FileBrowser::Colour(VIC2_COLOUR_INDEX_BLUE);
int height = screen.ScaleY(60); int height = screen.ScaleY(60);
@ -487,6 +487,9 @@ void UpdateScreen()
//refreshUartStatusDisplay = true; //refreshUartStatusDisplay = true;
} }
if (options.GraphIEC())
screen.DrawLineV(graphX, top3, bottom, BkColour);
value = IEC_Bus::GetPI_Atn(); value = IEC_Bus::GetPI_Atn();
if (options.GraphIEC()) if (options.GraphIEC())
{ {
@ -497,7 +500,6 @@ void UpdateScreen()
} }
else else
{ {
screen.DrawLineV(graphX, top3, bottom, BkColour);
if (value) screen.PlotPixel(graphX, top3, atnColour); if (value) screen.PlotPixel(graphX, top3, atnColour);
else screen.PlotPixel(graphX, bottom, atnColour); else screen.PlotPixel(graphX, bottom, atnColour);
} }
@ -520,7 +522,6 @@ void UpdateScreen()
} }
else else
{ {
screen.DrawLineV(graphX, top2, bottom, BkColour);
if (value) screen.PlotPixel(graphX, top2, dataColour); if (value) screen.PlotPixel(graphX, top2, dataColour);
else screen.PlotPixel(graphX, bottom, dataColour); else screen.PlotPixel(graphX, bottom, dataColour);
} }
@ -543,7 +544,6 @@ void UpdateScreen()
} }
else else
{ {
screen.DrawLineV(graphX, top, bottom, BkColour);
if (value) screen.PlotPixel(graphX, top, clockColour); if (value) screen.PlotPixel(graphX, top, clockColour);
else screen.PlotPixel(graphX, bottom, clockColour); else screen.PlotPixel(graphX, bottom, clockColour);
} }
@ -557,6 +557,9 @@ void UpdateScreen()
} }
if (graphX++ > screenWidthM1) graphX = 0; if (graphX++ > screenWidthM1) graphX = 0;
// black vertical line ahead of graph
if (options.GraphIEC())
screen.DrawLineV(graphX, top3, bottom, COLOUR_BLACK);
u32 track = pi1541.drive.Track(); u32 track = pi1541.drive.Track();
if (track != oldTrack) if (track != oldTrack)
@ -690,9 +693,13 @@ void emulator()
{ {
IEC_Bus::VIA = 0; IEC_Bus::VIA = 0;
IEC_Bus::Reset();
// workaround for occasional oled curruption
if (screenLCD)
screenLCD->ClearInit(0);
roms.ResetCurrentROMIndex(); roms.ResetCurrentROMIndex();
fileBrowser->ClearScreen(); fileBrowser->ClearScreen();
IEC_Bus::Reset();
fileBrowserSelectedName = 0; fileBrowserSelectedName = 0;
fileBrowser->ClearSelections(); fileBrowser->ClearSelections();
@ -948,6 +955,10 @@ void emulator()
if (diskCaddy.Empty()) if (diskCaddy.Empty())
IEC_Bus::WaitMicroSeconds(2 * 1000000); IEC_Bus::WaitMicroSeconds(2 * 1000000);
// workaround for occasional oled curruption
// if (screenLCD)
// screenLCD->ClearInit(0);
fileBrowser->ClearSelections(); fileBrowser->ClearSelections();
fileBrowser->RefeshDisplay(); // Just redisplay the current folder. fileBrowser->RefeshDisplay(); // Just redisplay the current folder.