• COP404: Obscurity by design

    Anders Dinsen01/08/2024 at 06:42 0 comments

    This log is about the COP404 microcontroller used in the operator panel. The COP404 has a particularly obscure instruction set and I'm going to dive into it.

    Today, 8 and 16 bit AVR, PIC and 32 and 64 bit ARM processors more or less set the standard for microcontrollers. These are powerful devices with beautiful instruction sets, but if you're seeking contrast and is courious how 4 bit microcontrollers of the late 1970's and early 80's were designed, read on!

    Below is a picture of what I found when I took the operator panel apart: A COP404LSN and 2716 EPROM, and some supporting circuitry are clearly identfied. 

    Apart from what you can see in the picture, the operator panel also contains an LCD display to output things like frequency and station name. It's all fitted on a flexible PCB. There are 22 input keys distributed over four of the six sides of the panel.

    With all that user interface, It's no wonder that Blaupunkt needed a small computer in the panel to talk to the TMS9981 host CPU.

    COP400 was a series of four bit processors originally designed by National Semiconductor for calculators. By the late 1970's, NS had three lines of processers: The COP400, the SC/MP and the IMP16. These were 4, 8, and 16 bit processors respectively. I happen to know the SC/MP very well as it was the CPU in my first computer. I had never worked with the COP400 though.

    The COP400 series were mainly mask programmable devices with up to 2K of on-chip ROM. In the IQR 83, however, the code resides in an external EPROM. Good for us! We can have some fun looking at code!

    Seeing the NS logo, I hoped the COP400 was similar to the SC/MP. While having its own quirks, the SC/MP instruction set was actually quite pretty. Studying the COP400 data sheet, I quickly realized the COP is much more strange! But let's look at the structure of the chip first to see what the instructions are controlling:

    The block diagram above comes from the datasheet and shows the internal blocks of the COP404:

    • I/O drivers and associated registers.
    • Various registers: ACC, C, PC, Br and Bd-registers, and the three level stack.
    • The 512 bit RAM block.
    • The ALU.
    • Supporting functions: Clock generator, reset logic, and the instruction decoder.

    The interface to the code EPROM is via the IP lines on the left. Instructions are 8 bit and the least significant 8 bits of the address bus are multiplexed with the instruction bus in the COP404 (an external 74C373 latch decodes them).

    The four bit ACC register is the source and destination for most I/O, arithmetic, logic, and data memory access operations. It can also be used to load input from registers. A 4 bit adder performs the artichmetic and logic functions. It outputs the carry bit to the one bit C register.

    Data memory is 128x4 and organized in 8 'registers' of 16 'digits', four bit each. To access data in the RAM, the address of whatever needs to be accessed must first be set up in the two parts of the B-register: Br (register number) and Bd (digit number).

    An unshown flag is the "SKIP" flag, which is internal to the instruction decoder: Many instructions have side effects setting that. When that happens, the following instruction is read, but not executed.

    Let's look at sime simple code:

    L110:	ININ		; Read Serial IN
    	AISC	15      ; Add 15 to A setting carry...
    	JP	$L111	; This jump is skipped if carry was set...
    	JMP	$L110	; Continue reading until its a start bit
    L111:   ...

    This is jumped to after initialization and reads the serial port into the accumulator register. The AISC instruction is the "add immediate" instruction essentially adding a 4 bit number to the contents of the accumulator. But it has the side effect that if Carry becomes set, the following instruction is skipped.

    This architecture may seem smart, but results in very convoluted and hard-to-read code. There are designated "TEST"-instructions that perform various tests on bit level or comparing the A register with a RAM...

    Read more »

  • TMS9981 CRU I/O in the IQR 83

    Anders Dinsen12/23/2023 at 13:42 0 comments

    The IQR83 main computer communicates with the outside world through the obscure TMS9900 "CRU" interface. CRU is short for "Communications Register Unit". 

    The CRU interface has been described as 4096 wires but it is actually one input pin, one output pin, a clock-out signal, and a number of address bits. The pinout of the TMS9981 is shown below with the CRU and address pins that are relevant on the IQR 83.

    On the IQR 83 only the four least significant address pins are brought out to the outside world, but there's a thing here to note about the TMS9981: Texas Instruments numbered the most significant address and data bits number 0, and the least significant number 15. This is opposite of what most other CPU manufacturers did at the time - and obviously opposite of what everybody does today. Blaupunkt/BOSCH, however decided to number the data- and address bits in the conventional way so in the schematics of the radio, the numbering of the bits are like we're used to today.

    That's why I've hand written A0, A1, A2, and A3 on the pinout and for the rest of this log entry, I'm using the numbering used by Blaupunkt/BOSCH. Below is the schematics for the bus board connecting the CPU board to the outside world with the relevant I/O lines highlighted:

    Another thing to note is that while A0-A3 is brought out, but A0 is used for the CRU-OUT signal, so the address pins in use for CRU I/O are A1, A2, A3.

    Confused? I hope not. Also, I think it makes sense once you see the software and hardware implementations.

    The idea behind the CRU interface is that the CPU addresses one I/O bit at a time: The CRUCLK latches out whatever bit is on A0 as to whatever address is selected. Decoding is simple and requires only an address decoder and a bit addressable latch. This can be implemented in standard TTL circuits. An 74LS259 8 bit latch for CRU-output is used in the IQR83.

    For input, the situation is a little different: There's one common CRU-IN signal shared by all input devices. However, only the one being addressed on the address lines must output a signal to CRU-IN. The CPU reads whatever is on the line. Again, this can be implemented in standard TTL circuits. An 74LS251 8 bit multiplexer for CRU-input is used in the IQR83.

    The image below is a cut-out of the interface schematics. I've marked the CRU-OUT, CRU-IN, and CRU-CLK signals yellow and the address pins green:

    The TMS9981 has three CRU I/O instructions:

    • Set bit to one: SBZ
    • Set bit to zero: SBO
    • Test bit: TB

    The first two take a CRU address and outputs either a 1 or 0 to the CRU-OUT line along with a CRU-CLK to latch it out. The third instruction takes a CRU address and loads the CRUIN into the "EQUAL" bit in the CPU status register. This bit can then be tested with a jump instruction, for example.

    Below is an example of disassembled routine in the TMS9981 firmware that outputs a command to the TMS5100 speech synthesizer. I'll describe how that works later, for now it's enough to know that the speech synthesizer is connected through a serial bus with a separate clock signal (NOT the CRU-clock, but a clock signal GENERATED by CRU-out-instructions SBZ and SBO), a data line, and an enable line that strobes data into the TMS5100. The routine illustrates how the SBO and SBZ instructions are used to send commands to the TMS5100:

    XOP4      LIMI    >0001            ; Send a command to the speech synthesizer interface
              MOVB    *r11+,r5         ; R11 contains a pointer to the command to send
              MOVB    *r11+,r4       
              SRL     r4,8             
              MOV     *r11+,r1       
              MOV     *r11,r12       
              SBZ     0                ; ENA0 = 0 => get ready to strobe data out 
              MOV     r11,r9           
              LI      r12,>0000       
    L1        LI      r2,>0001         
              MOV     *r1+,r3         
    L2        COC     r2,r3            ; Shift out a bit
              JEQ     L5               ; Bit is a ZERO
              SBZ     7
              JMP     L4          
    L5        SBO     7                ; Bit is a ONE
    L4        SBO     6                ; Trigger the clock = 1
              SBZ     6                ; Clock back to 0
    Read more »

  • The beginning

    Anders Dinsen11/28/2023 at 20:12 0 comments

    I got my Blaupunkt IQR 83 used, not working, and without history: It powered on and could play a tape, but the radio didn't work. My initial idea was to repair it but as I started looking into things, I realized that perhaps there was a better solution than "just" making it work.

    But let me go back to why I bought it at all and the nostalgia that got me. 

    I grew up north of Copenhagen in a posh area. These radios were outrageously expensive but there were people in my home area who could afford them back then. Mine carries an original sticker from Vedbæk Radio & TV, a shop in a nearby town that used to sell these units. 

    In 1983, when the IQR 83 was released, my family drove an old Renault 16. It was a 1973 model as far as I remember, blue where the rust hadn't already eaten the panels. Our car only had a fake radio in the dash but around 1980 my father bought the cheapest Blaupunkt radio he could find and made a wooden box with a pair speakers for it and fitted the assembly under the dash. The sound quality was horrible, but at least he could listen to the news when driving to and from work. 

    Much later, when the car was scrapped, I got the old Blaupunkt and took it apart. It eventually went in the trash but thinking about the ealy 1980's Blaupunkt has made me nostalgic about these units.

    When I saw the IQR 83 on the used market for a fair price I googled it and found a service manual. Three things caught my attention: The complexity of the system is impressive - it would take time and work to restore it: A good winter project. Also, the firmware for the microcomputer inside is stored in an EPROM meaning it can be disassembled and possibly modified.

    But one thing fascinated me even more: The CPU is a Texas Instruments TMS9981, the embedded version of the TMS9900.

    My sister used to have a TI-99/4A which had the TMS9900. I spent many hours reading data sheets on CPU's back in the early 1980's, and the TMS9900 series fascinated me. The TI-99/4A was an overcomplicated design for a home computer but the 16-bit CPU had an interesting architecture and a great instruction set. For a while I was looking at the TMS9995 based Cortex as something I could build for myself. I eventually got my hands on a Z80-based motherboard, a pair of diskette drives, and took the CP/M route though.

    Getting the chance to finally work with a TMS9900 based system here convinced me. I bought the kit for the asking price from the seller.

    Here's what I received nicely packed in the mail: