New CP/M-80 computer: Z80, SD cards, VGA, USB keyboard and power... Teensy 4.1

Sure!

Well "type it in" into a .ASM source file and compile with ASM.COM or equiv, and follow the usual CP/M rules, yes.

Or you could literally just type them in, directly to memory, using DDT.COM. I've done this. It accepts Intel mnemonics. ZSID.COM would accept Zilog mnemonics. (I prefer the TDL mnemonic set, which looks like the 8080, but expanded.)

It passes recognized Z80 CPU tests, I can't recall them off hand, same tests used by most of the serious emulators, Redcode, etc. I used the emulator buried in ntvcm, by @davidly on github. So yes, it has the full alternate register set and allegedly all of the subtle internal documented and undocumented side effects. I say allegedly simply because I have not done them myself.

None of my code, nor I doubt Digital Research's code, uses the alt reg set. CP/M is 8080 code, not z80.


I've been really vague about availability of Friendly eZ80. I've given a couple away, I intend to make and sell in some small way, but have been too entangled in code to think about it, and I have yet to make a cabinet for it. I've got 7 more of them, and will revise the board shortly, nothing serious.

Part of my ambivalence is that I have *absolutely no idea* what the market is for a "new" CP/M computer! 5? 20? 100? units? lol.
 
@tomicdesu - Here is what I have determined so far. 800x600 8x8 font size:
800x600_8x8_font.jpg

Cell phones and shakey hands do not make good photos :LOL: We get two windows (80x24) but the aspect ratio sucks.

800x600_8x16_font.jpg

This is 800x600 8x16 font size. Good aspect ratio but will only fit one window.

1024x768_8x8_font.jpg

This one is 1024x768 with 8x8 font size. fits three windows but again aspect ratio sucks.

1024x768_8x16_font.jpg

This one is 1024x768 8x16 font size. good aspect ratio but only fits 1.5 80x24 windows. Second window is 80x14.

Each pixel is 4 bits of one byte (16 colors). Each byte holds two pixels worth of color therefore an 800x600 screen only needs 400x300 bytes of memory which is 120000 bytes. A 1024x768 screen needs 393216 bytes. These are full screens. Since we are talking about window sizes of 80x24 we need 80x24x64 (122800) bytes memory. 8x16 characters are (8 bit wide / 2) is 4 and are 16 bytes vertically which is 4 x 16 = 64 bytes. And then we need to add in the size of the borders and title line. There are 3 vertical lines and 1 title line plus two columns for side borders per window. (80*3+80)/2+2*28 bytes more for borders and title lineo_O Memory for all of this is taken care of by the "vbox_get()" and "vbox_put()" functions. They do the all the calculations for malloc and then save the four coordinates of the window followed by the actual window contents for retrieval later.

So, the next step is going to be setting up virtual 80x24 windows that can be saved and recalled with the current contents at that time. I have virtual screens set up in my RA8876 driver. The RA8876 has 16Meg of video memory which allows me to have 10 virtual screens. My USB keyboard driver I use is setup to use the alt+F1 to alt+F10 keys to switch between screens. Kind of like the way Linux does. Only not in a real time environment.
Anyway, I'll start playing with virtual screens and see what I can come up with...
 
Last edited:
Wow! Very nice! All of the scroll bugs are gone. I'm using the T4_FIXES version, has the main one been updated?

I went in another path, and implemented four 24 x 80 character windows, that can be mapped to the screen. Each is a full H19 escape sequence machine. Each terminal is 24 x 80 x 2, so memory use is small. And copying in 24 x 80 characters to the screen is fast. I'm not yet writing attributes -- is there a function analogous to write() that writes the attribute byte? Trying to not do set-fg-bg-color for each character (and state machine to do so only on changes in a line etc).

What I'm working at is a screen paradigm where there's a big "+" crosshairs/cursor, a line top to bottom, a line left to right, (drawn with vertical bars and hyphens), with a + in the middle.... you "grab" the + with a magic key (it blinks or something) and you drag it around on the screen with arrow keys. This breaks the screen into four quadrants. These are four viewports into the four windows.

