Added support for ssd1306 128x64
Options.txt needs the line;- LCDName = ssd1306_128x64 and depending upon how you want the keyboard's pgup and pgdown keys to work;- keyboardBrowseLCDScreen = 1 Splits lines connect SDA to GPIO 2 pin 3 SCL to GPIO 3 pin 5 Non-split lines SDA to GPIO 0 pin 27 SCL to GPIO 1 pin 28
This commit is contained in:
parent
fdac3079dd
commit
e292de1179
19 changed files with 1337 additions and 230 deletions
4
Makefile
4
Makefile
|
@ -1,8 +1,8 @@
|
|||
OBJS = armc-start.o armc-cstartup.o armc-cstubs.o armc-cppstubs.o \
|
||||
exception.o main.o rpi-aux.o rpi-mailbox-interface.o rpi-mailbox.o \
|
||||
exception.o main.o rpi-aux.o rpi-i2c.o rpi-mailbox-interface.o rpi-mailbox.o \
|
||||
rpi-gpio.o rpi-interrupts.o cache.o ff.o interrupt.o Keyboard.o \
|
||||
Pi1541.o DiskImage.o iec_bus.o iec_commands.o m6502.o m6522.o \
|
||||
Drive.o gcr.o prot.o lz.o emmc.o diskio.o options.o Screen.o \
|
||||
Drive.o gcr.o prot.o lz.o emmc.o diskio.o options.o Screen.o SSD1306.o ScreenLCD.o \
|
||||
Timer.o FileBrowser.o DiskCaddy.o ROMs.o InputMappings.o xga_font_data.o
|
||||
|
||||
SRCDIR = src
|
||||
|
|
|
@ -34,6 +34,8 @@ static u32 red = RGBA(0xff, 0, 0, 0xff);
|
|||
|
||||
bool DiskCaddy::Insert(const FILINFO* fileInfo, bool readOnly)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
bool success;
|
||||
FIL fp;
|
||||
FRESULT res = f_open(&fp, fileInfo->fname, FA_READ);
|
||||
|
@ -41,13 +43,28 @@ bool DiskCaddy::Insert(const FILINFO* fileInfo, bool readOnly)
|
|||
{
|
||||
if (screen)
|
||||
{
|
||||
int x = screen->ScaleX(screenPosXCaddySelections);
|
||||
int y = screen->ScaleY(screenPosYCaddySelections);
|
||||
x = screen->ScaleX(screenPosXCaddySelections);
|
||||
y = screen->ScaleY(screenPosYCaddySelections);
|
||||
|
||||
snprintf(buffer, 256, "Loading %s\r\n", fileInfo->fname);
|
||||
screen->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red);
|
||||
}
|
||||
|
||||
if (screenLCD)
|
||||
{
|
||||
RGBA BkColour = RGBA(0, 0, 0, 0xFF);
|
||||
screenLCD->Clear(BkColour);
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
snprintf(buffer, 256, "Loading");
|
||||
screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), BkColour);
|
||||
y += 16;
|
||||
snprintf(buffer, 256, "%s ", fileInfo->fname);
|
||||
screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red);
|
||||
screenLCD->SwapBuffers();
|
||||
}
|
||||
|
||||
u32 bytesRead;
|
||||
SetACTLed(true);
|
||||
f_read(&fp, DiskImage::readBuffer, READBUFFER_SIZE, &bytesRead);
|
||||
|
@ -146,12 +163,14 @@ bool DiskCaddy::InsertNBZ(const FILINFO* fileInfo, unsigned char* diskImageData,
|
|||
|
||||
void DiskCaddy::Display()
|
||||
{
|
||||
if (screen)
|
||||
{
|
||||
unsigned numberOfImages = GetNumberOfImages();
|
||||
unsigned caddyIndex;
|
||||
int x = screen->ScaleX(screenPosXCaddySelections);
|
||||
int y = screen->ScaleY(screenPosYCaddySelections);
|
||||
int x;
|
||||
int y;
|
||||
if (screen)
|
||||
{
|
||||
x = screen->ScaleX(screenPosXCaddySelections);
|
||||
y = screen->ScaleY(screenPosYCaddySelections);
|
||||
|
||||
snprintf(buffer, 256, "Emulating\r\n");
|
||||
screen->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), red);
|
||||
|
@ -168,17 +187,71 @@ void DiskCaddy::Display()
|
|||
y += 16;
|
||||
}
|
||||
}
|
||||
|
||||
ShowSelectedImage(0);
|
||||
}
|
||||
|
||||
if (screenLCD)
|
||||
{
|
||||
RGBA BkColour = RGBA(0, 0, 0, 0xFF);
|
||||
screenLCD->Clear(BkColour);
|
||||
}
|
||||
ShowSelectedImage(0);
|
||||
}
|
||||
|
||||
void DiskCaddy::ShowSelectedImage(u32 index)
|
||||
{
|
||||
u32 x = screen->ScaleX(screenPosXCaddySelections) - 16;
|
||||
u32 y = screen->ScaleY(screenPosYCaddySelections) + 16 + 16 * index;
|
||||
u32 x;
|
||||
u32 y;
|
||||
if (screen)
|
||||
{
|
||||
x = screen->ScaleX(screenPosXCaddySelections) - 16;
|
||||
y = screen->ScaleY(screenPosYCaddySelections) + 16 + 16 * index;
|
||||
snprintf(buffer, 256, "*");
|
||||
screen->PrintText(false, x, y, buffer, white, red);
|
||||
}
|
||||
if (screenLCD)
|
||||
{
|
||||
unsigned numberOfImages = GetNumberOfImages();
|
||||
unsigned caddyIndex;
|
||||
|
||||
if (screenLCD)
|
||||
{
|
||||
RGBA BkColour = RGBA(0, 0, 0, 0xFF);
|
||||
//screenLCD->Clear(BkColour);
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
snprintf(buffer, 256, "Emulating %d/%d ", index + 1, numberOfImages);
|
||||
screenLCD->PrintText(false, x, y, buffer, RGBA(0xff, 0xff, 0xff, 0xff), RGBA(0xff, 0xff, 0xff, 0xff));
|
||||
y += 16;
|
||||
|
||||
if (numberOfImages > 3 && index > 2)
|
||||
{
|
||||
if (numberOfImages - index < 3)
|
||||
caddyIndex = numberOfImages - 3;
|
||||
else
|
||||
caddyIndex = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
caddyIndex = 0;
|
||||
}
|
||||
|
||||
for (; caddyIndex < numberOfImages; ++caddyIndex)
|
||||
{
|
||||
DiskImage* image = GetImage(caddyIndex);
|
||||
const char* name = image->GetName();
|
||||
if (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);
|
||||
y += 16;
|
||||
}
|
||||
if (y >= screenLCD->Height())
|
||||
break;
|
||||
}
|
||||
screenLCD->SwapBuffers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DiskCaddy::Update()
|
||||
|
@ -198,6 +271,11 @@ bool DiskCaddy::Update()
|
|||
ShowSelectedImage(oldCaddyIndex);
|
||||
}
|
||||
|
||||
if (screenLCD)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -29,10 +29,11 @@ public:
|
|||
DiskCaddy()
|
||||
: selectedIndex(0)
|
||||
, screen(0)
|
||||
, screenLCD(0)
|
||||
{
|
||||
}
|
||||
|
||||
void SetScreen(Screen* screen) { this->screen = screen; }
|
||||
void SetScreen(Screen* screen, ScreenBase* screenLCD) { this->screen = screen; this->screenLCD = screenLCD; }
|
||||
|
||||
void Empty()
|
||||
{
|
||||
|
@ -106,6 +107,7 @@ private:
|
|||
u32 oldCaddyIndex;
|
||||
|
||||
Screen* screen;
|
||||
ScreenBase* screenLCD;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -21,7 +21,6 @@
|
|||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <algorithm>
|
||||
#include "Screen.h"
|
||||
#include "debug.h"
|
||||
#include "Keyboard.h"
|
||||
#include "options.h"
|
||||
|
@ -33,8 +32,6 @@ extern "C"
|
|||
#include "rpi-gpio.h"
|
||||
}
|
||||
|
||||
extern Screen screen;
|
||||
|
||||
#define PNG_WIDTH 320
|
||||
#define PNG_HEIGHT 200
|
||||
|
||||
|
@ -75,6 +72,205 @@ static const u32 palette[] =
|
|||
RGBA(0x9F, 0x9F, 0x9F, 0xFF)
|
||||
};
|
||||
|
||||
void FileBrowser::BrowsableListView::Refresh()
|
||||
{
|
||||
char buffer1[128] = { 0 };
|
||||
char buffer2[128] = { 0 };
|
||||
u32 index;
|
||||
u32 entryIndex;
|
||||
u32 x = positionX;
|
||||
u32 y = positionY;
|
||||
u32 colour;
|
||||
RGBA BkColour = RGBA(0, 0, 0, 0xFF); //palette[VIC2_COLOUR_INDEX_BLUE];
|
||||
|
||||
// Ensure the current selection is visible
|
||||
if (list->currentIndex - offset >= rows)
|
||||
{
|
||||
//DEBUG_LOG("CI= %d O = %d R = %d\r\n", list->currentIndex, offset, rows);
|
||||
offset = list->currentIndex - rows + 1;
|
||||
if ((int)offset < 0) offset = 0;
|
||||
}
|
||||
|
||||
for (index = 0; index < rows; ++index)
|
||||
{
|
||||
entryIndex = offset + index;
|
||||
|
||||
if (entryIndex < list->entries.size())
|
||||
{
|
||||
FileBrowser::BrowsableList::Entry* entry = &list->entries[entryIndex];
|
||||
if (screen->IsMonocrome())
|
||||
{
|
||||
if (entry->filImage.fattrib & AM_DIR)
|
||||
{
|
||||
snprintf(buffer2, columns + 1, "[%s]", entry->filImage.fname);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (entry->caddyIndex != -1)
|
||||
snprintf(buffer2, columns + 1, "%d>%s", entry->caddyIndex, entry->filImage.fname);
|
||||
else
|
||||
snprintf(buffer2, columns + 1, "%s", entry->filImage.fname);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(buffer2, columns + 1, "%s", entry->filImage.fname);
|
||||
}
|
||||
memset(buffer1, ' ', columns);
|
||||
buffer1[127] = 0;
|
||||
strncpy(buffer1, buffer2, strlen(buffer2));
|
||||
if (/*showSelected && */list->currentIndex == entryIndex)
|
||||
{
|
||||
if (entry->filImage.fattrib & AM_DIR)
|
||||
{
|
||||
screen->PrintText(false, x, y, buffer1, palette[VIC2_COLOUR_INDEX_LBLUE], RGBA(0xff, 0xff, 0xff, 0xff));
|
||||
}
|
||||
else
|
||||
{
|
||||
colour = RGBA(0xff, 0, 0, 0xff);
|
||||
if (entry->filImage.fattrib & AM_RDO)
|
||||
colour = palette[VIC2_COLOUR_INDEX_RED];
|
||||
|
||||
screen->PrintText(false, x, y, buffer1, colour, RGBA(0xff, 0xff, 0xff, 0xff));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (entry->filImage.fattrib & AM_DIR)
|
||||
{
|
||||
screen->PrintText(false, x, y, buffer1, palette[VIC2_COLOUR_INDEX_LBLUE], BkColour);
|
||||
}
|
||||
else
|
||||
{
|
||||
colour = palette[VIC2_COLOUR_INDEX_LGREY];
|
||||
if (entry->filImage.fattrib & AM_RDO)
|
||||
colour = palette[VIC2_COLOUR_INDEX_PINK];
|
||||
screen->PrintText(false, x, y, buffer1, colour, BkColour);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(buffer1, ' ', 80);
|
||||
screen->PrintText(false, x, y, buffer1, BkColour, BkColour);
|
||||
}
|
||||
y += 16;
|
||||
}
|
||||
|
||||
screen->SwapBuffers();
|
||||
}
|
||||
|
||||
bool FileBrowser::BrowsableListView::CheckBrowseNavigation(bool pageOnly)
|
||||
{
|
||||
InputMappings* inputMappings = InputMappings::Instance();
|
||||
bool dirty = false;
|
||||
u32 numberOfEntriesMinus1 = list->entries.size() - 1;
|
||||
|
||||
if (inputMappings->BrowseDown())
|
||||
{
|
||||
if (list->currentIndex < numberOfEntriesMinus1)
|
||||
{
|
||||
if (!pageOnly)
|
||||
{
|
||||
list->currentIndex++;
|
||||
list->current = &list->entries[list->currentIndex];
|
||||
}
|
||||
if (list->currentIndex >= (offset + rows) && (list->currentIndex < list->entries.size()))
|
||||
offset++;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
if (inputMappings->BrowseUp())
|
||||
{
|
||||
if (list->currentIndex > 0)
|
||||
{
|
||||
if (!pageOnly)
|
||||
{
|
||||
list->currentIndex--;
|
||||
list->current = &list->entries[list->currentIndex];
|
||||
}
|
||||
if ((offset > 0) && (list->currentIndex < offset))
|
||||
offset--;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
if ((lcdPgUpDown && inputMappings->BrowsePageDownLCD()) || (!lcdPgUpDown && inputMappings->BrowsePageDown()))
|
||||
{
|
||||
u32 rowsMinus1 = rows - 1;
|
||||
|
||||
if (list->currentIndex == offset + rowsMinus1)
|
||||
{
|
||||
// Need to move the screen window down so that the currentIndex is now at the top of the screen
|
||||
offset = list->currentIndex;
|
||||
|
||||
// Current index now becomes the bottom one
|
||||
if (offset + rowsMinus1 > numberOfEntriesMinus1)
|
||||
list->currentIndex = numberOfEntriesMinus1; // Not enough entries to move another page just move to the last entry
|
||||
else // Move the window down a page
|
||||
list->currentIndex = offset + rowsMinus1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Need to move to list->offset + rowsMinus1
|
||||
if (offset + rowsMinus1 > numberOfEntriesMinus1)
|
||||
list->currentIndex = numberOfEntriesMinus1; // Run out of entries before we hit the bottom. Just move to the bottom.
|
||||
else
|
||||
list->currentIndex = offset + rowsMinus1; // Move the bottom of the screen
|
||||
}
|
||||
list->current = &list->entries[list->currentIndex];
|
||||
dirty = true;
|
||||
}
|
||||
if ((lcdPgUpDown && inputMappings->BrowsePageUpLCD()) || (!lcdPgUpDown && inputMappings->BrowsePageUp()))
|
||||
{
|
||||
if (list->currentIndex == offset)
|
||||
{
|
||||
// If the cursor is already at the top of the window then page up
|
||||
int offsetInWindow = (int)list->currentIndex - (int)rows;
|
||||
if (offsetInWindow < 0) offset = 0;
|
||||
else offset = (u32)offsetInWindow;
|
||||
list->currentIndex = offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->currentIndex = offset; // Move the cursor to the top of the window
|
||||
}
|
||||
list->current = &list->entries[list->currentIndex];
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
return dirty;
|
||||
}
|
||||
|
||||
void FileBrowser::BrowsableList::ClearSelections()
|
||||
{
|
||||
u32 entryIndex;
|
||||
|
||||
for (entryIndex = 0; entryIndex < entries.size(); ++entryIndex)
|
||||
{
|
||||
entries[entryIndex].caddyIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowser::BrowsableList::RefreshViews()
|
||||
{
|
||||
u32 index;
|
||||
for (index = 0; index < views.size(); ++index)
|
||||
{
|
||||
views[index].Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
bool FileBrowser::BrowsableList::CheckBrowseNavigation()
|
||||
{
|
||||
bool dirty = false;
|
||||
u32 index;
|
||||
for (index = 0; index < views.size(); ++index)
|
||||
{
|
||||
dirty |= views[index].CheckBrowseNavigation(index != 0);
|
||||
}
|
||||
return dirty;
|
||||
}
|
||||
|
||||
FileBrowser::BrowsableList::Entry* FileBrowser::BrowsableList::FindEntry(const char* name)
|
||||
{
|
||||
int index;
|
||||
|
@ -89,18 +285,38 @@ FileBrowser::BrowsableList::Entry* FileBrowser::BrowsableList::FindEntry(const c
|
|||
return 0;
|
||||
}
|
||||
|
||||
FileBrowser::FileBrowser(DiskCaddy* diskCaddy, ROMs* roms, unsigned deviceID, bool displayPNGIcons)
|
||||
FileBrowser::FileBrowser(DiskCaddy* diskCaddy, ROMs* roms, unsigned deviceID, bool displayPNGIcons, ScreenBase* screenMain, ScreenBase* screenLCD)
|
||||
: state(State_Folders)
|
||||
, maxOnScreen(38)
|
||||
, diskCaddy(diskCaddy)
|
||||
, selectionsMade(false)
|
||||
, roms(roms)
|
||||
, deviceID(deviceID)
|
||||
, displayPNGIcons(displayPNGIcons)
|
||||
, screenMain(screenMain)
|
||||
, screenLCD(screenLCD)
|
||||
{
|
||||
maxOnScreen = (int)(38.0f * screen.GetScaleY());
|
||||
if (maxOnScreen < 1)
|
||||
maxOnScreen = 1;
|
||||
u32 columns = screenMain->ScaleX(80);
|
||||
u32 rows = (int)(38.0f * screenMain->GetScaleY());
|
||||
u32 positionX = 0;
|
||||
u32 positionY = 17;
|
||||
|
||||
if (rows < 1)
|
||||
rows = 1;
|
||||
|
||||
folder.AddView(screenMain, columns, rows, positionX, positionY, false);
|
||||
|
||||
positionX = screenMain->ScaleX(1024 - 320);
|
||||
caddySelections.AddView(screenMain, columns, rows, positionX, positionY, false);
|
||||
|
||||
|
||||
|
||||
columns = 128 / 8;
|
||||
rows = 4;
|
||||
positionX = 0;
|
||||
positionY = 0;
|
||||
|
||||
if (screenLCD)
|
||||
folder.AddView(screenLCD, columns, rows, positionX, positionY, true);
|
||||
}
|
||||
|
||||
u32 FileBrowser::Colour(int index)
|
||||
|
@ -204,6 +420,7 @@ void FileBrowser::DisplayRoot()
|
|||
FolderChanged();
|
||||
}
|
||||
|
||||
/*
|
||||
void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* browsableList, int xOffset, bool showSelected)
|
||||
{
|
||||
char buffer1[128] = { 0 };
|
||||
|
@ -219,7 +436,7 @@ void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* brow
|
|||
if (terminal)
|
||||
printf("\E[2J\E[f");
|
||||
|
||||
u32 maxCharacters = screen.ScaleX(80);
|
||||
u32 maxCharacters = screenMain->ScaleX(80);
|
||||
|
||||
for (index = 0; index < maxOnScreen; ++index)
|
||||
{
|
||||
|
@ -238,7 +455,7 @@ void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* brow
|
|||
{
|
||||
if (terminal)
|
||||
printf("\E[34;47m%s\E[0m\r\n", buffer1);
|
||||
screen.PrintText(false, x, y, buffer1, palette[VIC2_COLOUR_INDEX_LBLUE], RGBA(0xff, 0xff, 0xff, 0xff));
|
||||
screenMain->PrintText(false, x, y, buffer1, palette[VIC2_COLOUR_INDEX_LBLUE], RGBA(0xff, 0xff, 0xff, 0xff));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -246,7 +463,7 @@ void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* brow
|
|||
if (entry->filImage.fattrib & AM_RDO)
|
||||
colour = palette[VIC2_COLOUR_INDEX_RED];
|
||||
|
||||
screen.PrintText(false, x, y, buffer1, colour, RGBA(0xff, 0xff, 0xff, 0xff));
|
||||
screenMain->PrintText(false, x, y, buffer1, colour, RGBA(0xff, 0xff, 0xff, 0xff));
|
||||
if (terminal)
|
||||
printf("\E[31;47m%s\E[0m\r\n", buffer1);
|
||||
}
|
||||
|
@ -255,7 +472,7 @@ void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* brow
|
|||
{
|
||||
if (entry->filImage.fattrib & AM_DIR)
|
||||
{
|
||||
screen.PrintText(false, x, y, buffer1, palette[VIC2_COLOUR_INDEX_LBLUE], BkColour);
|
||||
screenMain->PrintText(false, x, y, buffer1, palette[VIC2_COLOUR_INDEX_LBLUE], BkColour);
|
||||
if (terminal)
|
||||
printf("\E[34m%s\E[0m\r\n", buffer1);
|
||||
}
|
||||
|
@ -264,7 +481,7 @@ void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* brow
|
|||
colour = palette[VIC2_COLOUR_INDEX_LGREY];
|
||||
if (entry->filImage.fattrib & AM_RDO)
|
||||
colour = palette[VIC2_COLOUR_INDEX_PINK];
|
||||
screen.PrintText(false, x, y, buffer1, colour, BkColour);
|
||||
screenMain->PrintText(false, x, y, buffer1, colour, BkColour);
|
||||
if (terminal)
|
||||
printf("\E[0;m%s\E[0m\r\n", buffer1);
|
||||
}
|
||||
|
@ -273,13 +490,14 @@ void FileBrowser::RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* brow
|
|||
else
|
||||
{
|
||||
memset(buffer1, ' ', 80);
|
||||
screen.PrintText(false, x, y, buffer1, BkColour, BkColour);
|
||||
screenMain->PrintText(false, x, y, buffer1, BkColour, BkColour);
|
||||
if (terminal)
|
||||
printf("%s\r\n", buffer1);
|
||||
}
|
||||
y += 16;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void FileBrowser::RefeshDisplay()
|
||||
{
|
||||
|
@ -289,13 +507,16 @@ void FileBrowser::RefeshDisplay()
|
|||
u32 textColour = Colour(VIC2_COLOUR_INDEX_LGREEN);
|
||||
u32 bgColour = Colour(VIC2_COLOUR_INDEX_GREY);
|
||||
|
||||
screen.ClearArea(0, 0, (int)screen.Width(), 17, bgColour);
|
||||
screen.PrintText(false, 0, 0, buffer, textColour, bgColour);
|
||||
screenMain->ClearArea(0, 0, (int)screenMain->Width(), 17, bgColour);
|
||||
screenMain->PrintText(false, 0, 0, buffer, textColour, bgColour);
|
||||
}
|
||||
|
||||
u32 offsetX = screen.ScaleX(1024 - 320);
|
||||
RefeshDisplayForBrowsableList(&folder, 0);
|
||||
RefeshDisplayForBrowsableList(&caddySelections, offsetX, false);
|
||||
//u32 offsetX = screenMain->ScaleX(1024 - 320);
|
||||
//RefeshDisplayForBrowsableList(&folder, 0);
|
||||
//RefeshDisplayForBrowsableList(&caddySelections, offsetX, false);
|
||||
|
||||
folder.RefreshViews();
|
||||
caddySelections.RefreshViews();
|
||||
|
||||
DisplayPNG();
|
||||
DisplayStatusBar();
|
||||
|
@ -349,7 +570,7 @@ void FileBrowser::DisplayPNG(FILINFO& filIcon, int x, int y)
|
|||
if (image && (w == PNG_WIDTH && h == PNG_HEIGHT))
|
||||
{
|
||||
//DEBUG_LOG("Opened PNG %s w = %d h = %d cif = %d\r\n", fileName, w, h, channels_in_file);
|
||||
screen.PlotImage((u32*)image, x, y, w, h);
|
||||
screenMain->PlotImage((u32*)image, x, y, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -368,8 +589,8 @@ void FileBrowser::DisplayPNG()
|
|||
if (displayPNGIcons && folder.current)
|
||||
{
|
||||
FileBrowser::BrowsableList::Entry* current = folder.current;
|
||||
u32 x = screen.ScaleX(1024 - 320);
|
||||
u32 y = screen.ScaleY(666) - 240;
|
||||
u32 x = screenMain->ScaleX(1024 - 320);
|
||||
u32 y = screenMain->ScaleY(666) - 240;
|
||||
DisplayPNG(current->filIcon, x, y);
|
||||
}
|
||||
}
|
||||
|
@ -409,11 +630,6 @@ void FileBrowser::UpdateInput()
|
|||
}
|
||||
}
|
||||
|
||||
FileBrowser::Folder* FileBrowser::GetCurrentFolder()
|
||||
{
|
||||
return &folder;
|
||||
}
|
||||
|
||||
bool FileBrowser::FillCaddyWithSelections()
|
||||
{
|
||||
if (caddySelections.entries.size())
|
||||
|
@ -450,6 +666,7 @@ bool FileBrowser::AddToCaddy(FileBrowser::BrowsableList::Entry* current)
|
|||
}
|
||||
if (canAdd)
|
||||
{
|
||||
current->caddyIndex = caddySelections.entries.size();
|
||||
caddySelections.entries.push_back(*current);
|
||||
added = true;
|
||||
}
|
||||
|
@ -464,7 +681,7 @@ void FileBrowser::UpdateInputFolders()
|
|||
|
||||
if (folder.entries.size() > 0)
|
||||
{
|
||||
u32 numberOfEntriesMinus1 = folder.entries.size() - 1;
|
||||
//u32 numberOfEntriesMinus1 = folder.entries.size() - 1;
|
||||
bool dirty = false;
|
||||
|
||||
if (inputMappings->BrowseSelect())
|
||||
|
@ -531,7 +748,7 @@ void FileBrowser::UpdateInputFolders()
|
|||
}
|
||||
else if (inputMappings->Exit())
|
||||
{
|
||||
caddySelections.Clear();
|
||||
ClearSelections();
|
||||
dirty = true;
|
||||
}
|
||||
else if (inputMappings->BrowseInsert())
|
||||
|
@ -560,71 +777,7 @@ void FileBrowser::UpdateInputFolders()
|
|||
}
|
||||
}
|
||||
|
||||
if (inputMappings->BrowseDown())
|
||||
{
|
||||
if (folder.currentIndex < numberOfEntriesMinus1)
|
||||
{
|
||||
folder.currentIndex++;
|
||||
folder.current = &folder.entries[folder.currentIndex];
|
||||
if (folder.currentIndex >= (folder.offset + maxOnScreen) && (folder.currentIndex < folder.entries.size()))
|
||||
folder.offset++;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
if (inputMappings->BrowseUp())
|
||||
{
|
||||
if (folder.currentIndex > 0)
|
||||
{
|
||||
folder.currentIndex--;
|
||||
folder.current = &folder.entries[folder.currentIndex];
|
||||
if ((folder.offset > 0) && (folder.currentIndex < folder.offset))
|
||||
folder.offset--;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
if (inputMappings->BrowsePageDown())
|
||||
{
|
||||
u32 maxOnScreenMinus1 = maxOnScreen - 1;
|
||||
|
||||
if (folder.currentIndex == folder.offset + maxOnScreenMinus1)
|
||||
{
|
||||
// Need to move the screen window down so that the currentIndex is now at the top of the screen
|
||||
folder.offset = folder.currentIndex;
|
||||
|
||||
// Current index now becomes the bottom one
|
||||
if (folder.offset + maxOnScreenMinus1 > numberOfEntriesMinus1)
|
||||
folder.currentIndex = numberOfEntriesMinus1; // Not enough entries to move another page just move to the last entry
|
||||
else // Move the window down a page
|
||||
folder.currentIndex = folder.offset + maxOnScreenMinus1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Need to move to folder.offset + maxOnScreenMinus1
|
||||
if (folder.offset + maxOnScreenMinus1 > numberOfEntriesMinus1)
|
||||
folder.currentIndex = numberOfEntriesMinus1; // Run out of entries before we hit the bottom. Just move to the bottom.
|
||||
else
|
||||
folder.currentIndex = folder.offset + maxOnScreenMinus1; // Move the bottom of the screen
|
||||
}
|
||||
folder.current = &folder.entries[folder.currentIndex];
|
||||
dirty = true;
|
||||
}
|
||||
if (inputMappings->BrowsePageUp())
|
||||
{
|
||||
if (folder.currentIndex == folder.offset)
|
||||
{
|
||||
// If the cursor is already at the top of the window then page up
|
||||
int offset = (int)folder.currentIndex - (int)maxOnScreen;
|
||||
if (offset < 0) folder.offset = 0;
|
||||
else folder.offset = (u32)offset;
|
||||
folder.currentIndex = folder.offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
folder.currentIndex = folder.offset; // Move the cursor to the top of the window
|
||||
}
|
||||
folder.current = &folder.entries[folder.currentIndex];
|
||||
dirty = true;
|
||||
}
|
||||
dirty = folder.CheckBrowseNavigation();
|
||||
}
|
||||
|
||||
if (dirty) RefeshDisplay();
|
||||
|
@ -641,9 +794,6 @@ bool FileBrowser::SelectLST(const char* filenameLST)
|
|||
bool validImage = false;
|
||||
//DEBUG_LOG("Selected %s\r\n", filenameLST);
|
||||
if (DiskImage::IsLSTExtention(filenameLST))
|
||||
{
|
||||
FileBrowser::Folder* currentFolder = GetCurrentFolder();
|
||||
if (currentFolder)
|
||||
{
|
||||
DiskImage::DiskType diskType;
|
||||
FIL fp;
|
||||
|
@ -667,7 +817,7 @@ bool FileBrowser::SelectLST(const char* filenameLST)
|
|||
diskType = DiskImage::GetDiskImageTypeViaExtention(token);
|
||||
if (diskType == DiskImage::D64 || diskType == DiskImage::G64 || diskType == DiskImage::NIB || diskType == DiskImage::NBZ)
|
||||
{
|
||||
FileBrowser::BrowsableList::Entry* entry = currentFolder->FindEntry(token);
|
||||
FileBrowser::BrowsableList::Entry* entry = folder.FindEntry(token);
|
||||
if (entry && !(entry->filImage.fattrib & AM_DIR))
|
||||
{
|
||||
bool readOnly = (entry->filImage.fattrib & AM_RDO) != 0;
|
||||
|
@ -683,7 +833,6 @@ bool FileBrowser::SelectLST(const char* filenameLST)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return validImage;
|
||||
}
|
||||
|
||||
|
@ -717,17 +866,25 @@ void FileBrowser::UpdateInputDiskCaddy()
|
|||
void FileBrowser::DisplayStatusBar()
|
||||
{
|
||||
u32 x = 0;
|
||||
u32 y = screen.ScaleY(STATUS_BAR_POSITION_Y);
|
||||
u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y);
|
||||
|
||||
char bufferOut[128];
|
||||
snprintf(bufferOut, 256, "LED 0 Motor 0 Track 00.0 ATN 0 DAT 0 CLK 0");
|
||||
screen.PrintText(false, x, y, bufferOut, RGBA(0, 0, 0, 0xff), RGBA(0xff, 0xff, 0xff, 0xff));
|
||||
screenMain->PrintText(false, x, y, bufferOut, RGBA(0, 0, 0, 0xff), RGBA(0xff, 0xff, 0xff, 0xff));
|
||||
}
|
||||
|
||||
void FileBrowser::ClearScreen()
|
||||
{
|
||||
u32 bgColour = palette[VIC2_COLOUR_INDEX_BLUE];
|
||||
screen.Clear(bgColour);
|
||||
screenMain->Clear(bgColour);
|
||||
}
|
||||
|
||||
void FileBrowser::ClearSelections()
|
||||
{
|
||||
selectionsMade = false;
|
||||
caddySelections.Clear();
|
||||
|
||||
folder.ClearSelections();
|
||||
}
|
||||
|
||||
void FileBrowser::ShowDeviceAndROM()
|
||||
|
@ -735,10 +892,10 @@ void FileBrowser::ShowDeviceAndROM()
|
|||
char buffer[256];
|
||||
u32 textColour = RGBA(0, 0, 0, 0xff);
|
||||
u32 bgColour = RGBA(0xff, 0xff, 0xff, 0xff);
|
||||
u32 y = screen.ScaleY(STATUS_BAR_POSITION_Y);
|
||||
u32 y = screenMain->ScaleY(STATUS_BAR_POSITION_Y);
|
||||
|
||||
snprintf(buffer, 256, "Device %d %s \r\n", deviceID, roms->ROMNames[roms->currentROMIndex]);
|
||||
screen.PrintText(false, 43 * 8, y, buffer, textColour, bgColour);
|
||||
screenMain->PrintText(false, 43 * 8, y, buffer, textColour, bgColour);
|
||||
}
|
||||
|
||||
void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForIcon)
|
||||
|
@ -754,7 +911,7 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI
|
|||
char name[17] = { 0 };
|
||||
unsigned char buffer[260] = { 0 };
|
||||
int charIndex;
|
||||
u32 fontHeight = screen.GetCBMFontHeight();
|
||||
u32 fontHeight = screenMain->GetFontHeight();
|
||||
u32 x = 0;
|
||||
u32 y = 0;
|
||||
char bufferOut[128] = { 0 };
|
||||
|
@ -763,7 +920,7 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI
|
|||
|
||||
u32 usedColour = palette[VIC2_COLOUR_INDEX_RED];
|
||||
u32 freeColour = palette[VIC2_COLOUR_INDEX_LGREEN];
|
||||
u32 BAMOffsetX = screen.ScaleX(400);
|
||||
u32 BAMOffsetX = screenMain->ScaleX(400);
|
||||
|
||||
ClearScreen();
|
||||
|
||||
|
@ -798,12 +955,12 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI
|
|||
if (!used)
|
||||
{
|
||||
snprintf(bufferOut, 128, "%c", screen2petscii(87));
|
||||
screen.PrintText(true, x, y, bufferOut, usedColour, bgColour);
|
||||
screenMain->PrintText(true, x, y, bufferOut, usedColour, bgColour);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(bufferOut, 128, "%c", screen2petscii(81));
|
||||
screen.PrintText(true, x, y, bufferOut, freeColour, bgColour);
|
||||
screenMain->PrintText(true, x, y, bufferOut, freeColour, bgColour);
|
||||
}
|
||||
x += 8;
|
||||
bits <<= 1;
|
||||
|
@ -816,7 +973,7 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI
|
|||
for (int bit = 0; bit < DiskImage::SectorsPerTrack[bamTrack]; bit++)
|
||||
{
|
||||
snprintf(bufferOut, 128, "%c", screen2petscii(87));
|
||||
screen.PrintText(true, x, y, bufferOut, usedColour, bgColour);
|
||||
screenMain->PrintText(true, x, y, bufferOut, usedColour, bgColour);
|
||||
x += 8;
|
||||
}
|
||||
y += fontHeight;
|
||||
|
@ -824,10 +981,10 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI
|
|||
x = 0;
|
||||
y = 0;
|
||||
snprintf(bufferOut, 128, "0");
|
||||
screen.PrintText(true, x, y, bufferOut, textColour, bgColour);
|
||||
screenMain->PrintText(true, x, y, bufferOut, textColour, bgColour);
|
||||
x = 16;
|
||||
snprintf(bufferOut, 128, "\"%s\" %c%c%c%c%c%c", name, buffer[162], buffer[163], buffer[164], buffer[165], buffer[166], buffer[167]);
|
||||
screen.PrintText(true, x, y, bufferOut, bgColour, textColour);
|
||||
screenMain->PrintText(true, x, y, bufferOut, bgColour, textColour);
|
||||
x = 0;
|
||||
y += fontHeight;
|
||||
|
||||
|
@ -876,10 +1033,10 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI
|
|||
|
||||
//DEBUG_LOG("%d name = %s %x\r\n", blocks, name, fileType);
|
||||
snprintf(bufferOut, 128, "%d", blocks);
|
||||
screen.PrintText(true, x, y, bufferOut, textColour, bgColour);
|
||||
screenMain->PrintText(true, x, y, bufferOut, textColour, bgColour);
|
||||
x += 5 * 8;
|
||||
snprintf(bufferOut, 128, "\"%s\"", name);
|
||||
screen.PrintText(true, x, y, bufferOut, textColour, bgColour);
|
||||
screenMain->PrintText(true, x, y, bufferOut, textColour, bgColour);
|
||||
x += 19 * 8;
|
||||
char modifier = 0x20;
|
||||
if ((fileType & 0x80) == 0)
|
||||
|
@ -887,7 +1044,7 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI
|
|||
else if (fileType & 0x40)
|
||||
modifier = screen2petscii(60);
|
||||
snprintf(bufferOut, 128, "%s%c", fileTypes[fileType & 7], modifier);
|
||||
screen.PrintText(true, x, y, bufferOut, textColour, bgColour);
|
||||
screenMain->PrintText(true, x, y, bufferOut, textColour, bgColour);
|
||||
y += fontHeight;
|
||||
}
|
||||
entryOffset += 32;
|
||||
|
@ -903,7 +1060,7 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI
|
|||
x = 0;
|
||||
//DEBUG_LOG("%d blocks free\r\n", blocksFree);
|
||||
snprintf(bufferOut, 128, "%d BLOCKS FREE.\r\n", blocksFree);
|
||||
screen.PrintText(true, x, y, bufferOut, textColour, bgColour);
|
||||
screenMain->PrintText(true, x, y, bufferOut, textColour, bgColour);
|
||||
y += fontHeight;
|
||||
}
|
||||
|
||||
|
@ -914,8 +1071,8 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI
|
|||
FILINFO filIcon;
|
||||
if (CheckForPNG(filenameForIcon, filIcon))
|
||||
{
|
||||
x = screen.ScaleX(1024) - 320;
|
||||
y = screen.ScaleY(0);
|
||||
x = screenMain->ScaleX(1024) - 320;
|
||||
y = screenMain->ScaleY(0);
|
||||
DisplayPNG(filIcon, x, y);
|
||||
}
|
||||
}
|
||||
|
@ -938,7 +1095,7 @@ void FileBrowser::AutoSelectTestImage()
|
|||
|
||||
if (index != maxEntries)
|
||||
{
|
||||
caddySelections.Clear();
|
||||
ClearSelections();
|
||||
caddySelections.entries.push_back(*current);
|
||||
selectionsMade = FillCaddyWithSelections();
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "DiskImage.h"
|
||||
#include "DiskCaddy.h"
|
||||
#include "ROMs.h"
|
||||
#include "ScreenBase.h"
|
||||
|
||||
#define VIC2_COLOUR_INDEX_BLACK 0
|
||||
#define VIC2_COLOUR_INDEX_WHITE 1
|
||||
|
@ -51,51 +52,88 @@ class FileBrowser
|
|||
{
|
||||
public:
|
||||
|
||||
class BrowsableList;
|
||||
|
||||
class BrowsableListView
|
||||
{
|
||||
public:
|
||||
BrowsableListView(BrowsableList* list, ScreenBase* screen, u32 columns, u32 rows, u32 positionX, u32 positionY, bool lcdPgUpDown)
|
||||
: list(list)
|
||||
, screen(screen)
|
||||
, columns(columns)
|
||||
, rows(rows)
|
||||
, positionX(positionX)
|
||||
, positionY(positionY)
|
||||
, lcdPgUpDown(lcdPgUpDown)
|
||||
{
|
||||
}
|
||||
|
||||
void Refresh();
|
||||
bool CheckBrowseNavigation(bool pageOnly);
|
||||
|
||||
BrowsableList* list;
|
||||
u32 offset;
|
||||
|
||||
ScreenBase* screen;
|
||||
u32 columns;
|
||||
u32 rows;
|
||||
u32 positionX;
|
||||
u32 positionY;
|
||||
bool lcdPgUpDown;
|
||||
};
|
||||
|
||||
class BrowsableList
|
||||
{
|
||||
public:
|
||||
BrowsableList()
|
||||
: current(0)
|
||||
, currentIndex(0)
|
||||
, offset(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
u32 index;
|
||||
entries.clear();
|
||||
current = 0;
|
||||
currentIndex = 0;
|
||||
offset = 0;
|
||||
for (index = 0; index < views.size(); ++index)
|
||||
{
|
||||
views[index].offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AddView(ScreenBase* screen, u32 columns, u32 rows, u32 positionX, u32 positionY, bool lcdPgUpDown)
|
||||
{
|
||||
BrowsableListView view(this, screen, columns, rows, positionX, positionY, lcdPgUpDown);
|
||||
views.push_back(view);
|
||||
}
|
||||
|
||||
void ClearSelections();
|
||||
|
||||
struct Entry
|
||||
{
|
||||
Entry() : caddyIndex(-1)
|
||||
{
|
||||
}
|
||||
FILINFO filImage;
|
||||
FILINFO filIcon;
|
||||
int caddyIndex;
|
||||
};
|
||||
|
||||
Entry* FindEntry(const char* name);
|
||||
|
||||
void RefreshViews();
|
||||
bool CheckBrowseNavigation();
|
||||
|
||||
std::vector<Entry> entries;
|
||||
Entry* current;
|
||||
u32 currentIndex;
|
||||
u32 offset;
|
||||
|
||||
std::vector<BrowsableListView> views;
|
||||
};
|
||||
|
||||
class Folder : public BrowsableList
|
||||
{
|
||||
public:
|
||||
Folder()
|
||||
: BrowsableList()
|
||||
, name(0)
|
||||
{
|
||||
}
|
||||
|
||||
FILINFO* name;
|
||||
};
|
||||
|
||||
FileBrowser(DiskCaddy* diskCaddy, ROMs* roms, unsigned deviceID, bool displayPNGIcons);
|
||||
FileBrowser(DiskCaddy* diskCaddy, ROMs* roms, unsigned deviceID, bool displayPNGIcons, ScreenBase* screenMain, ScreenBase* screenLCD);
|
||||
|
||||
void AutoSelectTestImage();
|
||||
void DisplayRoot();
|
||||
|
@ -111,7 +149,7 @@ public:
|
|||
|
||||
bool SelectionsMade() { return selectionsMade; }
|
||||
const char* LastSelectionName() { return lastSelectionName; }
|
||||
void ClearSelections() { selectionsMade = false; caddySelections.Clear(); }
|
||||
void ClearSelections();
|
||||
|
||||
void ShowDeviceAndROM();
|
||||
|
||||
|
@ -119,8 +157,6 @@ public:
|
|||
|
||||
void SetDeviceID(u8 id) { deviceID = id; }
|
||||
|
||||
Folder* GetCurrentFolder();
|
||||
|
||||
static const long int LSTBuffer_size = 1024 * 8;
|
||||
static unsigned char LSTBuffer[];
|
||||
|
||||
|
@ -138,7 +174,7 @@ private:
|
|||
void UpdateInputFolders();
|
||||
void UpdateInputDiskCaddy();
|
||||
|
||||
void RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* browsableList, int xOffset, bool showSelected = true);
|
||||
//void RefeshDisplayForBrowsableList(FileBrowser::BrowsableList* browsableList, int xOffset, bool showSelected = true);
|
||||
|
||||
bool FillCaddyWithSelections();
|
||||
|
||||
|
@ -153,8 +189,7 @@ private:
|
|||
State_DiskCaddy
|
||||
} state;
|
||||
|
||||
Folder folder;
|
||||
u32 maxOnScreen;
|
||||
BrowsableList folder;
|
||||
DiskCaddy* diskCaddy;
|
||||
bool selectionsMade;
|
||||
const char* lastSelectionName;
|
||||
|
@ -164,6 +199,9 @@ private:
|
|||
|
||||
BrowsableList caddySelections;
|
||||
|
||||
ScreenBase* screenMain;
|
||||
ScreenBase* screenLCD;
|
||||
|
||||
char PNG[FILEBROWSER_MAX_PNG_SIZE];
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,7 @@ unsigned InputMappings::directDiskSwapRequest = 0;
|
|||
//unsigned InputMappings::escapeSequenceIndex = 0;
|
||||
|
||||
InputMappings::InputMappings()
|
||||
: keyboardBrowseLCDScreen(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -136,6 +137,7 @@ bool InputMappings::CheckKeyboardBrowseMode()
|
|||
|
||||
keyboardFlags = 0;
|
||||
|
||||
// TODO: add KEY_HOME and KEY_END
|
||||
if (keyboard->KeyHeld(KEY_ESC))
|
||||
SetKeyboardFlag(ESC_FLAG);
|
||||
else if (keyboard->KeyHeld(KEY_ENTER))
|
||||
|
@ -149,11 +151,25 @@ bool InputMappings::CheckKeyboardBrowseMode()
|
|||
else if (keyboard->KeyHeld(KEY_UP))
|
||||
SetKeyboardFlag(UP_FLAG);
|
||||
else if (keyboard->KeyHeld(KEY_PAGEUP) || keyboard->KeyHeld(KEY_LEFT))
|
||||
{
|
||||
if (keyboardBrowseLCDScreen)
|
||||
SetKeyboardFlag(PAGEUP_LCD_FLAG);
|
||||
else
|
||||
SetKeyboardFlag(PAGEUP_FLAG);
|
||||
}
|
||||
else if (keyboard->KeyHeld(KEY_DOWN))
|
||||
SetKeyboardFlag(DOWN_FLAG);
|
||||
else if (keyboard->KeyHeld(KEY_PAGEDOWN) || keyboard->KeyHeld(KEY_RIGHT))
|
||||
{
|
||||
if (keyboardBrowseLCDScreen)
|
||||
SetKeyboardFlag(PAGEDOWN_LCD_FLAG);
|
||||
else
|
||||
SetKeyboardFlag(PAGEDOWN_FLAG);
|
||||
}
|
||||
//else if (keyboard->KeyHeld(KEY_HOME))
|
||||
// SetKeyboardFlag(PAGEUP_LCD_FLAG);
|
||||
//else if (keyboard->KeyHeld(KEY_END))
|
||||
// SetKeyboardFlag(PAGEDOWN_LCD_FLAG);
|
||||
else
|
||||
{
|
||||
unsigned index;
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
#define INSERT_FLAG (1 << 10)
|
||||
#define NUMBER_FLAG (1 << 11)
|
||||
|
||||
#define PAGEDOWN_LCD_FLAG (1 << 12)
|
||||
#define PAGEUP_LCD_FLAG (1 << 13)
|
||||
|
||||
class InputMappings : public Singleton<InputMappings>
|
||||
{
|
||||
protected:
|
||||
|
@ -42,6 +45,8 @@ protected:
|
|||
unsigned keyboardFlags;
|
||||
unsigned buttonFlags;
|
||||
|
||||
bool keyboardBrowseLCDScreen;
|
||||
|
||||
//inline void SetUartFlag(unsigned flag) { uartFlags |= flag; }
|
||||
//inline bool UartFlag(unsigned flag) { return (uartFlags & flag) != 0; }
|
||||
inline void SetKeyboardFlag(unsigned flag) { keyboardFlags |= flag; }
|
||||
|
@ -64,6 +69,11 @@ public:
|
|||
buttonFlags = 0;
|
||||
}
|
||||
|
||||
void SetKeyboardBrowseLCDScreen(bool value)
|
||||
{
|
||||
keyboardBrowseLCDScreen = value;
|
||||
}
|
||||
|
||||
inline bool Exit()
|
||||
{
|
||||
return KeyboardFlag(ESC_FLAG)/* | UartFlag(ESC_FLAG)*/ | ButtonFlag(ESC_FLAG);
|
||||
|
@ -103,6 +113,10 @@ public:
|
|||
{
|
||||
return KeyboardFlag(PAGEUP_FLAG)/* | UartFlag(PAGEUP_FLAG)*/;
|
||||
}
|
||||
inline bool BrowsePageUpLCD()
|
||||
{
|
||||
return KeyboardFlag(PAGEUP_LCD_FLAG);
|
||||
}
|
||||
|
||||
inline bool BrowseDown()
|
||||
{
|
||||
|
@ -113,6 +127,10 @@ public:
|
|||
{
|
||||
return KeyboardFlag(PAGEDOWN_FLAG)/* | UartFlag(PAGEDOWN_FLAG)*/;
|
||||
}
|
||||
inline bool BrowsePageDownLCD()
|
||||
{
|
||||
return KeyboardFlag(PAGEDOWN_LCD_FLAG);
|
||||
}
|
||||
|
||||
inline bool BrowseInsert()
|
||||
{
|
||||
|
|
251
src/SSD1306.cpp
Normal file
251
src/SSD1306.cpp
Normal file
|
@ -0,0 +1,251 @@
|
|||
// Pi1541 - A Commodore 1541 disk drive emulator
|
||||
// Copyright(C) 2018 Stephen White
|
||||
//
|
||||
// This file is part of Pi1541.
|
||||
//
|
||||
// Pi1541 is free software : you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Pi1541 is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pi1541. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "SSD1306.h"
|
||||
#include "debug.h"
|
||||
#include <string.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "xga_font_data.h"
|
||||
}
|
||||
|
||||
|
||||
#define SSD1306_CMD_SET_MEMORY_ADDRESSING_MODE 0x20
|
||||
|
||||
#define SSD1306_CMD_SET_PAGE_ADDRESS 0x22
|
||||
#define SSD1306_CMD_DEACTIVATE_SCROLL 0x2E
|
||||
#define SSD1306_CMD_ACTIVATE_SCROLL 0x2F
|
||||
|
||||
#define SSD1306_CMD_SET_CONTRAST_CONTROL 0x81 // Set Contrast Control for BANK0
|
||||
#define SSD1306_ENABLE_CHARGE_PUMP 0x8D
|
||||
|
||||
#define SSD1306_CMD_ENTIRE_DISPLAY_ON 0xA4
|
||||
#define SSD1306_CMD_ENTIRE_DISPLAY_OFF 0xA5
|
||||
#define SSD1306_CMD_NORMAL_DISPLAY 0xA6 // 1 = on pixel
|
||||
#define SSD1306_CMD_INVERT_DISPLAY 0xA7 // 0 = on pixel
|
||||
|
||||
#define SSD1306_CMD_DISPLAY_OFF 0xAE
|
||||
#define SSD1306_CMD_DISPLAY_ON 0xAF
|
||||
#define SSD1306_CMD_MULTIPLEX_RATIO 0xA8
|
||||
|
||||
#define SSD1306_CMD_SET_START_LINE 0x40
|
||||
|
||||
#define SSD1306_CMD_SET_DISPLAY_OFFSET 0xD3
|
||||
#define SSD1306_CMD_SET_DISPLAY_CLOCK_DIVIDE_RATIO 0xD5
|
||||
#define SSD1306_CMD_SET_PRE_CHARGE_PERIOD 0xD9
|
||||
#define SSD1306_CMD_SET_COM_PINS 0xDA
|
||||
#define SSD1306_CMD_SET_VCOMH_DESELECT_LEVEL 0xDB
|
||||
|
||||
#define SSD1306_CONTROL_REG 0x00
|
||||
#define SSD1306_DATA_REG 0x40
|
||||
|
||||
unsigned char frame[SSD1306_128x64_BYTES];
|
||||
|
||||
SSD1306::SSD1306(int BSCMaster, u8 address)
|
||||
: BSCMaster(BSCMaster)
|
||||
, address(address)
|
||||
{
|
||||
RPI_I2CInit(BSCMaster, 1);
|
||||
|
||||
// SSD1306 data sheet configuration flow
|
||||
SendCommand(SSD1306_CMD_DISPLAY_OFF);
|
||||
SendCommand(SSD1306_CMD_MULTIPLEX_RATIO);
|
||||
SendCommand(0x3F); // SSD1306_LCDHEIGHT - 1
|
||||
|
||||
SendCommand(SSD1306_CMD_SET_DISPLAY_OFFSET);
|
||||
SendCommand(0x00); // no Offset
|
||||
|
||||
SendCommand(SSD1306_CMD_SET_START_LINE | 0x0);
|
||||
|
||||
SendCommand(0xA1); // Set Segment Re-Map
|
||||
|
||||
SendCommand(0xC8); // Set COM Output Scan Direction
|
||||
|
||||
SendCommand(SSD1306_CMD_SET_COM_PINS); // Layout and direction
|
||||
SendCommand(0x12);
|
||||
|
||||
SendCommand(SSD1306_CMD_SET_CONTRAST_CONTROL);
|
||||
SendCommand(0x7F);
|
||||
|
||||
SendCommand(SSD1306_CMD_ENTIRE_DISPLAY_ON);
|
||||
|
||||
SendCommand(SSD1306_CMD_NORMAL_DISPLAY);
|
||||
SendCommand(0xD5);
|
||||
SendCommand(0x80);
|
||||
|
||||
SendCommand(SSD1306_CMD_SET_PRE_CHARGE_PERIOD);
|
||||
SendCommand(0xF1);
|
||||
|
||||
SendCommand(SSD1306_CMD_SET_VCOMH_DESELECT_LEVEL);
|
||||
SendCommand(0x40);
|
||||
|
||||
SendCommand(SSD1306_CMD_SET_DISPLAY_CLOCK_DIVIDE_RATIO);
|
||||
SendCommand(0x80); // upper nibble is rate, lower nibble is divisor
|
||||
|
||||
SendCommand(SSD1306_ENABLE_CHARGE_PUMP); // Enable charge pump regulator
|
||||
SendCommand(0x14); // external = 0x10 internal = 0x14
|
||||
|
||||
|
||||
|
||||
|
||||
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_PAGE_ADDRESS);
|
||||
SendCommand(0x00);
|
||||
SendCommand(0x07);
|
||||
|
||||
SendCommand(SSD1306_CMD_DEACTIVATE_SCROLL);
|
||||
}
|
||||
|
||||
void SSD1306::SendCommand(u8 command)
|
||||
{
|
||||
char buffer[2];
|
||||
|
||||
buffer[0] = SSD1306_CONTROL_REG;
|
||||
buffer[1] = command;
|
||||
|
||||
RPI_I2CWrite(BSCMaster, address, buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
void SSD1306::SendData(u8 data)
|
||||
{
|
||||
char buffer[2];
|
||||
|
||||
buffer[0] = SSD1306_DATA_REG;
|
||||
buffer[1] = data;
|
||||
|
||||
RPI_I2CWrite(BSCMaster, address, buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
void SSD1306::MoveCursorByte(u8 row, u8 col)
|
||||
{
|
||||
if (col > 127) { col = 127; }
|
||||
if (row > 7) { 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)
|
||||
{
|
||||
if (col > 15) { col = 15; }
|
||||
if (row > 7) { row = 7; }
|
||||
|
||||
MoveCursorByte(row, col << 3);
|
||||
}
|
||||
|
||||
void SSD1306::RefreshScreen()
|
||||
{
|
||||
int i;
|
||||
Home();
|
||||
for (i = 0; i < SSD1306_128x64_BYTES; i++)
|
||||
{
|
||||
SendData(frame[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void SSD1306::ClearScreen()
|
||||
{
|
||||
memset(frame, 0, sizeof(frame));
|
||||
RefreshScreen();
|
||||
}
|
||||
|
||||
void SSD1306::DisplayOn()
|
||||
{
|
||||
SendCommand(SSD1306_CMD_DISPLAY_ON);
|
||||
ClearScreen();
|
||||
}
|
||||
|
||||
void SSD1306::DisplayOff()
|
||||
{
|
||||
ClearScreen();
|
||||
SendCommand(SSD1306_CMD_DISPLAY_OFF);
|
||||
}
|
||||
|
||||
void SSD1306::Plottext(int x, int y, char* str, bool inverse)
|
||||
{
|
||||
int i;
|
||||
i = 0;
|
||||
while (str[i] && x < 16)
|
||||
{
|
||||
PlotCharacter(x++, y, str[i++], inverse);
|
||||
}
|
||||
}
|
||||
|
||||
// Pg 143 - 145. Transposing an 8x8 bit matrix. Hacker's Delight
|
||||
void transpose8(unsigned char* B, const unsigned char* A, bool inverse)
|
||||
{
|
||||
unsigned x, y, t;
|
||||
x = (A[7] << 24) | (A[6] << 16) | (A[5] << 8) | A[4];
|
||||
y = (A[3] << 24) | (A[2] << 16) | (A[1] << 8) | A[0];
|
||||
if (inverse)
|
||||
{
|
||||
x = ~x;
|
||||
y = ~y;
|
||||
}
|
||||
|
||||
t = (x ^ (x >> 7)) & 0x00AA00AA; x = x ^ t ^ (t << 7);
|
||||
t = (y ^ (y >> 7)) & 0x00AA00AA; y = y ^ t ^ (t << 7);
|
||||
|
||||
t = (x ^ (x >> 14)) & 0x0000CCCC; x = x ^ t ^ (t << 14);
|
||||
t = (y ^ (y >> 14)) & 0x0000CCCC; y = y ^ t ^ (t << 14);
|
||||
|
||||
t = (x & 0xF0F0F0F0) | ((y >> 4) & 0x0F0F0F0F);
|
||||
y = ((x << 4) & 0xF0F0F0F0) | (y & 0x0F0F0F0F);
|
||||
x = t;
|
||||
|
||||
|
||||
B[0] = x >> 24; B[1] = x >> 16; B[2] = x >> 8; B[3] = x;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
99
src/SSD1306.h
Normal file
99
src/SSD1306.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
// Pi1541 - A Commodore 1541 disk drive emulator
|
||||
// Copyright(C) 2018 Stephen White
|
||||
//
|
||||
// This file is part of Pi1541.
|
||||
//
|
||||
// Pi1541 is free software : you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Pi1541 is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pi1541. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SSD1306_H
|
||||
#define SSD1306_H
|
||||
#include "types.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "rpi-i2c.h"
|
||||
}
|
||||
|
||||
// 8 pages * (128 columns * 8 bits)
|
||||
//0 127
|
||||
//0 127
|
||||
//0 127
|
||||
//________________________________________________________
|
||||
//7777777 | 7
|
||||
//6666666 | 6
|
||||
//5555555 | 5
|
||||
//4444444 PG(ROW)0 | PG(ROW)1 4
|
||||
//3333333 | 3
|
||||
//2222222 | 2
|
||||
//1111111 | 1
|
||||
//0000000 | 0
|
||||
//________________________________________________________
|
||||
//7777777 | 7
|
||||
//6666666 | 6
|
||||
//5555555 | 5
|
||||
//4444444 PG(ROW)2 | PG(ROW)3 4
|
||||
//3333333 | 3
|
||||
//2222222 | 2
|
||||
//1111111 | 1
|
||||
//0000000 | 0
|
||||
//________________________________________________________
|
||||
//7777777 | 7
|
||||
//6666666 | 6
|
||||
//5555555 | 5
|
||||
//4444444 PG(ROW)4 | PG(ROW)5 4
|
||||
//3333333 | 3
|
||||
//2222222 | 2
|
||||
//1111111 | 1
|
||||
//0000000 | 0
|
||||
//________________________________________________________
|
||||
//7777777 | 7
|
||||
//6666666 | 6
|
||||
//5555555 | 5
|
||||
//4444444 PG(ROW)6 | PG(ROW)7 4
|
||||
//3333333 | 3
|
||||
//2222222 | 2
|
||||
//1111111 | 1
|
||||
//0000000 | 0
|
||||
//________________________________________________________
|
||||
#define SSD1306_128x64_BYTES ((128 * 64) / 8)
|
||||
|
||||
class SSD1306
|
||||
{
|
||||
public:
|
||||
// 128x32 0x3C
|
||||
// 128x64 0x3D or 0x3C (if SA0 is grounded)
|
||||
SSD1306(int BSCMaster = 1, u8 address = 0x3C);
|
||||
|
||||
void PlotCharacter(int x, int y, char ascii, bool inverse);
|
||||
void Plottext(int x, int y, char* str, bool inverse);
|
||||
|
||||
void DisplayOn();
|
||||
void DisplayOff();
|
||||
|
||||
void ClearScreen();
|
||||
void RefreshScreen();
|
||||
|
||||
protected:
|
||||
void SendCommand(u8 command);
|
||||
void SendData(u8 data);
|
||||
|
||||
void Home();
|
||||
void MoveCursorByte(u8 row, u8 col);
|
||||
void MoveCursorCharacter(u8 row, u8 col);
|
||||
|
||||
unsigned char frame[SSD1306_128x64_BYTES];
|
||||
|
||||
int BSCMaster;
|
||||
u8 address;
|
||||
};
|
||||
#endif
|
|
@ -148,14 +148,6 @@ void Screen::PlotPixel8(u32 pixel_offset, RGBA Colour)
|
|||
framebuffer[pixel_offset++] = RED(Colour);
|
||||
}
|
||||
|
||||
void Screen::ClipRect(u32& x1, u32& y1, u32& x2, u32& y2)
|
||||
{
|
||||
if (x1 > width) x1 = width;
|
||||
if (y1 > height) y1 = height;
|
||||
if (x2 > width) x2 = width;
|
||||
if (y2 > height) y2 = height;
|
||||
}
|
||||
|
||||
void Screen::ClearArea(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour)
|
||||
{
|
||||
ClipRect(x1, y1, x2, y2);
|
||||
|
@ -195,7 +187,7 @@ void Screen::Clear(RGBA colour)
|
|||
ClearArea(0, 0, width, height, colour);
|
||||
}
|
||||
|
||||
u32 Screen::GetCBMFontHeight()
|
||||
u32 Screen::GetFontHeight()
|
||||
{
|
||||
if (CBMFont)
|
||||
return 8;
|
||||
|
|
41
src/Screen.h
41
src/Screen.h
|
@ -19,28 +19,14 @@
|
|||
#ifndef SCREEN_H
|
||||
#define SCREEN_H
|
||||
|
||||
#include "types.h"
|
||||
#include "ScreenBase.h"
|
||||
|
||||
typedef u32 RGBA;
|
||||
|
||||
#define RED(colour) ( (u8)(((u32)colour) & 0xFF) )
|
||||
#define GREEN(colour) ( (u8)(((u32)colour >> 8) & 0xFF) )
|
||||
#define BLUE(colour) ( (u8)(((u32)colour >> 16) & 0xFF) )
|
||||
#define ALPHA(colour) ( (u8)(((u32)colour >> 24) & 0xFF) )
|
||||
|
||||
#define RGBA(r, g, b, a) ( ((u32)((u8)(r))) | ((u32)((u8)(g)) << 8) | ((u32)((u8)(b)) << 16) | ((u32)((u8)(a)) << 24) )
|
||||
|
||||
class Screen
|
||||
class Screen : public ScreenBase
|
||||
{
|
||||
|
||||
public:
|
||||
Screen()
|
||||
: opened(false)
|
||||
, width(0)
|
||||
, height(0)
|
||||
, bpp(0)
|
||||
, pitch(0)
|
||||
, framebuffer(0)
|
||||
: ScreenBase()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -61,37 +47,26 @@ public:
|
|||
|
||||
void PlotImage(u32* image, int x, int y, int w, int h);
|
||||
|
||||
u32 Width() const { return width; }
|
||||
u32 Height() const { return height; }
|
||||
|
||||
u32 GetCBMFontHeight();
|
||||
|
||||
float GetScaleX() const { return scaleX; }
|
||||
float GetScaleY() const { return scaleY; }
|
||||
|
||||
u32 ScaleX(u32 x) { return (u32)((float)x * scaleX); }
|
||||
u32 ScaleY(u32 y) { return (u32)((float)y * scaleY); }
|
||||
|
||||
u32 GetFontHeight();
|
||||
|
||||
void SwapBuffers() {}
|
||||
private:
|
||||
|
||||
typedef void (Screen::*PlotPixelFunction)(u32 pixel_offset, RGBA Colour);
|
||||
|
||||
PlotPixelFunction plotPixelFn;
|
||||
|
||||
void PlotPixel32(u32 pixel_offset, RGBA Colour);
|
||||
void PlotPixel24(u32 pixel_offset, RGBA Colour);
|
||||
void PlotPixel16(u32 pixel_offset, RGBA Colour);
|
||||
void PlotPixel8(u32 pixel_offset, RGBA Colour);
|
||||
|
||||
void ClipRect(u32& x1, u32& y1, u32& x2, u32& y2);
|
||||
|
||||
PlotPixelFunction plotPixelFn;
|
||||
|
||||
bool opened;
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 bpp;
|
||||
u32 pitch;
|
||||
volatile u8* framebuffer;
|
||||
|
||||
float scaleX;
|
||||
float scaleY;
|
||||
};
|
||||
|
|
97
src/ScreenBase.h
Normal file
97
src/ScreenBase.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
// Pi1541 - A Commodore 1541 disk drive emulator
|
||||
// Copyright(C) 2018 Stephen White
|
||||
//
|
||||
// This file is part of Pi1541.
|
||||
//
|
||||
// Pi1541 is free software : you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Pi1541 is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pi1541. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SCREENBASE_H
|
||||
#define SCREENBASE_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef u32 RGBA;
|
||||
|
||||
#define RED(colour) ( (u8)(((u32)colour) & 0xFF) )
|
||||
#define GREEN(colour) ( (u8)(((u32)colour >> 8) & 0xFF) )
|
||||
#define BLUE(colour) ( (u8)(((u32)colour >> 16) & 0xFF) )
|
||||
#define ALPHA(colour) ( (u8)(((u32)colour >> 24) & 0xFF) )
|
||||
|
||||
#define RGBA(r, g, b, a) ( ((u32)((u8)(r))) | ((u32)((u8)(g)) << 8) | ((u32)((u8)(b)) << 16) | ((u32)((u8)(a)) << 24) )
|
||||
|
||||
class ScreenBase
|
||||
{
|
||||
|
||||
public:
|
||||
ScreenBase()
|
||||
: opened(false)
|
||||
, width(0)
|
||||
, height(0)
|
||||
, bpp(0)
|
||||
, pitch(0)
|
||||
, framebuffer(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ClearArea(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour) = 0;
|
||||
virtual void Clear(RGBA colour) = 0;
|
||||
|
||||
virtual void ScrollArea(u32 x1, u32 y1, u32 x2, u32 y2) = 0;
|
||||
|
||||
virtual void WriteChar(bool petscii, u32 x, u32 y, unsigned char c, RGBA colour) = 0;
|
||||
virtual u32 PrintText(bool petscii, u32 xPos, u32 yPos, char *ptr, RGBA TxtColour = RGBA(0xff, 0xff, 0xff, 0xff), RGBA BkColour = RGBA(0, 0, 0, 0xFF), bool measureOnly = false, u32* width = 0, u32* height = 0) = 0;
|
||||
virtual u32 MeasureText(bool petscii, char *ptr, u32* width = 0, u32* height = 0) = 0;
|
||||
|
||||
virtual void PlotPixel(u32 x, u32 y, RGBA colour) = 0;
|
||||
|
||||
virtual void PlotImage(u32* image, int x, int y, int w, int h) = 0;
|
||||
|
||||
u32 Width() const { return width; }
|
||||
u32 Height() const { return height; }
|
||||
|
||||
virtual float GetScaleX() const { return 1; }
|
||||
virtual float GetScaleY() const { return 1; }
|
||||
|
||||
virtual u32 ScaleX(u32 x) { return x; }
|
||||
virtual u32 ScaleY(u32 y) { return y; }
|
||||
|
||||
virtual u32 GetFontHeight() = 0;
|
||||
|
||||
virtual void SwapBuffers() = 0;
|
||||
|
||||
bool IsMonocrome() const { return bpp == 1; }
|
||||
|
||||
protected:
|
||||
|
||||
//typedef void (ScreenBase::*PlotPixelFunction)(u32 pixel_offset, RGBA Colour);
|
||||
|
||||
//PlotPixelFunction plotPixelFn;
|
||||
|
||||
void ClipRect(u32& x1, u32& y1, u32& x2, u32& y2)
|
||||
{
|
||||
if (x1 > width) x1 = width;
|
||||
if (y1 > height) y1 = height;
|
||||
if (x2 > width) x2 = width;
|
||||
if (y2 > height) y2 = height;
|
||||
}
|
||||
|
||||
bool opened;
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 bpp;
|
||||
u32 pitch;
|
||||
u8* framebuffer;
|
||||
};
|
||||
|
||||
#endif
|
100
src/ScreenLCD.cpp
Normal file
100
src/ScreenLCD.cpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
// Pi1541 - A Commodore 1541 disk drive emulator
|
||||
// Copyright(C) 2018 Stephen White
|
||||
//
|
||||
// This file is part of Pi1541.
|
||||
//
|
||||
// Pi1541 is free software : you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Pi1541 is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pi1541. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "ScreenLCD.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "debug.h"
|
||||
|
||||
void ScreenLCD::Open(u32 widthDesired, u32 heightDesired, u32 colourDepth, int BSCMaster)
|
||||
{
|
||||
bpp = 1;
|
||||
|
||||
if (widthDesired < 128)
|
||||
widthDesired = 128;
|
||||
if (heightDesired < 64)
|
||||
heightDesired = 64;
|
||||
if (widthDesired > 128)
|
||||
widthDesired = 128;
|
||||
if (heightDesired > 64)
|
||||
heightDesired = 64;
|
||||
|
||||
width = widthDesired;
|
||||
height = heightDesired;
|
||||
|
||||
DEBUG_LOG("BSCMaster = %d\r\n");
|
||||
ssd1306 = new SSD1306(BSCMaster);
|
||||
ssd1306->DisplayOn();
|
||||
ssd1306->Plottext(5, 1, "Pi1541", false);
|
||||
ssd1306->RefreshScreen();
|
||||
|
||||
opened = true;
|
||||
}
|
||||
|
||||
void ScreenLCD::ClearArea(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour)
|
||||
{
|
||||
ClipRect(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
void ScreenLCD::ScrollArea(u32 x1, u32 y1, u32 x2, u32 y2)
|
||||
{
|
||||
}
|
||||
|
||||
void ScreenLCD::Clear(RGBA colour)
|
||||
{
|
||||
ssd1306->ClearScreen();
|
||||
}
|
||||
|
||||
void ScreenLCD::WriteChar(bool petscii, u32 x, u32 y, unsigned char c, RGBA colour)
|
||||
{
|
||||
if (opened)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenLCD::PlotPixel(u32 x, u32 y, RGBA colour)
|
||||
{
|
||||
}
|
||||
|
||||
void ScreenLCD::PlotImage(u32* 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);
|
||||
return len;
|
||||
}
|
||||
|
||||
u32 ScreenLCD::MeasureText(bool petscii, char *ptr, u32* width, u32* height)
|
||||
{
|
||||
return PrintText(petscii, 0, 0, ptr, 0, 0, true, width, height);
|
||||
}
|
||||
|
||||
u32 ScreenLCD::GetFontHeight()
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
void ScreenLCD::SwapBuffers()
|
||||
{
|
||||
ssd1306->RefreshScreen();
|
||||
}
|
||||
|
58
src/ScreenLCD.h
Normal file
58
src/ScreenLCD.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
// Pi1541 - A Commodore 1541 disk drive emulator
|
||||
// Copyright(C) 2018 Stephen White
|
||||
//
|
||||
// This file is part of Pi1541.
|
||||
//
|
||||
// Pi1541 is free software : you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Pi1541 is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Pi1541. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SCREENLCD_H
|
||||
#define SCREENLCD_H
|
||||
|
||||
#include "ScreenBase.h"
|
||||
#include "SSD1306.h"
|
||||
|
||||
class ScreenLCD : public ScreenBase
|
||||
{
|
||||
|
||||
public:
|
||||
ScreenLCD()
|
||||
: ScreenBase()
|
||||
, ssd1306(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Open(u32 width, u32 height, u32 colourDepth, int BSCMaster);
|
||||
|
||||
void ClearArea(u32 x1, u32 y1, u32 x2, u32 y2, RGBA colour);
|
||||
void Clear(RGBA colour);
|
||||
|
||||
void ScrollArea(u32 x1, u32 y1, u32 x2, u32 y2);
|
||||
|
||||
void WriteChar(bool petscii, u32 x, u32 y, unsigned char c, RGBA colour);
|
||||
u32 PrintText(bool petscii, u32 xPos, u32 yPos, char *ptr, RGBA TxtColour = RGBA(0xff, 0xff, 0xff, 0xff), RGBA BkColour = RGBA(0, 0, 0, 0xFF), bool measureOnly = false, u32* width = 0, u32* height = 0);
|
||||
u32 MeasureText(bool petscii, char *ptr, u32* width = 0, u32* height = 0);
|
||||
|
||||
void PlotPixel(u32 x, u32 y, RGBA colour);
|
||||
|
||||
void PlotImage(u32* image, int x, int y, int w, int h);
|
||||
|
||||
u32 GetFontHeight();
|
||||
|
||||
void SwapBuffers();
|
||||
|
||||
private:
|
||||
SSD1306* ssd1306 = 0;
|
||||
};
|
||||
|
||||
#endif
|
20
src/main.cpp
20
src/main.cpp
|
@ -18,12 +18,14 @@
|
|||
|
||||
#include "defs.h"
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "Timer.h"
|
||||
#include "ROMs.h"
|
||||
#include "stb_image.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "rpi-aux.h"
|
||||
#include "rpi-i2c.h"
|
||||
#include "rpi-gpio.h"
|
||||
#include "startup.h"
|
||||
#include "cache.h"
|
||||
|
@ -37,12 +39,13 @@ extern "C"
|
|||
#include "diskio.h"
|
||||
#include "Pi1541.h"
|
||||
#include "FileBrowser.h"
|
||||
#include "ScreenLCD.h"
|
||||
|
||||
#include "logo.h"
|
||||
#include "sample.h"
|
||||
|
||||
unsigned versionMajor = 1;
|
||||
unsigned versionMinor = 2;
|
||||
unsigned versionMinor = 3;
|
||||
|
||||
// When the emulated CPU starts we execute the first million odd cycles in non-real-time (ie as fast as possible so the emulated 1541 becomes responsive to CBM-Browser asap)
|
||||
// During these cycles the CPU is executing the ROM self test routines (these do not need to be cycle accurate)
|
||||
|
@ -84,6 +87,7 @@ DiskCaddy diskCaddy;
|
|||
Pi1541 pi1541;
|
||||
CEMMCDevice m_EMMC;
|
||||
Screen screen;
|
||||
ScreenLCD* screenLCD = 0;
|
||||
Options options;
|
||||
const char* fileBrowserSelectedName;
|
||||
u8 deviceID = 8;
|
||||
|
@ -570,8 +574,8 @@ void emulator()
|
|||
|
||||
roms.lastManualSelectedROMIndex = 0;
|
||||
|
||||
diskCaddy.SetScreen(&screen);
|
||||
fileBrowser = new FileBrowser(&diskCaddy, &roms, deviceID, options.DisplayPNGIcons());
|
||||
diskCaddy.SetScreen(&screen, screenLCD);
|
||||
fileBrowser = new FileBrowser(&diskCaddy, &roms, deviceID, options.DisplayPNGIcons(), &screen, screenLCD);
|
||||
fileBrowser->DisplayRoot();
|
||||
pi1541.Initialise();
|
||||
|
||||
|
@ -598,6 +602,7 @@ void emulator()
|
|||
selectedViaIECCommands = false;
|
||||
|
||||
inputMappings->Reset();
|
||||
inputMappings->SetKeyboardBrowseLCDScreen(screenLCD && options.KeyboardBrowseLCDScreen());
|
||||
|
||||
fileBrowser->ShowDeviceAndROM();
|
||||
|
||||
|
@ -1145,6 +1150,15 @@ extern "C"
|
|||
|
||||
CheckOptions();
|
||||
|
||||
if (strcasecmp(options.GetLCDName(), "ssd1306_128x64") == 0)
|
||||
{
|
||||
screenLCD = new ScreenLCD();
|
||||
screenLCD->Open(128, 64, 1, options.SplitIECLines() ? 1 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
|
||||
IEC_Bus::SetSplitIECLines(options.SplitIECLines());
|
||||
IEC_Bus::SetInvertIECInputs(options.InvertIECInputs());
|
||||
IEC_Bus::SetInvertIECOutputs(options.InvertIECOutputs());
|
||||
|
|
|
@ -135,6 +135,7 @@ Options::Options(void)
|
|||
, ignoreReset(0)
|
||||
, screenWidth(1024)
|
||||
, screenHeight(768)
|
||||
, keyboardBrowseLCDScreen(0)
|
||||
{
|
||||
strcpy(ROMFontName, "chargen");
|
||||
starFileName[0] = 0;
|
||||
|
@ -186,10 +187,15 @@ void Options::Process(char* buffer)
|
|||
ELSE_CHECK_DECIMAL_OPTION(ignoreReset)
|
||||
ELSE_CHECK_DECIMAL_OPTION(screenWidth)
|
||||
ELSE_CHECK_DECIMAL_OPTION(screenHeight)
|
||||
ELSE_CHECK_DECIMAL_OPTION(keyboardBrowseLCDScreen)
|
||||
else if ((strcasecmp(pOption, "StarFileName") == 0))
|
||||
{
|
||||
strncpy(starFileName, pValue, 255);
|
||||
}
|
||||
else if ((strcasecmp(pOption, "LCDName") == 0))
|
||||
{
|
||||
strncpy(LCDName, pValue, 255);
|
||||
}
|
||||
else if ((strcasecmp(pOption, "ROM") == 0) || (strcasecmp(pOption, "ROM1") == 0))
|
||||
{
|
||||
strncpy(ROMName, pValue, 255);
|
||||
|
|
|
@ -66,6 +66,12 @@ public:
|
|||
inline unsigned int ScreenWidth() const { return screenWidth; }
|
||||
inline unsigned int ScreenHeight() const { return screenHeight; }
|
||||
|
||||
// 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?
|
||||
inline unsigned int KeyboardBrowseLCDScreen() const { return keyboardBrowseLCDScreen; }
|
||||
|
||||
const char* GetLCDName() const { return LCDName; }
|
||||
|
||||
static unsigned GetDecimal(char* pString);
|
||||
|
||||
private:
|
||||
|
@ -87,7 +93,10 @@ private:
|
|||
unsigned int screenWidth;
|
||||
unsigned int screenHeight;
|
||||
|
||||
unsigned int keyboardBrowseLCDScreen;
|
||||
|
||||
char starFileName[256];
|
||||
char LCDName[256];
|
||||
|
||||
char ROMFontName[256];
|
||||
char ROMName[256];
|
||||
|
|
186
src/rpi-i2c.c
Normal file
186
src/rpi-i2c.c
Normal file
|
@ -0,0 +1,186 @@
|
|||
#include <stdio.h>
|
||||
#include "rpi-aux.h"
|
||||
#include "rpi-base.h"
|
||||
#include "rpi-gpio.h"
|
||||
#include "startup.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#include "rpiHardware.h"
|
||||
|
||||
/* Define the system clock frequency in MHz for the baud rate calculation.
|
||||
This is clearly defined on the BCM2835 datasheet errata page:
|
||||
http://elinux.org/BCM2835_datasheet_errata */
|
||||
#define FALLBACK_SYS_FREQ 250000000
|
||||
|
||||
#define I2C_BSC0_BASE (PERIPHERAL_BASE + 0x205000)
|
||||
#define I2C_BSC1_BASE (PERIPHERAL_BASE + 0x804000)
|
||||
|
||||
#define GetBaseAddress(BSCMaster) (BSCMaster == 0 ? I2C_BSC0_BASE : I2C_BSC1_BASE)
|
||||
|
||||
#define I2C_BSC_C 0x00 // Control register
|
||||
#define I2C_BSC_S 0x04 // Statis register
|
||||
#define I2C_BSC_DLEN 0x08
|
||||
#define I2C_BSC_A 0x0C // Slave address
|
||||
#define I2C_BSC_FIFO 0x10
|
||||
#define I2C_BSC_DIV 0x14
|
||||
#define I2C_BSC_DEL 0x18
|
||||
#define I2C_BSC_CLKT 0x1C
|
||||
|
||||
#define CONTROL_BIT_READ (1 << 0) // READ Read Transfer
|
||||
#define CONTROL_BIT_CLEAR0 (1 << 4) // CLEAR FIFO 00 = No action. x1 = Clear FIFO. One shot operation. 1x = Clear FIFO.
|
||||
#define CONTROL_BIT_CLEAR1 (1 << 5)
|
||||
#define CONTROL_BIT_ST (1 << 7) // ST Start Transfer
|
||||
#define CONTROL_BIT_INTD (1 << 8) // INTD Interrupt on DONE
|
||||
#define CONTROL_BIT_INTT (1 << 9) // INTT Interrupt on TX
|
||||
#define CONTROL_BIT_INTR (1 << 10) // INTR Interrupt on RX
|
||||
#define CONTROL_BIT_I2CEN (1 << 15) // I2C Enable
|
||||
|
||||
|
||||
#define STATUS_BIT_TA (1 << 0) // Transfer Active
|
||||
#define STATUS_BIT_DONE (1 << 1) // Done
|
||||
#define STATUS_BIT_TXW (1 << 2) // FIFO needs Writing (full)
|
||||
#define STATUS_BIT_RXR (1 << 3) // FIFO needs Reading (full)
|
||||
#define STATUS_BIT_TXD (1 << 4) // FIFO can accept Data
|
||||
#define STATUS_BIT_RXD (1 << 5) // FIFO contains Data
|
||||
#define STATUS_BIT_TXE (1 << 6) // FIFO Empty
|
||||
#define STATUS_BIT_RXF (1 << 7) // FIFO Full
|
||||
#define STATUS_BIT_ERR (1 << 8) // ERR ACK Error
|
||||
#define STATUS_BIT_CLKT (1 << 9) // CLKT Clock Stretch Timeout
|
||||
|
||||
#define FIFO_SIZE 16
|
||||
|
||||
void RPI_I2CSetClock(int BSCMaster, int clock_freq)
|
||||
{
|
||||
_data_memory_barrier();
|
||||
|
||||
int sys_freq = get_clock_rate(CORE_CLK_ID);
|
||||
|
||||
if (!sys_freq) {
|
||||
sys_freq = FALLBACK_SYS_FREQ;
|
||||
}
|
||||
|
||||
unsigned short divider = (unsigned short)(sys_freq / clock_freq);
|
||||
write32(GetBaseAddress(BSCMaster) + I2C_BSC_DIV, divider);
|
||||
|
||||
_data_memory_barrier();
|
||||
}
|
||||
|
||||
void RPI_I2CInit(int BSCMaster, int fast)
|
||||
{
|
||||
if (BSCMaster == 0)
|
||||
{
|
||||
RPI_SetGpioPinFunction(RPI_GPIO0, FS_ALT0);
|
||||
RPI_SetGpioPinFunction(RPI_GPIO1, FS_ALT0);
|
||||
}
|
||||
else
|
||||
{
|
||||
RPI_SetGpioPinFunction(RPI_GPIO2, FS_ALT0);
|
||||
RPI_SetGpioPinFunction(RPI_GPIO3, FS_ALT0);
|
||||
}
|
||||
|
||||
RPI_I2CSetClock(BSCMaster, fast != 0 ? 400000 : 100000);
|
||||
}
|
||||
|
||||
int RPI_I2CRead(int BSCMaster, unsigned char slaveAddress, void* buffer, unsigned count)
|
||||
{
|
||||
int success = 0;
|
||||
if (slaveAddress < 0x80)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
unsigned baseAddress = GetBaseAddress(BSCMaster);
|
||||
unsigned char* data = (unsigned char*)buffer;
|
||||
|
||||
write32(baseAddress + I2C_BSC_A, slaveAddress);
|
||||
write32(baseAddress + I2C_BSC_C, CONTROL_BIT_CLEAR1);
|
||||
write32(baseAddress + I2C_BSC_S, STATUS_BIT_CLKT | STATUS_BIT_ERR | STATUS_BIT_DONE);
|
||||
write32(baseAddress + I2C_BSC_DLEN, count);
|
||||
write32(baseAddress + I2C_BSC_C, CONTROL_BIT_I2CEN | CONTROL_BIT_ST | CONTROL_BIT_READ);
|
||||
|
||||
while (!(read32(baseAddress + I2C_BSC_S) & STATUS_BIT_DONE))
|
||||
{
|
||||
while (read32(baseAddress + I2C_BSC_S) & STATUS_BIT_RXD)
|
||||
{
|
||||
*data++ = (unsigned char)read32(baseAddress + I2C_BSC_FIFO);
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
while (count > 0 && (read32(baseAddress + I2C_BSC_S) & STATUS_BIT_RXD))
|
||||
{
|
||||
*data++ = (unsigned char)read32(baseAddress + I2C_BSC_FIFO);
|
||||
count--;
|
||||
}
|
||||
|
||||
unsigned status = read32(baseAddress + I2C_BSC_S);
|
||||
if (status & STATUS_BIT_ERR)
|
||||
{
|
||||
write32(baseAddress + I2C_BSC_S, STATUS_BIT_ERR);
|
||||
}
|
||||
else if ((status & STATUS_BIT_CLKT) == 0 && count == 0)
|
||||
{
|
||||
success = 1;
|
||||
}
|
||||
|
||||
write32(baseAddress + I2C_BSC_S, STATUS_BIT_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = 1;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
int RPI_I2CWrite(int BSCMaster, unsigned char slaveAddress, void* buffer, unsigned count)
|
||||
{
|
||||
int success = 0;
|
||||
if (slaveAddress < 0x80)
|
||||
{
|
||||
if (count > 0)
|
||||
{
|
||||
unsigned baseAddress = GetBaseAddress(BSCMaster);
|
||||
unsigned char* data = (unsigned char*)buffer;
|
||||
|
||||
write32(baseAddress + I2C_BSC_A, slaveAddress);
|
||||
write32(baseAddress + I2C_BSC_C, CONTROL_BIT_CLEAR1);
|
||||
write32(baseAddress + I2C_BSC_S, STATUS_BIT_CLKT | STATUS_BIT_ERR | STATUS_BIT_DONE);
|
||||
write32(baseAddress + I2C_BSC_DLEN, count);
|
||||
|
||||
for (unsigned i = 0; count > 0 && i < FIFO_SIZE; i++)
|
||||
{
|
||||
write32(baseAddress + I2C_BSC_FIFO, *data++);
|
||||
count--;
|
||||
}
|
||||
|
||||
write32(baseAddress + I2C_BSC_C, CONTROL_BIT_I2CEN | CONTROL_BIT_ST);
|
||||
|
||||
while (!(read32(baseAddress + I2C_BSC_S) & STATUS_BIT_DONE))
|
||||
{
|
||||
while (count > 0 && (read32(baseAddress + I2C_BSC_S) & STATUS_BIT_TXD))
|
||||
{
|
||||
write32(baseAddress + I2C_BSC_FIFO, *data++);
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned status = read32(baseAddress + I2C_BSC_S);
|
||||
if (status & STATUS_BIT_ERR)
|
||||
{
|
||||
write32(baseAddress + I2C_BSC_S, STATUS_BIT_ERR);
|
||||
}
|
||||
else if ((status & STATUS_BIT_CLKT) == 0 && count == 0)
|
||||
{
|
||||
success = 1;
|
||||
}
|
||||
|
||||
write32(baseAddress + I2C_BSC_S, STATUS_BIT_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = 1;
|
||||
}
|
||||
}
|
||||
//DEBUG_LOG("I2C Write %d %d\r\n", count, success);
|
||||
return success;
|
||||
}
|
11
src/rpi-i2c.h
Normal file
11
src/rpi-i2c.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef RPI_AUX_H
|
||||
#define RPI_AUX_H
|
||||
|
||||
#include "rpi-base.h"
|
||||
|
||||
extern void RPI_I2CInit(int BSCMaster, int fast);
|
||||
extern void RPI_I2CSetClock(int BSCMaster, int clock_freq);
|
||||
extern int RPI_I2CRead(int BSCMaster, unsigned char slaveAddress, void* buffer, unsigned count);
|
||||
extern int RPI_I2CWrite(int BSCMaster, unsigned char slaveAddress, void* buffer, unsigned count);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue