English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 16 January 2020, 01:29   #1
Herpes
... aka Amix73
 
Herpes's Avatar
 
Join Date: Jan 2009
Location: Austria
Posts: 87
Cannot use AUDX-INT (Level 4 IRQ) to stop sample.

Hi there!
Since I have some days off I play around with 68K assembly. What I want is to play samples one time and than it should stop or bet stopped.

Unfortunately, I have a behavior I don't understand.

I wanted to use Level 4 interrupts (AUDx) to stop the sample which was started via DMA. My understanding was whenever the last data-word was read a Level 4 INT for the channel is issued.

My handler code loooks like this:
own_level4_handler:
Code:
movem.l   d0-a6,-(a7)
    ; waste some time - but show it
    move.w  #$0fff,$180(a6)            ; WHITE flash
    move.w    #$2ff,d0                     ; wait x lines to waste some time
    bsr.w    loop_n_time
    move.w    #$0000,$180(a6)       ; back to black
    ; The plan was to stop DMA of channel 0 by:
    ; move.w    #$0001,$096(a6)     ; AUD0 DMA off
    move.w    #$0080,$09c(a6)
    movem.l   (a7)+,d0-a6       
   rte
I registered the handler like this:[/FONT]
Code:
 
    ; in a4 is the vbr
    lea        own_level4_handler(pc),a1
    move.l    a1,$70(a4)
I enabled ONLY AUD0 INT (level 4) with the following statement:
Code:
move.w    #$c080,$9a(a6)                    ; intena-wr SET:INTEN--|---AUD0|----|----
When I trigger to play a sample via the rmb
the sample plays continuously of course and the screen flashes white on different locations since DMA-switch-off is disabled. That's what I expected.

BUT when I enable the line: 'move.w #$0001,$096(a6)' to stop the AUD0-DMA
I hear NOTHING at all - it seems that the DMA is instantly stopped.
Furthermore I see 3 white areas on the screen which indicates that the IRQ-handler is called 3 times consecutively.

WHAT am I doing wrong.
Any help much appreciated.
Thanks.

Last edited by Herpes; 16 January 2020 at 01:33. Reason: removed the font-tags
Herpes is offline  
Old 16 January 2020, 04:25   #2
FSizzle
Registered User
 
Join Date: Nov 2017
Location: Los Angeles
Posts: 49
The Audio interrupt triggers not at the end of playback, but rather shortly after the start when the audio registers have been internally copied. This allows you to queue the "next" waveform shortly after the start of the current one so that you can have seamless playback.

In your interrupt, you are stopping the DMA at the very start of playback, which is why you no longer hear anything. As I understand it, the correct way to stop the audio from looping is in the interrupt to set it to point to a short and "empty" sample so the "next" sample plays nothing.

If you really want to stop DMA entirely, then you'll need to do that on the second interrupt (for the start of the "empty" sample). You usually need to track some global state for your interrupt to know what state a given channel is in and what you should do.

Last edited by FSizzle; 16 January 2020 at 04:38.
FSizzle is offline  
Old 16 January 2020, 09:18   #3
Herpes
... aka Amix73
 
Herpes's Avatar
 
Join Date: Jan 2009
Location: Austria
Posts: 87
First, thanks for your quick answer.
I have to test your approach - I had this in mind but did not give it a chance because I thought I would trigger another Interrupt when I initialize the empty sample.
BUT OK, if it is like you say - then I misinterpreted the Amiga-HRM.
Quote:
This level 4 interrupt signals "audio block done."
When the audio DMA is operating in automatic mode , this interrupt occurs when the last word in an audio data stream has been accessed. In manual mode , it occurs when the audio data register is ready to accept another word of data.
For me it reads as I would have the chance to initialize the next sample while the last audio word is 'streamed'.
Furthermore it does not make much sense to trigger after the start since this is the exact time I know anyway since I just kicked off the sample.

So I am not sure where my mistake is.
Anyway, thanks to your input I can experiment a little without being too frustrated.

