Toastie

LEGO Interface A (9750/9771) – LEGO Technic Control 1 (TC1) reference/ideas thread

Recommended Posts

16 hours ago, Toastie said:

Interestingly, exactly this behavior is replicated in DOSBox-X. A hiccup occurs every 24 ms, as per measurement. Which makes me believe, DOSBox-X simulates a 8520 UART for the serial port. You can choose a Pentium processor - but I believe the serial port behavior remains identical.

Can further support this speculation:

My Satellite 4090 laptop (I believe @alexGS is also using, correct Alex?), a 16550 equivalent UART is doing the serial communication. That one handles baud rates > 9600 and has serial I/O buffers: https://www.minuszerodegrees.net/manuals/Toshiba/Satellite/Toshiba Satellite 4090XCDT - Product Specifications.pdf

On this computer, TCLogo_s works absolutely fine within margin of error using 19200 baud for the serial communication with the Arduino. There is some very minor jitter, I can't even quantify on my scope. But there is no hiccup at all. I may have a look at my 5 lines of Arduino c++ code, but that seems to be fine. Just as a test: 38400 baud work as well - this gives more time to do other things on the Arduino, if desired :D (when not wanting to use interrupts, that is).

There is of course no real reason to run the serial TCLogo version Alex made on this particular machine, as the 4090 has a parallel port as well, and thus TCLogo_p runs perfectly well. However, it is always good to know what causes which jitter or hiccup ;) on home brew stuff made by an amateur.

Conclusion: The slightly off timing at 9600 baud in DOSBox-X is due to the 8250 UART simulation. The hiccup (= 1 ms wrong output after 24 ms) is due to the 9600 baud. The weird behavior at 19200 baud in DOSBox-X (timing becomes simulated processor dependent) is a simulation artifact, mostly caused by the 8250 simulation, I believe.

Best regards,
Thorsten

 

Edited by Toastie

Share this post


Link to post
Share on other sites

So I heard my group was just awarded with a major EU program fund - this needs some attention from my side :D It is within a consortium of some chip manufacturers, research institutions and universities, all playing around with EUV light and such things ...

So just FYI - here is the 5 line c++ code (plus a lot of text, so I still may understand what I did. Tend to forget such things after a couple of days ...)

Few remarks:

  • The LED illumination is entirely optional, as 9750 has its own LEDs. It was just for me during programming as quick visual feedback. I am a BASIC person. For me, C++ is like coming from outer space and I have to look up nearly everything - and over and over again ...
  • In other words, this reduces the "code" to 4 lines w/o the remarks and definitions :D
  • I am using direct port manipulation only (which is NOT recommended by the Arduino folks, as this is of course board/microcontroller specific. But I find it cool. Also, all bits are changed >simultaneously< as the register content is thrown onto the outputs in essentially one instruction step. I like that. 6 x digitalWrite is not cool :D. It is more an homage to the 9771 card and 9771/9750 communication :pir-laugh: The traditional way of I/O pin handling is thus commented out and just for me to remember.
  • All that is needed is either an Arduino Nano or Uno (watch the pinout, microcontrollers have identical port descriptors), I have tested both; a serial2TTL converter just running in parallel to the TX/RX lines of the Arduino. For programming, only the RX line of the converter needs to be temporarily disconnected, as otherwise the Arduino can't listen to the USB port. This is why I installed a little switch, see page 1 of this thread.
  • I bet there is a much more elegant way to manipulate the ports in c++ using &|<>!^ ...:pir-laugh:

But: It works.

//
//Serial Interface for TCLogo to 9750 parallel input/output
//Uses port manipulation: https://playground.arduino.cc/Learning/PortManipulation/                         
//  
//Port commands: DDRX  : port direction of port X; 0=in, 1=out
//               PORTX : write to port X
//               PINX  : read port X (also to read back output status
//Works on Arduino Uno R3 and 
//Arduino Nano using the "Processor: ATmega328P/old bootloader" option in menu Tools  
/*
Traditional pin definition setup
#define bit0_output 2                         // 9750 output 0 
#define bit1_output 3                         //             1
#define bit2_output 4                         //             2
#define bit3_output 5                         //             3 
#define bit4_output 6                         //             4
#define bit5_output 7                         //             5
#define bit6_input 8                          // 9750 input  6 
#define bit7_input 9                          //             7
*/

void setup() {
  // Init IO pins ----------------------------------------------------------------------------------------------
  /*
  Traditional I/O setup
  pinMode (bit0_output, OUTPUT);
  pinMode (bit1_output, OUTPUT);
  pinMode (bit2_output, OUTPUT);
  pinMode (bit3_output, OUTPUT);
  pinMode (bit4_output, OUTPUT);
  pinMode (bit5_output, OUTPUT);
  pinMode (bit6_input, INPUT);
  pinMode (bit7_input, INPUT);
  */
  pinMode (8, INPUT_PULLUP);                  // Pullup needs to be defined >before< port direction settings
  pinMode (9, INPUT_PULLUP);                  // This mimics the behavior of the 9750 sensor ports: Open = true

  //Port configuration for Arduino; see above Arduino reference link
  //     pins    76543210
  //     port D  765432XX
  //     TCLogo  543210
  //     9750    543210
  DDRD = DDRD | B11111100;                    // Port D direction setting 1 = output; 0 input.
                                              // This is safe: It sets pins 2 to 7 as outputs
                                              // without changing the mode of pins 0 & 1 (RX/TX) 
  //     pins    XXX21098                     // Port B: Ports 5-7; pins 13-15 not usable on Nano
  //     port B  XX543210                     // 
  DDRB |= B00001100;                          // Ports B2/B3 = outputs, all other unchanged (B5-7 not usable).
  DDRB &= B11111100;                          // Ports B0/B1 = inputs, all other unchanged.
    
    
  // Init serial ports -----------------------------------------------------------------------------------------
  Serial.begin(19200);                        // Init hardware serial port (pins 0+1)
                                              // Notes: 9600 baud is the native QBasic maximum as well as the 
                                              // maximum on the IBM XT. 
                                              // 19200 baud work when reprogamming the UART using DEBUG within
                                              // DOSBox-X (although not fully) and on the Toshiba 4090.
                                              // 38400 baud work (only) on the 4090 as well 
                                              // using DOSBox-x
  while (!Serial) {}                          // Wait for serial port to connect
      
} // end setup -------------------------------------------------------------------------------------------------                                                       


void loop() { //------------------------------------------------------------------------------------------------
    
  uint8_t newPINB;                            // For temporal storage of port B status.
  
  newPINB = PINB & B00000011;                 // Read port B, lower 2 bits (=> sensors 6+7 on 9750).
                                              // Need to use a variable for temporal storage of port B status: 
                                              // PORTB |= ((PINB & B00000011) << 2) does not work.
  //PORTB |= (newPINB << 2);                  // CRAP, DOES ONLY WORK ONCE!!! The LEDs simply stay ON.
  PORTB = newPINB <<2                         // Much better: LEDs on port B 3+4 showing the sensor status (optional). 

  if (Serial.available()){                    // Something arrived at the serial port = TCLogo_s write 
                                              // -> no error checking!
    PORTD = Serial.read() << 2;               // Arduino output port LEDs (0-5 on 9750 = PORTD 3-8). Optional.                                                                                         
    Serial.write(((PIND & B11111100) >> 2) | (newPINB << 6));
                                              // Reply to TCLogo_s: 
                                              // Read the output status, shift right by 2 = bits 0-5.
                                              // Add bits 6+7 by shifting the port B input bits left by 6 
  }  
            
}//void loop ---------------------------------------------------------------------------------------------------

Best wishes,
Thorsten

AND EDITED AGAIN - oh my. Don't code in C++ if you are a BASIC person ... the line: PORTB |= (newPINB) << 2); works exactly once when an input on 9750 goes low - after that no changes occur on the IN LEDs anymore; they simply stay on.
The code needs to be PORTB = newPINB << 2. I am very sorry - change that above as well.

Edited by Toastie
C++ code

Share this post


Link to post
Share on other sites

Does anyone have a scan of the original instructions for connecting a BBC Micro (B, B+, Master) to Interface A? I know it's just the 20-pin ribbon cable, but I am curious to see how Lego documented it for BBC computers. I have the Apple II, Commodore 64, and IBM PC instructions. 

Share this post


Link to post
Share on other sites
On 3/20/2023 at 1:32 AM, evank said:

I know it's just the 20-pin ribbon cable, but I am curious to see how Lego documented it for BBC computers.

Hi Evan,
is/was there any impetus to reach out to TLG on these issues? I bet there are/were - I am a "bit" late to the game.

All the best,
Thorsten

Share this post


Link to post
Share on other sites

I'm skeptical that they would help, but I left a message through their web chat system.

Share this post


Link to post
Share on other sites

Hi Evan,

this is certainly not what you are looking for, but maybe you get some info you are looking for.

Daniel Schmatz (from Austria) who is operating a "museum for pinball machines and LEGO sets" near Vienna/Austria ("eitle Kinderkram", this is the webpage: https://kinderkram.eitle.at/), made a YouTube video in 2021 "showing" all pages of the booklets that came along with 1455 in 1986. The video quality is really not that good, but as said, almost all pages are shown.

I accidentally ran across this website when I tried to understand what 9771 is and does, as you know regarding TC, I started from scratch in late 2022. Daniel has a >very< impressive collection of LEGO sets including Technic/Dacta - and has also the Apple II and IBM PC cards. Not sure about the C64 cable only connection, though. The video is 2 years old, that may have changed, but it is nice to see how surprised he is in the video, that the BBC does not need an interface card: About 11 minutes into the video, the hardware setup is shown, and he really takes some time to comprehend the setup (fingers running across the BBC, the disk station, interface A - but no interface card, and gets excited about it.

So just have a look and enjoy the nice Austrian accent of his German :D

 

All the best,
Thorsten   

Share this post


Link to post
Share on other sites

Thanks @Toastie I will check out the video.

>> has also the Apple II and IBM PC cards. Not sure about the C64 cable only connection

I have all three of those.  :)

Update: I watched the video, and that's definitely what I need! I emailed him just now. Thanks again for the tip.

Edited by evank

Share this post


Link to post
Share on other sites
2 hours ago, evank said:

I have all three of those.  :)

I know :) You wrote it - and that is so unbelievably cool!

Well, my youth never ran into the C64, it was Sinclair world ...

But I found one C64 with floppy drive in the storage room of my resarch group. I joined the University of Wuppertal in 2001 as chair of the Physical Chemistry group. In 2010, we merged PChem and Theoretical Chem (TC) into PTC. My predecessors joined in 1974 - 1980; and since then, it appears as if - no - things have piled up :pir-wink:. My colleagues are all "gone" - either left Earth (2) or are retired (2). And new colleagues (not me) hired recently don't ... want to deal with 1980s - 1990s crap. That is why there are still (1) C64, (3) Ataries (1024) with three 30MByte HD drives, and "my" IBM XT ... and much more in electronic stuff, even Germanium transistors (the "AC" series and the like :D).

So, I guess - I should make a ZX Spectrum fit for operating interface A - all it needs is a cable :pir-sweet:. And yes, the connectors to the backplane of the Speccy are in the basement as well. It was a small world, back then, in the 1980s. OK, I need to make a program as well. But my love for the Speccy never faded, so it will be fun to do so.

2 hours ago, evank said:

I emailed him just now.

How cool is that!!! Hope he replies! And - one day - there may be scans of these booklets on the Internet Archive.

All the best,
Thorsten

 

 

Edited by Toastie

Share this post


Link to post
Share on other sites

Long time, no necro-bump … :pir-huzzah2:

Little update: Looked into TCLogo assembly code, as @alexGS has already done. Alex chased the occurrence(s) of the addresses used in the TCLogo I/O routines writing to and reading from the LEGO #9774 PC ISA card (either 39Dh/925d or 39Eh/926d, depending on address bridge presence on the PCB; out/in) in order to change them to parallel port addresses (TCLogo_p.com, 378h/888d out; 379h/889d in) or serial port addresses (TCLogo_s.com, 3F8h/1016d; out/in), so that semi-vintage computers lacking vintage ISA bus support can natively run the respective TCLogo version. He succeeded and has hacked and provided these TCLogo variants on his Bricksafe folder (https://bricksafe.com/pages/alexGSofNZ/interface-a-tc-logo).

My interest focuses on the PWM pulses present on the 6 outputs of the LEGO interface A box #9750. As per oscilloscope measurements it became clear that each power setting in TCLogo (0-7; 0 = off, 7 = on, all other = PWM) is changing its output status from 0 to 1 with 1 ms temporal resolution. The thing is: independent of computer used, be it an original IBM XT or a Toshiba laptop – even in the DOSBox-X emulator running TCLogo_s on a i7/Win11 laptop. This strongly suggested the presence of a hardware interrupt routine to be responsible for this behavior – at least under MSDOS, regardless of DOS version.

Executive summary:

When starting up, TCLogo

1) changes partly the DOS interrupt vector table content

2) changes the time base of the programmable interrupt timer to 1 ms

3) hooks int 8 = IRQ 0 (timer interrupt) for 1ms PWM output

4) chains from int 8 to int 95 (which points to the original int 8 vector) every 55 times, int 8 is executed, to maintain the correct system time.

My ultimate goal is to use this approach in combination with QuickBasic 4.5, so that PWM control becomes available as well in this programming environment (I am struggling with TCLogo’s programming logic …) – I am a BASIC person. QuickBasic 4.5 is also from the olden days, when 4.5V LEGO Technic Control was around, i.e, from the mid to late 1980ies.

 

In more detail:

For the analysis of TCLogo, Alex suggested to do that with the DOSBox-X debugger, as the assembly code of TCLogo swiftly becomes hard to trace using a disassembler.

I first tried a disassembler as well; however when an assembly program begins with a relative rather long “jmp“ and then does a few things like producing the splash screen and then just waits for the user to hit return, things get a bit messy right away as you need to follow the jump targets – everything in between may just be – something, data, whatever – but not assembly code instructions.

The free version of IDA Pro dissembler (5.0 from 2010) is a) disassembling 8086 assembly very well and b) does analyze the assembly code by tracing jumps. Nevertheless, after asking for the “return” key it is over as well. Particularly as TCLogo does what apparently was done back in the days, when games or other nifty programs needed to be fast: It changes some of the DOS interrupt vector table content, then manipulates the programmable system timer (PIT) and then hooks some of the new interrupt vectors. Then it does some house-keeping, produces the splash screen, and finally waits for the user to press “return”. This made it rather tough to produce any reasonable disassembler output even with IDA. This is entirely due to my limited capabilities, of course, I bet, IDA tells you everything when you know how to use it properly.

Even worse, in the beginning I had no clue what “segment” and “offset” meant. My assembly world was so far limited to 64k computers = linear address space. It took me a while to figure out how this works … also the register operations of the 8086 seemed to be odd sometimes … very steep learning curve – and that still remains so.

So I followed (again) Alex’ advice and used the debugger of DOSBox-X, as said, to log/read the code, TCLogo actually executes. The log file also contains all register content and so on. The debugger can also list the DOS interrupt table content – this way I figured out what changed after TCLogo is running. And sure enough, among others, the DOS interrupt vector 8 (hardware IRQ 0 = timer interrupt) is not  pointing to BIOS anymore, but to TCLogo code. Somewhere else in the manipulated vector table the original interrupt 8 vector is stored. The two tables are listed in the spoilers below.

 

Spoiler 1: Interrupt table DOS only (warning: 256 lines long)

Spoiler

 


INT 00:  F000:CA60
INT 01:  0070:00F4
INT 02:  0070:00F4
INT 03:  0070:00F4
INT 04:  0070:00F4
INT 05:  F000:FF54
INT 06:  F000:CA60
INT 07:  F000:CA60
INT 08:  F000:FEA5
INT 09:  F000:E987
INT 0A:  F000:FF55
INT 0B:  F000:CE80
INT 0C:  F000:CE80
INT 0D:  F000:CE80
INT 0E:  F000:CCE0
INT 0F:  0070:00F4
INT 10:  C000:00EE
INT 11:  F000:CB20
INT 12:  F000:CB40
INT 13:  F000:CF60
INT 14:  F000:CB80
INT 15:  F000:CBA0
INT 16:  F000:CFC0
INT 17:  F000:CBC0
INT 18:  F000:CD00
INT 19:  F000:CC60
INT 1A:  F000:CBE0
INT 1B:  F000:D1C0
INT 1C:  F000:CC00
INT 1D:  F000:C958
INT 1E:  F000:CA60
INT 1F:  C000:05E9
INT 20:  F000:D0E0
INT 21:  F000:D100
INT 22:  F000:DAC8
INT 23:  072F:0000
INT 24:  072F:0110
INT 25:  F000:D120
INT 26:  F000:D140
INT 27:  F000:D160
INT 28:  F000:D180
INT 29:  F000:D1A0
INT 2A:  F000:D240
INT 2B:  F000:CA60
INT 2C:  F000:CA60
INT 2D:  F000:CA60
INT 2E:  072F:0118
INT 2F:  F000:D220
INT 30:  00D1:E0EA
INT 31:  F000:CAF0
INT 32:  F000:CA60
INT 33:  C402:0010
INT 34:  F000:CA60
INT 35:  F000:CA60
INT 36:  F000:CA60
INT 37:  F000:CA60
INT 38:  F000:CA60
INT 39:  F000:CA60
INT 3A:  F000:CA60
INT 3B:  F000:CA60
INT 3C:  F000:CA60
INT 3D:  F000:CA60
INT 3E:  F000:CA60
INT 3F:  F000:CA60
INT 40:  F000:CA60
INT 41:  F000:CF80
INT 42:  F000:CA60
INT 43:  C000:01E9
INT 44:  F000:CA60
INT 45:  F000:CA60
INT 46:  F000:CFA0
INT 47:  F000:CA60
INT 48:  F000:CA60
INT 49:  F000:CA60
INT 4A:  F000:CA60
INT 4B:  F000:D280
INT 4C:  F000:CA60
INT 4D:  F000:CA60
INT 4E:  F000:CA60
INT 4F:  F000:CA60
INT 50:  F000:CA60
INT 51:  F000:CA60
INT 52:  F000:CA60
INT 53:  F000:CA60
INT 54:  F000:CA60
INT 55:  F000:CA60
INT 56:  F000:CA60
INT 57:  F000:CA60
INT 58:  F000:CA60
INT 59:  F000:CA60
INT 5A:  F000:CA60
INT 5B:  F000:CA60
INT 5C:  F000:CA60
INT 5D:  F000:CA60
INT 5E:  F000:CA60
INT 5F:  F000:CA60
INT 60:  0000:0000
INT 61:  0000:0000
INT 62:  0000:0000
INT 63:  0000:0000
INT 64:  0000:0000
INT 65:  0000:0000
INT 66:  F000:CA60
INT 67:  C401:0004
INT 68:  F000:CA60
INT 69:  F000:CA60
INT 6A:  F000:CA60
INT 6B:  F000:CA60
INT 6C:  F000:CA60
INT 6D:  F000:CA60
INT 6E:  F000:CA60
INT 6F:  F000:CA60
INT 70:  F000:CC20
INT 71:  F000:CC40
INT 72:  F000:CE80
INT 73:  F000:CE80
INT 74:  F000:D020
INT 75:  0000:0000
INT 76:  F000:CCA0
INT 77:  F000:CCC0
INT 78:  0000:0000
INT 79:  0000:0000
INT 7A:  0000:0000
INT 7B:  0000:0000
INT 7C:  0000:0000
INT 7D:  0000:0000
INT 7E:  0000:0000
INT 7F:  0000:0000
INT 80:  0000:0000
INT 81:  0000:0000
INT 82:  0000:0000
INT 83:  0000:0000
INT 84:  0000:0000
INT 85:  0000:0000
INT 86:  0000:0000
INT 87:  0000:0000
INT 88:  0000:0000
INT 89:  0000:0000
INT 8A:  0000:0000
INT 8B:  0000:0000
INT 8C:  0000:0000
INT 8D:  0000:0000
INT 8E:  0000:0000
INT 8F:  0000:0000
INT 90:  0000:0000
INT 91:  0000:0000
INT 92:  0000:0000
INT 93:  0000:0000
INT 94:  0000:0000
INT 95:  0000:0000
INT 96:  0000:0000
INT 97:  0000:0000
INT 98:  0000:0000
INT 99:  0000:0000
INT 9A:  0000:0000
INT 9B:  0000:0000
INT 9C:  0000:0000
INT 9D:  0000:0000
INT 9E:  0000:0000
INT 9F:  0000:0000
INT A0:  0000:0000
INT A1:  0000:0000
INT A2:  0000:0000
INT A3:  0000:0000
INT A4:  0000:0000
INT A5:  0000:0000
INT A6:  0000:0000
INT A7:  0000:0000
INT A8:  0000:0000
INT A9:  0000:0000
INT AA:  0000:0000
INT AB:  0000:0000
INT AC:  0000:0000
INT AD:  0000:0000
INT AE:  0000:0000
INT AF:  0000:0000
INT B0:  0000:0000
INT B1:  0000:0000
INT B2:  0000:0000
INT B3:  0000:0000
INT B4:  0000:0000
INT B5:  0000:0000
INT B6:  0000:0000
INT B7:  0000:0000
INT B8:  0000:0000
INT B9:  0000:0000
INT BA:  0000:0000
INT BB:  0000:0000
INT BC:  0000:0000
INT BD:  0000:0000
INT BE:  0000:0000
INT BF:  0000:0000
INT C0:  0000:0000
INT C1:  0000:0000
INT C2:  0000:0000
INT C3:  0000:0000
INT C4:  0000:0000
INT C5:  0000:0000
INT C6:  0000:0000
INT C7:  0000:0000
INT C8:  0000:0000
INT C9:  0000:0000
INT CA:  0000:0000
INT CB:  0000:0000
INT CC:  0000:0000
INT CD:  0000:0000
INT CE:  0000:0000
INT CF:  0000:0000
INT D0:  0000:0000
INT D1:  0000:0000
INT D2:  0000:0000
INT D3:  0000:0000
INT D4:  0000:0000
INT D5:  0000:0000
INT D6:  0000:0000
INT D7:  0000:0000
INT D8:  0000:0000
INT D9:  0000:0000
INT DA:  0000:0000
INT DB:  0000:0000
INT DC:  0000:0000
INT DD:  0000:0000
INT DE:  0000:0000
INT DF:  0000:0000
INT E0:  0000:0000
INT E1:  0000:0000
INT E2:  0000:0000
INT E3:  0000:0000
INT E4:  0000:0000
INT E5:  0000:0000
INT E6:  0000:0000
INT E7:  0000:0000
INT E8:  0000:0000
INT E9:  0000:0000
INT EA:  0000:0000
INT EB:  0000:0000
INT EC:  0000:0000
INT ED:  0000:0000
INT EE:  0000:0000
INT EF:  0000:0000
INT F0:  0000:0000
INT F1:  0000:0000
INT F2:  0000:0000
INT F3:  0000:0000
INT F4:  0000:0000
INT F5:  0000:0000
INT F6:  0000:0000
INT F7:  0000:0000
INT F8:  0000:0000
INT F9:  0000:0000
INT FA:  0000:0000
INT FB:  0000:0000
INT FC:  0000:0000
INT FD:  0000:0000
INT FE:  0000:0000
INT FF:  0000:0000

 