So you could drag the "cursor" so that one window is really large, and others would suffer for size. But! for lots of tasks this is just fine -- edit in one window, compile in another. Compiles just scroll off the bottom. A small one in the corner could display date and time etc. A tricky-to-think-about issue is to locate the viewport to the bottom-left of each virtual window, I'm calling it the "hot spot", where the A> prompt is displayed, so that you can see stuff scroll in a small window.

The fixed 24 x 80 window means that you *could* have a graphical program running in a window, see only the bottom few lines, and move the viewports around to see it all, or more of it.

Fixed hot keys for "select window N and make it full size" etc.

It's working now, and works in any VGA mode, so your new larger ones will be helpful!

I'm doing this all for MP/M. I've got an XIOS to the testable point, set it aside to do this screen and magic key thing. For four consoles, I'll need 3 * 48K of additional RAM for the Z80. I've allocated it to make sure, but it's all fitting OK.
 
Here's a sketch of the scheme. The pen line is the screen, the lighter pencil four 24x80 windows, the rightmost two dangling over the edge. A simple case.

The cursor thingie of course consumes character cells, but is probably necessary. I'm thinking different background or foreground color in each window would help. And maybe enough. Or maybe the cursor thingie delineating the active window.

With CP/M it's maddening -- you switch windows, and it feels like it ought to be completely independent, but it's simply the wrong screen contents for what you were doing before! It's not for CP/M though, just testing. So used to multitasking today it's hard to accept that it's not, here...


The blinking cursor indicates which one is active in MP/M.
 

Attachments

  • IMG_20250723_131623.jpg
    IMG_20250723_131623.jpg
    171.1 KB · Views: 54
I have not merged the changes to the main branch yet, but I have done enough testing that I am confident it will not break any code previously written with the main branch.
There is no attribute byte. Characters are graphically drawn in video memory. Each character represents an 8x8 or 8x16 byte array. An 8x8 character would be 8 bytes and an 8x16 character would be 16 bytes for each character. But remember each byte represents 2 pixels as each nibble represents one pixel and each nibble represents one of 16 colors. Each bit of each font byte is is scanned and if it is 1 then the current foreground color is used else the current background color is used. This can be real confusing. Here is the two main functions used to draw characters to video memory:
Code:
//========================================
// drawPixel()
// fb is pointer to selected frame buffer.
// x and y are selected pixel coords.
// fg is foreground color. (0 to 15)
//========================================
FLASHMEM void FlexIO2VGA::drawPixel(int16_t x, int16_t y, uint8_t fg) {
  _fb = s_frameBuffer[frameBufferIndex];

  if((x>=0) && (x<=fb_width) && (y>=0) && (y<=fb_height)) {// No neg x or y.
    unsigned int sel = (x & 1) << 2; // 4 or 0 (nibble)
    uint8_t c = getByte(x/2,y); // Get current 4 bit pixel pair.
    // remove old color
    c &= (0xf0 >> sel);
    // insert new color
    c |= fg << sel;
    _fb[(y*_pitch)+(x/2)] = c; // Write to video memory
  }
}
This draws one pixel to the screen. Then this:
Code:
//=========================================
// Draw a string in one of four directions. (or one character)
// Right, Left, Up and Down.
//=========================================
FLASHMEM void FlexIO2VGA::drawText(int16_t x, int16_t y, const char * text, uint8_t fgcolor, uint8_t bgcolor, vga_text_direction dir) {
  uint8_t t;
  int i,j;
  const uint8_t *charPointer;
  uint8_t b;
  uint8_t pix;
 
  while ((t = *text++)) {
    if(font_height == 8)
      charPointer = &font_8x8[t*font_height];
    else
//      charPointer = &font_8x16[t*font_height];
      charPointer = &currentFont[t*font_height]; // currentFont[] is a loadable font buffer.
    for(j = 0; j < font_height; j++) {
      b = *charPointer++;
      for(i = 0; i < font_width; i++) {
       pix = b & (128 >> i);
        // pixel to draw or non transparent background color ?
        if((pix) || (bgcolor != -1)) {
          switch(dir) {
            case VGA_DIR_RIGHT:
              drawPixel(x + i, y + j, (pix ? fgcolor : bgcolor));
              break;
            case VGA_DIR_TOP:
              drawPixel(x + j, y - i, (pix ? fgcolor : bgcolor));
              break;
            case VGA_DIR_LEFT:
              drawPixel(x - i, y - j, (pix ? fgcolor : bgcolor));
              break;
            case VGA_DIR_BOTTOM:
              drawPixel(x - j, y + i, (pix ? fgcolor : bgcolor));
              break;
          }
        }
      }
    }
    switch(dir) {
      case VGA_DIR_RIGHT:
        x += font_width;
        break;
      case VGA_DIR_TOP:
        y -= font_width;
        break;
      case VGA_DIR_LEFT:
        x -= font_width;
        break;
      case VGA_DIR_BOTTOM:
        y += font_width;
        break;
    }
  }
}
draws a character or string of characters to the video memory. The "write()" function uses the above "drawText()" function.
The only real attributes are the foreground color and background color which is determined by "(pix ? fgcolor : bgcolor)".
Right now it is a set each character fgc and bgc scenario. There would have to be another array to hold attributes for each character used in video memory. So for each 24x80 screen that would be (24*4)*(80*4) = 30720 bytes of memory. Am I right? I will have to play with this :)