Last edited by Herpes; 16 January 2020 at 09:18. Reason: typo
Herpes is offline  
Old 16 January 2020, 12:21   #4
Herpes
... aka Amix73
 
Herpes's Avatar
 
Join Date: Jan 2009
Location: Austria
Posts: 87
CHEEESSSSS!
It seems you are right! I cannot believe it!
Now I used a bit longer sample, started its DMA and immediately its AUDx channel INT was triggered.

To achieve a single-shot-sample using the IRQ handler I have to ignore the first INT. Then when the sample restarts I process the INT and switch off the DMA to stop it.
That works so far...

Haha, BUT doing that during the INT leads IMMEDIATELY to another execution of the INT-handling routine again - unbelievable!

My code might be broken but this is it:
Code:
own_level4_handler:
    ; AUD0 INT ocurred -  because no other Level4 INT is allowed
    movem.l    d0-a6,-(a7)        ; save all registers
    move.w    #$0080,d0           ; erase IRQ bit: off---|----|AUD0---|----
    move.w    d0,$dff09c          ; intreq (write)
    move.w    d0,$dff09c          ; twice to avoid a4k hw bug
    lea        aud0_cnt(pc),a0    ; fetch the counter to ignore first INT
    move.w    (a0),d1
    bne.s    .process_irq
    addq.w    #1,d1
    move.w    #$0f00,$180(a6)     ; RED flash to indicate ignorance of INT
    move.w    #$02ff,d0           ; wait 767 loops to waste some time
    bsr.w    loop_n_times
    move.w    #$0000,$180(a6)     ; back to black
    bra.s     .exit_aud0
.process_irq
    move.w    #$0fff,$180(a6)     ; WHITE flash to indicate processing of INT
    move.w    #$02ff,d0           ; wait 767 loops to waste some time
    bsr.w    loop_n_times
    move.w    #$0000,$180(a6)     ; back to black
    move.w    #$1,$dff096         ; switch OFF the DMA for J.Miner's sake!
    moveq    #0,d1                ; rest counter to ignore next INT.
 .exit_aud0    
    move.w    d1,(a0)             ; store irq count
    movem.l    (a7)+,d0-a6        ; restore all registers
    rte
aud0_cnt:    dc.w    0
This leads to the following screenshots:

[1] First_INT_Trigger.png
Click image for larger version

Name:	First_INT_Trigger.png
Views:	82
Size:	1.7 KB
ID:	65919

[2] Second_INT_Trigger.png
Click image for larger version

Name:	Second_INT_Trigger.png
Views:	95
Size:	1.7 KB
ID:	65920

@First_INT_Trigger - you see I triggered the start of the sample. which can be seen by the purple area, followed immediately by the red area which is the IGNORED AUD0-INT.

@Second_INT_Trigger - you see there are TWO WHITE areas. IMO this is BECAUSE when switching OFF the DMA triggers an AUD0-INT as well, BUT obviously it must have been triggered BEFORE I could reset the counter 'aud0_cnt', otherwise the are would have to be RED.

For me this is completely strange and show that I did not understand ANYTHING of the documentation of the HRM.
Maybe ANYONE can explain these findings or tell me what I have done wrong?

I will check a physical Amiga and test this once more I would be happy if that's only an emulation problem.


Any hints are highly appreciated.
Herpes is offline  
Old 16 January 2020, 12:26   #5
meynaf
son of 68k
 
meynaf's Avatar
 
Join Date: Nov 2007
Location: Lyon / France
Age: 51
Posts: 5,323
There is an audio intreq not only when a sample starts playing, but also when it stops.
meynaf is offline  
Old 16 January 2020, 12:40   #6
Herpes
... aka Amix73
 
Herpes's Avatar
 
Join Date: Jan 2009
Location: Austria
Posts: 87
Yes, looks like that - although the HRM docs says something different.
But with 'stopping' you mean stopping the DMA. Because, I don't get 2 INTs when the sample restarts (one slightly before and one slightly after restart), but when I actively stop the DMA.
Anyway according to the documentation from the HRM the INT should be triggered when last word of sample was accessed. This would make sense because otherwise I don't know when it is over and cannot easily stop it.
But with the behavior shown it looks like I ONLY get an INT when the AUDx DMA starts AND I switch off the AUDx DMA but definitely NOT when the sample reached its end and is about to be restarted.

Anyway I can live (and of course have to) with the triggering of the INT at start of the sample. I am just stunned about the documentation AND about the feature that when stopping the AUDx-DMA that a AUDx-IRQ is issued.
Herpes is offline  
Old 16 January 2020, 12:46   #7
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
"Joining tones" section in audio chapter explains it better.

When channel starts, interrupt is generated when first word has been DMAd. When sample ends (=first new word of next sample has been already DMAd and about to start playing), interrupt is also generated.
Toni Wilen is online now  
Old 16 January 2020, 13:13   #8
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
This is how I see it in my head and which allows me to understand how it works (which is logically as Toni said).
I hope it helps you and can clarify things a little better

When you write the AUDxLEN/PER values and activate the DMA, at the next fetch of the DMA channel the 'internal' LEN counter is at 1 (attention: 1 not 0!), triggers an IRQ and then reloads the value that you have set (buffered) in the custom register.
(EDIT: even if you set a large PER, first DMA fetch is at the next audio DMA slot available, so max ~ a video line)

This allows to immediately reload new pointer value for the next concatenated sample that will be used the next time LEN counter goes to 1.
The length of the audio buffer is always respected because it's always a fetch 'ahead' (the fundamental point is that it never count down to 0 but trigger at 1).

EDIT2: in practice it's the internal transition that would bring from the value 1 to 'virtual' 0 that triggers the IRQ and that reloads the register buffered value of LEN.
This also allows you to even have a value of 0 for the LEN, a sample exactly 128k long

Last edited by ross; 16 January 2020 at 13:58.
ross is offline  
Old 16 January 2020, 14:34   #9
Herpes
... aka Amix73
 
Herpes's Avatar
 
Join Date: Jan 2009
Location: Austria
Posts: 87
Quote:
Originally Posted by Toni Wilen View Post
"...
When channel starts, interrupt is generated when first word has been DMAd. When sample ends (=first new word of next sample has been already DMAd and about to start playing), interrupt is also generated.
Well that said means that this is the very same event and not two different. The first word of the sample being DMAd and the first word of the next sample DMAs is the same event. It does not matter if the initial sample is replayed once more OR another one is configured. It is always the first word which is DMAs.
The thing which threw me into confusion is that this is just fundamentally different as one expects when reading about it in the HRM (which is official doc) ... I once more stress to quote here:
Quote:
This level 4 interrupt signals "audio block done."
When the audio DMA is operating in automatic mode , this interrupt occurs when the last word in an audio data stream has been accessed.
In reality it is:
[QUOTE]When the audio DMA is operating in automatic mode, this interrupt occurs when the *first* word in an audio data stream has been accessed.[QUOTE]

Anyways I now learned through confusing and your input that the IRQ is issued when the channel starts. Thank you for your help.

This alone does NOT explain everything - namely the triggering of the AUDx-IRQ handler when one turns OFF the enabled DMA.
When one just executes the following line of code in the AUD0-IRQ-handler:
Code:
move.w    #$1,$dff09
... one sees TWO consecutive 'triggerings' of the AUD0-IRQ handler. One for the sample-start and the second executing the switch-off DMA code. Fortunately switching off a disabled AUDx-DMA does NOT trigger the AUDx-IRQ handler - otherwise one would end up in recursion.

What started my confusion was my initial idea to do the switch-off in the handler - unfortunately and now I understand - one does not hear anything because of the immediate switch-off after the DMA was started

With your explanations and the experiments done I conclude it should be documented like this:
Quote:
This level 4 interrupt signals "audio block done *started*."
When the audio DMA is operating in automatic mode , this interrupt occurs when the *first* word in an audio data stream has been accessed. OR the active AUDx-DMA is deactivated.
... at least it would have completely avoided my confusion.
Anyway - this forum always is a great help! Thank you very much.

Last edited by Herpes; 16 January 2020 at 14:39. Reason: thanks
Herpes is offline  
Old 16 January 2020, 14:53   #10
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Herpes View Post
... one sees TWO consecutive 'triggerings' of the AUD0-IRQ handler. One for the sample-start and the second executing the switch-off DMA code. Fortunately switching off a disabled AUDx-DMA does NOT trigger the AUDx-IRQ handler - otherwise one would end up in recursion.

What started my confusion was my initial idea to do the switch-off in the handler - unfortunately and now I understand - one does not hear anything because of the immediate switch-off after the DMA was started
This is because Paula internal counter are still counting!
So you do not have a DMA fetch but IRQ
You need to stop immediately the trigger, disabling through INTENA.
ross is offline  
Old 16 January 2020, 16:33   #11
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Ok, written a brutal snippet to test it:

Code:
	lea	$dff000,a0
	move.w	#$7fff,d0
	move.w	d0,$9a(a0)
	move.w	d0,$9c(a0)
	move.w	d0,$96(a0)
	move.l	#i4,$70.w
	
	move.l	#smp,$a0(a0)
	move.w	#(eraw-smp)>>1,$a4(a0)
	move.l	#$02000040,$a6(a0)
	move.w	#$8201,$96(a0)
	move.w	#$c080,$9a(a0)
stp	bra.b	stp

i4	lea	$dff000,a0
	subq.w	#1,cnt
	bpl.b	.ex
	move.w	#$80,$9a(a0)
	move.w	#1,$96(a0)
.ex	move.w	#$80,$9c(a0)
	move.w	#$80,$9c(a0)
	rte
	
cnt	dc.w	5

smp	dc.w	0
raw	incbin	"audio.raw"
eraw
audio.raw is played cnt times.
ross is offline  
Old 16 January 2020, 16:50   #12
FSizzle
Registered User
 
Join Date: Nov 2017
Location: Los Angeles
Posts: 49
The HRM is confusing in places, and this is certainly one of them. As Toni says, the "joining tones" section is probably the best description of the behavior for "automatic" mode (DMA based sample fetching).

Quote:
To achieve a single-shot-sample using the IRQ handler I have to ignore the first INT. Then when the sample restarts I process the INT and switch off the DMA to stop it.
I think this is not robust and could result in audio pops.

If you ignore the first interrupt, the second interrupt is the sample restarting playback. Your interrupt must stop the DMA before any data is read, which generally means it must happen very quickly (probably within less than one raster line). Failure to do it quickly enough will result in audio pops.

On the 68000, servicing an interrupt reliably within one raster line can be tricky, if you consider:
- the CPU invoking the interrupt alone is quite expensive (storing CPU state takes quite a lot of cycles even before the first instruction of your interrupt)
- you have to save registers in your interrupt handler
- other DMA going will compete with your interrupt routine (copper, bitplane fetch, sprites, blitter, audio, disk etc), assuming you're running from code in memory on the chip ram bus
- you may have other higher priority interrupts already running
- you might have multiple samples start on the same raster line

Some of these issues might be mitigated if you are targeting a faster CPU or running from fastram, but I think it's ultimately still unreliable