Spoiler 2: Interrupt table DOS + TCLogo_s running (warning: 256 lines long)

Spoiler

INT 00:  F000:CA60
INT 01:  0070:00F4
INT 02:  0070:00F4
INT 03:  0070:00F4
INT 04:  0070:00F4
INT 05:  1481:04CE ; TCLogo code; DOS: Print Screen key
INT 06:  F000:CA60
INT 07:  F000:CA60
INT 08:  1481:0365 ; TCLogo code; DOS: Timer interrupt (was F000:FEA5 -> Int 95 has this vector w/ TCLogo)
INT 09:  F000:E987
INT 0A:  F000:FF55
INT 0B:  F000:CE80
INT 0C:  F000:CE80
INT 0D:  F000:CE80
INT 0E:  F000:CCE0
INT 0F:  0070:00F4
INT 10:  C000:00EE
INT 11:  F000:CB20
INT 12:  F000:CB40
INT 13:  F000:CF60
INT 14:  F000:CB80
INT 15:  F000:CBA0
INT 16:  F000:CFC0
INT 17:  F000:CBC0
INT 18:  F000:CD00
INT 19:  F000:CC60
INT 1A:  F000:CBE0
INT 1B:  1481:04CE ; TCLogo code; DOS: CTRL BREAK key - same as INT 05
INT 1C:  F000:CC00
INT 1D:  F000:C958
INT 1E:  F000:CA60
INT 1F:  C000:05E9
INT 20:  F000:D0E0
INT 21:  F000:D100
INT 22:  F000:DAC8
INT 23:  072F:0000
INT 24:  0A64:02E4 ; TCLogo code; DOS: FATAL ERROR handler
INT 25:  F000:D120
INT 26:  F000:D140
INT 27:  F000:D160
INT 28:  F000:D180
INT 29:  F000:D1A0
INT 2A:  F000:D240
INT 2B:  F000:CA60
INT 2C:  F000:CA60
INT 2D:  F000:CA60
INT 2E:  072F:0118
INT 2F:  F000:D220
INT 30:  00D1:E0EA
INT 31:  F000:CAF0
INT 32:  F000:CA60
INT 33:  C402:0010
INT 34:  F000:CA60
INT 35:  F000:CA60
INT 36:  F000:CA60
INT 37:  F000:CA60
INT 38:  F000:CA60
INT 39:  F000:CA60
INT 3A:  F000:CA60
INT 3B:  F000:CA60
INT 3C:  F000:CA60
INT 3D:  F000:CA60
INT 3E:  F000:CA60
INT 3F:  F000:CA60
INT 40:  F000:CA60
INT 41:  F000:CF80
INT 42:  F000:CA60
INT 43:  C000:01E9
INT 44:  F000:CA60
INT 45:  F000:CA60
INT 46:  F000:CFA0
INT 47:  F000:CA60
INT 48:  F000:CA60
INT 49:  F000:CA60
INT 4A:  F000:CA60
INT 4B:  F000:D280
INT 4C:  F000:CA60
INT 4D:  F000:CA60
INT 4E:  F000:CA60
INT 4F:  F000:CA60
INT 50:  F000:CA60
INT 51:  F000:CA60
INT 52:  F000:CA60
INT 53:  F000:CA60
INT 54:  F000:CA60
INT 55:  F000:CA60
INT 56:  F000:CA60
INT 57:  F000:CA60
INT 58:  F000:CA60
INT 59:  F000:CA60
INT 5A:  F000:CA60
INT 5B:  F000:CA60
INT 5C:  F000:CA60
INT 5D:  F000:CA60
INT 5E:  F000:CA60
INT 5F:  F000:CA60
INT 60:  0000:0000
INT 61:  0000:0000
INT 62:  0000:0000
INT 63:  0000:0000
INT 64:  0000:0000
INT 65:  0000:0000
INT 66:  F000:CA60
INT 67:  C401:0004
INT 68:  F000:CA60
INT 69:  F000:CA60
INT 6A:  F000:CA60
INT 6B:  F000:CA60
INT 6C:  F000:CA60
INT 6D:  F000:CA60
INT 6E:  F000:CA60
INT 6F:  F000:CA60
INT 70:  F000:CC20
INT 71:  F000:CC40
INT 72:  F000:CE80
INT 73:  F000:CE80
INT 74:  F000:D020
INT 75:  0000:0000
INT 76:  F000:CCA0
INT 77:  F000:CCC0
INT 78:  0000:0000
INT 79:  0000:0000
INT 7A:  0000:0000
INT 7B:  0000:0000
INT 7C:  0000:0000
INT 7D:  0000:0000
INT 7E:  0000:0000
INT 7F:  0000:0000
INT 80:  0000:0000
INT 81:  0000:0000
INT 82:  0000:0000
INT 83:  0000:0000
INT 84:  0000:0000
INT 85:  0000:0000
INT 86:  0A64:0020 ; TCLogo code; DOS: Used by BASIC interpreter
INT 87:  1481:0020 ; TCLogo code; DOS: Used by BASIC interpreter
INT 88:  131A:0020 ; TCLogo code; DOS: Used by BASIC interpreter
INT 89:  0000:0000
INT 8A:  0A64:06BD ; TCLogo code; DOS: Used by BASIC interpreter
INT 8B:  0000:0000
INT 8C:  0000:0000
INT 8D:  0000:0000
INT 8E:  0000:0000
INT 8F:  0000:0000
INT 90:  0000:0000
INT 91:  0000:0000
INT 92:  0000:0000
INT 93:  0000:0000
INT 94:  0000:0000
INT 95:  F000:FEA5 ; TCLogo code; DOS: Used by BASIC interpreter; this is the original DOS int 8 interrupt vector
INT 96:  0000:0000
INT 97:  0000:0000
INT 98:  0000:0000
INT 99:  0000:0000
INT 9A:  0000:0000
INT 9B:  0000:0000
INT 9C:  0000:0000
INT 9D:  0000:0000
INT 9E:  0000:0000
INT 9F:  0000:0000
INT A0:  0000:0000
INT A1:  0000:0000
INT A2:  0000:0000
INT A3:  0000:0000
INT A4:  0000:0000
INT A5:  0000:0000
INT A6:  0000:0000
INT A7:  0000:0000
INT A8:  0000:0000
INT A9:  0000:0000
INT AA:  0000:0000
INT AB:  0000:0000
INT AC:  0000:0000
INT AD:  0000:0000
INT AE:  0000:0000
INT AF:  0000:0000
INT B0:  0000:0000
INT B1:  0000:0000
INT B2:  0000:0000
INT B3:  0000:0000
INT B4:  0000:0000
INT B5:  0000:0000
INT B6:  0000:0000
INT B7:  0000:0000
INT B8:  0000:0000
INT B9:  0000:0000
INT BA:  0000:0000
INT BB:  0000:0000
INT BC:  0000:0000
INT BD:  0000:0000
INT BE:  0000:0000
INT BF:  0000:0000
INT C0:  0000:0000
INT C1:  0000:0000
INT C2:  0000:0000
INT C3:  0000:0000
INT C4:  0000:0000
INT C5:  0000:0000
INT C6:  0000:0000
INT C7:  0000:0000
INT C8:  0000:0000
INT C9:  0000:0000
INT CA:  0000:0000
INT CB:  0000:0000
INT CC:  0000:0000
INT CD:  0000:0000
INT CE:  0000:0000
INT CF:  0000:0000
INT D0:  0000:0000
INT D1:  0000:0000
INT D2:  0000:0000
INT D3:  0000:0000
INT D4:  0000:0000
INT D5:  0000:0000
INT D6:  0000:0000
INT D7:  0000:0000
INT D8:  0000:0000
INT D9:  0000:0000
INT DA:  0000:0000
INT DB:  0000:0000
INT DC:  0000:0000
INT DD:  0000:0000
INT DE:  0000:0000
INT DF:  0000:0000
INT E0:  0000:0000
INT E1:  0000:0000
INT E2:  0000:0000
INT E3:  0000:0000
INT E4:  0000:0000
INT E5:  0000:0000
INT E6:  0000:0000
INT E7:  0000:0000
INT E8:  0000:0000
INT E9:  0000:0000
INT EA:  0000:0000
INT EB:  0000:0000
INT EC:  0000:0000
INT ED:  0000:0000
INT EE:  0000:0000
INT EF:  0000:0000
INT F0:  0000:0000
INT F1:  0000:0000
INT F2:  0000:0000
INT F3:  0000:0000
INT F4:  0000:0000
INT F5:  0000:0000
INT F6:  0000:0000
INT F7:  0000:0000
INT F8:  0000:0000
INT F9:  0000:0000
INT FA:  0000:0000
INT FB:  0000:0000
INT FC:  0000:0000
INT FD:  0000:0000
INT FE:  0000:0000
INT FF:  0000:0000

 

What helped a lot in getting further into the TCLogo code per DOSBox-X debug log file was applying the “CPU = 8086” and “CPU speed of 8088 XT/4.77MHz” = 240 emulator cycles/ms options. That produces much smaller log files and got me faster to the timing sequence in TCLogo. I typed “TCLogo_s” in the program window (no return), then started the debugger, asked to log 200000 cycles, quickly returned to the program window and hit return. That took a while … the splash screen appeared, then the return prompt, then the logging was also done. I did not press return.

The analysis of the log file took me quite some time – just to trace the output/input timing related things! This has nothing to do what TCLogo does as its main task: Providing a powerful programming language for (LEGO) robotics; this is just about the PWM timing loop.

What happens upon TCLogo program startup in this regard is essentially the following. Note though that the segment:offset pairs shown below in the assembly code snippets are most probably different on other systems; these are from the debugger output of DOSBox-X, I have no clue if that changes on another machine. TCLogo is a true DOS COM file and thus should use only 64k of addressing, but I am not sure at all.

Here we go:

  • (1) Directly after startup at segment offset 100h, many things happen, memory is cleared, byte/words are “defined”, etc. I did not follow entirely through here.
  • (2) At some point, the PWM signatures for the initial power setting of the 9750 outputs 0-5 (FF = 1111 1111 = power 7) are defined using four words. Each individual power PWM signature consists of 8 “serial bits”, as measured with the oscilloscope, shown in an earlier post in this thread. A further byte located at [9315] is set to 0, this is the mask for the 6 outputs; see below how the 6 bit parallel output signal to 9750 are (most probably) generated from the 8 bit signatures:
1481:0A0E  mov  word [9317],3F3F       ;eight bytes are set to 3F = 0011 1111
1481:0A14  mov  word [9319],3F3F
1481:0A1A  mov  word [931B],3F3F
1481:0A20  mov  word [931D],3F3F

 

  • (3) The presence of the interface is tested. This is where Alex has most probably hacked the original TCLogo software: First, 15h = 00010101 is sent out on the (hard coded) address (03F8) of the serial port, then TCLogo listens on this address for a reply of the same value. As my Arduino Nano does exactly that, just reply back what came in (plus the 2 input bits), TCLogo assumes a valid interface is present:

1481:0A26  mov  dx,03F8                ;load serial port address into dx
1481:0A29  mov  al,15                  ;load 15h = bin 0001 0101 into al
1481:0A2B  out  dx,al                  ;write bin 0001 0101 to serial port
1481:0A2C  in   al,dx                  ;read serial port into al
1481:0A2D  and  al,3F                  ;al = al AND 3F (bin 0011 1111)
1481:0A2F  cmp  al,15                  ;compare al to 15h = 0001 0101
1481:0A31  je   0A82 ($+4f)            ;je=jump if zero flag is set; as the
                                       ;Arduino on the USB2Serial port replies
                                       ;with 0001 0101, the compare result is 1
                                       ;= no jump
  • TCLogo then stores this address two times; I believe these are the two other locations, Alex hacked TCLogo; one is used for the “out” command in the new interrupt 8 routine, providing the PWM signatures for the six 9750 outputs, the other for the “in” command reading the digital values of the two sensor inputs of 9750 in the same routine. Note that out/in addresses are identical for 9771 and the serial card, but different for the parallel card. Thus they are the same for TCLogo_s (serial version):
1481:0A87  mov  word [9343],03F8       ;used for output
1481:0A8D  mov  word [9345],03F8       ;used for input

 

  • (4) TCLogo stores a number of original interrupt vectors in an unused section of the DOS interrupt table, among these is int 8 = IRQ 0 (system timer interrupt), which becomes int 95 and points to the original BIOS section, where the system timing is handled. One example of how to get an interrupt vector is given below for int 5 = Print screen key:
1481:02B4  mov  al,05                  ;prepare call DOS int 21, function 35h (in ah):
                                       ;get vector for interrupt 5 (in al) - Print screen key
1481:02B6  mov  ah,35                  ;prepare call DOS int 21; return ES:BX = current int handler
1481:02B8  int  21                     ;call DOS int 21 f35 i5
F000:D100  sti                         ;set interrupt flag; external, maskable interrupts enabled at
                                       ;the end of the next instruction
F000:D101  callback 0038  (DOS Int 21) ;this loads requested data into ES:BX
F000:D105  iret                        ;ES:BX now contains the (far) interrupt vector 5

 

  • (5) New interrupt vectors are copied into the interrupt table, among these is int 8 as well. DOS int 21, function 25h is used for this purpose, same way as above. The new vectors point to TCLogo code (interrupt service routines, ISRs).
     
  • (6) The programmable interrupt timer (PIT; Intel 8253 on the XT, may be other but “compatible” timers on other DOS systems) is manipulated. I believe up-to the latest DOS version, int 8 = IRQ 0 is thrown every 55 ms, regardless of the hardware setup. On the XT, the CPU needs a number of peripheral chips to work the system, among them are the PIT and the Intel 8259 PIC (programmable interrupt controller). On the XT, the PIT uses a system crystal oscillating at 4.77 MHz. This frequency is divided by 3 = 1.193181 … MHz (for money saving reasons explained much better here: https://de.wikipedia.org/wiki/Programmable_Interval_Timer) and then further by a user accessible divisor register of the PIT. The original divisor is 65536; thus the system clock fires at 1193181 s-1 / 65536 = 18.2 s-1 => every 55 ms – as it apparently does on all DOS systems.
    To change the PIT clock rate i) the PIT mode may be (optionally) selected, then ii) the divisor latch has to be changed:
    • (i) The PIT mode register is listening to I/O port 43h. TCLogo uses counter 0 of the PIT; low then high byte write to the 16 bit divisor register; runs the PIT in mode 3 (rate generator with symmetrical square wave output rather than short pulses); and sets the counter to 16 bit binary rather than BCD. The corresponding 8 bit word is thus 00-11-011-0 or 36h.
    • (ii) The divisor latch of the PIT listens to I/O port 40h; TCLogo first writes A9h then 04h to this port = 4*256+169 = 1193 (decimal).

      (i) + (ii) assembly code:
1481:0358  mov  al,36                  ;00 11 011 0 = 36h
1481:035A  out  43,al                  ;set PIT mode
1481:035C  mov  al,A9                  ;divisor, low byte (A9h=169d)
1481:035E  out  40,al                  ;write to PIT divisor latch
1481:0360  mov  al,04                  ;divisor, high byte
1481:0362  out  40,al                  ;write to PIT divisor latch
1481:0364  ret
  • From this point on, the PIT fires with a frequency of 1193181 Hz/1193 = 1000.15 Hz => 0.9998 ms. This occurs before even the splash screen appears.
     
  • (7) As TCLogo hooks int 8, the new interrupt service routine for int 8 (IRQ 0) needs to chain to the original int 8 BIOS routine (now int 95, which chains further to int 1C) every 55th time it was called; otherwise the system time and thus many things may screw up.
    The “count up” counter storage location is at [92FC] in the new int 8 ISR:
(More code above; e.g. “PWM out” to and “sensor in” from the serial port connected to Arduino/9750) followed by

1481:0408  add  word [92FC],04A9       ;this is the counter for calling int 95:
                                       ;04A9 = 1193 dec = 1/1000 of 8253 PIT frequency
                                       ;1,19318181818 … MHz)
1481:040E  jnc  00000415 ($+5)         ;(down) jump if no carry: Carry flag does not
                                       ;change here. It will change from 0 to 1, when
                                       ;[92FC] > FFFF. This will occur 55 times after
                                       ;this routine was called:
                                       ;55 * 1193 = 65615 = 1004F.
                                       ;4F is then stored in [92FC] - and thus adds up
                                       ;?to sync most accurately with system time?
1481:0415  mov  al,20                  ;20h=function "end of interrupt (EOI)" for PIC
1481:0417  out  20,al                  ;PIC listens on I/O port 20h
1481:0419  pop  ds                     ;restore registers
1481:041A  pop  dx
1481:041B  pop  bx
1481:041C  pop  ax
1481:041D  iret                        ;return from HW interrupt
  • When the Carry flag is changing to 1 (this is during the 55th call of int 8) int 95 is chained (the original int 8 BIOS routine):
(Same entry point as above)

1481:0408  add  word [92FC],04A9       ;this sets the carry flag to 1:
                                       ;FBA6 + 04A9 = 1009E and thus int 95 is called;
                                       ;9E is stored in [92FC]
1481:040E  jnc  0415 ($+5)             ;(no jmp) no jump = int 95 call via seg:04AD
1481:0410  call 04AD ($+9a)
1481:04AD  int  95                     ;interrupt chain 1: int 95
                                       ;(= original int 8 (IRQ 0) call)
F000:FEA5  sti
F000:FEA6  callback 0008  (IRQ 0 Clock)
F000:FEAA  push ds
F000:FEAB  push ax
F000:FEAC  push dx
F000:FEAD  int  1C
F000:CC00  callback 0010  (Int 1c Timer) ;interrupt chain 2: int 1C
F000:CC04  iret                        ;return from int 1C
F000:FEAF  cli
F000:FEB0  mov  al,20                  ;only last chain ISR signals EOI to PIC
F000:FEB2  out  20,al
F000:FEB4  pop  dx
F000:FEB5  pop  ax
F000:FEB6  pop  ds
F000:FEB7  iret                        ;return from new int 95

 

That is pretty much it with regard to the I/O timing for the serial (and of course parallel or 9774 card) in TCLogo.

 

PWM signal generation

One last section on the PWM signal generation on the 6 out lines (0-5), which go to 9750 via either Arduino (TCLogo_s), the parallel port (TCLogo_p) or the 9774 card (TCLogo).

Upon further inspection of the int 8 routine (again using the DOSBox-X debugger log repeatedly, but logging after hitting return and setting each output to an individual power level (6x “tto X”; “setpower Y”; “on”), I believe to having understood, how that works.

The PWM signatures are 8 bit serial “packets” continuously sent out at a 1 ms rep rate to the 6 individual output lines. These packets are re-calculated only, when the user changes the power setting. They are stored as bytes in locations (cf. section 2)

[9317] to [931E]

Let us assume the following:

TCLogo Settings:

talkto setpower on/off
----------------------
  0        1      on
  1        2      on
  2        3      on
  3        4      on
  4        5      on
  5        7      on

The output mask byte at [9315] is now 00111111 = 3F=all on

Tracing "out dx,al" in the consecutive int 8 code calls (every ms) yields:

                     (9750 output#:   54 3210)
1) 1481:0394  out  dx,al  ;AL: 3C = 0011 1100; byte [9317]
2) 1481:0394  out  dx,al  ;AL: 32 = 0011 0010; byte [9318]
3) 1481:0394  out  dx,al  ;AL: 3C = 0011 1100; byte [9319]
4) 1481:0394  out  dx,al  ;AL: 29 = 0010 1001; byte [931A]
5) 1481:0394  out  dx,al  ;AL: 36 = 0011 0110; byte [931B]
6) 1481:0394  out  dx,al  ;AL: 38 = 0011 1000; byte [931C]
7) 1481:0394  out  dx,al  ;AL: 3C = 0011 1100; byte [931D]
8) 1481:0394  out  dx,al  ;AL: 23 = 0010 0011; byte [931E]
                 (9750 power level:   75 4321 -> as measured)

The columns “9750 output#” 5->0 represent the PWM signatures for each 9750 output. These signatures are thus as listed below, in full accord with the oscilloscope data:

 7: 1111 1111 = FFh = 255d
(6: 1111 1110 = FEh = 254d) ;not used in the above experiment)
 5: 1110 1110 = EEh = 238d
 4: 1011 0110 = B6h = 182d
 3: 1010 1010 = AAh = 170d
 2: 0100 1001 = 49h =  73d
 1: 0001 0001 = 11h =  17d
(0: 0000 0000 = 00h =   0d) ;not used in the above experiment

In conclusion (on PWM output generation):

  1. TCLogo calculates and stores 8x8-bit data (bytes) each time the power data of 1 (or several) channels is (are) changed.
  2. The new PWM data have to be calculated only once after the change(s) and then simply 1ms repetitive mov/out instructions generate the PWM pattern for all 6 outputs, which saves a lot of time within the interrupt routine.
  3. This behavior is readily replicated in QuickBasic – but it takes much longer to execute – certainly not at 1 ms rep rate! But it works as expected. Nevertheless, the TCLogo code is simply beautiful!!!

 

Summary

I believe it may be worthwhile to program this behavior into the QuickBasic program I am currently using for controlling 9750 also with PWM. So far the outputs are simply “on” at power level 7 or off. Nothing in between. The nice thing is that QuickBasic does not claim any of the new interrupt vectors, TCLogo is occupying for hooking. So I can maybe do some c/p’ing here. Who knows, it will be a (very) long journey for sure!

All the best,
Thorsten

 

(P.S.: Will edit this surely quite often, as there will be many typos)

Edited by Toastie

Share this post


Link to post
Share on other sites

Hello Thorsten - nice work with proving the operation of the 1ms interrupt timer for the PWM - that explains how it works consistently across systems of different speeds. I think you will be successful in your quest to use the same approach from QuickBASIC (or QBASIC?)

Thank you for your kind words about my ‘hacking’ - and for proving that the use of the port address in three places is (i) for testing the port, (ii) for outputs, and (iii) for inputs - I appreciate that.

Meanwhile, I have had some difficulties with parallel port use on later laptops from the early 2000s, but since these usually have USB ports as well, I hope to try using USB to feed the (relatively hungry) 5V supply to the Interface A of the later type with the flat-top LEDs. I need to do a little more testing to check this solves the problem of not being able to activate more than two or three outputs simultaneously. The parallel port alone cannot supply enough current in this situation (it can for the earlier interfaces, or for earlier laptops).

Last night I became aware of this rather-bizarre piece of new hardware:
https://www.aliexpress.us/item/1005005528944178.html
It has sold out already, even at the rather high price for what it is. You’ll notice that while it doesn’t have a printer port, it does expose the ISA bus - so could support a version of the LEGO 9771 card - check your post above for the typo under “PWM Signal Generation” ;)

