Jump to content
IGNORED

TI 99/4A interfacing


Vorticon

Recommended Posts

If it works, do you want me to convert it to a set of Express PCB and standard Gerber files for you? That one looks like a really quick kill on layout work. . .and it may be a lot of fun. :)

 

The software I use, Circuit Wizard, can actually output Gerber and drill files. Thanks for the offer though :) What PCB house do you use to produce your boards? I did a quick look see last night and the prices are ridiculous.

In any case, unless for some odd reason there is a demand for that board, I see no reason to go beyond the prototype as long as it works.

Link to comment
Share on other sites

I use Sitopway, Vorticon. Their prices are generally quite reasonable for small board runs when compared to US suppliers--and they are reasonably fast. Just send an email with your Gerbers to: sales at sitopway dot com and ask for a quote. I usually ask for a gold coating on the boards (it increases the cost, but they solder a lot better).

  • Like 1
Link to comment
Share on other sites

I use Sitopway, Vorticon. Their prices are generally quite reasonable for small board runs when compared to US suppliers--and they are reasonably fast. Just send an email with your Gerbers to: sales at sitopway dot com and ask for a quote. I usually ask for a gold coating on the boards (it increases the cost, but they solder a lot better).

 

Thanks for the info. I'll keep this in mind for the future.

Link to comment
Share on other sites

Well, I spent over 4 hrs last night debugging the board. I had a ton of cold solder joints for some reason, which was surprising because I consider myself pretty experienced given the number of kits I have built in the past. I suspect that I did not do a good job of completely cleaning the photoresist layer. There was also a short caused by 2 traces being too close to each other. The resolution of the manual PCB etching is fairly coarse, so I need to be careful in the future and leave a decent clearance between traces. Finally I used wire wrap wire to connect the vias, which was a mistake as it did not solder very well. Best to use thicker hookup wire, and this caused me endless headaches.

 

Finally, after testing every single trace, I managed to get it to work. The good news was that I was no longer seeing any stray signals on the lines. However I was still having huge timing issues, primarily because the Rpi is orders of magnitude faster than the TI. So right now I'm running a series of timing tests to determine the kind of delay needed to slow down the Rpi so it does not overwhelm the TI. I'm able to get reliable communication with a 0.05 secs delay, but I'm not happy with the resulting transfer speed. Does anybody know how fast I can theoretically run the PIO port on the TI in terms of bytes per second? For a 256x192 RGB image (3 bytes per pixel), I'm looking at 147,456 bytes per image to transfer, and for now it's taking, without any processing on the TI side as of yet, upward of 15 minutes to complete... I've got to find a way to speed this up more.

Link to comment
Share on other sites

Just treating it as a simple 8-bit memory address (ie: no handshaking), you should be able to do the same as my movie player manages to VDP, which is about 71k/s - definitely should be able to beat 15 minutes in any event! I'm sorry if you already covered this, what does your final handshaking look like?

Link to comment
Share on other sites

Tursi I am no where near those speeds... The first bottleneck is with the Rpi itself because it does not have a parallel port, so it is emulating one on the fly during the transfer. Furthermore, the Rpi is not an ideal platform for timing critical applications because of the underlying OS management as compared to a dedicated microcontroller, and so this adds a layer of unpredictability which needs to be accounted for on the TI side.

Under my current scheme, no processing is done by the Rpi except capturing an image with the Pi Camera and sending the resulting raw RGB file to the TI one byte at a time.

Obviously the TI lacks the memory to store the RGB file directly in memory, so it processes it on the fly, and so this also slows things down. I am using an extremely primitive processing scheme where the average RGB values for each group of 8 pixels is compared to the standard TI colors (I used your Classic99 RGB conversion values :) ) and the entire pixel row is displayed using the closest matching color with the exception of individual pixels which are turned off if they are close to black.This does yield a recognizable image, but it's very coarse.

As for handshaking, the process goes as such:

 

1- HANDSHAKEOUT pulse: Request data from the Rpi, which places a single byte on the data lines

2- SPAREIN pulse: the RPI signals to the TI that data is available on the data lines

 

The TI reads the byte, processes it, then goes back to 1, until all 147,456 bytes have been read. It displays the image 8 pixels at a time as it is received.

 

Unfortunately, if I run this at full machine speed on both sides, timing errors occur and the process crashes. I have had to introduce a huge delay of 50ms on the Rpi side between SPAREIN high and low (pulse) in order to have the TI reliably capture it, otherwise it happens too fast (intermittently) and the TI simply sits there waiting for the SPRIN pulse and the Rpi waiting for the HSKOUT pulse... This is slowing things down to a crawl. Even going down to 40ms causes errors.

 

Any suggestions?

Link to comment
Share on other sites

Well... I'd first suggest that any crash that happens at high speed /can/ happen at low speed too, so it's worth investigating it. Usually that's a race condition.

 

Bitbanging on the RPI side should be okay... I'm not completely clear on your handshake, but since you have a full bi-directional protocol, I'd propose going fully synchronous rather than pulsing:

 

-Both handshake output lines start LOW

-TI polls the RPI handshake line, waiting for HIGH

-RPI sets the data port pins with valid data

-RPI then sets its handshake output HIGH to indicate data is available on the port

-RPI then polls the TI's handshake output, waiting for HIGH

-When TI see the RPI handshake high, it reads the data byte from the data pins

-TI then sets its output HIGH as an acknowledge

-TI then polls the RPI handshake line, waiting for LOW

-RPI sees the TI pin go HIGH, and releases its handshake (sets it LOW). RPI is now free to go process the next byte

-TI see the RPI line go LOW, and sets it's handshake LOW. TI is now free to process the byte.

-This process resumes at the top.

 

This is a fully synchronous handshake that will work at the speed of the slower system, it shouldn't require any delay loops. It's fully tolerant of processing time on either side. As it's fully synchronous, it's got some inefficiencies, but they are minimal (the TI could make assumptions of the RPI's speed, for instance, but I'm a fan of 'get it working, then optimize').

 

I might also suggest moving the data processing to the RPI side - take advantage of where the horsepower is, then you can send fully processed bytes to the TI. Excepting the crash problem, I wouldn't be surprised if most of your time is spent mapping the RGB colors. But your existing code should be able to work with that handshake without delay loops.

  • Like 1
Link to comment
Share on other sites

My first attempts actually involved a fully synchronous protocol with even error checking, but I could never get it to work properly. I'll give your suggestion a try and see what happens.
As for moving the processing to the Rpi, I had opted from the start not to do it because I wanted the TI to do all the work and just use the Rpi as a camera only. The results so far are not very promising though as seen in the video below, so I may end up doing just that :) And if I do, I may as well implement some sort of conversion like the one used in your Convert9918 utility in order to have a higher quality image.
But first let's see if I can get a decent transfer rate...

 

https://youtu.be/ZJZ1XagaM4g

  • Like 1
Link to comment
Share on other sites

Ah, I totally get that desire. In that case, though... I might suggest that it's not cheating to reduce the camera bit depth! ;) Instead of sending RGB 888 data, maybe send RGB 332, packed into a single byte. You could then build a 256 byte lookup table on the TI side to instantly map a byte to a color. ;) It should still be reasonably close (not close enough for a great dither, probably, but good enough for a remap, I think ;) ).

 

The video was fun!

 

As for making Linux a little closer to RT, there are a few approaches you can use. There are some user mode timers you can use, and if you're willing to build a driver, you can usually tie an unused hardware timer (if there is one) to an interrupt to get /very/ deterministic processing -- but this task probably doesn't need that level of precision.

 

The TI side picture is pretty damn good though! Nice work :)

Link to comment
Share on other sites

Thanks :) Unless I can speed things up significantly though, this whole experiment will remain an academic exercise. But even then, I have learned a tremendous amount in the process, and had a huge amount of fun!

 

I'll have to see if I can change the RGB format using the current python libraries for the Pi Camera. As for working with user mode timers and such, I'm afraid this is way beyond my knowledge base as my familiarity with Linux is very basic.

Link to comment
Share on other sites

Yeah, I wouldn't bother with timers or even worrying about precise timing in this application - it doesn't offer any real benefit. I only wanted to mention it's possible even under an OS.

 

You probably won't be able to change the camera format to 332 - just change it in your RPI side software. Read the three bytes into separate variables (R,G,B), and shift and mask. For instance, this should work (assuming R,G,B and outbyte are integers):

 

r=(r>>5)&0x07

g=(g>>5)&0x07

b=(b>>6)&0x03

outbyte = (r<<5) | (g<<2) | b

 

The first three lines reduce the values of each color to 3 bits, 3 bits, and 2 bits, respectively, and the last line merges the three back together. On the TI side, just unpack in the reverse order (or use the lookup table idea ;) But for getting it working quickly, you could try just this -- it reduces your traffic to 1/3rd so should give you a bit of a speed boost right off the bat?)

Link to comment
Share on other sites

Sorry... it's bit manipulation.

 

I'm starting with the assumption that you have your three camera bytes stored in variables "R", "G" and "B".

 

R=(R>>5)&0x07

 

This first (R>>5) shifts R 5 bit positions right, which reduces the 8 bit value to a 3 bit value (filling the more significant bits with zeros). It's equivalent (with integers) to dividing by 2 raised to the power of 5, which is 32, although the CPU literally does it as a shift.

 

The &0x07 applies a bitwise AND to the result. 0x07 is a hexadecimal number (although I guess it didn't need to be) with just the three least significant bits set. If R was truly an 8-bit unsigned or positive value, it's redundant, but this just covers the case where the value was treated as negative by the compiler, or was somehow out of range, by throwing away all but the 3 bits we care about.

 

B is similar, except we shift one position farther and use a smaller mask to end up with two bits. The loss of color resolution on blue tends to be less noticeable than the other colors. 332 doesn't make a fantastic palette, but it's not terrible and it should retain enough color information for remapping to the TI.

 

The last line outbyte = (r<<5) | (g<<2) | b -- this is just to pack the three sets of bits together in a single byte, with the intent of sending it over to the TI. The '<<' symbol is for left shift, and '|' is bitwise OR.

 

For sake of example, let's say we have an RGB of 255,165,144 (chosen at semi-random). In binary that's 11111111, 10100101, 10010000

 

R=(R>>5)&0x07 -> 11111111 >> 5 -> 00000111 & 0x07 == 00000111
G=(G>>5)&0x07 -> 10100101 >> 5 -> 00000101 & 0x07 == 00000101
B=(B>>6)&0x03 -> 10010000 >> 6 -> 00000010 & 0x03 == 00000010

outbyte = (r<<5) | (g<<2) | b
  r<<5 -> 00000111 << 5 -> 11100000
  g<<2 -> 00000101 << 2 -> 00010100
  b    -> 00000010      -> 00000010
(OR them together)      -> 11110110 == 0xF6 == 246
Notice in the little table how the final shifting lines up each color into its own "dedicate" bit slots. On the TI side, you get the original RGB values back (with some loss in accuracy due to the division) by doing the reverse. While you can optimize the steps, for the sake of clarity, make a copy of the received byte for each of red, green, and blue. Shift red and green back to the least significant bits with SRL (so shift 5 right for red, and 2 right for green), then mask each of them with ANDI (using >07 for red and green, and >03 for blue. This makes sure the other colors are removed, and is necessary for unpacking rather than for safety as in the RPI side). Finally, either adapt your color matching to deal with the smaller colors (R and G from 0-7 and B from 0-3), or shift back left again with SLA to make the bits most significant again (undoing the first step, so 5 positions for R and G, and 6 for B). If you do that, they will look like the 888 values you are currently sending again and the existing mapping code should work. Something like this:

 

* input byte from port in R0
* RGB output in R1,R2,R3
* treats as 16-bit words

* make copies
 mov r0,r1
 mov r0,r2
 mov r0,r3

* extract red, result is 8-bit value in LSB
 srl r1,5    * shift down into position
 andi r1,7   * mask out residue from others
 sla r1,5    * shift back up to 8-bit value

* extract green
 srl r2,2    * shift down into position
 andi r2,7   * mask out residue (red for instance!)
 sla r2,5    * shift back up to 8-bit value

* extract blue (no shift needed, already in LSb)
 andi r3,3   * mask out residue (only 2 bits for blue)
 sla r3,6    * shift up to 8-bit value (larger shift for 2 bits)
That can be optimized a LOT, but I hope it's understandable. If you get it working, and the results are acceptable, 8-bits of color data is small enough even on the TI for a lookup table, and that will be the fastest way to get the color remapping and would be my recommendation for optimizing. :)

 

Hope that makes sense!

  • Like 1
Link to comment
Share on other sites

It totally does. I just was not familiar with the bit manipulation representation :)

