Testing an MC6828 Priority Interrupt Controller

I bought several MC6828 Priority Interrupt Controllers (PICs) and would like to use my Arduino Uno to test them. These are peripheral chips for Motorola's MC6800 and MC6809 CPUs.

I've built a test harness on breadboard and written code. At first I thought the chips were bogus (bought from Chinese seller) but I found the same behavior with another (bought from US seller) so think I've messed up my hardware setup.

Background
When the MC6800 CPU receives an interrupt signal (IRQ input pulled low) it requests the location of the interrupt service routine at memory locations $FFF8 and $FFF9. The 6828 can change the address requested depending on which of its eight input lines is pulled low.

It does this by sitting on four lines on the 16-bit address bus (A1-A4). During ordinary operation the 6828 passes the A1-A4 bits through to Z1-Z4. When an interrupt pulls one of its eight interrupt lines low the 6828 signals the CPU IRQ line and then sets Z1-Z4 so that execution jumps to an address that is specific to the incoming interrupt.

Test Hardware
This high-level schematic illustrates where the 6828 sits in relation to the CPU and the "external memory device" (i.e. ROM).

6828_Arduino_Tester_Logical.png

This abbreviated test harness schematic shows how I've configured the testing hardware. GND and +5V connect to the Uno. The Arduino controls the clock input E, chip select CS1, and IN0 (interrupt zero). It monitors the CPU interrupt INT, Z1-Z4, and the clock stretch output STR.

6828_Arduino_Tester_Schematic.png

The 6828 datasheet defines a HIGH output as >= 2.4V (and the INT output is open collector) so pullups are activated on the Arduino input pins. LOW output is 0.5V.

Expected output on Z1-Z4 is b0010.

Algorithm:
Here is the waveform diagram for the interrupt process (ignore the "Masked Mode section") as well as a functional flowchart (flowchart has an error: it says interrupt vectors go on A1-A4 when they actually go on Z1-Z4).

Here's my code:

/*
MC6828 Priority Interrupt Controller test program.
*/

// 6828 outputs
const int _6828_STR  =  6;  // inverted
const int _6828_INT  =  8;  // inverted
const int _6828_Z4   =  9;
const int _6828_Z3   = 10;
const int _6828_Z2   = 11;
const int _6828_Z1   = 12;
// 6828 inputs
const int _6828_E    = 13;
const int _6828_IN0  =  7;  // inverted
const int _6828_CS1  =  5;


void clockPulse(const int clock_pin) {
    digitalWrite(clock_pin, HIGH);
    delayMicroseconds(1);
    digitalWrite(clock_pin, LOW);
    delayMicroseconds(1);
}

void print6828PinData(const char* msg) {
    int intPin     = digitalRead(_6828_INT);
    int stretchPin = digitalRead(_6828_STR);
    int z4Pin      = digitalRead(_6828_Z4);
    int z3Pin      = digitalRead(_6828_Z3);
    int z2Pin      = digitalRead(_6828_Z2);
    int z1Pin      = digitalRead(_6828_Z1);

    Serial.print(msg);
    Serial.print(" : ");
    Serial.print("/INT: ");
    Serial.print(intPin);
    Serial.print(", /STRETCH: ");
    Serial.print(stretchPin);
    Serial.print(", Z4: ");
    Serial.print(z4Pin);
    Serial.print(", Z3: ");
    Serial.print(z3Pin);
    Serial.print(", Z2: ");
    Serial.print(z2Pin);
    Serial.print(", Z1: ");
    Serial.println(z1Pin);
}

void setup() {
    Serial.begin(9600);

    Serial.println("Initializing Arduino pins...");
    pinMode(_6828_INT,  INPUT_PULLUP);
    pinMode(_6828_STR,  INPUT_PULLUP);
    pinMode(_6828_Z4,   INPUT_PULLUP);
    pinMode(_6828_Z3,   INPUT_PULLUP);
    pinMode(_6828_Z2,   INPUT_PULLUP);
    pinMode(_6828_Z1,   INPUT_PULLUP);
    pinMode(_6828_E,    OUTPUT);
    pinMode(_6828_IN0,  OUTPUT);
    pinMode(_6828_CS1,  OUTPUT);

    digitalWrite(_6828_CS1, LOW);
    digitalWrite(_6828_IN0, HIGH);
    digitalWrite(_6828_E,   LOW);

}

