Skip to content

A hard day with the timer

October 26, 2015

I spent a couple of hours today banging my head against the timer interrupt circuit. My original idea of having the avr issue a 1khz square wave didn’t quite work because the Z80’s interrupt is level sensitive. The interrupt routine just kept triggering for half of each millisecond. Looking at the front panel circuit, lee is using a 74hc393 as a sort of flip flop with a 1khz clock setting it and the cpu card’s /OUT signal clearing it. I tried wiring up a pair of and gates as a flipflop but this didn’t work and was too messy to debug.
15-10-26 flipflop
I moved the set/reset logic into the avr and so far so good. The /out reset pulse is fairly short and i wasn’t sure the avr was fast enough to catch it and turn off the signal before the Z80 triggers again. I wrote the code below which, after much dicking around, works.

	while(1){		//loop
		PORTB=((1<<nkhz)|(1<<rst));//assert the clock(leave /rst high)
		while(PINB & (1<<ntclr)); //wait for z80 to clear it
		PORTB=((1<<khz)|(1<<rst));//de-assert the clock;(leave /rst high)
		_delay_us(1000);	// 1khz cycle
	}

In the screenshot below I’m using the serial monitor to display the tick counter and i see it changing from one call to the next.
15-10-26 terminal

I feel like the code is risky though. you could, in theory get some sort of stall where the avr was waiting for an ack which the z80 doesn’t send. a reset or serial data would clear it but it feels icky.

In terms of timing, the logic analyzer trace below shows the /khz clock go low on the top line. Below that and 33 uS later, the Z80 acknowledges the interrupt with a .5 uS pulse. The AVR then takes about .5 uS to de-assert the signal. This should allow enough headroom for me to improve the code to avoid a race or stall.
15-10-26 saleae

//Oct 21 2015 attiny85 pgm to power on reset Z80 then provide 1 khz clock
//oct 26 corrected def of nkhz
//oct 26 zmckhz1 - tyring to incorporate logic to let z80 clear interrupt

//to program with pololu programmer 
//-choose AVRISP (near bottom of programmer list)
//-can leave port at auto
#include <avr/io.h>     
#define F_CPU 8000000UL // 8 MHz
#include <util/delay.h>
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif 
#define khz		4	//my +1khz clock output on PB4(IC pin 3) to /INT
#define nkhz	2	//my -1khz clock output on PB2(IC pin 7) to IN6
#define rst 	3	//reset signal on PB3(IC pin 2)
#define ntclr	0	//timer interrupt clear on PB0 (IC 4) from/out

int main(void)
{
	sbi(DDRB,rst);	//z80 reset pin as output
	sbi(DDRB,khz);	//khz clock pin as output
	sbi(DDRB,nkhz);	//nkhz inverted clock pin as output
	cbi(DDRB,ntclr);//khz clock pin as input

	cbi (PORTB,rst);	//drive z80 into reset
	_delay_ms(200);	//to clear startup jitters
	sbi (PORTB,rst);	//take z80 out of reset

	while(1){		//loop
		PORTB=((1<<nkhz)|(1<<rst));//assert the clock(leave /rst high)
		while(PINB & (1<<ntclr)); //wait for z80 to clear it
		PORTB=((1<<khz)|(1<<rst));//de-assert the clock;(leave /rst high)
		_delay_us(1000);	// 1khz cycle
	}

	return 1;
}
Advertisements

From → Olduino/Z

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: