STOP instruction and DRAM refresh

Nagging hardware related question? Post here!
Post Reply
Silvester
Gold Card
Posts: 436
Joined: Thu Dec 12, 2013 10:14 am
Location: UK

STOP instruction and DRAM refresh

Post by Silvester »

Back in 1994 I added some 8 bit DACs to Trump card QL to control an analogue synthesiser. Just for fun I tried playing 8-bit stereo sampled sound though them. I used the timer in a 6522 to generate level 5 interrupts at appropriate rate (8KHz etc). Problem was I got a crackling sound along with the audio. Thinking about I realised the interrupt latency on 7.5MHz 68008 during a MOVEM.L versus MOVEQ instruction would be significant enough to cause noise. Solution was to use STOP instruction to halt CPU until timer interrupt woke up CPU to serve DAC ports, result was clear sound :-)

(Q40 interrupts 40MHz 68040 at 10/20 KHz for sound, I guess it may use low pass filter on output?)

Only recently I was looking at Trump card and ExpanderRam and realised 68008 DSL output is used as clock source to refresh DRAMs!. AFAIK this means using the STOP instruction could potentially upset refresh and corrupt DRAM. OK, bit specific to my use, but unexpected. Though I guess ordinarily it would be possible use STOP instruction and shut out refresh for upto 20mS waiting on level 2 interrupt.

Reminds me of when I built ZX81 programmer for 2K eproms (from a magazine design). It stalled Z80 using 50mS monostable to hold WAIT low during programming pulse, somehow it worked. Playing around, I found it sometimes took up to 2 seconds holding WAIT low to corrupt ZX81 16K rampack contents.


David
Nasta
Gold Card
Posts: 443
Joined: Sun Feb 12, 2012 2:02 am
Location: Zapresic, Croatia

Re: STOP instruction and DRAM refresh

Post by Nasta »

I'm sorry to say the way yo were doing the DAC write would be considered bas system design. The correct way is to use double-buffering. I.e. the interrupt source (timer) actually writes the previous sample from a buffer register into the DAC (so no latency) and then expects the CPU to re-fill the buffer register before the ext interrupt occurs (which gives it a lot of latency tolerance before problems arise). In fact, it may also come to a proper selection of the DAC chip as some indeed have input buffers precisely for this purpose.
Another possibility is using a hardware FIFO buffer - this is even better if you have multiple DACs, as you can then buffer data for all of them in the same FIFO. FIFO chips often are 9 bit wide instead of 8. This is used for various purposes and in your case could be used to re-synch the order in which the DACs are written, so simple logic can cater for any number of DACs to be written per interrupt. If the FIFO length is chosen well, you can even avoid having a synchronous interrupt for sample playback, as long as there is another interrupt that is fast enough for the software to trigger on it and check and fill-up the FIFO.


Silvester
Gold Card
Posts: 436
Joined: Thu Dec 12, 2013 10:14 am
Location: UK

Re: STOP instruction and DRAM refresh

Post by Silvester »

The DACs were never intended to do 8 bit sound, just a relatively slow control voltage for analog synth.

But there is a difference between interrupt occurring mid-instruction (68008 7.5MHz = 133nS clock)

MOVEM.L A0-6/D0-D7,-(a7) (IIRC 300+ clocks)

versus

MOVEQ #0,D0 (8)

i.e. regardless of what/where interrupt serviced

Whereas STOP curtailed noise because the reaction time to interrupt is consistent.


David
Nasta
Gold Card
Posts: 443
Joined: Sun Feb 12, 2012 2:02 am
Location: Zapresic, Croatia

Re: STOP instruction and DRAM refresh

Post by Nasta »

Yes, I understand that, it's a common problem.
But I am not sure you understood the hardware technique to get around it in order not to stop the CPU completely while controlling the DACs.
Double buffering means putting a register (usually something like a 74HC273) in front of the DAC data lines (unless it already has one built in) so that interrupt servicing actually writes the data for the DAC that is going to be valid on the NEXT interrupt, not the current one, while the contents of DAC are valid for this one.
The timer which is the source of the interrupt writes the contents of the buffer register into the DAC(s) by hardware (so new data is written into the DAC synchronously with the timer timeout and not subject to CPU interrupt latency) and at the same time causes an interrupt. The contents of the buffer register are now free to be written by the CPU with new data, and the CPU can then service the interrupt at it's leisure as long as it does it before the next timer timeout, by fetching the required byte for the DAC and writing it into the buffer register.
Of course, when this is set-up, the first byte of a series of bytes to be written into the DAC(s) is written initially into the buffer and then the timers are set and interrupt enabled. When the last byte is written, one more interrupt has to occur (for data to be written into the DAC) but the only thing the CPU has to do at this point is stop the timer and disable further interrupts.