One thing I am not understanding is "Each terminal is 24 x 80 x 2". What does the "x 2" represent?
 
I looked at drawpixel after I posted, sorry! should have looked first. ....

Not a big deal. I am storing color per character, and will make a little state machine do set..color before calling write as needed.

The x 2 is 2 bytes per character, char and color. A window is then 3 dimensions.

A window is 24 x 80, for the character plane, and a parallel 24 x 80 plane for colors packed into a byte. So windows are fairly compact.

Lots of things are technically feasible, so I'm gonna experiment with this. I'm looking the magic key business. F10 might be "whole screen" like CP/m is now, and F1 to f4 for the resizable windows.

I've got wordstar modified to query screen size, alas only at startup. But then F1 to F10 etc could copy screen contents as needed.
 
Last edited:
OK, a did a thing. I wrote a window manager in Teensy, split the screen into four, with a big "cursor" that divides the screen. Hit F-+ to enter resize, draw the cursor with arrow keys. Programs can be running.

The Z80 thinks it had four "Heath/Zenith H89" terminals (selectable via IO port). Each are 100% independent. The cursor resizes all four at once, and each window's "hot spot", the lower left corner of the command interpreter, always visible; hidden portions are always top and right. That and the four-way as design constraints made for a succinct and fast manager.

Each window can be up to 30x90. Instant keys select the window, another key "maximizes" the current window, etc.

This is silly for CP/M, but its designed for MP/M, which I'll make work next. I have the XIOS written, untested, realized I needed to deal with the terminal in some way.

The chosen constraints, especially the resize cursor, mean it would not easily scale up to more windows, so it's a kind of singular solution.

Each window consists of an array I think 30 x 90 x 2 (depth two for char and colors) and the alignment constraints makes the geometry calcs just additions and .LT. tests for bounds, so it's fast and relatively simple math. The whole thing, including the keyboard console, is ~1400 lines, one module, not including VGA4BIT. All of it, including the SD cards and Z80, are single-threaded event loops, no interrupts, so clean and drop in. I will come up with a means to modularize it.

There's a crappy 10-sec video, here: https://www.bleeve.me/fZ80/resize1.mp4

It uses VGA4BIT of course in 1024x768 for this photo and vid. You can, in a window! resize the VGA display, from a Z80 program, and the window manager does the right thing, the windows stay the same dimension, but of course the viewport shows less of each window on the screen.

The Z80 sees it as an IO port, VGA_DATA and VGA_STATUS for writing, and VGA_WINDOW for which window to write to. Each window keeps it's full state, cursors, etc, though there's only one cursor type and color for the screen. Active screen is the one with the blinking cursor.

Tried to keep the "decoration" to zero, for a consistent CP/M paradigm, it was tempting to add on screen window sizes and other fluff, but I resisted.
 

