-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from GmEsoft/develop
Going public
- Loading branch information
Showing
76 changed files
with
15,579 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,3 +30,6 @@ | |
*.exe | ||
*.out | ||
*.app | ||
|
||
# Junk | ||
*.tws |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,88 @@ | ||
# Z80-MBC2_VGA32 | ||
Z80-MBC2 Emulator running on TTGO ESP VGA32 | ||
|
||
|
||
## Z80-MBC2 Emulator running on TTGO ESP VGA32 | ||
|
||
This is a Z80-MBC2 emulator running on a TTGO ESP VGA32 board, | ||
an ESP32 device with a VGA connector, PS/2 keyboard and mouse | ||
connectors, an audio output jack and a Micro-SD card connector. | ||
|
||
This emulator runs a Z-80 processor at ca. 5.7 MHz (without throttling). | ||
The emulated Z80-MBC2 system is internally connected to the FABGL terminal, | ||
emulating an extended color ANSI terminal. | ||
|
||
It has a terminal configuration menu, accessible when the USER button is pressed | ||
on boot. The configuration menu has the following options: | ||
- `[D]isplay mode`: select the VGA resolution and color depth; | ||
- `[K]eyboard layout`: select an international keyboard layout; | ||
- `[T]ime settings`: automatic clock set-up on boot, via an Internet time server; | ||
- `[W]i-Fi settings`: select a Wi-Fi network, used to set the clock. | ||
|
||
The Z80-MBC2 configuration menu is also accessible using the USER button. | ||
The menu has been modified from the real Z80-MBC2 system: | ||
- `6: set Z80 clock speed`, changed to `6: Change user debug mode` - to invoke the simple | ||
debugger by pressing the USER button while the emulated Z80 is running; | ||
- `9: change RTC time/date`, changed to `9: Change auto-boot mode` - to choose between | ||
always invoking this menu on start-up or only via the USER button. | ||
|
||
|
||
## Build | ||
|
||
To build this sketch, the following items are needed: | ||
- Espressif ESP-32 hardware support tools and libraries for | ||
the Arduino IDE, either integrated using the "Additional | ||
Boards Manager URL": | ||
<https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json> | ||
or by cloning the GitHub repo or downloading the ZIP from | ||
<https://github.com/espressif/arduino-esp32> (be sure to | ||
select the release branch "release/v1.0"; | ||
- FabGL library from Fabrizio Di Vittorio from GitHub: | ||
<https://github.com/fdivitto/FabGL.git> or my fork, which | ||
also contains support for the Belgian keyboard layout: | ||
<https://github.com/GmEsoft/FabGL.git>. | ||
|
||
In Arduino IDE v1.8.x, in Tools - Board:, select the "ESP32 Dev Module" | ||
board. In the configuration settings, select the following: | ||
- Partition Scheme: "Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)"; | ||
- PSRAM: "Disabled". | ||
|
||
|
||
## Run | ||
|
||
To start this emulator, get a FAT32-formatted Micro-SD card, copy all files from | ||
the original Z80-MBC2 card image onto it, insert the card in the VGA32 module's | ||
SD connector. Connect a VGA monitor to the VGA blue connector, a PS/2 keyboard | ||
to the PS/2 purple connector, and an USB power supply to the Micro-USB connector. | ||
|
||
|
||
## Credits | ||
|
||
Thanks to the Z80-MBC2 Just4Fun project and its author SuperFabius - Fabio Defabis: | ||
<https://hackaday.io/project/159973-z80-mbc2-a-4-ics-homebrew-z80-computer> | ||
and <https://github.com/SuperFabius/Z80-MBC2>. | ||
|
||
Also thanks to the FabGL library from Fabrizio Di Vittorio that turns an ESP32 | ||
embedded system into a smart VGA terminal with keyboard, mouse and audio output, | ||
and a Micro-SD card slot: <https://github.com/fdivitto/FabGL>. | ||
|
||
|
||
## GPLv3 License | ||
|
||
Created by Michel Bernard ([email protected]) - <http://www.github.com/GmEsoft/Z80-MBC2_VGA32> | ||
Copyright (c) 2021 Michel Bernard. | ||
All rights reserved. | ||
|
||
This file is part of Z80-MBC2_VGA32. | ||
|
||
Z80-MBC2_VGA32 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. | ||
|
||
Z80-MBC2_VGA32 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 Z80-MBC2_VGA32. If not, see <https://www.gnu.org/licenses/>. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
/* | ||
Z80-MBC2_VGA32 - Simple Memory Allocator | ||
Created by Michel Bernard ([email protected]) | ||
- <http://www.github.com/GmEsoft/Z80-MBC2_VGA32> | ||
Copyright (c) 2021 Michel Bernard. | ||
All rights reserved. | ||
This file is part of Z80-MBC2_VGA32. | ||
Z80-MBC2_VGA32 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. | ||
Z80-MBC2_VGA32 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 Z80-MBC2_VGA32. If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "log.h" | ||
|
||
#include "HardwareSerial.h" | ||
|
||
class Allocator | ||
{ | ||
private: | ||
|
||
enum Status | ||
{ | ||
BOOKED = 0xA10CA7ED, // Allocated | ||
FREE = 0xF2EEF00D // Free food | ||
}; | ||
|
||
struct Header | ||
{ | ||
Header *prev_, | ||
*next_; | ||
size_t size_; | ||
int status_; | ||
//char ptr_[0]; | ||
}; | ||
|
||
public: | ||
|
||
Allocator( void *pool, size_t size ) | ||
: pOrigin_( (Header*)pool ), initSize_( size ) | ||
{ | ||
} | ||
|
||
void *malloc( size_t size ) | ||
{ | ||
if ( initSize_ ) | ||
{ | ||
pOrigin_->prev_ = pOrigin_->next_ = pOrigin_; | ||
pOrigin_->size_ = initSize_ - sizeof( Header ); | ||
pOrigin_->status_ = FREE; | ||
LOGD( "New allocator for size 0x%X at %p", pOrigin_->size_ , pOrigin_ ); | ||
debug( "Origin", pOrigin_ ); | ||
initSize_ = 0; | ||
} | ||
|
||
LOGD( "Allocating 0x%x bytes from pool %p", size, pOrigin_ ); | ||
|
||
Header *ptr = pOrigin_; | ||
do { | ||
ptr = ptr->prev_; | ||
|
||
debug( "Candidate", ptr ); | ||
|
||
if ( ptr->status_ == FREE ) { | ||
debug( "Free", ptr ); | ||
if( ptr->size_ >= size + sizeof( Header ) ) { | ||
debug( "Taking", ptr ); | ||
Header *pNewFree = (Header*)( (char*)ptr + size + sizeof( Header ) ); | ||
pNewFree->prev_ = ptr; | ||
pNewFree->next_ = ptr->next_; | ||
pNewFree->size_ = ptr->size_ - size - sizeof( Header ); | ||
pNewFree->status_ = FREE; | ||
ptr->next_ = pNewFree; | ||
ptr->size_ = size; | ||
ptr->status_ = BOOKED; | ||
pOrigin_->prev_ = pNewFree; | ||
debug( "New", ptr ); | ||
debug( "Prev", ptr->prev_ ); | ||
debug( "Next", ptr->next_ ); | ||
check(); | ||
LOGD( "Returning %p", ptr + 1 ); | ||
return (void*)( ptr + 1 ); | ||
} | ||
} else if ( ptr->status_ != BOOKED ) { | ||
LOGE( "ABEND! Memory Pool Corrupt at %p", ptr ); | ||
Serial.printf( "ABEND! Memory Pool Corrupt at %p", ptr ); | ||
for (;;); | ||
} | ||
} while( ptr != pOrigin_ ); | ||
|
||
return 0; // malloc failed | ||
} | ||
|
||
void free( void *pFree ) | ||
{ | ||
Header *ptr = (Header*)pFree - 1; | ||
|
||
if ( ptr->status_ == FREE ) { | ||
LOGE( "ABEND! Already free pointer: %p", pFree ); | ||
Serial.printf( "ABEND! Already free pointer: %p", pFree ); | ||
for (;;); | ||
} else if ( ptr->status_ != BOOKED ) { | ||
LOGE( "ABEND! Memory Pool Corrupt at %p", ptr ); | ||
Serial.printf( "ABEND! Memory Pool Corrupt at %p", ptr ); | ||
for (;;); | ||
} | ||
|
||
ptr->status_ = FREE; | ||
debug( "free", ptr ); | ||
|
||
// merge with next block if free | ||
if ( ptr->next_ != pOrigin_ && ptr->next_->status_ == FREE ) { | ||
LOGD( "Merging with next, deleting next" ); | ||
debug( "Delete", ptr->next_ ); | ||
ptr->next_ = ptr->next_->next_; | ||
ptr->next_->prev_ = ptr; | ||
ptr->size_ += ptr->next_->size_ + sizeof( Header ); | ||
debug( "Prev", ptr ); | ||
debug( "Next", ptr->next_ ); | ||
} | ||
|
||
// merge with previous block if free | ||
if ( ptr != pOrigin_ && ptr->prev_->status_ == FREE ) { | ||
LOGD( "Merging with next, deleting this" ); | ||
debug( "Delete", ptr ); | ||
ptr->prev_->next_ = ptr->next_; | ||
ptr->next_->prev_ = ptr->prev_; | ||
ptr->prev_->size_ += ptr->size_ + sizeof( Header ); | ||
debug( "Prev", ptr->prev_ ); | ||
debug( "Next", ptr->next_ ); | ||
} | ||
|
||
check(); | ||
} | ||
|
||
void debug( const char *name, const Header *header ) | ||
{ | ||
LOGD( "%-10s: %p prev=%p next=%p size=0x%x status=%x", name, header, header->prev_, header->next_, header->size_, header->status_ ); | ||
} | ||
|
||
void check() | ||
{ | ||
LOGD( "Checking block chain" ); | ||
Header *ptr = pOrigin_; | ||
int i = 0; | ||
do { | ||
String block( "Block " ); | ||
block += i; | ||
debug( block.c_str(), ptr ); | ||
if ( ptr->next_->prev_ != ptr ) | ||
LOGE( "Error: ptr->next_->prev_ (=0x%x) != ptr (=0x%x)", ptr->next_->prev_, ptr ); | ||
if ( ptr->prev_->next_ != ptr ) | ||
LOGE( "Error: ptr->prev_->next_ (=0x%x) != ptr (=0x%x)", ptr->prev_->next_, ptr ); | ||
if ( ptr < ptr->next_ && ptr->status_ == FREE && ptr->next_->status_ == FREE ) | ||
LOGE( "Error: unmerged free blocks %p & %p", ptr, ptr->next_ ); | ||
ptr = ptr->next_; | ||
++i; | ||
} while ( ptr != pOrigin_ ); | ||
} | ||
|
||
private: | ||
Header *pOrigin_; | ||
size_t initSize_; | ||
}; |
Oops, something went wrong.