V-Tech Genius Leader / PreComputer 1000/2000/4000

Discussion about other targets
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

V-Tech Genius Leader / PreComputer 1000/2000/4000

Post by hotkey »

Hello everyone,
during the last year I have been reverse-engineering several learning notebooks by V-Tech. They are called "Pre Computer" in the US and "Genius Leader" in Germany. Those laptops were manufactured during the 80s and 90s and are dirt cheap on eBay. They usually offer a standard 1-, 2- or 4-line LCD display, rather complete keyboard, a speaker, a parallel port (!) and a proprietary mouse port.

Initially I just wanted to take all the guts out of them and stick a Raspberry Pi into them, while maintaining the original keyboard (super funky layout by the way, and tons of function keys) and interface with the on-board LCDs on those things. But when I openend up a vintage 2000 model and saw that beautiful Z80 processor at its heart, I just couldn't do it any harm ;-)

So went the long road and analyzed the cartridge port and got into my first hw reverse engineering project.

I am now at as point where I can burn my own EEPROMs which get recognized as "autorun game cartridges", I can display text on the screen, read the keyboard, bit-bang the parallel port to FTDI-compatible levels and even built my own hardware-expander which can be hooked up to an RPi, so you can actually use the laptop as a dumb terminal without modifying the stock hardware! I also wrote a little "debugging console" program that allows for memory inspection, dumping, injecting and even supports turning the laptoip into a MIDI in/out station when attaching DIN-ports to the expander ;-)

I used the z88dk for compilation and pretty much "hacked together" some runtime asm files and headers. They work, but they do not stick to any recommended z88dk platform guidelines. That's why I need your help: I want to port my "hacked together" stuff into nice z88dk platform files.

