Martin, I wonder what happens if the reset is out of sync and the Atmega88 is raising busy too late or is loosing serial clocks. Is the 65C02 on 1 MHz? What is the startup delay (fuses) for the Atmega88? If you reset the board when it is working, does it come back working all the time?
You may want to try a weak pullup (about 47k) on the handshake bit to guarantee, that the Atmega88 signals busy early in its reset
Daryl, instead of defining a fixed busy signal, toggeling the handshake bit after receiving a character would remedy many of the current workarounds. The old idle state automatically becomes the new busy state, so the 6502 does not need to wait for it. The Atmega toggles to idle again when the data in SPDR has been saved to the input register instead of waiting for jsr ProcChr or the minimum time of 8 µs.
There is one disadvantage: 1 Byte is needed in RAM, preferably in zeropage.
Proposed code changes not tested! The 6502 Video driver:
Code:
; The modification to toggled handshake requires a reserved byte in RAM
V_idle = $ee ; Bit 7 holds the next expected idle state
;----------------------------------------------------------------------
; Output contents of A to the Video Display
; A is preserved, Flags are changed.
;----------------------------------------------------------------------
VOutput
pha
lda V_idle ; toggle to new expected idle state
eor #$80
sta V_idle
VOutput1
lda Via2PRB ; test handshake bit (pb7)
eor V_idle ; is old idle state (xored bit7=1)?
bpl VOutput1 ; if pb7=busy wait for AVR idle
pla
sta Via2SR ; send to display via shift register
rts
;----------------------------------------------------------------------
; Call this once to initialize the interface
; it sets up Port B, pin 7 and CB1/CB2 for serial mode
; A is changed and Flags are changed.
;----------------------------------------------------------------------
VInitDisp
sei ; disable interrupts
lda Via2DDRB ; get ddr b
and #$7F ; force bit 7=0
sta Via2DDRB ; set bit 7 to input
lda Via2ACR ; get ACR contents
and #$E3 ; mask bits 2,3,4
ora #$18 ; set Shift out under control of PHI2 mode
sta Via2ACR ; store to acr
lda #$04 ; shift register flag in IER
sta Via2IER ; disable shift register interrupts
lda #0 ; set initial expected idle state
sta V_idle
cli ; Enable Interrupts again
rts ; done
The ATMega's video.asm main loop part checking for new data in SPDR:
Code:
main3:
SERIN1:
in i, SPSR ; get shift register status
sbrs i, SPIF ; Wait for reception complete
rjmp Main
st Y, Curschr ; restore chr under cursor
in inpt, SPDR ; Read received data
sbi pinb,hsp ; Toggle busy -> idle (SPDR available)
; on the older ATMega8 you need to replace the SBI pinx with the next 4 lines
; in i,portb ; Toggle busy -> idle (SPDR available)
; ldi j,(1<<hsp)
; eor i,j
; out portb,i
rcall ProcChr ; process received data
rjmp Main ; repeat