void loop() {
    clockPulse(_6828_E);
    print6828PinData("Initial    ");

    // INj goes low
    digitalWrite(_6828_IN0, LOW);
    clockPulse(_6828_E);

    // PIC pulls IRQ low
    print6828PinData("Interrupt! ");
    clockPulse(_6828_E);

    // Processor starts interrupt routine
    // Processor puts FFF8 on address bus
    // Decoder enables PIC
    digitalWrite(_6828_CS1, HIGH);
    // Stretch goes low, slowing clock
    // PIC puts 1st interrupt vector on Z1-Z4 (0010)
    print6828PinData("Chip select");
    // Processor reads 1st translated address byte from ROM
    clockPulse(_6828_E);

    // Processor puts FFF9 on address bus
    // Stretch goes low, slowing clock
    // PIC puts 2nd interrupt vector on Z1-Z4
    print6828PinData("Vector2     ");
    // Processor reads 2nd translated address byte from ROM
    clockPulse(_6828_E);

    digitalWrite(_6828_CS1, LOW);
    digitalWrite(_6828_IN0, HIGH);
    print6828PinData("Clear      ");
    clockPulse(_6828_E);

    print6828PinData("Final      ");
}

[Edit: corrected subject; added expected Z1-Z4 output; moved images into text]

6828_Arduino_Tester_Logical.png

6828_Arduino_Tester_Schematic.png

The following output appears in the serial monitor:

Initial     : /INT: 1, /STRETCH: 1, Z4: 1, Z3: 1, Z2: 0, Z1: 0
Interrupt!  : /INT: 1, /STRETCH: 1, Z4: 1, Z3: 1, Z2: 0, Z1: 0
Chip select : /INT: 1, /STRETCH: 0, Z4: 1, Z3: 1, Z2: 0, Z1: 0
Vector2      : /INT: 1, /STRETCH: 0, Z4: 1, Z3: 1, Z2: 0, Z1: 0
Clear       : /INT: 1, /STRETCH: 1, Z4: 1, Z3: 1, Z2: 0, Z1: 0
Final       : /INT: 1, /STRETCH: 1, Z4: 1, Z3: 1, Z2: 0, Z1: 0

So it looks like the Interrupt output doesn't go low and Z1-Z4 are the same as A1-A4. But the stretch output looks correct.

If I unplug the +5V pin, though, this is the output:

Initial     : /INT: 1, /STRETCH: 1, Z4: 1, Z3: 1, Z2: 0, Z1: 0
Interrupt!  : /INT: 0, /STRETCH: 0, Z4: 0, Z3: 0, Z2: 0, Z1: 0
Chip select : /INT: 0, /STRETCH: 0, Z4: 0, Z3: 1, Z2: 0, Z1: 0
Vector2      : /INT: 0, /STRETCH: 0, Z4: 0, Z3: 1, Z2: 0, Z1: 0
Clear       : /INT: 0, /STRETCH: 1, Z4: 0, Z3: 1, Z2: 0, Z1: 0
Final       : /INT: 1, /STRETCH: 1, Z4: 1, Z3: 1, Z2: 0, Z1: 0

This looks correct! Can someone help me understand what's going on?

[Edit: Thanks in advance for any help, and I apologize if this is too much data or if it's in the wrong place]

Since this is an arduino forum, not a 6800 forum, you can probably omit all of the explanation of the 6800 operation and simply refer to arduino pins and code or the 6828 pins. There is no IRQ pin on an arduino so mentioning this
doesn't really help. All we need to know should be how the arduino relates to the 6828, not how the 6828 relates
to the 6800. At least that's my opinion (humble or not).

To be frank, I don't see a schematic showing the arduino connected to the 6828, which I would think we need.
Can you draw a schematic showing the arduino and the connections to the 6828 on a blank sheet of printer paper , take a photo, and post it ? I know you listed the arduino pins in the declarations but it's much easier to visualize
with an actual schematic and I don't see one of the arduino connected to the 6828. The hard wired 6828 connections are useful though, for reference anyway.
I don't think the waveform diagram is helping since we don't have a scope to look at. Not sure if the flow chart helps either. Both of those seem to complicate matters. Can we just stick to the arduino connections and code ?

Hi raschemmel, thanks for your response.

My goal with this tester is to verify that the 6828s I received are genuine. To do that I need to verify the outputs and timings. So while there's no IRQ pin on the Arduino I still would like to monitor the 6828 interrupt pin output over time. You're quite correct about the focus of these forums and I apologize about the quantity of 6800-related content. I debated whether or not to include the waveforms & flowchart and decided to err on the side of too much info.

Here's an updated version of the schematic. I hope it's clearer:

6828_Arduino_Tester_Schematic.png

There is clearly some sort of electrical incompatibility in play between the NMOS 6828 and the CMOS Arduinio/ATmega328. I've heard of instances in which TTL chips have been powered via their input pins but usually that messes things up. This is the first time I've seen a case in which that caused an ic to function properly.

Here are some possibilities. Maybe there are others?

  1. Use a pin other than 13 for the input clock. I seem to recall reading somewhere that it's not guaranteed to output 5V because it also drives the LED.
  2. Power the 6828 from a dedicated supply instead of using the Arduino's power pins. But make sure to use a common ground!
  3. Buffer the 6828 outputs.
  4. The clock input needs to be at a regular frequency, so use a dedicated frequency source and use it to trigger interrupts on the Arduino to check pin levels.
  5. That blindingly obvious thing that, when understood, will cause me to smack my head and then take a nap.

[Edited for clarity]

6828_Arduino_Tester_Schematic.png

There is clearly some sort of electrical incompatibility in play between the NMOS 6828 and the CMOS Arduinio/ATmega328. I've heard of instances in which TTL chips have been powered via their input pins but usually that messes things up. This is the first time I've seen a case in which that caused an ic to function properly.

First things first. I read your OP, and I don't know why , but I am unable to locate the following:
List of symtoms
1. blah blah
2. blah , blah
3. blah, blah

Output and problem description are provided in my second post.

If I can make a suggestion, before doing anything else, can you just change the baud rate to 115200 and try it
again. If that doesn't work then do you know how to read and write to the arduino EEPROM , or maybe before
trying that, can you create variables and store values in variables with NO SERIAL PRINT OUTPUT during the test
and when the test has completed, dump all the print all the values to the serial monitor ? I have found that the
serial print delay messes up a lot of things and there is no error checking so I wouldn't even believe any serial
output that is occuring during the test. Disable all serial output and dump the variables to the screen later after
the test is done. You obviously know how to capture serial output so it doesn't matter how long the dump is.
Personally, my preference is to do one thing and one thing only and not proceed to the next thing until the first
thing works. This means change your code such that it checks one pin and if that pin output is correct then it
proceeds to the next one. Obviously , this a diagnostic measure and not a test plan. The second thing is you need
to eliminate timing (as opposed to electrical incompatabilities) before making any assumptions, so you need to
change the code so it does not go to the next pin until you hit the spacebar to confirm that the current pin
has output a correct value. This completely eliminates timing as an issue during this stage of testing. This means
you need to look at the code and generate a numbered "to do " list that has one test (pin or whatever) and one
output associated each item on the list such that at the end you can say "everything was correct except items
15 and 27 etc."
There is no point in performing 20 or 30 pin tests if half of them are garbage . Don't test any pins until the previous pins have behaved properly. Yes, you are slowing down time, which increases total test time, but right now, what
do have of value really ?

Thanks raschemmel. I'll try those. I really like the idea of storing values and printing them after.

I was worried about timing especially with the clock input, but the 6828 datasheet only specifies a minimum width for the clock pulse (100ns) and not a maximum.

Thanks again and good luck.

Thanks again and good luck.

I think you're the one who needs the luck. I'm an old Electronics Engineering Technician making more money
working during a pandemic than I ever have in my 38 years in the industry so I think I'm good on luck.

LOL--sure thing buddy. Bye.

You might try increasing your delays or compare values read with known correct value or some other error checking method.

I would connect the R/W to an Arduino output on these sorts of chips for a thorougher work out of the chip.

So how's it going ? Made any progress ?