I think a lookup table would definitely be the way to go here. A pain to setup, but I think well worth it from a performance standpoint.

Thanks! I'll work on this as well as the synchronous transfer protocol over the next week and report back on the results.

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

So I finally had a chance to play with this again. Tursi's synchronous protocol was not that much different from mine, except in mine I had additional verification steps. In any case, when I implemented it, I still needed to insert time delays in order to get an error free transfer. Finally, after much head scratching, I figured out what the problem was:

With my setup, the Rpi cannot send and receive control signals simultaneously because it does not have enough GPIO lines for my application. The way I got around this was to use a single GPIO line to flip between control in and control out, thus saving a line. The problem arises if the RPI sends out say a handshakeout high signal and then has to wait for an acknowledgment from the TI, and currently the only way to do it is to first set control to out, send the HSK high out, flip control to in, and wait for the TI. When control is set to in, the HSK out line on the Rpi side goes into high impedance, and thus the TI cannot read it accurately. While this works for low speeds, at higher speeds the TI simply does not have enough time to read the HSK out line from the Rpi before it goes into high impedance, and so the system hangs. That is why I need to introduce delays between flipping between control in and out...

 

Unfortunately, there is no way to correct this unless I switch to the Rpi Model B+ which has more GPIO lines. This will require a minor modification to the interface and minor software changes. On the other hand, the current prototype will work just fine for robotics and any other application which does not require high speed bidirectional data transfers.

 

EDIT: OK I don't know what the hell I was smoking when I designed the interface... I woke up this morning and realized that while the data lines are shared for both input and output, the control lines are NOT! Due to differences in voltages between the Rpi and the TI (3.3 versus 5 volts), I have a separate chip interfacing for the HSKOUT and SPROUT lines and another for the HSKIN and SPRIN ones. There is really no reason not to have both chips active at the same time all the time instead of toggling between them. This will save 2 GPIO lines for other uses and will likely solve my data transfer problems. It's just a matter of cutting a couple of traces and soldering in a couple of jumper wires and I should be all set. Hopefully I'll have some time this weekend to do this, so we shall see :)

One more time: DOH!

  • Like 1
Link to comment
Share on other sites

Hey, gentlemen I do not want to be rude here, but since this is a thread on TI interfacing, I would like to interrupt the train of thought here and ask a question. Since I have been out of the TI world for about 15 years, I have not been able to keep track of hardware events except what I have been able to glean from here and other sites. I was just starting to investigate the possibility of using 8 bit XT cards and 16 bit PC cards when the bottom fell out for me and I had to pack up and move in the late 90's. After reading the Asgard article mentioned in another thread, http://atariage.com/forums/topic/240729-midi-module-or-synthesizer-connected-to-the-ti-994a/, I would like to know if anyone ever interfaced pc compatible cards to the TI. I have a ton of such cards and have toyed with the idea of trying to use them in my own projects and it seems that just producing an adapter and maybe writing a DSR would be all that is necessary for each endeavor. I have MFM cards, Ide cards, IO cards, and so forth, just lying around, going to waste and want to put them to use. Thanks for your input. Ricky

Link to comment
Share on other sites

There aren't that many of us out there with a Rave PE/2. Unfortunately, they never developed any cards that used the additional bus connector other than their TI-99 Interface board (which I don't have, as I bought mine for a Geneve, back in the day), although I may eventually do something in that direction. . .just to see what is possible.

Link to comment
Share on other sites

I have the interface card and it is possible to put both a TI and Geneve in the same box and have them run at the same time. I will have to some comparisons on the bus and see if I can build something. I am imagining the use of a MFM, ESDI, RLL, or Scsi controller with existing MDOS or Ti code, or a Vga card, you get the picture. I have just completed a company course on C# and have just learned some Visual Basic( a long way from real code I know (Assembly and GPL)), but I will be tinkering as time and opportunity permit.


Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...