Attachments

  • IMG_20250805_092541_890.jpg
    IMG_20250805_092541_890.jpg
    271.9 KB · Views: 58
Last edited:
Here's the entire "interface" for resizing! The black gap in the image above has the cursor (drawn with | - and + characters) in the gap, draggable. I'll rummage around in the charset to find line drawing characters; is there a displayable list of them?
 

Attachments

  • IMG_20250805_095153_047.jpg
    IMG_20250805_095153_047.jpg
    266 KB · Views: 56
Here's the entire "interface" for resizing! The black gap in the image above has the cursor (drawn with | - and + characters) in the gap, draggable. I'll rummage around in the charset to find line drawing characters; is there a displayable list of them?
Nice work(y) Looking forward to trying it out when you are done. Box characters are chr$(179) to chr$(218) using the standard font files. These are documented and shown in the link above provided by @kd5rxt-mark.

I have not had much time to play recently but hope to get back to it soon...
 
May I ask two question?
I have some asm code from the 80s (on paper). So, I simply can type it in and is should work, right?
Also, I recall that one of the nice features of the Z80 was that it had 2 independent register sets, so that context switching was fast. Is that also implemented?

Oh sorry, somehow I missed your post!

Yes, every feature of the Z80 is implemented, including "documented undocumented" side effects. I did not write the emulator, @davidly did, it passes all known to me Z80 test suites, of which there are many.
 
@tomicdesu - Found some significant bugs in the driver during creation of a simple menu system. They had to do with the getChar(), putChar(), vboxGet() and VboxPut() functions. Most of the examples had to be updated unfortunately.

The menu system helped find a lot of the bugs. It uses the vboxGet() and vboxput() a lot, The problem had to do with calculating the size of the box to be saved with malloc() and then later when the box was closed. It was just saving whatever the first character of the box was repeatedly for the size of the box. Which wasn't noticed at first because the folowing characters were the same as the first character. (The background pattern). That was due to bad code in getChar() and putChar() not returning the incremented buffer pointer to the vboxGet() and VboxPut() functions. Anyway, the library should be more stable now.
There are two new sketches:
- get_key_mouse_testing.ino - This just tests using the mouse and keyboard together with the mouse imitating the arrow keys on the keyboard.
- VGA_T4_MenuTest.ino - This sketch does a simple test of the menu system. The mouse emulates the four arrow keys. The left mouse button acts as the enter key and the right mouse button acts as the ESC key. The menu entries are arrays of strings like:
Code:
const char    *info_box[] =
            {
            " INSTRUCTIONS ",
            "This is a demonstration of the MENU functions.  The menu bar",
            "above lets you select and try the many combinations of",
            "menu display options.  To access a menu, press the cursor",
            "movment keys or the first letter of a choice. The enter key",
            "selects the hilighted item.  The ESC key cancels a menu.",
            "< This box was created by menu_message() >",
            (const char *)'\0'
            };

const char    *bar_main = "  Lines  Colors  Shadow  Quit  ";

const char    *drop_quit[] = {
            "< Quit? >",
            "No",
            "Yes",
            "< Select >",
            (const char *)'\0'
            };
The first string is the title and the last string is used as the prompt. The rest are the menu selections.
Uncolored boot screen:
menu_uncolored.jpg


And after using the menu to color a few items of the menu system:
Menu-colored.jpg


I adapted this from a program I found and used years ago on an 8086 PC with a CGA video adapter :D
The updated library is in the fixes branch.
Hope you are doing well with your projects...
 
Wow! That's a lot!! And they look really great, like 90's unix! And great news on the bug fixes. I've not had a single issue that I'm aware of. But I'm not directly using any *box drawing stuff, and not even putchar, just write. So maybe I've side-stepped them. But I'll get and test with the new library.

For a month I've been down the MP/M rabbit hole, spent the last week on one of those bugs that turns out to be dumb and simple to fix but a huge oversight to begin with. I'll come up for air soon.

I have to say, your library has been flawless for me. It worked first thing and keeps working.
 
