Shop OBEX P1 Docs P2 Docs Learn Events
Capturing ZX81 video — Parallax Forums

Capturing ZX81 video

blittledblittled Posts: 681
edited 2014-06-16 19:24 in Propeller 1
The ZX81 was a marvel for its time since it generated its video using software and ttl logic rather than a separate video chip like other computers. It generated black and white output with a resolution of 256 x 192 in 8 x 8 blocks. They made 3 revisions and they cheated in the first 2 by having no back porch in the video output. In Revision 3 they had put it in since TVs were becoming more sensitive to the lack of a back porch. If you have a ZX81 or Timex Sinclair 1000 and hook it into a AV input to most digital TVs you'll get an almost unreadable signal. You need to find an old TV in a garage sale or goodwill store to get it up and running.

There are a couple of adapters for the TV signal out there but all require opening up the ZX81 and patching hardware into it. The ZX81 has a membrane keyboard that has become brittle with age and a custom chip that fails easily when static electricity hits it. For that reason I do not want to open my one working, never opened Timex Sinclair 1000 to be potentially damaged adding the mod.

Since the signal is only composed of black and white signals it should be able to be "digitized" by using a simple op-amp as a voltage comparator with its output connected to a switching transistor to convert it to logic level voltages. The Propeller should be fast enough to capture the pulses and recreate the bytes. The trick will be in locking into the vertical and horizontal syncs so timing will be correct. Once enough bytes are reconstructed it could be put in a video register for output to a TV to minimize delays. If possible the bytes should also be saved in a buffer so that a VGA driver can output it as well.

Is this a doable project or are there any other approaches of capturing the video output without opening my computer? Thanks!
«1

Comments

  • jmgjmg Posts: 15,173
    edited 2013-09-12 18:58
    If you think the issue is only back porch related, you could fix just that portion of the signal, using a Prop and some analog switches ?
  • kwinnkwinn Posts: 8,697
    edited 2013-09-12 21:37
    A monochrome video scan line is approximately 63.5uSec long, and this time includes the sync, front porch, and back porch time. That leaves about 52.5uSec for the video signal, so each of the 256 pixels would be about 205nSec or 4 PASM instructions in length. Might just be possible with multiple cogs, but for sure not simple or easy.

    Probably simpler to do it in hardware with a high speed comparator to detect the sync signal and a one shot (or 2) to modify the video signal. You could use a prop to modify the signal but you would still need a comparator or some other circuit to detect the sync signal.
  • BeanBean Posts: 8,129
    edited 2013-09-13 04:10
    blittled,
    The TS1000 was my first computer. And I remember it fondly.
    I even have a couple around but the keyboards have failed on them.

    One thing, don't forget that the output at the jack is modulated for TV channel 2 or 3. So you will have to demodulate the signal first before you can do anything with it.

    If the keyboard works on yours then DON'T OPEN IT. That is a sure way to crack the fragile ribbon cable.

    I would look at connecting the propeller to the edge connector and writing a video routine that sends the screen data to the propeller. You can intercept the video routine with code (that is how the pseudo hi-res graphics are done). It shouldn't be hard to send the video data to a Z80 port and have the propeller look for data at that port address.

    Because of the strange way the zx81 does video, you might even be able to detect when the zx81 is doing video and sniff the data from the bus.

    Bean
  • blittledblittled Posts: 681
    edited 2013-09-13 05:31
    Bean you can find original and "new and improved" ZX81 keyboard membranes at http://www.sellmyretro.com/search?keyword=molex&phraseType=anyWord&countryId=GB&categoryId=&price=&zip=&type=BuyItNow not to mention other modern and original parts for the Sinclair line. In fact I bought a breakout board for the edge connector from that site.
    I have looked into the timing of the video on the bus and it isn't much better than the video stream. You have to capture data at two points with only enough time to do 8 pasm commands for each capture.

    This may be a dead end but I am looking at using the Propeller through a Z80PIO so I'll post what I'm doing when I get somewhere with it.

    Edit: I found a site that shows actual oscilloscope displays of ZX80 signals http://searle.hostei.com/grant/zx80/zx80ScopePics.html and if the ZX81 is the same my timing calculations have been way off. It looks like I could do 35-50 pasm instructions between captures which makes it possible to get the video as Bean mentioned.
  • Toby SeckshundToby Seckshund Posts: 2,027
    edited 2013-09-13 09:43
    Remember that Grant's timings will be for 50Hz PAL rather than NTSC
  • BeanBean Posts: 8,129
    edited 2013-09-13 09:56
    I wonder if you could have the propeller use hub memory to act like the 16K ram pack.

    Then you could have another cog read the video area of hub memory and display it on VGA.

    You could also run the ZX81 in FAST mode with a display. So it would be four times faster.

    Bean
  • blittledblittled Posts: 681
    edited 2013-09-13 10:14
    @Toby you are correct. I'll have to take my own oscope readings. It will shorten the timing but if I overclock the Propeller with a 6.25MHz crystal it still should be enough time to do things if the code is efficient.

    @Bean you bring up an interesting idea with the Propeller as a pseudo ram pack. I wonder if the Propeller has the speed to do memory transfers. If you can't and have to pull video data from the address and data bus you will have to keep it in slow mode since none of those signals are present in fast mode.
  • kwinnkwinn Posts: 8,697
    edited 2013-09-13 23:22
    @blitted

    Are you planning to have the prop read the data in parallel from the ZX video shift register? If so that makes things much simpler.

    A single cog could use a waitcnt to monitor the “load” signal (IC9 pin 1) to synchronize reading the video byte as it is output to the video shift register. The bytes could then be written to hub memory where one of the video display objects (modified to suit) could access the data to display it.
  • BasherBasher Posts: 25
    edited 2013-09-14 09:00

    I wonder if the Propeller has the speed to do memory transfers. If you can't and have to pull video data from the address and data bus you will have to keep it in slow mode since none of those signals are present in fast mode.

    There should be plenty of time I've been doing something similar with the sinclair spectrum, I'm using a 6.355mhz crystal x 16
    I've got a bit of a description on the worldofspectrum website
    http://www.worldofspectrum.org/forums/showthread.php?t=44669


    I've just had a look at the link you posted and realised that I was assuming that the zx81 generated video in a similar way to the spectrum.
    I've read through the description a few times and still don't quite understand whats going on!

    If the z80 program reaches an address in screen memory the hardware forces it to execute nops and uses the refresh counter+the character byte to index a character look up table in Rom. When the refresh counters bit 6 goes low that signals the end of line and is used to signal the hysnc?
    frown.gif
    I'd always ignored the zx80 and zx81 I thought they were boring predecessors to the spectrum (my first computer) but reading that makes me want one!
  • BeanBean Posts: 8,129
    edited 2013-09-14 16:03
    Basher,
    It is only when the CPU tried to execute code from above 32K that the ULA takes control. (The lower 32K is echoed into the upper 32K).
    So to start the display the CPU basically does a jmp to D-FILE+32K, this tries to execute the display file.
    While the PC is above 32K any instruction with bit 6 cleared will cause the ULA to force a NOP to be executed.
    At the end of each display line is a HALT instruction (which by chance has bit 6 set) when the CPU reads the HALT instruction is is executed causing the CPU to wait until the hsync signal causes a NMI interrupt breaking it free from the HALT state. (The hsysnc signal is generated by the ULA inself, not by the CPU at all).
    While executing NOPs the I register is used along with the value in RAM to lookup the character bitmap in the ROM.

    In all it is a pretty strange way to generate a display, but I guess in those days that is what had to be done to make such a cheap computer.

    Bean
  • kwinnkwinn Posts: 8,697
    edited 2013-09-14 21:22
    It may be a strange way to do things but there were at least two inexpensive 80 x 24 character video terminals that did something similar. One model used a Z80. Can't recall what the other one used but I think it was either a 6800 or 6502. At the time I was amazed that a Z80 could do that so I studied the hardware and software very carefully.
  • Toby SeckshundToby Seckshund Posts: 2,027
    edited 2013-09-15 02:20
    @ Basher

    If you are into AVRs then there is all of this -

    http://www.jcwolfram.de/projekte/avr/ax81b/main.php

    He has done a whole load of stuff before this, and there is aSpectrum version too but that needs a CPLD.

    There are translated pages about, it all a bit too early, on a Sunday, to find :-)

    Alan
  • blittledblittled Posts: 681
    edited 2013-09-15 18:57
    kwinn I like your idea of pulling off the signal from IC9 but the main reason I was making the project was to capture video without opening the ZX81 for modification.

    I've been reviewing my docs on how the video works and Bean's idea of pulling the information from the expansion edge connector may work, Just like the propeller the Z80 instructions take 4 clock cycles. During the period the video data is set up there are two points where the data bus needs to be polled. At the second clock cycle the character in the D-File is on the bus. This is needed since bit 7 tells if the character is inverted and bit 6 which works as Bean described. Then on the 3rd and 4th cycles during the Dynamic Ram refresh the 8 bit pattern for one of the 8 rows of the D-File character is present.

    What I'm thinking of is have one cog to capture the D-File character and put it into a buffer. Another cog will take the D-File character and the 8 bit pattern and creates a buffer that the NTSC or VGA cog uses to display the output.
  • kwinnkwinn Posts: 8,697
    edited 2013-09-15 22:02
    The signals D0' to D7' that are available on the edge connector are the same ones that go to the IC9 video shift register. Now all you need is the S/L signal generated by IC16 and you have the video data. Unfortunately that signal does not go to the edge connector, but it is generated by IC13 and16 using
  • blittledblittled Posts: 681
    edited 2013-09-16 06:39
    kwinn that is very useful information Thank you. It looks like info on the Z80 or the home brew ZX97 since the ZX81 only has about 4 or 5 ICs and you mentioned IC16. Where did you find that info? My resources have been the book "The Explorer's Guide to the ZX-81 and Timex Sinclair 1000" and Wilf Rigter's website. None of those have the typos you mentioned.
  • BasherBasher Posts: 25
    edited 2013-09-16 13:31
    This site has lots of info on all the Sinclair micros collected together, it's aimed at writers of emulators but I've found the spectrum section useful. It's got a lot of info on the zx80/81 you might find something useful in here.

    http://nocash.emubase.de/zxdocs.htm#zx80zx81keyboardassignment

    I'm looking out for an affordable zx81 on ebay, so I might have need your finished project soon. No pressure :smile:
  • BasherBasher Posts: 25
    edited 2013-09-16 13:51
    I've just been scanning through the zx81 info on the site I posted a link to above. I noticed the following.
    MIC - Cassette Output (from ZX81 to recorder microphone socket)



    Ring: Ground Tip: Cassette Output


    This is in fact the video signal, output through resistor and capaciator, causing black and white stripes to be displayed during cassette output.

    and
    ZX81 Cassette File Structure



    x seconds your voice, saying "filename" (optional) x seconds video noise 5 seconds silence (only some clock cycles required for ZX81) 1-127 bytes filename (bit7 set in last char) LEN bytes data, loaded to address 4009h, LEN=(4014h)-4009h. 1 pulse video retrace signal (only if display was enabled) x seconds silence / video noise


    The data field contains the system area, the basic program, the video memory, and VARS area.

    Maybe you can do something with the signal from the mic socket without having to open up the case?
  • BasherBasher Posts: 25
    edited 2013-09-16 14:14
    since the ZX81 only has about 4 or 5 ICs and you mentioned IC16.

    could IC16 be a typo for pin 16 of the ULA IC in which case, according to this pin out, it is both the the video signal and the tape out.
    ZX81 Ferranti ULA

    1 A7' 2 A8' 3 A2' 4 A1' 5 A0' 6 /RD 7 /IORQ 8 /WR 9 /MREQ 10 M1 11 A14 12 /RAMCS 13 /ROMCS 14 OSC (EXPANSION) 15 /NMI 16 TV/TAPE 17 /HALT 18 A15 19 D7 20 TAPE.IN 21 D6 22 /NTSC 23 D5 24 D4 25 KDB4 26 D3 27 KDB3 28 D2 29 KDB2 30 D1 31 KDB1 32 D0 33 KBD0 34 GND 35 OSC (CERAM) 36 A3' 37 A4' 38 A5' 39 A6' 40 +5V
  • lanternfishlanternfish Posts: 366
    edited 2013-09-16 15:46
    A schematic for the ZX81 can be found here. The tape output IS the TV output put through a RC filter/integrator.
  • blittledblittled Posts: 681
    edited 2013-09-16 16:01
    Basher, The Tape out and Tape in use part of the some hardware and software to generate a signal compatible with cassette players. This does produce "bars" on the screen when the signal goes out but there is no way of using it to stream video out.

    EDIT:
    I just looked at the schematic again and Basher is right. The Video and Audio use the same output with the exception of a couple of resistors, capacitors and a diode (USA).
  • kwinnkwinn Posts: 8,697
    edited 2013-09-16 21:29
    blittled wrote: »
    kwinn that is very useful information Thank you. It looks like info on the Z80 or the home brew ZX97 since the ZX81 only has about 4 or 5 ICs and you mentioned IC16. Where did you find that info? My resources have been the book "The Explorer's Guide to the ZX-81 and Timex Sinclair 1000" and Wilf Rigter's website. None of those have the typos you mentioned.

    You posted the link I started from in post 5 of this thread so I thought you would be working from the same schematic. The schematic link is “http://searle.hostei.com/grant/zx80/zx80.pdf”, and it let me download a PDF schematic of the ZX80 board. With that in hand it was just a matter of chasing back through some gates to see how the load signal for the video shift register was generated.

    The circuit uses a 47pF capacitor, 2 nand gates from IC16 (74LS10), and 2 inverters from IC13 (74LS04). I am pretty sure the load signal could be generated using only a single 74LS10 and 2 prop pins (maybe even just 1 pin) in addition to the 8 data pins. Of course if you can spare a total of 14 pins on the prop no chips are needed, just "waitpeq" for the right condition.
  • WombleWomble Posts: 20
    edited 2013-09-24 09:45
    I have had som e success capturing video using a PIC16f84 through RLA off one port. I stopped work on it but
    it is possible to get a good capture by synching the PIC clock to the incoming video.

    I managed multiple level grey scal ecapturwe by PWM addition onto the video signal during multiple fame captures. Slow - but energy efficvient


    Pete
  • lanternfishlanternfish Posts: 366
    edited 2013-09-29 14:48
    Another option is to 'snoop' the address/data buses for valid video buffer writes.

    The ZX81 has a display 'buffer' pointer that is pointed to by a value (DFILE) at 4000h.
    The DFILE is formatted starting with the Sinclair equivalent of a Carriage Return (CHR$ 118) followed by up to 32 CHR$ codes, this repeated 24 times and ending with a CHR$ 118. CHR$ 118 is the opcode for the Z80 HALT instruction for reasons which will be explained later. All other character codes are illegal and if loaded into DFILE will generally cause a system crash. The collapsed DFILE is used in the 1K and 2K basic ZX81 to minimize screen memory requirements. When empty a collapsed DFILE consists of just 25 CHR$ 118 codes. Each line is expanded when characters are printed to that line. When equipped with 4K or more of memory, DFILE is initialized to the fully expanded format with 24 lines of 32 CHR$ 00 (space) characters and 25 CHR$ 118 line termination characters.

    If the prop waits for a 4000h read or write it could capture the DFILE address and then could listen for reads/writes from/to those memory spaces and build up a picture of the display. And then using a lookup table for the characters, output them via a suitable VGA/TV object.

    This process could be sync'd to the NMI display routines.

    Thoughts?
  • lanternfishlanternfish Posts: 366
    edited 2013-10-03 20:09
    I have done a bit more reading and would like to suggest the following way to capture ZX81 video:
    The character display starts when the last blank line at the top of the screen has occurred and the video routine jumps to the DFILE echo above 32K.
    The hardware in the ZX81 ULA takes control when any opcode is executed above 32K (A15 high and M1 low) with data bit 6 equal to zero.

    I propose that a Prop monitors A15, /M1 and D6 (at the expansion connector ) and reads the data on D0 - D7 (at the expansion connector ) when A15, /M1 and D6=0 . This may need to be followed by a second read to ensure data has settled.

    The display file starts with a $118 and each line contains the the display character codes and ends with a $118. The display file ends with a $118(?).

    It would be easy to copy the ZX81 character table to the Prop and build the display from there.

    Cheers
  • BeanBean Posts: 8,129
    edited 2013-10-04 04:42
    Monitoring D6 I don't think is needed. That mechanism is only to allow the Z80 to execute the HALT instruction instead of feeding the cpu nops.
    Of course you would have to read D0 thru D7 to get the character that was being displayed.
    And remember that each line is displayed 8 times.

    The timing might get tricky because you don't know when a new screen is starting, but there is probably enough time in the top and bottom blank lines to detect that.

    So I see it as:
    1) wait until A15 is low for xxx uSec [ZX81 is producing bottom blank lines, vsync, and top blank lines no memory access]
    2) wait until A15 is high, M1 is low and D0-7 = $118 (the beginning halt instruction of video frame)
    3) now each character is output on D0-D7 when A15 is high and M1 goes low, each video line ends with a $118 and each character line is repeated 8 times
    4) after 24 character lines go back to step 1

    I have a couple ZX81s around, but I would have to find an edge connector to hook up to them.

    Bean
  • lanternfishlanternfish Posts: 366
    edited 2013-10-04 19:09
    Hi Bean

    Will the following help?
    The detailed sequence of operations for each character byte is ... described as follows:

    1. Each character code (CHR$) byte in DFILE is addressed by the CPU Program Counter. On the rising edge T2 data is loaded from DFILE into the ULA: bits 0-5 into a 6 bit ULA address latch while bit 7 is loaded into 1 bit ULA video invert latch.

    This is when I think the Prop needs to capture the data bus. Syncing to the Z80 to the T2 time would be based on the values of A15 and /M1 as described in my previous post.
    2. On the falling edge of T2, the ULA forces all CPU data lines to zero.

    3. On the rising edge of T3 the low data lines are interpreted by the CPU as a NOP instruction.

    4. During T3/4, the CPU executes the Refresh cycle and ROM address lines are generated with I register on A9-A15, the ULA 6 bit character code register on A3-A8, and the ULA modulo 8 line counter on line A0-A2.

    5. On the falling edge of T4, pattern data from the ROM is loaded into ULA video shift register and 8 video pixels are shifted out at 6.5MHz

    This is how the ZX81ULA generates the video signal
    6. If character code latch bit 7 (in the ULA) equals 1, the video pixels are inverted.

    Prop can test this bit and invert character data for inverse character generation.
    7. The CPU increments the program counter and fetches the next character code.

    8. This repeats until a HALT (Sinclair) is fetched.

    9. HALT opcode bit 6 = 1 and is therefore executed (no NOP)
    .
    Thus we continue sampling based on the A15, /M1 and D6 values until D6=1 which signals the end of a line and ultimately the end of the video field.
    10. The ULA generates a HSYNC pulse independent of the CPU timing and the ULA LCNTR is incremented

    11. The halted CPU continues to execute NOPs, incrementing register R and samples the INT input on the rising edge of each T4.
    12. When A6, which is hardwired to INT, goes low during refresh time, (bit 6 of the R reg = 0), the Z80 executes the INT routine (below 32K)

    This is the way the ZX81 executes the ZXBasic program
    13. CPU returns from INT and resumes "execution" of DFILE CHR$ codes.

    14. The process repeats 192 times and then INT routine returns to the main video routine, turns on the NMI generator and switches back to the application code.

    I could be way off but by reading D6 during the opcode fetch above 32K would this provide the screen sync albeit at the end if the display period.

    I really wish I had kept my ZX81's now.

    EDIT: Tidied up formatting so post is more readable
  • zx81vgazx81vga Posts: 56
    edited 2014-06-15 07:42
    Hello,

    I been new here, and read this Thread with most Interrest.

    I'm a great Propeller Fan and make some Work...

    Maybe i can help blittled

    Here is my Work:

    http://zx81vga.ws-nbg.de

    Greetings from Germany, Nuremberg

    P.S.
    Sorry for my bad English
  • PublisonPublison Posts: 12,366
    edited 2014-06-15 10:09
    zx81vga wrote: »
    Hello,

    I been new here, and read this Thread with most Interrest.

    I'm a great Propeller Fan and make some Work...

    Maybe i can help blittled

    Here is my Work:

    http://zx81vga.ws-nbg.de

    Greetings from Germany, Nuremberg

    P.S.
    Sorry for my bad English

    Welcome to the forums!

    Thank you for the awesome link!

    I think there are a bunch of people around here that will find it very useful.
  • lanternfishlanternfish Posts: 366
    edited 2014-06-15 17:03
    Hi,

    I look forward to reading through the documentation.

    Many thanks
  • BaggersBaggers Posts: 3,019
    edited 2014-06-16 07:50
    Hi ZX81VGA,

    Welcome to the forum :)

    Great project btw!
Sign In or Register to comment.