(EDIT: It might even be that the interrupt triggers after the fetch of the first pair of samples (i'm not sure about this) in which case you'd also have to make all your samples contain leading zeros to avoid pops)
FSizzle is offline  
Old 16 January 2020, 17:11   #13
Herpes
... aka Amix73
 
Herpes's Avatar
 
Join Date: Jan 2009
Location: Austria
Posts: 87
Wow, yes, that's a lot to consider.... and everything makes sense. I just wonder how the replay routines do all the tricks - never had the interest to dig in... but maybe now.
Herpes is offline  
Old 16 January 2020, 17:25   #14
Herpes
... aka Amix73
 
Herpes's Avatar
 
Join Date: Jan 2009
Location: Austria
Posts: 87
Quote:
Originally Posted by ross View Post
Ok, written a brutal snippet to test it:
audio.raw is played cnt times.
Thanks.
The thing is the code is very similar to the code I tried after you mentioned that in you post unfortunately it does not stop the replay - at least not on my 'machine' which actually is an emulator...
I will recheck later.

EDIT: what you mentioned works - I just was too eager and made the error to enable the interrupts in the Interrupt-handler again - which is not a good idea ;-) Actually your code also ignores the first N interrupts. So I will use the idea of switching AUDx-INTs off in the handler. This spares one extra trigger.

Last edited by Herpes; 16 January 2020 at 22:10. Reason: Ross' code works - \o/
Herpes is offline  
Old 16 January 2020, 17:52   #15
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Herpes View Post
I just wonder how the replay routines do all the tricks - never had the interest to dig in... but maybe now.
If by 'replay routines' you mean those by module replayer then you can not find IRQ4 routine there.
It use IRQ3 (or 2 or 6 if CIA timed).

You can find IRQ4 used by some non-usual replay routines that mix samples, so two little double buffer replenished alternatively when one another is exhausted
(the duration time required for a effect/note change).
ross is offline  
Old 16 January 2020, 18:53   #16
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
HRM audio state diagram will explains almost everything but it isn't that simple to understand.
Toni Wilen is online now  
Old 16 January 2020, 19:34   #17
mc6809e
Registered User
 
Join Date: Jan 2012
Location: USA
Posts: 372
Interrupt latency depends on when interrupt pins are sampled and this is instruction dependent.

Worst case is MOVE.L all regs followed by DIVS -- over 300 cycles.

MOVEM.L samples pins at beginning of instruction while DIVS samples at the end.
mc6809e is offline  
Old 16 January 2020, 22:33   #18
Herpes
... aka Amix73
 
Herpes's Avatar
 
Join Date: Jan 2009
Location: Austria
Posts: 87
Quote:
Originally Posted by ross View Post
If by 'replay routines' you mean those by module replayer then you can not find IRQ4 routine there.
It use IRQ3 (or 2 or 6 if CIA timed). You can find IRQ4 used by some non-usual replay routines that mix samples, so two little double buffer replenished alternatively when one another is exhausted
(the duration time required for a effect/note change).
Yes, right. I have seen and used only a few and most of them were either CIA-Timer based or VBL driven. I think octamed replayer used IRQ4 but I did not bother to have a look at the source but just checked the HRM ...
CIA-Timers that's the next hot topic - a pandora's box - I will open ;-) never tried them so far.
Herpes is offline  
Old 16 January 2020, 22:37   #19
Herpes
... aka Amix73
 
Herpes's Avatar
 
Join Date: Jan 2009
Location: Austria
Posts: 87
Quote:
Originally Posted by Toni Wilen View Post
HRM audio state diagram will explains almost everything but it isn't that simple to understand.
To be honest - I did not get that far in the HRM - I only wanted to simply shut up the sample after it finished playing and I thought Level4 IRQs would do the job easily and I thought I understand interrupts ... How little did I know
Pointing out the state diagram I gave it a quick glance - only 5 states are of interest so it can't be that complicated, can it? I have to give it a read. Thanks.
Herpes is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Spurious PORTS irq ross Coders. Asm / Hardware 37 27 February 2019 20:20
Irq Blitter LeCaravage Coders. Asm / Hardware 9 16 June 2017 10:21
VBCC: complain about static int (*calltrap)(...) = (int (*)(...))0xF0FF60; mbergmann-sh Coders. C/C++ 3 17 March 2017 01:19
IRQ Virus redblade request.Apps 8 01 September 2012 08:22
How to stop sample playback ? AmiGer Coders. General 6 11 December 2004 10:44

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 11:11.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.27779 seconds with 16 queries