I finally got some time to use the latest posted version of fz80. Just can't seem to figure out how to get the sizing cursor to appear and how to switch between windows. Any hint's...
 
F1 through F12 are the window-changing keys. I think F12 brings up the big cross cursor. You've run VGA M to get into multiwindow mode? You see four windows?

F1..F4 selects window 1..4. In the version you have, F12 should bring up the resize cursor (big screen sized +) and arrow keys move it. Its been changed to non-modal, F5 .. F8 bring up the cursor, move it left, right, up, down, 400 mS after the last one screen redraws. Much cleaner. But the version you have should be F12 for resize.

I've got MP/M reliable now; I'm working on the cabinet and (printed) manual. MP/M forced some redesigns, as expected, but it's all fairly seamless now.
 
Thanks, It works perfect (y) I really like that you keep margins on all four sides when resizing the panels. That way all four panels are always in view. I am working on a complete rewrite of a file manager for the Teensy that I had cobbled together a few years back. I originally wrote it for use with the Buy Display RA8876 10.1" display. Now I rewrote it for use with the VGA_4bit_T4 library. Then I will update the RA8876 version later.
Not sure how useful it would be but it does use my DiskIO library that allows SDIO, USB and littleFS devices to be accessed under one file system and is based on the Teensy FS file system. It also is compatible with my TeensyEXT4 library that allows using EXT4 formatted devices to be used as well. I want to add FTP support, Ethernet, WIFI??? HINT HINT:D
Here is a couple of pictures:
FileManager.jpg

Sorry, a little blurryo_O
ChangeDrive.jpg

Copy_Files.jpg

QPINAND_Copy.jpg


To be honest I am really amazed at the things that can be done with @jmarsh 's original FlexIO2VGA library:D
 
Sorry for the slow response.I have been working with the SD cards as well and found that the only time I get the ACDM41 error is with a card formatted as FAT16.

Touche! My slower response! lol

I had not been keeping track of card format, FAT16, FAT32, etc.

Regarding the SD card read error, SD_CARD_ERROR_CMD18, frequently reported when accessing either of the removable SD cards... I had them wired in parallel (bussed) with separate selects of course. If both boards were installed at once, I'd get SD_CARD_ERROR_CMD18 errors, "often".

It narrowed down to writes easily enough. Reading, only, near zero incidence. Testing with my crappy DISKTEST.COM random drive (1 of 2) random sector, infrequent errors. Testing with random drive, random sector, random read or write, high error rate (seconds to tens of seconds).

I did a board revision, added tristate drivers to the SD card data-outputs (in case they were dragging their feet) on the two removable cards. The error rate on read-only plummeted to almost acceptable (one error per half million); mixed read/write hardly improved if at all.

I added a brute-force variable delay between card access to characterize; no delay, 0, 1 to 100 mS, had any effect.