All the best

-Alex

Edited by alexGS

Share this post


Link to post
Share on other sites
On 5/20/2023 at 4:24 AM, alexGS said:

Last night I became aware of this rather-bizarre piece of new hardware:

Hi Alex,
WHAT A FIND!!! Oh my - hopefully this comes back alive -  will purchase one right away!!! How cool is that. I love the way they expose the CPU and other chips ... beautiful, simply beautiful!!! I shall also plow Tindie.com for similar things ...

Will come back later ... back :D

Yes, I also believe the USB or any other power supply providing 5V/100(+) mA should do the trick. In the schematics for 9750, LTV-817 M is listed as (4x) opto-coupler. Each draws 10 mA (max.) when on, if I am not mistaken (5V/560 Ohm). All couplers on = 60 mA max. The ULN2003 easily sinks that current.

All the best,
Thorsten 

Edited by Toastie
Came back :D

Share this post


Link to post
Share on other sites

Hi all,

just to wrap up the hardware setup(s), I am currently using for the operation of interface A / #9750 with the computers I have, particularly the IBM XT / #9771 interface card <=> #9750 combo and my win11 laptop USB <=> Arduino <=> #9750 combo. This is for direct operation of TCLogo.com (original, TCLogo_s, TCLogo_p) and/or QuickBasic 4.5 or QBasic 1.1.

Essentially all computers (vintage/ISA, direct cable, serial-Arduino, USB-Arduino should work with one of the options shown in the picture below:

 

800x475.jpg

Figure legend

  • (A) IBM XT or any compatible system with ISA bus (or directly addressable bus system via out/in CPU commands) available. The communication is via ISA cards; either LEGOs #9771, parallel, and/or RS232 serial card.
  • (B) Semi-vintage computer, i.e., one with parallel or serial port available, again directly addressable, as in (A).
  • (C) Modern computer lacking any directly addressable serial/parallel ports - this requires a DOS emulator, here DOSBox-X.
  • 20 ribbon cable = 20 wire flat cable which attaches directly to 9750.
  • S2T = Serial (RS232) to TTL adapter; this is for BASIC programs using the serial port or TCLogo_s to operate 9750 via an Arduino "serial-to-parallel adapter"
  • U2S = USB to serial (RS232 adapter); this can be used on modern machines for RS232 serial communication. As my Arduino is a one-4-all solution, this is the most flexible approach as it works flawlessly with all computer systems I tested.
  • U2T = USB to TTL adapter; this is for computers with USB port only, as in the U2S <=> S2T approach. The charm is that the U2T +5V line can be used to feed power to the Arduino as well, just connect +5V out of the adapter to the +5V power rail of the Arduino board, it can't do any harm.
  • DB-X = DOSBox-X emulator with serial port emulation enabled.
  • The "/" broken line means long cable can be used.
  • Arduino = Arduino Nano, Uno, Mega - these are the ones I tested - they all work fine. For the Nano, this program works fine as serial to parallel converter (note that the direct port addressing is specific to the specific Arduino boards): https://bricksafe.com/files/Toastie/lego-interface-a---9750---9771---tclogo/program-files-/9750_Parallel2Serial_Interface.ino
  • Note 1 on the Arduino: The Arduino needs +5V as power supply; this is not shown here. The Arduino supplies/sinks 20 mA (cont) on each output pin (200 mA total); this should be more than enough for all 9750 varieties out there.
  • Note 2 on the Arduino: The Arduino USB port for programming/power supply does not show up as "com port" in device manager and can thus not be used as com port device for serial / in/out communication in DOSBox-X. You need to use a USB to serial or USB to TTL adapter as com port, which can then be configured in DOSBox-X.
  • Note 3 on the Arduino: The Uno and Nano have only one hardware serial port, RX/TX. These two pins are exposed on the board, but do also connect to the on-board USB chip for programming/power supply. I am not trusting the software serial solutions very much. When attaching the U2T or S2T adapters to the RX/TX pins directly, programming of the Arduino via USB port does not work anymore. There is a very simple solution: Either remove the adapter cable that goes to the RX pin when programming or put a simple switch in between that line. The TX pin on both the adapter and on board USB chip does not interfere at all. See also photograph on page one of this thread.  
  • Note on custom parallel cable: As noted by @alexGS, not all parallel computer ports can drive the 9750 opto-coupler input circuity; in this case, an additional +5V power supply is required here as well.
  • Note on operating system: Essentially all DOS versions should work running TCLogo and/or BASIC; I tested DOS 3.3 (MS and PC/IBM versions). Win98 DOS prompt works as well. Not sure about WinXP. All other Windows consoles do not; for Win11, the DOS emulator DOSBox-X is working fine.

Guess this is it.

All the best,
Thorsten

Edited by Toastie

Share this post


Link to post
Share on other sites

Hello Thorsten, Alex, and others,

Thank you for one of the most interesting threads I've ever read! I like to consider myself relatively computer-adept, but I'm definitely a little out of my element here :laugh_hard: ... I like fiddling with older LEGO electronics; recently I've been playing with the 90s Control Lab and VLL with the scout, and I finally decided to conquer the Interface A.

I have the Interface itself, a USB to TTL adapter, Arduino Nano, and a hodge podge of ribbon cables. I understand (based on your most recent post on this thread, @Toastie) that's all I need to get the interface running on my modern computer via DOSBox, correct? I'm only unsure about which arduino pins to connect to which pins on the interface. If you could help me figure that out, I would be greatly appreciative!

Thanks for all your work on this,

-Ry

Share this post


Link to post
Share on other sites
3 hours ago, RyBreaddddd said:

If you could help me figure that out, I would be greatly appreciative!

Hi Ry,

nice that more folks are enjoying vintage LEGO!

Now when you navigate here:

you can see in one of the pictures how the Nano is connected to the Interface A:

Arduino pin    Lego Interface A pin
     D2                  6          (to LI output 0)
     D3                  8          (to LI output 1)
     D4                  10         (to LI output 2)
     D5                  12         (to LI output 3)
     D6                  14         (to LI output 4)
     D7                  16         (to LI output 5)
     D8                  18         (from LI input 0)
     D9                  20         (from LI input 1)

Lego Interface A pins 5 - 19 are GND and 1+3 are +5V.

The USB to TTL adapter outputs go to TX and RX on the Nano - make sure you have an on/off switch in the RX line, otherwise you can't program the Nano on the fly.

This configuration works only with a Nano running my little program available on Bricksafe, as I am using direct register manipulation (for fun ...)

And lastly: I have tested this with DOSBox-X only. No idea whether DOSBox works as well.

All the best,
Thorsten

Share this post


Link to post
Share on other sites
On 7/3/2023 at 6:39 AM, RyBreaddddd said:

 I finally decided to conquer the Interface A.

I have the Interface itself, a USB to TTL adapter, Arduino Nano, and a hodge podge of ribbon cables. I understand (based on your most recent post on this thread, @Toastie) that's all I need to get the interface running on my modern computer via DOSBox, correct? I'm only unsure about which arduino pins to connect to which pins on the interface. If you could help me figure that out, I would be greatly appreciative!

Thanks for all your work on this,

-Ry

Hello Ry - sorry I’m late to the party (again) - not enough free time here at the moment, sometimes I have a lot and other times little (self-employed)…

Thorsten has made a nice diagram above showing that there are different approaches, and he has done an enormous amount of work to test and refine the Arduino-based serial-to-parallel conversion for a modern PC.

Meanwhile, I’d like to point out that the parallel cable approach (B) is still a simple way to go - IF you happen to have suitable old PCs lying around that have parallel ports and boot into DOS or Windows 3.1/95/98.

My requirement is that it must allow the use of the TC-LOGO programming environment as described in the original materials (e.g. the Reference Guide downloadable from EvanK’s page at the Internet archive; search ‘vintage LEGO robotics). That’s why the hack came about; to allow TC-LOGO to run without the original ISA card. And the PWM (Setpower) still works, since that’s done in software as Thorsten proved.

I happen to have a 1995 Compaq Contura 410/1994 Contura Aero (Win 3.1), 1999 Toshiba Satellite 4800 (Win 98), and 2004 Compaq Evo n620c (Win 98) - actually a couple of each - and these are all laptops with native parallel ports that work with the interface cable. The 9750 interface with the flat-top LEDs may require a ‘boost’ from a USB port to supply the 5V to the interface, which is easy on the latter two machines as they include USB ports. The older 9750 interface with round-top LEDs doesn’t require the ‘boost’. EDIT: I just tested with the Contura 410C and the flat-top LED interface works fine without the extra ‘boost’.

So that’s still the way I do it, just a parallel cable without Arduino and without DOSBox (although I feel guilty for not using Thorsten’s solution!)

I think it’s up to you to decide which path you’d like to take. I like collecting and restoring early laptops - 1994-era is old enough for Interface A in my opinion, even though it also works with Control Lab (Interface B).

To quote a LEGO ideas book from the 1980s - “the most important thing is to use the bricks you have in new ways. Have fun!”

-Alex

Edited by alexGS

Share this post


Link to post
Share on other sites
On 7/4/2023 at 11:29 AM, alexGS said:

My requirement is that it must allow the use of the TC-LOGO programming environment as described in the original materials

Hello Alex!

You are absolutely right - and it should be stressed: Nothing is better than using a direct hardware approach, particularly when the hardware is still readily available (semi modern PCs and laptops, eBay is your friend) and b) "all" you have to do is making a cable AND carefully follow the instructions provided by you for making such a cable!!! I screwed up on this initially, because I was NOT carefully reading the instructions. The good old world of schematics and focused work on multiple wires ... I love that.

I'd also say that the parallel approach/access to 9750, either via 9771, the Apple equivalent, or any true PC parallel port, is much "closer" to the original setup. The Arduino/serial approach just works because hardware has become so much faster over the years. Back in the TC days, it was simply not possible to do PWM via serial communication, as discussed above

I have been seriously side-tracked by @evank as Evan told me, there was no version of TC available for Atari's. I resurrected a working Atari 1040 STFM and a Mega St4 from being trashed (BTW: NO more vintage stuff anywhere in the basement of my institute - nothing. Today it was cleared entirely. Sneaked in on Monday and snatched the Atari's - today, everything else was relocated to Building A = trash & recycling. Interestingly, this building is right next to Building B (duh) = Administration: Rectorate etc. pp. :D). As BASIC is BASIC, I am entertaining the idea of adapting my DOS QBasic program to GWGFABasic ... the Atari's provide direct access to the data/address bus :pir-stareyes:. We'll see. No time right now, but 5 and 1/2 years and I'll retire :pir-huzzah2:

All the best,
Thorsten

   

 

Edited by Toastie

Share this post


Link to post
Share on other sites

Nice one, Thorsten - again, I really respect that you have developed the idea of the old software on modern hardware with a new USB interface as a workable solution :)

And then; yes, writing one’s own software opens up all kinds of platforms and possibilities! An Amiga from the period has a parallel port, perhaps it’s possible to control with AmigaBASIC, I mean to try that. And someone gave me a Psion Organiser - a handheld thing that appears to include BBC BASIC and a number of I/O lines. I joined the dots and wondered if it’s possible to control Interface A with it; the two-line LCD is rudimentary, may not be worth the trouble ;) but it would be a ‘period’ hack…

Then finally there’s the idea of using a RaspberryPi, with programming in Python or Scratch (a modern hack). Although at that point it’s perhaps easier to forgo the Interface A altogether and use modern motor controllers and IR sensors (something I’ve done already).

-Alex

Share this post


Link to post
Share on other sites

Hi Alex,

(I am trying to have the Dacta Control lab thread of Brian untangled, let's see what happens)

with regard to the additional 5V supply required for some of the parallel port/9750 combos using the method you describe above: For my PoweredUp/TC "coupling", I used the permanent ~4V DC output from 9750 to supply 9V DC to the Technic hub with the help of miniature step-up-converter (https://www.eurobricks.com/forum/index.php?/forums/topic/194832-lego-technic-control-tc-1986-meets-lego-poweredup-pup-2019-bridging-a-30-years-lego-technic-electronics-“gap”).

Now, I believe you can either use the 4V DC directly to power the opto-couplers of 9750 directly, i.e., feeding that power into 1+3 (+) and any of the even pins (GND). This way, you won't need an external power supply. This "violates" TLGs approach of not exposing any 9750 voltage to the controlling computer or interface card, but whatever. Should that voltage not be high enough, the little step-up-converter would easily do it, as it produces the 9V DC for the hub without any problems.

Not that it makes any difference, it would just look cool ;)

Best,
Thorsten

 

Edited by Toastie

Share this post


Link to post
Share on other sites

Thanks for the idea, Thorsten :) Worth a try, using the 4V to supply the Interface A’s optocouplers instead of relying on parallel port control outputs.

The laptop PCs that were having problems turning on the outputs were new enough to have USB ports, so I decided taking the 5V from USB was the easier ‘fix’; I think it’s electrically better to have the 5V coming from the PC rather than externally, but I could be wrong.

There doesn’t seem much ‘rhyme or reason’, i.e. no obvious pattern to which laptops can turn on enough outputs or which laptops need this 5V boost. I was disappointed that my 2004 Compaq Evo laptop had difficulty where my 2002 Toshiba did not. I think on balance, Toshiba seems a good choice of retro laptop :)


Thank you for your efforts to move the Interface A software discussion into a new thread. It was confusing me when I had email notifications about the Control Lab thread updates.

Incidentally, for the sake of completeness in this thread, here is my document about the parallel port cable (trying to make it easy for anyone who stumbles into this).

https://bricksafe.com/files/alexGSofNZ/interface-a-tc-logo/ParallelPortInterfaceAConnection.pdf

Edited by alexGS

Share this post


Link to post
Share on other sites
1 hour ago, alexGS said:

I think it’s electrically better to have the 5V coming from the PC rather than externally, but I could be wrong.

No, you are not, as far as I am concerned; this USB supply approach >is< he much better and more "in line with TLGs" philosophy way to do it.

1 hour ago, alexGS said:

here is my document about the parallel port cable

This is just a marvel! Thank you so very much for composing this document. It is of true teaching style - meaning it is a tutorial, a reference, and an instruction. The best of three worlds!

All the best,
Thorsten 

Share this post


Link to post
Share on other sites

Just found this video today, I'm sure most of the information is known to folks in this thread but I'm glad it exists!  If nothing else it's something to share with people who haven't seen it before without having to explain everything from the ground up :laugh:

 

Share this post


Link to post
Share on other sites

Hi Brian,

what a nice find!!! And Aaron must be soooo excited and totally in LEGO heaven ...

Thank you very much for sharing!

All the best,
Thorsten

Share this post


Link to post
Share on other sites
1 hour ago, BatteryPoweredBricks said:

Just found this video today, I'm sure most of the information is known to folks in this thread but I'm glad it exists!  If nothing else it's something to share with people who haven't seen it before without having to explain everything from the ground up :laugh:

 

Thanks for the video link!

I hadn’t seen it - the video is produced to a very high standard, well-edited, nice and concise, very clear (accent is pleasant to those of us overseas), no egregious errors in the technicalities that we know so well. This would be an ideal sales video for @evank ; he has some of these hardware/software packages available 😁

Edited by alexGS

Share this post


Link to post
Share on other sites
On 8/24/2023 at 5:33 PM, alexGS said:

no egregious errors in the technicalities 

Except that the video title says 90s! It should be 80s.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.