-
GITLab Repo Updated
04/13/2021 at 03:53 • 0 comments -
PS/2 Pain and Suffering and Happiness
04/12/2021 at 18:42 • 0 commentsPS/2 keyboards are awesome - super cheap (a few bucks from a thrift store!) and easy to interface with - clock and data, sample the data when the clock ticks, build a word, and you've got a scan code. There's work to do in converting scan codes, treating SHIFT etc correctly, and so on. Fortunately, there are Arduino libraries that make this all pretty simple.
I started with https://github.com/PaulStoffregen/PS2Keyboard which is really easy to use and gives you (mostly) ASCII codes in response to key presses. Worked great with my CMStorm mechanical keyboard (they're technically all mechanical, right?) with a PS/2 adpater. But then I tried to use a flexible USB keyboard I had sitting around, and no joy - couldn't detect keystrokes.
After looking online, I decided maybe this was just a peculiar keyboard, so I ordered a PS/2 KB from Amazon. Alas, no joy there either.
I switched libraries to https://github.com/techpaul/PS2KeyAdvanced which let me see raw codes, and discovered the KB was repeatedly sending 0xAA. Some googling revealed this page: https://forum.arduino.cc/index.php?topic=57610.0 which suggests that the 0xAA is the PASS code for a power-on self test, but is sent with flipped parity, and needs to be responded to with 0xFE, also with flipped parity. Sounded far fetched, but this is the beauty of open source: with access to the source code, it was easy to experiment.
First, I tweaked the code in the interrupt handler, to detect receipt of 0xAA and then call send_now_special(). send_now_special() calls the usual send_now() to send a byte to the keyboard, but I modified it to send with true or inverted parity. This is done by initializing the parity bit to a user-supplied flag instead of 1.
Bingo! The KB works great!
The final change was using https://github.com/techpaul/PS2KeyMap to map from 2-byte status+code to ASCII codes.
case 11: // Stop bit lots of spare time now //if( _parity >= 0xFD ) // had parity error // detect weird AA code - njm if (_shiftdata == 0xAA) // compulsive reset/something... { // changed this to respond with FE with wrong parity (srkinsky et al) - njm send_now_special( PS2_KC_RESEND ); // hacked _tx_ready |= _HANDSHAKE; } else // Good so save byte in _rx_buffer
void send_now_raw( uint8_t command , int flag) // old send_now...can toggle parity - njm { _shiftdata = command; _now_send = command; // copy for later to save in last sent #if defined( PS2_CLEAR_PENDING_IRQ ) _bitcount = 0; // AVR/SAM ignore extra interrupt #else _bitcount = 1; // Normal processors #endif _parity = flag; // haha - njm _ps2mode |= _TX_MODE + _PS2_BUSY;
-
User Manual
04/12/2021 at 18:27 • 0 commentsI've finished a draft of a user manual for the board: for now it's available at https://gitlab.com/nickmacias/z80sbcpublicrepo/-/blob/master/manual.pdf but I'm working on a cleaned up GITLab repo for all the doc, files, etc. related to this project.
-
CP/M Running :)
04/12/2021 at 18:26 • 0 commentsBeen a while since I logged here, but have been working on lots of things. Downloaded the assembly source for CP/M 2.2, designed an interface board for talking to an Arduino (nano), wrote a bit of BIOS code for console and disk access, and got everything running :)
I had this working through the nano's USB port, but again, that means having an extra computer involved, which feels like it defeats the point! So now IO have a PS/2 keyboard hooked directly to the nano, as well as a 20x4 LCD display.
The floppy drive is actually a uSD card (32G lol). Each floppy is in its own directory (a, b, c, d) and each directory has 77 files (00-76), one per track. Each file is 128*26 bytes, storing the 26 sectors of the track. seek()/read()/write() commands from the Arduino access these sectors within the appropriate file.
I also wrote a bootloader to read the loaded CP/M bytes off track 0 from floppy a. This bootloader is saved on the Z80 board in file 0x20, which can be loaded from the front panel, and, when run, will copy CP/M from disk a/track 0 into memory and then jump to the CP/M boot code.
-
Tiny BASIC :)
03/25/2021 at 08:48 • 0 commentsSo I decided to play with the headers I added to the board, and see if I could interface a terminal to the system. I used an Arduino Nano and several discrete chips to make a 4-port interface between the Z80 and a KB/display. Then I modified a Tiny BASIC hexfile to use the new ports, and voila! got BASIC running on the Z80 :)
I'll upload the circuit diagrams and Arduino code to the Files section of this project.
Here's a long video showing the details.
-
Status Update - Pretty Much Done :)
03/22/2021 at 02:12 • 0 commentsFinished soldering LEDs (39) and switches (10 + 2 banks of 8) to the front of the board, and everything seems to work. Added the LiPo connector on the back and it all fits nicely in the case.
I had a bug in the layout. My first version treated all I/O requests (IN and OUT instructions) as coming from the switch bank/to the Program Output LED display. On this version, I decided to get fancy and only use those for I/O on port 0xFF. Unfortunately, I messed up and NAND'd D7-D0 instead of A7-A0. So I didn't solder the 7430 (8-input nand), and instead jumped the output pin (pin 8) to a via carrying A7. As a result, 128 ports (0x00-0x7F) request the switch bank/LED bank on the board; but the other 128 (0x80-0xFF) are available for external use (via the IORQ, RD, WR and address signals in the header).
Next step, I may play with that, and hook up a simple keyboard or something. After that, possibly find some code for BASIC or something (if I decide to dig into CP/M again?!?)
-
LiPo/Power Sub-system
03/20/2021 at 20:21 • 0 commentsThe system is meant to be runnable from either a rechargable (3.7V LiPo) battery, or from the USB connection. Ideally (since the WiFi might draw power faster than the battery can be charged), power should come from the USB connection when available, with any spare power being used to recharge the battery. The term here is "load sharing." My favorite chip for this is the MCP 73871. Small, inexpensive, and packed with features, this was a step up for me from the MCP 73831, which is a bit easier to use (and easier for me to solder!) but doesn't do automatic load sharing.
This video talks about the issues I ran into with the 73871 and how I found/fixed the problems. Also shows off the EPS-01 WiFi interface to the board :)
-
Back of new (4-layer) board populated :)
03/17/2021 at 07:49 • 0 commentsMost chips, caps and resistors are in place on the back of board. Fixed a few solder bridges/one missing resistor, and now I can talk to the CLI via the FT231.
Basic Z80/SRAM functionality looks good. I was having problems writing the flash memory, but that was just software - the flash initialization code was commented out lol.
Ready for WiFi-related parts (arriving tomorrow?) which will let me test the ESP-01 interface. Then I'll populate the front of the board, print a case, add a battery and see how it works :)
-
Build Update
03/15/2021 at 15:43 • 0 comments -
New Files - Schematic and BoM
03/04/2021 at 04:54 • 0 commentsThe new (4-layer) board is working its way through JLCPCB - already 20% completed! I ordered 15 boards, not because I expect to use 15, but because it was like $5 more than 10 boards. They should arrive around finals week, which means I have some time over spring break to build them.
I uploaded a PDF of the newest schematic to GITLab. This includes:
- fixes for the polarity of the output register CLR input
- tying A16 of the SRAM to ground
- a bypass solder point (BBP): in case the 5V boost doesn't work, I can remove those components and solder this jumper closed
- an 800 mA LVD 3V3 regulator
- connections for an ESP-01 which, when powered, will send/receive serial data to/from the AT328P; when not powered, the FTI-231 will exchange data with the AT328P. Multiplexer logic is driven by the output of the WiFi switch (which drives the 3V3 regulator, which powers the ESP-01)
- added logic for decoding the address bus so only port 0xFF interacts with the user I/O (and dang! I just realized as I typed that that there's a problem...my 8-input NAND gate is connected to the DBUs instead of the address bus :/ oh well, always good to do some board re-work! Will just skip the NAND gate and hardwire the output point low); and
- edge connectors for all Z80 signals.