Last few days back at the problem and I then looked at my two test cards: one is FAT16 the other FAT32. The FAT16 reported countless errors, the FAT32, none. How had I not noticed that before? (In between tests, doing other things, I'd take the cards out, and put them back into arbitrary sockets, that's how, thinking the format didn't matter.)

Put the FAT16 card in the linux machine, did mkfs.vfat. It's now FAT32.

No errors; yet, but at least another order of magnitude better, from a day's testing so far.

This seems weird to me, because all the mkfs is doing is rearranging the furniture, I thought; different disk logical organization, and I'm not testing with filesystem, but sector level. But it definitely matters.

Lesson: DO NOT USE FAT16 SD CARDS!

Thank you so much for the report back in July!
 
Thanks, It works perfect (y) I really like that you keep margins on all four sides when resizing the panels. That way all four panels are always in view.

Cool. I'm finishing up the current revision. It's quite a lot of work done. Reliability all around is up, as is performance.

MP/M II 2.1 is half way to usable in a modern sense. I'm editing in one window, compile and test in another, and can be looking at another file in a 3rd, with the other unused. Except for the silly Y2K problem (year displays as ">5", lol) RTC works. Haven't played with the scheduler ("cron" like). Its shockingly good software, 45 years old.

There's a simple API to write into the inter-window margin, eg time of day or other status type stuff. It's another H19 window, only one row high!

I'm having nice aluminum cabinets made. Here's the base part, making those first, the top will be next (next week I hope). The tops will be painted. I'll send you one. Favor any particular color? (I use Montana paints, the tagger/graffiti choice, great colors; pick one!)

I'm printing a "tablet" sized book, 6 x 9 or so, 80 pages, users and programmers guide, old style. That will be another month. I'll send you one too.

I think I'm gonna sell the remainder of the dozen I have; I could make more but I think the world market for a new MP/M II 2.1 machine may easily be saturated with a dozen.
 

Attachments

  • IMG_20251026_123821_340.jpg
    IMG_20251026_123821_340.jpg
    151.3 KB · Views: 15
  • IMG_20251026_123831_619.jpg
    IMG_20251026_123831_619.jpg
    246.3 KB · Views: 17
....

:D
Here is a couple of pictures:

To be honest I am really amazed at the things that can be done with @jmarsh 's original FlexIO2VGA library:D

Wow! OK that's a lot. I think there's something really interesting here.

Is there some sort of p-code machine you could write/find an efficient interpreter for? And make a dense, succinct general purpose machine from? With high level "primitives" like your display and filesystems you could have a small or pocket machine of great capability
 
Touche! My slower response! lol

I had not been keeping track of card format, FAT16, FAT32, etc.

Regarding the SD card read error, SD_CARD_ERROR_CMD18, frequently reported when accessing either of the removable SD cards... I had them wired in parallel (bussed) with separate selects of course. If both boards were installed at once, I'd get SD_CARD_ERROR_CMD18 errors, "often".

It narrowed down to writes easily enough. Reading, only, near zero incidence. Testing with my crappy DISKTEST.COM random drive (1 of 2) random sector, infrequent errors. Testing with random drive, random sector, random read or write, high error rate (seconds to tens of seconds).

I did a board revision, added tristate drivers to the SD card data-outputs (in case they were dragging their feet) on the two removable cards. The error rate on read-only plummeted to almost acceptable (one error per half million); mixed read/write hardly improved if at all.

I added a brute-force variable delay between card access to characterize; no delay, 0, 1 to 100 mS, had any effect.

Last few days back at the problem and I then looked at my two test cards: one is FAT16 the other FAT32. The FAT16 reported countless errors, the FAT32, none. How had I not noticed that before? (In between tests, doing other things, I'd take the cards out, and put them back into arbitrary sockets, that's how, thinking the format didn't matter.)

Put the FAT16 card in the linux machine, did mkfs.vfat. It's now FAT32.

No errors; yet, but at least another order of magnitude better, from a day's testing so far.

This seems weird to me, because all the mkfs is doing is rearranging the furniture, I thought; different disk logical organization, and I'm not testing with filesystem, but sector level. But it definitely matters.

Lesson: DO NOT USE FAT16 SD CARDS!

Thank you so much for the report back in July!
Nice:)I had forgot about that discussion...
 
Cool. I'm finishing up the current revision. It's quite a lot of work done. Reliability all around is up, as is performance.

MP/M II 2.1 is half way to usable in a modern sense. I'm editing in one window, compile and test in another, and can be looking at another file in a 3rd, with the other unused. Except for the silly Y2K problem (year displays as ">5", lol) RTC works. Haven't played with the scheduler ("cron" like). Its shockingly good software, 45 years old.

There's a simple API to write into the inter-window margin, eg time of day or other status type stuff. It's another H19 window, only one row high!

I'm having nice aluminum cabinets made. Here's the base part, making those first, the top will be next (next week I hope). The tops will be painted. I'll send you one. Favor any particular color? (I use Montana paints, the tagger/graffiti choice, great colors; pick one!)

I'm printing a "tablet" sized book, 6 x 9 or so, 80 pages, users and programmers guide, old style. That will be another month. I'll send you one too.

I think I'm gonna sell the remainder of the dozen I have; I could make more but I think the world market for a new MP/M II 2.1 machine may easily be saturated with a dozen.
Those cabinets will be nice. Mat black? Sounds like you are getting close to the finish line. You are being very generous😀 can't wait to play with MP/M ||. I have never messed with it before...
 
Wow! OK that's a lot. I think there's something really interesting here.

Is there some sort of p-code machine you could write/find an efficient interpreter for? And make a dense, succinct general purpose machine from? With high level "primitives" like your display and filesystems you could have a small or pocket machine of great capability
I have been playing with the file manager for quite a while back when I first wrote the driver for the RAIO RA8876 TFT driver. That was a 10.1" TFT from Buy Display. That was around 2018. Shortly after that I modified a version of STBASIC09 which is a structured basic adding my RA8876 driver, keyboard driver, mouse driver and a lot of the TEENSY library functions to it. then I started on my version of the Kilo editor which is used by STBasic or can be used standalone. Next came DiskIo which was my attempt at being able to combine access to all of the the different file systems like MSC which is my USB mass Storage driver that is now part of USBHost_t36, SD/SDfat, LittlFS and TeensyEXT4 which I adapted to the Teensy from LWEXT allowing ext4 file system usage. Then I added POSIX file system capabilities to use with Diskio and the file manager. Finally I took a version of MicroBox which is a small Linux like shell to combine it all into a small OS. That's when I started running out of memory 🤨

Anyway, I lost some of the libraries so it went on hold until I finally found some backups of some of the programs. Now I am rewriting a lot of the libraries and also adapting them to the VGA driver. Now it feels like play time again with the Teensy😁

Edit: Just wanted to add that @KurtE and @mjs513 and a few others contributed a lot to the Ra8876 driver library and MSC massStorage library.
 
Last edited:
I've been working almost (no, not almost, ...) obsessively getting the fZ80 reliable. I had a huge random-memory-corrupt error, a true heisenbug, that I finally traced solidly to interaction between the IntervalTimer object and something in the FlexIO2VGA DMA and/or interrupt. I spent a month getting it first repeatable, then tracking it down.

It only happens on MP/M, though both CP/M and MP/M used that IntervalTimer, for a simple 50 Hz tick.

The immediate trigger was a full screen rewrite, after re-sizing windows, presumably the 50 Hz tick, then the z80 executed some random byte because an array read, after bank logic, array [index] or b= *ptr, simply returns the wrong value.

Here's the thing: on MP/M the "Z80" is running in 64K allocated in DMARAM, and 146K in ram1 (four 54K banks, one 16K fixed in DMARAM, etc). (I've used the full megabyte of the machine; about 400K for the VGA, 210 K for MP/M's four banks, etc.)

So VGA DMA is doing it's thing, IntervalTimer is interrupting at 50 Hz, and the main CPU task loop is doing high-speed large block writes into DMARAM, from ram1, while an interleaved task loop is doing high speed read and write to DMARAM. KABOOM! on thr 50Hz tick -- a byte read from DMARAM returns the wrong value.

I'm solving the Z80 50 Hz tick through other means (software timer sync'ed with one-second from the RTC for long term stability).

The bug was so nasty... I was doubting sanity and my skills. Nailed it though.

It's a big blob of complexity to reproduce, I'll snapshot that revision and maybe you can reproduce it.


MEANWHILE, lol, I've got the 120 page book done, minus some tweaks I'm making to the resize-screen keys, aesthetic stuff, the two-piece aluminum chassis top arriving hopefully today. Attached is what the base looks like. Working on a sticker for the front panel. Gonna have a dozen to sell.[/I]
 

Attachments

  • IMG_20251103_091201_706.jpg
    IMG_20251103_091201_706.jpg
    220.5 KB · Views: 12
Last edited:
Sure you want flat black? I use Montana paints, the graffiti folk use them. Amazing colors. Here's the choice, lol.


I've been thinking something bright, and period-incorrect. Vivid red, Kalani orange, Electra violet, Valley green... I'll want to pick one or two colors for the dozen, but I also have some colors laying around: black, white, Bozai green (looks "surplus"), Kalani orange. Lol flat black works.

The top cover will be painted, the base aluminum with a clear coat. Rubber feet on bottom not shown here.
 
Last edited:
Back
Top