User avatar
Dave
SandySuperQDave
Posts: 2765
Joined: Sat Jan 22, 2011 6:52 am
Location: Austin, TX
Contact:

Re: STOP instruction and DRAM refresh

Post by Dave »

I did a DAC circuit in the early 90s that was double buffered as Nasta described, also to produce a CV output for controlling an analogue synth. It also warbled and was quite unstable.

It turned out that each step the buffer and logic would eat power and the R2R ladder would see a drop in input current. Using larger tants and a better PSU solved the problem.


Nasta
Gold Card
Posts: 443
Joined: Sun Feb 12, 2012 2:02 am
Location: Zapresic, Croatia

Re: STOP instruction and DRAM refresh

Post by Nasta »

Heh, it is easy to forget that even digital is 'analog' and where the two meet, if one is not careful, trouble is guaranteed. With both DAC and ADC chips, it must be carefully considered what the analog and digital supplies are. Strangely enough, some chips (not to mention datasheets) have odd notions about this. For instance, a small DAC chip made by Philips that used to be very popular, does not even have a separate digital power supply which prove to be a nearly endless source of confusion when implementing it...


Silvester
Gold Card
Posts: 436
Joined: Thu Dec 12, 2013 10:14 am
Location: UK

Re: STOP instruction and DRAM refresh

Post by Silvester »

Perhaps this might help.

The interrupt routine takes a consistent time from the moment of the interrupt to serve DAC port (see below). The latency in response (erratic) was due to instruction completing. Stopping the processor using STOP made this delay consistent.

Here's the actual code used (back in 1994)

(BTW the 68008 IPL1 & IPL0/2 lines need to be rewired through priority encoder to use level 5)

Code: Select all

* this code just CALLed from Basic

        ...                   set up timer to generate interrupts
        move.w  sr,d7         preserve SR
        trap    #0            into supervisor mode
        move.l  #busyptr,a4   pointer to busy flag
        sf      (a4)          busy ($00)
wait    stop    #$2200        freeze CPU until interrupt >2 occurs
        tst.b   (a4)          playback completed?
        beq.s   wait          no
        ...                   clear timer interrupts
        move.w  d7,sr
        moveq   #0,d0
        rts

* interrupt level 5 points here (constant execution time)

level5  movem.l a4-5,-(a7)    two registers required
        move.l  #queue,a4     queue pointer
        move.l  (a4)+,a5      get current position
        move.b  (a5)+,dac1    left
        move.b  (a5)+,dac2    right
        cmpa.l  (a4),a5       are we at end?
        slt     busyptr       $FF if done
        move.l  a5,-4(a4)     update running pointer
        movem.l (a7)+,a4-5    restore registers used
        tst.b    iack         acknowledge interrupt
        rte

* sample data 

busyptr dc.b    $FF           busy flag ($00 if busy)

queue   dc.l    sample        running pointer
        dc.l    last          end pointer

sample  dc.w    ....          left/right bytes
        dc.w    ....
last

******************************************************
* Minerva ROM alterations for level 5 use:           *
*                                                    *
* M_ss_base_asm    redirect level 5 interrupt        *
*                                                    *
* M_ip_int_asm     only raise interrupts to level 2  *
* M_mt_ipcom_asm   "    (ie. replace ori #$0700,sr   *
* M_mt_baud_asm    "         with move.w #$2200,sr ) *
* M_od_ser_asm     "                                 *
*                                                    *
* M_dd_mdvsc_asm   unchanged (ori #$0700,sr)         *
* M_md_formt_asm   "                                 *
* M_nd_phys_asm    "                                 *
******************************************************



David
Silvester
Gold Card
Posts: 436
Joined: Thu Dec 12, 2013 10:14 am
Location: UK

Re: STOP instruction and DRAM refresh

Post by Silvester »

Oops, for some weird reason I didn't see other messages from Sunday onwards when posting last message (old page cached?).

Nasta, I understand the hardware solutions you suggested, but I never intended to play samples on a 68008 QL. My design simply used HC273 latch in front of ZN426 (which has no latch itself).

(I wouldn't have mentioned playback problem, it was just cited to qualify using STOP instruction, and possible refresh problem.)

Wonder what Q40 does, TT's SSSS code does pretty much what I did for interrupt server. Q40 docs only detail hardware registers, no mention of dual latch mechanism for DACs.

Update: Q40 uses DAC8228 (dual 8 bit), single latch for each channel, each separately addressed internally using common 8 bit bus (so no dual-latching). Though nice device, has internal CMOS Op-amps and fast 50nS access time.


David
Post Reply