Since I started that project the z88dk introduced the "new" clib stuff. Honestly, I am a bit overwhelmed on how the platform specific files are spread all over the code base (e.g. take the nc100 files which are in include, lib, libsrc and several sub-directories therein). I kind of lost the overview.... :-(

Can anyone recommend me how to cleanly add the new V-Tech platform using the new lib? Which files are the bare minimum, where should I put them etc. I would like to start with the bare minimum console in/out and add sound, serial, printer etc. later on. I have the sources, I just need to known where they should go.

Any help is greatly appreciated!


Greetings from pre-Octoberfest Munich!
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

It sounds like you've been having some fun :) Is there a community around these devices?
You're targetting a rom cartridge then - do you have access to the full 64k space and how much ram do you have (or maybe you can decide that on cartridge)?
Can anyone recommend me how to cleanly add the new V-Tech platform using the new lib? Which files are the bare minimum, where should I put them etc. I would like to start with the bare minimum console in/out and add sound, serial, printer etc. later on. I have the sources, I just need to known where they should go.
The first step should be a bare initial target so you know all the mechanics are in place.

For the newlib, the source tree is completely contained in:
z88dk/libsrc/_DEVELOPMENT ( https://github.com/z88dk/z88dk/tree/mas ... EVELOPMENT )

The headers are defined in:
z88dk/include/_DEVELOPMENT/proto ( https://github.com/z88dk/z88dk/tree/mas ... MENT/proto )

These headers are written in an m4 form so that they can be expanded for each of the supported c compilers in the ../sccz80, ../sdcc, ../clang subdirectories, which you can look at for a more normal header. The compilers will use their version of the headers.

In the source tree, everything to do with a specific target is in:
z88dk/libsrc/_DEVELOPMENT/target ( https://github.com/z88dk/z88dk/tree/mas ... ENT/target )

For your target, you will create a new directory using the same acronym passed to zcc when compiling. Eg, "zcc +zx ..." is used to compile zx spectrum programs so the zx spectrum gets a "zx" subdirectory.

Inside the target's subdirectory, you will be specifying what functions are part of the library (in library/ - paths are relative to z88dk/libsrc/_DEVELOPMENT), what crt code is available (in startup/ - this is the small bit of code that runs before main to perform initialization and it would also include the restarts if the org address is zero), any drivers (in driver/ - these are mainly for devices that attach to stdio), and configuration information (in config/). The configuration files are normally per "logical unit", eg c library / sound device / etc, and they are collected together by the file "config.m4" in the main target directory.

Outside of the target directory in z88dk/libsrc/_DEVELOPMENT, there are some places for target-specific code. The arch/ subdirectory is set aside for target specific code and it has corresponding header files in z88dk/include/_DEVELOPMENT/proto/arch ( https://github.com/z88dk/z88dk/tree/mas ... proto/arch ).

Some of the code is also intended to be a common cross-platform interface. For example, the input library is intended to be a cross-platform means to read keyboard, joysticks and mice. So z88dk/libsrc/_DEVELOPMENT/input contains code for different targets that implement a common interface to these devices. This is something that can be optionally added later.

Once these files are in place, you inform z88dk of the target's existence by creating a .cfg file in z88dk/lib/config ( https://github.com/z88dk/z88dk/tree/master/lib/config ). Each target's acronym gets a file as in "zx.cfg" for the zx spectrum (zcc +zx ...). This cfg file contains default settings that will be loaded by zcc when it starts.

And you add the target to the list of z80 libraries to build by editing z88dk/libsrc/_DEVELOPMENT/Winmake.bat (for windows) and z88dk/libsrc/_DEVELOPMENT/Makefile (for everything else). Build the library on your own with "Winmake targetname" or "make TARGET=targetname" (eg "Winmake zx" or "make TARGET=zx") from the z88dk/libsrc/_DEVELOPMENT directory.

After these things are done, the target is live and you can specialize it further.

==================

I know that's a lot so maybe the best course is to just enumerate the steps for adding a target in a step by step manner as you're finishing them.


The first goal will be to have a bare minimum target functioning.

1. Pick an acronym that is used in compile lines as in "zcc +vt2k .." (I don't know what the best one would be - here I'm trying on vtech2000). The acronym should be short and descriptive somehow and needs to be unique in z88dk/lib/config ( https://github.com/z88dk/z88dk/tree/master/lib/config ) because it will be getting a cfg file there.

2. Create a target directory in z88dk/libsrc/_DEVELOPMENT/target ( https://github.com/z88dk/z88dk/tree/mas ... ENT/target ). You can see there are directories for cpm,zx,etc. Add another like "vt2k".

3. Copy the contents of z88dk/libsrc/_DEVELOPMENT/target/z80 to z88dk/libsrc/_DEVELOPMENT/target/vt2k. The z80 target is the minimum newlib target. So copying that will get you to the minimum state quickly.

4. Inside the new z88dk/libsrc/_DEVELOPMENT/target/vt2k, delete "config_z80.h", "config_z80_private.inc", "config_z80_public.inc". These files are automatically generated when the library is built.

Modify each of the new files for the vt2k target.

5. In z88dk/libsrc/_DEVELOPMENT/target/vt2k/config:

"config_clib.m4" does some configuration of the library. You can make any changes you like up to line 512 ( https://github.com/z88dk/z88dk/blob/mas ... ib.m4#L512 ) where the end of the user configuration is - the rest of the lines are just generating output from the config. You probably won't want to make any changes.

"config_clib.m4.bak" should be a copy of "config_clib.m4". This is intended to allow someone to make changes to the main file and then quickly change them back by restoring from the backup.

"config_clib_const.m4" contains clib constant definitions, of which there are none for now. Things like ioctl messages will go here when the stdio drivers are written.

"config_clib_const.m4.bak" is a copy of "config_clib_const.m4"

"config_cpu.m4" contains information on the z80. You'll want to set the correct clock "define(`__CPU_CLOCK', 4000000)". If you have an nmos z80 or you don't know, always keep options on nmos z80. There is a bug concerning the "ld a,i" instruction in nmos z80s for which the library can provide a workaround that will work on both nmos and cmos z80s.

"config_cpu.m4.bak" is a copy of "config_cpu.m4"

"config_target.m4" contains defines pertaining to the machine itself. This file is also defining a label that will be used to identify the target while compiling and assembling. You'll want to do a search and replace of "__EMBEDDED_Z80" with something like "__VT2K" over the entire file. You may also be giving names to io ports here - see some of the other targets for examples. We always have two leading underscores for names in config files so that they remain in the "system's namespace". The idea is c headers will selectively expose these names by eliminating the two leading underscores.

"config_target.m4.bak" is a copy of "config_target.m4"

6. In z88dk/libsrc/_DEVELOPMENT/target/vt2k/library:

The three files here determine what functions go into the target's library. Initially you want all the generic stuff and none of the target-specific things. The list files copied from the z80 target do exactly that so you shouldn't have to make any changes. But you can see what is in the library by following the list files yourself. The root directory for the list files is z88dk/libsrc/_DEVELOPMENT.

There are three list files here for three different versions of the library: one version is for sccz80, one for sdcc_ix and one for sdcc_iy (sdcc operated with --reserve-regs-iy flag).

7. In z88dk/libsrc/_DEVELOPMENT/target/vt2k/startup

This directory contains all the crts - ie the startup code. Some targets have many, you'll be starting with one. The mechanism that z88dk uses to select a specific crt is via a startup value either provided on the compile line (-startup=10) or selected in the target's cfg file. So the crts are typically numbered by startup value and here the crt is number 0.

Rename the crt from "z80_crt_0.asm.m4" to "vt2k_crt_0.asm.m4"

Editing "vt2k_crt_0.asm.m4" ( https://github.com/z88dk/z88dk/blob/mas ... t_0.asm.m4 ):

lines 1-9 you'll want to change the comments to reference the vtech pre-computer 2000 and update the path listed.

line 15, change to include "config_vt2k_public.inc". This will be a file containing all the defined constants from the config directory. When the library is built, the file will be generated.

line 24, change to include(`vt2k_rules.inc'). This file will process target-specific pragmas, of which you will initially have none.

The compile time options are a collection of defaults overruled by compile-time pragmas:
https://www.z88dk.org/wiki/doku.php?id= ... figuration
The rules files are determining the final value of those compile time options, which the crt will implement (or not, but the ones provided by z88dk do).

line 30 sets the memory map. No change here.

lines 32-49 is driver instantiation. This is where devices are attached to stdin, stdout, stderr. For now, leave as is. There will be no stdin,stdout,stderr defined. This section is the primary difference between crts for a target.

lines 61-70 no change. The user can choose to insert code that is executed first with appropriate pragma.

lines 72-80 no change. If the org is 0, the page zero code will be supplied ( https://github.com/z88dk/z88dk/blob/mas ... ro_z80.inc )
Inside the crt the root dir for includes is z88dk/libsrc/_DEVELOPMENT/target/vt2k . If you need different page zero code, you would include it here and save it in target/vt2k as include "crt_page_zero_vt2k.inc" or similar.

line 86 is where the main part of the crt starts. It's going to optionally disable interrupts, optionally set the stack location, optionally set a command line for argc/argv (this code will do none or empty), initialize data and bss sections. Most likely no changes.

line 124. section code_crt_init allows programs to insert initialization code just before main is called.
Then interrupts are optionally enabled and main is called.

After that there's the exit stack to run and returning (or not) appropriately to the caller.
None of these things you are likely to have to change - you will instead be setting compile time defaults that will govern default behaviour below.

8. In z88dk/libsrc/_DEVELOPMENT/target/vt2k/config.m4

lines 39-43 change the paths from "target/z80/..." to "target/vt2k/..."
This file gathers all the config files from the config directory.

9. In z88dk/libsrc/_DEVELOPMENT/target/vt2k/crt_config.inc ( https://github.com/z88dk/z88dk/blob/mas ... config.inc )

This is where you will define the default compile time behaviour such as where in memory things go and how the program exits.
Have this page open ( https://www.z88dk.org/wiki/doku.php?id= ... figuration ) to understand the settings.

You're targetting a rom cartridge so it will only make sense to do rom and compressed-rom compiles. So you may want to get rid of the CRTCFG=0 case in lines 16-61.
Instead of "embedded rom model" you can put "vt2k rom model".

"crt_config.inc.bak" should be a copy of "crt_config.inc"

10. In z88dk/libsrc/_DEVELOPMENT/target/vt2k/crt_memory_map.inc

No change. This sets the memory map for the compile and the library supplied one is adequate for 64k systems.

11. In z88dk/libsrc/_DEVELOPMENT/target/vt2k/z80_rules.inc

Rename to vt2k_rules.inc. This is an empty file as you don't have any target specific pragmas yet.

12. In z88dk/libsrc/_DEVELOPMENT/target/vt2k/z80_crt.asm.m4

Rename to vt2k_crt.asm.m4. This is the master crt that selectes the actual crt used from the startup directory depending on the startup value.

lines 24-39. The user is supplying a crt, you supply defaults for CRTCFG and MMAP. The values were defined in crt_config.inc and crt_memory_map.inc.

lines 41-111. You define cases for different startup values. The startup values are going to indicate quick default configurations. I would keep startup=1 and 2 as they define rom and compressed rom compiles as defined for the z80 target. You may want to change the startup values when you add console io.

line 8. Choose a default compile by selecting a default startup value.

===========

Add the vt2k target to the library build list.

13. In z88dk/libsrc/_DEVELOPMENT/Winmake.bat

line 8 add vt2k in alphabetical order.

14. In z88dk/libsrc/_DEVELOPMENT/Makefile

line 5 add vt2k in alphabetical order.

You should now be able to build the vt2k library without errors.
From a console in z88dk/libsrc/_DEVELOPMENT

run "Winmake vt2k" (windows) to build the vt2k libraries
run "make TARGET=vt2k" (other) to build the vt2k libraries

The library files will be deposited in the subdirectories of z88dk/libsrc/_DEVELOPMENT/lib

============

Make z88dk aware of the new target.

Create file z88dk/lib/config/vt2k.cfg :

Code: Select all

#
# Target configuration file for z88dk
#

# Asm file which contains the startup code (without suffix)
# Not supported in classic library
CRT0                 DESTDIR/lib/vt2k_crt0

# Any default options you want - these are options to zcc which are fed
# through to compiler, assembler etc as necessary
OPTIONS                 -v -O2 -SO2 -iquote. -D__Z88DK -D__VT2K -D__Z80 -clib=sdcc_iy -subtype=default

CLIB     default -lvt2k_clib -lndos -Cc-standard-escape-chars
CLIB     new -Cc-standard-escape-chars -D__SCCZ80 -Ca-D__SCCZ80 -Cl-D__SCCZ80 -nostdlib -isystemDESTDIR/include/_DEVELOPMENT/sccz80 -Ca-IDESTDIR/libsrc/_DEVELOPMENT/target/vt2k -lvt2k -LDESTDIR/libsrc/_DEVELOPMENT/lib/sccz80 -Cl-IDESTDIR/libsrc/_DEVELOPMENT/target/vt2k -crt0=DESTDIR/libsrc/_DEVELOPMENT/target/vt2k/vt2k_crt.asm.m4
CLIB     sdcc_ix -compiler=sdcc -D__SDCC -D__SDCC_IX -Ca-D__SDCC -Ca-D__SDCC_IX -Cl-D__SDCC -Cl-D__SDCC_IX -nostdlib -isystemDESTDIR/include/_DEVELOPMENT/sdcc -Ca-IDESTDIR/libsrc/_DEVELOPMENT/target/vt2k -lvt2k -LDESTDIR/libsrc/_DEVELOPMENT/lib/sdcc_ix -Cl-IDESTDIR/libsrc/_DEVELOPMENT/target/vt2k -crt0=DESTDIR/libsrc/_DEVELOPMENT/target/vt2k/vt2k_crt.asm.m4
CLIB     sdcc_iy -compiler=sdcc --reserve-regs-iy -D__SDCC -D__SDCC_IY -Ca-D__SDCC -Ca-D__SDCC_IY -Cl-D__SDCC -Cl-D__SDCC_IY -nostdlib -isystemDESTDIR/include/_DEVELOPMENT/sdcc -Ca-IDESTDIR/libsrc/_DEVELOPMENT/target/vt2k -lvt2k -LDESTDIR/libsrc/_DEVELOPMENT/lib/sdcc_iy -Cl-IDESTDIR/libsrc/_DEVELOPMENT/target/vt2k -crt0=DESTDIR/libsrc/_DEVELOPMENT/target/vt2k/vt2k_crt.asm.m4
CLIB     clang_ix -compiler=clang -D__SDCC -D__SDCC_IX -Ca-D__SDCC -Ca-D__SDCC_IX -Cl-D__SDCC -Cl-D__SDCC_IX -nostdlib -isystemDESTDIR/include/_DEVELOPMENT/sdcc -Ca-IDESTDIR/libsrc/_DEVELOPMENT/target/vt2k -lvt2k -LDESTDIR/libsrc/_DEVELOPMENT/lib/sdcc_ix -Cl-IDESTDIR/libsrc/_DEVELOPMENT/target/vt2k -crt0=DESTDIR/libsrc/_DEVELOPMENT/target/vt2k/vt2k_crt.asm.m4
CLIB     clang_iy -compiler=clang --reserve-regs-iy -D__SDCC -D__SDCC_IY -Ca-D__SDCC -Ca-D__SDCC_IY -Cl-D__SDCC -Cl-D__SDCC_IY -nostdlib -isystemDESTDIR/include/_DEVELOPMENT/sdcc -Ca-IDESTDIR/libsrc/_DEVELOPMENT/target/vt2k -lvt2k -LDESTDIR/libsrc/_DEVELOPMENT/lib/sdcc_iy -Cl-IDESTDIR/libsrc/_DEVELOPMENT/target/vt2k -crt0=DESTDIR/libsrc/_DEVELOPMENT/target/vt2k/vt2k_crt.asm.m4

SUBTYPE  none 
SUBTYPE default -Cz+rom
"CRT0" and "CLIB default" specify things for the classic library so have nothing to do with newlib. (Your target will not work with classic until another crt and library for it is added).
"OPTIONS" defines "__VT2K" - this should be the same symbol as defined in the config file way back.
"SUBTYPE default" is causing "appmake +rom" to be used when -create-app appears on the compile line. It will make a rom as output. If you want an intel hex file too, you can add the relevant option.

=======

Add a case in arch.h:
https://github.com/z88dk/z88dk/blob/mas ... oto/arch.h

Code: Select all

#ifdef __VT2K
#include <../../../libsrc/_DEVELOPMENT/target/vt2k/config_vt2k.h>
#endif
This will allow the defines from your config files to be made available with #include <arch.h>.

Rebuid the headers by running "Winmake" (windows) or "make" (other) from:
z88dk/include/_DEVELOPMENT/


=========


At this point you should have a functioning minimal target.


Try compiling:

Code: Select all

#include <stdio.h>

unsigned char buffer[100];

void main(void)
{
   sprintf(buffer, "Hello World\n");
}
(sdcc as compiler)
zcc +vt2k -vn -clib=sdcc_iy -SO3 --max-allocs-per-node200000 hello.c -o hello -create-app

and

(sccz80 as compiler)
zcc +vt2k -vn -clib=new hello.c -o hello -create-app

Maybe check that the binary generated is ok by disassembling using z88dk-dis or other.


If you got this far the next step would be console io.
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

Thank you, alvin!!

This is what I call extensive :-) I will give it a shot!

And for your question about community:
* No, there is no community around these machines (that I know of), but there is absolutely no reason not to start one. These machines get thrown out of households, because children grow up and want their iPads, so now is the time to get hold of them. Pulling one of these out of your backpack as a serious RaspberryPi console just has sooo much style! Even makes your local Starbuck's Hipsters go green with envy :-)

* There is actually (limited) emulation support on MAME when searching for "PreComputer 1000/2000" or using the ROM ids "gl2000", "gl2000p", "gj4000", "gl4004" or "gj5000". Those are marked as "NOT WORKING", but it worked well enough for simple I/O and sound. To get the ROMs you can dump your own or consider finding ...errrr.... some sort of "paradise" of "emus" somewhere and search for the term "Genius"...

* I can also provide annotated pictures of the PCBs which took me quite some time to trace and label. But especially the older models are just text-book-style Z80 systems with nicely layed out busses, ROMs, RAM and just one proprietary chip that handles keyboard and LCD (I simply call it the "V-Chip" ;-) )


With my old implementation I needed to store some variables, but my C skills weren't sufficient enough to find an elegant solution of forcing the heap to be at 0xC000- so I used "extern" with explicitly specified address, like "extern byte a @VTECH_VAR_START+0". Super dirty, but it works for the most basic cases.

What is the most elegant mechanics of forcing the heap to be at a certain location? Are there reserved symbols/arguments/switches/defines for that? (I am really not experienced in those sorts of compilation "voodoo")
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

Ah! Found it! crt_config.inc is the file I was desparately searching for.
The newlib way of doing things is really THAT much neater -- totally loving it!

Thank you again, alvin!
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

hotkey wrote:With my old implementation I needed to store some variables, but my C skills weren't sufficient enough to find an elegant solution of forcing the heap to be at 0xC000- so I used "extern" with explicitly specified address, like "extern byte a @VTECH_VAR_START+0". Super dirty, but it works for the most basic cases.

What is the most elegant mechanics of forcing the heap to be at a certain location? Are there reserved symbols/arguments/switches/defines for that? (I am really not experienced in those sorts of compilation "voodoo")
I think you found it but one of the compile time variables "CLIB_MALLOC_HEAP_SIZE" controls the heap and its default setting is set by you in crt_config.inc.

The documentation for this variable:
https://www.z88dk.org/wiki/doku.php?id= ... figuration

You can see a picture of memory usage for the default case here:
https://www.z88dk.org/wiki/doku.php?id= ... e_compiler

When generating roms you have the code section stored in rom and then the DATA/BSS sections stored in ram with the stack at the top of the ram block. To get that arrangement you set CRT_ORG_CODE to first available rom address (maybe 0x0), CRT_ORG_DATA to the first ram address (maybe 0x8000), CRT_ORG_BSS to -1 (so that it appends to DATA) and REGISTER_SP = 0 (stack grows downward, first used address is 0xffff). Then if CLIB_MALLOC_HEAP_SIZE=-1, the crt will take all the space between the end of BSS to the bottom of the stack for the heap. The heap size is a runtime calculation and if it comes out negative, the program will silently exit instead of starting. If CLIB_MALLOC_HEAP_SIZE is a value greater than 14, then a heap of that size will be made part of the BSS section, so that's a second way to get the heap in ram someplace.

If you need the heap at a specific memory location, there is a write-up on that:
https://www.z88dk.org/wiki/doku.php?id= ... y_location

What you do is tell the crt not to make a heap (CLIB_MALLOC_HEAP_SIZE=0) and then you create one yourself at a specific memory location as part of the compile. This is something that is intended to be done by the user at compile time but if there is a special need, the crt can replace the library's heap creation code and use its own and in that case the crt can create whatever heap it needs to.
The newlib way of doing things is really THAT much neater -- totally loving it!
When the assembler saw some significant updates, there was an opportunity to rethink things from scratch. So far it's looking to be a very flexible system able to meet all needs so far.
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Post by stefano »

I remember I sent vtech an email more than 15 years ago asking for technical references, but they never answered. Well done !
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

Yay, it compiles!
I called the platform "vgl" (as in "V-Tech Genius Leader"), since just "gl" might collide with future Z80 OpenGL implementations ;-)

The new lib is perfect for all the different start up signatures I have identified for this platform. There are standard ROMs, auto-start ROMs, quiz-ROMs (data only) and file system like SRAM cartridges. In my own dev console I also allow run-time code injection, so a RAM model is absolutely useful, too.

For anyone interested I've uploaded the PCB trace of my model 2000 which helped me on my journey so far:
http://projects.spr.at/content/VTechInt ... ard002.pdf

I'll keep you all updated on my progress of actually implementing the I/O.
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

Update: I have forked the project to
https://github.com/hotkeymuc/z88dk
and I am busy incorporating all the steps alvin told me. The new platform has been created and +vgl already compiles, resulting in somewhat valid ROM binaries.

Today I started implementing the I/O drivers. So far, it compiles, but it doesn't do much instead of NOT crashing - which is at least something ;-) Oh, and I have a working "beep()" function, which is my small beacon of hope ;-)

The V-Tech I/O is handled by the "V-Chip", so we get easy keyboard input without having to do manual scanlines. The V-Chip provides a "reset/poll" memory-mapped interface for the keyboard (0xdce0 / 0xdb00) , as well as a character memory (0xdca0-0xdcef) to write to.

I am still struggling a bit to find my way around all those small asm fragments needed for terminal input/output, but I think I am eventually mastering it.

Thank you for the great support so far! (and expect a pull request soon! :-) )
stefano
Well known member
Posts: 2137
Joined: Mon Jul 16, 2007 7:39 pm

Post by stefano »

It looks great ! Congratulations for your achievement !
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

hotkey wrote:Thank you for the great support so far! (and expect a pull request soon! :-) )
That's great -- look forward to it.
I am still struggling a bit to find my way around all those small asm fragments needed for terminal input/output, but I think I am eventually mastering it.
Yes I expect you would need some help here. I'll come back later tonight and add some information.

stdio in newlib is object oriented. It generates a small set of messages that are delivered to the driver. Your driver can implement those messages directly or you can subclass from a library driver that does some of the work. The latter is most appropriate for console and all the targets in newlib do some sort of subclassing. There is a class for basic putchar/getchar, on top of that there is a fixed-width font terminal that does windows and on top of that there is a proportional text driver for bitmapped displays.

The subclassing is quite simple. First your code gets the stdio message and you check if you want to deal with it. If not, you forward the message to the parent class.
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

alvin wrote:stdio in newlib is object oriented. It generates a small set of messages that are delivered to the driver. Your driver can implement those messages directly or you can subclass from a library driver that does some of the work.
I have a proof-of-concept CHARACTER driver working! It is hackisch, but at least you can do a printf("hello world") and it actually does that. By looking on the other system's implementations it was pretty clear how the messaging and inheritance of functionality works. (Another proof that the newlib is really clear in what it does).

The V-Chip seems to support character output (via ports 0x0a and 0x0b) as well as direct VRAM manipulation. I do not fully understand the port accesses, yet, so I am using manual VRAM-poking. As far as I understand, I should hence be implementing a TERMINAL driver (manual scrolling and cursor position management etc.) instead of a CHARACTER driver.

For now I have a proof-of-concept CHARACTER driver, just because it only requires the "printc"-message in order to show something on screen.
Since I have VRAM access, a TERMINAL driver would be much more suitable. I have all the neccessary "set cursor to pos X/Y", "scroll up", "switch cursor visibility on/off" etc. methods working, even the BELL ;-)

I have two small questions:

* How does the newlib decide whether to use the TERMINAL or the CHARACTER driver on systems where both of them are implemented? Could you perhaps give me a small overview on how the control flow of a simple prtintf() usually is?

* In case of the TERMINAL driver: How/where should I declare my internal variables (current cursor position, current system's number of rows, ...)? Is there a standardized way of declaring them or does the parent terminal driver have those automatically somewhere?

Cheers!
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

hotkey wrote:I have two small questions:

* How does the newlib decide whether to use the TERMINAL or the CHARACTER driver on systems where both of them are implemented? Could you perhaps give me a small overview on how the control flow of a simple prtintf() usually is?
There is a driver instantiation section in the crt. I've give you a long winded example from the cpm target just to show you have freedom to create more than just stdin/stdout/stderr:

https://github.com/z88dk/z88dk/blob/mas ... asm.m4#L65

Code: Select all

include(`../clib_instantiate_begin.m4')

ifelse(eval(M4__CRT_INCLUDE_DRIVER_INSTANTIATION == 0), 1,
`
   include(`driver/terminal/cpm_00_input_cons.m4')
   m4_cpm_00_input_cons(_stdin, 0x0100, M4__CRT_ITERM_EDIT_BUFFER_SIZE)

   include(`driver/terminal/cpm_00_output_cons.m4')
   m4_cpm_00_output_cons(_stdout, 0x0010)

   include(`../m4_file_dup.m4')dnl
   m4_file_dup(_stderr, 0x80, __i_fcntl_fdstruct_1)dnl

   include(`driver/character/cpm_00_input_reader.m4')
   m4_cpm_00_input_reader(_stdrdr, 0x0100)

   include(`driver/character/cpm_00_output_punch.m4')
   m4_cpm_00_output_punch(_stdpun, 0x0010)

   include(`driver/character/cpm_00_output_list.m4')
   m4_cpm_00_output_list(_stdlst, 0x0010)
',
`
   include(`crt_driver_instantiation.asm.m4')
')

include(`../clib_instantiate_end.m4')
What is happening here is that between the "begin" and "end" macros, each driver's m4 file is creating static structures in memory to hold their data. In addition, the library's file descriptor table and FILE* are being created incrementally. The file descriptors are assigned in order from 0 and up. The first driver instantiation "driver/terminal/cpm_00_input_cons.m4" is being placed on fd=0 which is stdin by convention in the library. Likewise, fd=1 and fd=2 should be stdout and stderr respectively. There's more than that for the cpm target because cpm defines other standard streams associated with punch cards, printer and whatever. FILE* associated with the driver are optionally created by name. So you can see "_stdout" up there - this corresponds to C name "stdout" (the compiler always adds preceding underscore to names). If you leave that entry blank, there will be no FILE* created, only a file descriptor. There are also "drivers" provided by the library that allow you to skip a particular file descriptor (maybe you don't have stdin) or allow you to dup another file descriptor (stderr = stdout for example).

The strategy in the library is to create many crts for each common set of driver instantiations and then the user can choose one by startup value in the compile line. One of these crts should be a minimal one where there are no drivers instantiated. Many people want that to have the option of using lower level output functions instead (like the set of primitives you've already written).

We're also going a step further, which I can use the zxn target as example.

The zxn target has these basic crts and associated startup value:

crt 0 = standard 32 column screen with input
crt 1 = standard 32 column screen understands escape sequencs, with input
crt 4 = 64 columns with input
crt 5 = 64 columns understands escape sequences, with input
crt 8 = proportional fonts with input
crt 9 = proportional fonts understands escape sequences, with input
crt 30 = use rom driver no input (primarily to reduce program size)
crt 31 = no drivers instantiated.

The above crts are meant for the most common compile for the machine's ram and are selected like this on the compile line:
zcc +zxn -startup=5 ....

However, there are other types of compiles that need a different memory map. But we still want the same basic set of drivers. For those compiles we're defining new crts with an offset added:

crt 0+256 = standard 32 column screen with input
crt 1+256 = standard 32 column screen understands escape sequencs, with input
crt 4+256 = 64 columns with input
crt 5+256 = 64 columns understands escape sequences, with input
crt 8+256 = proportional fonts with input
crt 9+256 = proportional fonts understands escape sequences, with input
crt 30+256 = use rom driver no input (primarily to reduce program size)
crt 31+256 = no drivers instantiated.

These are for dot commands which compile to a different region of memory. The compile line uses the same crt values as the first set but a subtype is added to the compile:
zcc +zxn -startup=5 -subtype=dot ...

The user gets the expected 64 column driver with startup=5. This magic happens in the target's cfg file, zxn.cfg ( https://github.com/z88dk/z88dk/blob/mas ... ig/zxn.cfg ).

Line 32:
SUBTYPE dot -Cz"+zxn --dot" -startupoffset=0x100

If "-subtype=dot" appears on the compile line those options are added, including "-startupoffset=0x100" which will add 256 to the startup value and that's how we get the corresponding dot command crt instead of the regular crt5.

The subtypes are mainly used to determine an output file format. For the zxn's case it determines output file format and compile type via the offset.


======


The control flow for printf:

1. Printf generates a character or string fragment for output in a temporary buffer on the stack.

2. A stdio message STDIO_MSG_PUTC or STDIO_MSG_WRIT is created to communicate the string fragment to print to the driver. See https://github.com/z88dk/z88dk/blob/mas ... me.txt#L90 . The message is simply setting up registers in a certain way.

3. FILE* stdout is loaded into IX. IX now points at a FILE structure ( https://github.com/z88dk/z88dk/blob/mas ... me.txt#L10 ). You'll note that ix+0,ix+1,ix+2 hold a jump instruction to the corresponding file descriptor. This structure is mainly for stdio as it holds state corresponding to generating character output. So the library will access that data with ix+n addressing and when its ready to send a message it exectues an effective "call ix". This then transfers control to the file descriptor device.

4. The call through the FILE* actually jumps into a new data structure called FDSTRUCT that is associated with the driver. I don;t think this is documented on github yet. The FDSTRUCT contains some code that acquires a lock and then advances IX to point at the FDSTRUCT proper. This part contains a new JP at ix+0,ix+1,ix+2 that will jump to your driver code. So when your driver runs, you can send messages to yourself by executing an effective "call ix" (in the library "call l_jpix" where "l_jpix: jp (ix)") and the parent classes that you inherit from will do this, consuming messages you don't handle and generating new messages that you do handle.

The first seven bytes or so of the FDSTRUCT ix+0->ix+7 are used by the library. After that, drivers append their own data. So if you inherit from a library class, it will put data on ix+8 and higher. Then if you want to add data, you would simply append to whatever they need and you would access it via ix+? in your code. It is the m4 instantiation in the driver section of the crt that creates this structure statically in memory at compile time.

As an example, if you subclass " " to implement a windowed fixed width font terminal, the FDSTRUCT would contain this ( https://github.com/z88dk/z88dk/blob/mas ... r.asm#L169 ):

Code: Select all

; offset (wrt FDSTRUCT.JP)  description
;
;  8..13                    mutex
;   14                      x coordinate
;   15                      y coordinate
;   16                      window.x
;   17                      window.width
;   18                      window.y
;   19                      window.height
;   20                      scroll_limit
If your driver needs more data you would append to this structure and use offsets 21 and up.

This driver will take care of most things and it expects you to implement a few messages (line 59 https://github.com/z88dk/z88dk/blob/mas ... ar.asm#L59 ):

; * OTERM_MSG_TTY (optional)
; * OTERM_MSG_PRINTC
; * OTERM_MSG_BELL (optional)
; * OTERM_MSG_SCROLL
; * OTERM_MSG_CLS
; * OTERM_MSG_PAUSE
; * ITERM_MSG_BELL (optional)

The optional ones you can skip.

* In case of the TERMINAL driver: How/where should I declare my internal variables (current cursor position, current system's number of rows, ...)? Is there a standardized way of declaring them or does the parent terminal driver have those automatically somewhere?
The parent driver will manage most state that you will need. If you need more, you just append to the data structure as mentioned.

The zx target does this. This driver ( https://github.com/z88dk/z88dk/blob/mas ... 2.asm#L141 ) subclasses from the terminal driver described above and expands the structure like this:

Code: Select all

; offset (wrt FDSTRUCT.JP)  description
;
;  8..13                    mutex
;   14                      x coordinate
;   15                      y coordinate
;   16                      window.x
;   17                      window.width
;   18                      window.y
;   19                      window.height
;   20                      scroll_limit
; 21..22                    font address
;   23                      text colour
;   24                      text colour mask (set bits = keep bgnd)
;   25                      background colour (cls colour)
Offsets up to 20 come from the base class and then this driver adds more state to keep track of font and colour.

This extra data must be added in the m4 static instantiation used in the crt.

You can see the zx instantiator here https://github.com/z88dk/z88dk/blob/mas ... 32.m4#L142
Line 142 you can see the last few bytes up to scroll limit from the base class. Then the extra bytes are added. When extra bytes are added, there is also a data structure size that has to be modified. The m4 instantiator is setting up the data structure for the library too so it's a bit freaky. If you need help with this let me know.
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

Update: I am making progress! :-D
Thanks to your info, I was able to implement a working terminal output driver, including setting the cursor and scrolling. The number of "dirty boot instructions" is shrinking at a fast pace, finding their new home in dedicated drivers. I even found more information on those mysterious ports 0x0a and 0x0b -- turns out, they are just directly connected to the HD44780(ish) LCD driver and accept all the common commands. Now even the weird series of "0x38" values being sent to that port in my disassemblies make sense, as they are just run-off-the-mill LCD init instructions. Yay!


Now, I got somehow stuck in "terminal input driver land"... I looked at other terminal drivers and paid close attention to the heap sizes inside the driver instanciation, the message types and all that goodness.

But still, it seems as if my ITERM_MSG_GETC handler does not get called at all when I invoke a "getchar()" in C. The call returns immediately with a "random" byte as its return value, even though I implemented a blocking call. Very strange (for me)...

Is there anything more I need to take care of, in order to get input working? Is there, for example, a STDIO_MSG_ICTL I must answer or do the CRT_ITERM_TERMINAL_FLAGS need to have a specific value (could not find any information on them)? Any hint on the flow of "getchar()" would be great!
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

hotkey wrote:Update: I am making progress! :-D
Thanks to your info, I was able to implement a working terminal output driver, including setting the cursor and scrolling. The number of "dirty boot instructions" is shrinking at a fast pace, finding their new home in dedicated drivers. I even found more information on those mysterious ports 0x0a and 0x0b -- turns out, they are just directly connected to the HD44780(ish) LCD driver and accept all the common commands. Now even the weird series of "0x38" values being sent to that port in my disassemblies make sense, as they are just run-off-the-mill LCD init instructions. Yay!
Great!
Is there anything more I need to take care of, in order to get input working? Is there, for example, a STDIO_MSG_ICTL I must answer or do the CRT_ITERM_TERMINAL_FLAGS need to have a specific value (could not find any information on them)? Any hint on the flow of "getchar()" would be great!
The good news is the input side should be easier to do than the output.

If you're inheriting from CONSOLE_01_INPUT_TERMINAL ( https://github.com/z88dk/z88dk/blob/mas ... al.asm#L37 ) then you shouldn't have to implement more than ITERM_MSG_GETC unless you need to update your own state in response to flush, etc and you may have to do that too.

There are two main types of input drivers implemented in the library now:


1.
Like zx_01_input_kbd_inkey ( https://github.com/z88dk/z88dk/blob/mas ... _inkey.asm ). This one is a poll method that scans pressed / unpressed state of keys and implements things like repeat period, repeat rate, etc. It deals with raw hardware with keys read as switch state.

* ITERM_MSG_GETC ( https://github.com/z88dk/z88dk/blob/mas ... g_getc.asm )

All the code here is generic except the call to asm_in_inkey (this is a cross platform function defined in the input library which is technically generic if it's implemented for the target). asm_in_inkey returns 0 if no key is pressed (this includes multiple simultaneous keypresses) or else the ascii code of the keypress. Most of the code is taking care of repeat and all that. The bit at line 150 is doing some cr/lf conversion. The C side only wants to see CHAR_LF for line terminators so a keyboard end of line (eg ENTER) should be mapped to CHAR_LF. The library is normally set to shorten CR/LF sequences to LF outside this function.

* STDIO_MSG_FLSH ( https://github.com/z88dk/z88dk/blob/mas ... g_flsh.asm )

This only forwards to the library so it looks like some driver-specific state was being cleared on flush but then that was removed.

* STDIO_MSG_ICTL ( https://github.com/z88dk/z88dk/blob/mas ... g_ictl.asm )

ioctls were added to reset driver-specific state and to set key repeat rates, etc. You can straight copy this or eliminate it.


2.
Like cpm_01_input_kbd_dcio ( https://github.com/z88dk/z88dk/blob/mas ... d_dcio.asm ). This one gets ascii characters from some driver. This could be an os call as in cpm. The main characteristic is that the driver takes care of repeat and all that.

* ITERM_MSG_GETC ( https://github.com/z88dk/z88dk/blob/mas ... g_getc.asm )

The code just requests a key and loops until it gets one, followed by character set translation as above.

* ITERM_MSG_INTERRUPT ( https://github.com/z88dk/z88dk/blob/mas ... errupt.asm )

This could also be implemented for the previous driver but may not be necessary. In cpm, it's expected that ctrl-c terminates the program so that's what this does. If your code returns to call with interrupt indicated, the input driver will stop line editing and deliver the line as is with crtl code at the end (I think? I can't recall if it puts the ctrl code at front).

* STDIO_MSG_FLSH ( https://github.com/z88dk/z88dk/blob/mas ... g_flsh.asm )

cpm's internal input buffer is flushed by reading from it until no keys are returned. Then the flush is forwarded to the base class.


The main function to implement is ITERM_MSG_GETC. The m4 instantiation can be variations on these - the input buffer is normally set to 64 by default in the target's crt file.

Eg, from the zx's crt file ( https://github.com/z88dk/z88dk/blob/mas ... asm.m4#L80 ):

Code: Select all

include(`driver/terminal/zx_01_input_kbd_inkey.m4')dnl
m4_zx_01_input_kbd_inkey(_stdin, __i_fcntl_fdstruct_1, CRT_ITERM_TERMINAL_FLAGS, M4__CRT_ITERM_EDIT_BUFFER_SIZE, CRT_ITERM_INKEY_DEBOUNCE, CRT_ITERM_INKEY_REPEAT_START, CRT_ITERM_INKEY_REPEAT_RATE)dnl
The default values of these variables are coming from a zx_rules.inc file ( https://github.com/z88dk/z88dk/blob/mas ... _rules.inc ) that is included at the top of the crt. This way these values can be overridden by the user using pragmas at compile time.

Code: Select all

   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   ; Input Terminal Settings
   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

   IFNDEF CRT_ITERM_TERMINAL_FLAGS
      defc CRT_ITERM_TERMINAL_FLAGS = 0x03b0
   ENDIF

   ; buffer size must be available to m4 (requires special case in zcc)
   
   ifdef(`M4__CRT_ITERM_EDIT_BUFFER_SIZE',,`define(`M4__CRT_ITERM_EDIT_BUFFER_SIZE', 64)')

   IFNDEF CRT_ITERM_EDIT_BUFFER_SIZE
      defc CRT_ITERM_EDIT_BUFFER_SIZE = M4__CRT_ITERM_EDIT_BUFFER_SIZE
   ENDIF

   ;
   ; LASTK Input Terminal Only
   ;

   IFNDEF CRT_ITERM_LASTK_ADDRESS
      defc CRT_ITERM_LASTK_ADDRESS = 23560
   ENDIF

   ;
   ; INKEY Input Terminal Only (used by supplied CRTs)
   ;

   IFNDEF CRT_ITERM_INKEY_DEBOUNCE
      defc CRT_ITERM_INKEY_DEBOUNCE = 1
   ENDIF

   IFNDEF CRT_ITERM_INKEY_REPEAT_START
      defc CRT_ITERM_INKEY_REPEAT_START = 500
   ENDIF

   IFNDEF CRT_ITERM_INKEY_REPEAT_RATE
      defc CRT_ITERM_INKEY_REPEAT_RATE = 15
   ENDIF
For the terminal flags:

Code: Select all

   IFNDEF CRT_ITERM_TERMINAL_FLAGS
      defc CRT_ITERM_TERMINAL_FLAGS = 0x03b0
   ENDIF

bits 15..10  reserved (includes some state for driver base class)
bit 9 = 1 to enable printed cursor
bit 8 = 1 to enable crlf conversion (will be filtered to generate lf only)
bit 7 = 1 to echo typed input characters
bit 6 = 1 to enable password mode (input printed as *)
bit 5 = 1 to enable line mode (input is edited before being delivered)
bit 4 = 1 to enable cook mode (input characters are interpretted in some way)
bit 3 = 1 for caps lock
bits 2..0  reserved (device state)
The ascii codes that the base class uses for things like caps lock (see https://github.com/z88dk/z88dk/blob/mas ... c.asm#L233 ) are defined in the target's clib config file ( https://github.com/z88dk/z88dk/blob/mas ... ib.m4#L242 ). These are the program side ascii codes and are the codes after your (optional) character set translation in the driver.


====


Flow for getchar :-

1. If there is an unget char available return that.
2. Send message STDIO_MSG_GETC to the driver ( https://github.com/z88dk/z88dk/blob/mas ... e.txt#L134 ).
3. Your driver will likely forward this to the base class ( https://github.com/z88dk/z88dk/blob/mas ... c_getc.asm ) where line editing may occur if a previous line is not present. Any keyboard reading is done by sending an ITERM_MSG_GETC message to your driver. As long as you obey the register preservation and return values (including carry flag state) then it should work ok.
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

Thank you, alvin.

I have re-written my input driver from scratch (for the 3rd time now), based on the cpm_01_input_kbd_dcio. When I was done, I did a diff and was actually byte-identical to my previous attempts. I also quadrouple-checked that my FDSTRUCT points to "console_01_input_terminal_fdriver" and my own "vgl_01_input_kbd" with all the rest of the struct being the same as other drivers. The heap size is also correct on both occurences. My ITERM_MSG_GETC handler simply sets A, clears C and returns (same as with the other drivers).

This is what happens when I test it:

Code: Select all

unsigned char c;

c = 4; // some initial value

c = getchar(); // Poll keyboard

sprintf(buffer, "%d", c);
printf(buffer);
Result: The driver is not being invoked.
And now for the mind boggle: variable c will always stay at its initial value! It almost seems as if the call to getchar() and assignment to c is... errr... not being compiled...? (I need to check the disassembly tomorrow to tell for sure.). But shouldn't c at least become zero or EOF?

Could I be missing some configuration/switch that simply strips out that call? Hmmm... puzzling!
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

Now that I think about it, it may be some error in my memory layout, which, accidentally, leaves stdout working, but corrupts stdin and local variables. I think I need to sleep over that (it's close to 3am now) ;-)
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

That's it. Moving the data origin up solved it. *siiiiiiiiiiigh*
Sorry for the false alarm!
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

Glad to hear it you got it working!
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

It's all working now: keyboard input, terminal output and sound. I even compiled and played around with the "eliza" example without modifications.

At the moment, I only have the start up files for the model 4000/4004QL, but models 1000 and 2000 are soon to follow.

Should I create a pull request so the VGL target becomes an official part of the family or do you have any "quality assurance" guidelines I should have a look at?
I am also happy to supply all my knowledge about the platform to the Wiki.

Cheers!
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

Go ahead and do the pull request. Once it's in we can have a look to see if anything is missing.
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

Thanks for the submission hotkey :) I haven't had a lot of time the past couple of weeks but I will spend some time coming up making sure everything is ok with newlib's structure:
https://github.com/z88dk/z88dk/issues/469
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

You're welcome!
I am currently doin some more hardware/historical research. For example, I just now found out that V-Tech was branded "YENO" in Germany and France during the early 80s.

For example: The "PreComputer 1000" was branded "YENO Mister X" and the famous "Socrates" was called "Prof. Wei? Alles". I had a blast from the past when I realized that I was actually playing with these machines at a friends house when I was a little kid! :-D *flashback*
munchausen
New member
Posts: 5
Joined: Wed Sep 19, 2018 12:45 pm

Post by munchausen »

@hotkey I was wondering if you have shared your reverse engineering effort anywhere, with information about how to create cartridges for these machines for homebrew?

I am also wondering if you have any knowledge of the later machines... I had a PreComputer Power Pad when I was a kid, which I think is the UK name of the Genius Leader 4000. I wanted to get one for my son, and wanted one of the old ones since they support programming in basic (the new ones have no programming facilities), but I have bought him a PreComputer Prestige because it has a graphics display that is much larger. I think it's equivalent to the Genius Leader 6000 SL, but also looks like very similar hardware to the 5005 X.

Due to your work here I'm very tempted to get a Power Pad (4000) now as well...
hotkey
Member
Posts: 14
Joined: Thu Sep 14, 2017 9:32 am

Post by hotkey »

@munchausen
There is a little bit of information on my (pretty neglected) project page at http://projects.spr.at

During my "adventures" I have created some plans for the Cartridge PCB in KiCAD and I am happy to share them! I am TERRIBLE at PCB design, that's why someone else should finish it and order some PCBs. I haven't dared ordering them with my crappy design ;-)
(I mainly used the PCB designs as a template for some (a lot) of hand soldering.)

I just uploaded ALL the files to thingiverse: https://www.thingiverse.com/thing:3108809
I am happy for any help in improving this.

Unfortunately I don't know much about the later models (say, starting from GL 7007 with its high-res LCD and all the modern ones. They use a completely different architecture)
munchausen
New member
Posts: 5
Joined: Wed Sep 19, 2018 12:45 pm

Post by munchausen »

Thanks for sharing!

I see from your blog that you bought both a 5005 X and a 6000 SL, are those also Z80 machines with the same cartridge slot, or are they different from the 1000/2000/4000 completely?

I'm also not much good at PCB design, I can manage schematics but PCB designing is harder... but I will check out your design files :)
Post Reply