RMPA Instruction - confusion?

Software questions and issues with the FV-1

Moderator: frank

Post Reply
jwhitmore
Posts: 19
Joined: Tue Mar 10, 2020 6:37 am

RMPA Instruction - confusion?

Post by jwhitmore »

There's not a lot to the 'rmpa' instruction. As the SPINAsmUsersManual.pdf states:

"RMPA will fetch the indirectly addressed sample from the delay ram, multiply it by C and add the result to the previous content of ACC"

There's even an example code segment in the manual:

Code: Select all

; Crude variable delay line addressing
sof   0,0         ; Clear ACC
rdax  POT1,1.0    ; Read POT1 value
wrax  ADDR_PTR,0  ; Write value to pointer register, clear ACC
rmpa  1.0         ; Read sample from delay line
wrax  DACL,0      ; Result to DACL and clear ACC
That's fairly clear in so far as it goes, but if you're doing a stereo delay with two delay buffers:

Code: Select all

delay_l	mem	8000
delay_r	mem	8000

 	ldax	ADCR		
 	wra     delay_r, 0

 	ldax	ADCL
 	wra     delay_l, 0
The the description of the 'rmpa' instruction is less clear, ""RMPA will fetch the indirectly addressed sample from the delay ram". I have two sections of delay memory defined, one for the left channel and one for the right. It's not clear to me how I indirectly address the section of delay memory that I'm interested in, left or right.

Could I complete my stereo delay code with, the 'crude' example given in the manual:

Code: Select all

sof   0,0         ; Clear ACC
rdax  POT1,1.0    ; Read POT1 value
wrax  ADDR_PTR,0  ; Write value to pointer register, clear ACC
rmpa  1.0         ; Read sample from LEFT delay line
wrax  DACL,0      ; Result to DACL and clear ACC
rmpa  1.0         ; Read sample from RIGTH delay line
wrax  DACR,0      ; Result to DACL and clear ACC
That doesn't feel right. I guess I'm writing the same sample to the left and right channel?
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Re: RMPA Instruction - confusion?

Post by frank »

The indirect address would be the base of the delay + any offset.

So if the delay starts at 0x20 and you are using a POT to adjust the offset into the delay from 0 to 0x10 then the indirect address to put into ADDR_PTR would be calculated by 0x20 + (POT * 0x10)
Frank Thomson
Experimental Noize
jwhitmore
Posts: 19
Joined: Tue Mar 10, 2020 6:37 am

Re: RMPA Instruction - confusion?

Post by jwhitmore »

Thanks Frank but sorry I'm still struggling with it.

I get the indirect addressing mode, I've no problem with that, and the offset stored in the ADDR_PTR register. If we had somehow stored an offset of 0x100 in the ADDR_PTR register that's the required offset, What I'm struggling with is how the code specifies the base address that the offset if applied to. In the case of stereo I have delay_mem_left and delay_mem_right. You might assume that you specify the base address by loading it into the ACC before the RMPA instruction, but offset can't be in the ACC as the contents of delay mem is added to the existing contents of ACC.

Ah hold on this instruction just works on the, unstructured by me, delay memory. So if I split the max delay memory between two channels of delay. Max delay mem is 32K so 0x8000

Code: Select all

delay_l  equ $4000
delay_r equ  $4000
So if I want to read the offset of 0x100 from each delay channel left and right, if we assume that the first delay memory segment is lower in memory I'd have to load the ADDR_PTR with 0x0000 + 0x100 for the left channel and sizeof(delay_l) 0x4000 + 0x100 to the ADDR_PTR for the right channel. So:

Code: Select all

    ;; Left Channel
    ldax    ADCL
    wrax   delay_l
    ;;  Read from offset 0x100 and write out
    ldax    $0000 + $100        ; Loading of an immediate value into ACC can't find instruction for it but something like load $100 into ACC
    wrax   ADDR_PTR, 0
    rmpa   1.0
    wrax    DACL, 0

    ;; Right channel
    ladx    ADCR
    wrax   delay_r
    ;; Read from the offset 0x100 in the right delay buffer
    ldax    $4000 + $100
    wrax    ADDR_PTR, 0
    rmpa    1.0
    wrax     ADDR_PTR, 0
Think I have it now, just have to work out how to get an immediate value 0x1100 into ACC.
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Re: RMPA Instruction - confusion?

Post by frank »

You will need to do something like:

Code: Select all

clr               ; clear acc
or delay_r*256    ; put base address of delay in acc shifted to align bits for addressing
wrax reg0,0       ; save it
or $4000*256      ; length of delay aligned for addressing into acc
mulx pot0         ; mult by pot for adjustable delay
rdax reg0,1.0     ; add base address
wrax addr_ptr, 0  ; write to address ptr
rmpa 1            ; get sample
Frank Thomson
Experimental Noize
jwhitmore
Posts: 19
Joined: Tue Mar 10, 2020 6:37 am

Re: RMPA Instruction - confusion?

Post by jwhitmore »

Thanks a million Frank, That's so helpful, the 'or' instruction, I was looking over the instruction set trying to figure out how to load an immediate value into the Accumulator. Never occurred to me to use an or.

Thanks for all your help, think I'm up and running.
John
jwhitmore
Posts: 19
Joined: Tue Mar 10, 2020 6:37 am

Re: RMPA Instruction - confusion?

Post by jwhitmore »

The previous answer got me moving, but after some looking I could not find the answer to a couple of questions on the code given. So given the code:

Code: Select all

clr               ; clear acc
or delay_r*256    ; put base address of delay in acc shifted to align bits for addressing
wrax reg0,0       ; save it
or $4000*256      ; length of delay aligned for addressing into acc
mulx pot0         ; mult by pot for adjustable delay
rdax reg0,1.0     ; add base address
wrax addr_ptr, 0  ; write to address ptr
rmpa 1            ; get sample
The symbol 'delay_r' is a moving target on each execution that address is moved for each sample. So every execution you can simple read from the ADC and write to 'delay_r'. So whilst I agree with the comment and what it's doing I'm not 100% sure it's doing what the comment suggests.

Secondly I can't find a reference to multiplying that address, and the $4000, but 256. (In my code I had a delay memory size of decimal 4000 so I assume that '$' is a typo.)

The example from page 46 of the SPINAsmUserManual.pdf is even more confusing, where the value of the pot is written on addr_ptr before the rmpa instruction. The Pot value is between zero and 1 so that address is weird, even if you multiplied it by 256.
potul
Posts: 76
Joined: Tue Sep 26, 2017 12:33 am

Re: RMPA Instruction - confusion?

Post by potul »

jwhitmore wrote: Thu Apr 08, 2021 2:58 pm The symbol 'delay_r' is a moving target on each execution that address is moved for each sample. So every execution you can simple read from the ADC and write to 'delay_r'. So whilst I agree with the comment and what it's doing I'm not 100% sure it's doing what the comment suggests.
delay_r is the base address of your delay memory. This is a circular buffer that rolls at each sample cycle. so if you write ADC to delay_r, and read from delay_r+4000, you get a delay of 4000. If you multiply by the pot value(from 0 to 1), you get a variable delay time, from 0 to 4000
jwhitmore
Posts: 19
Joined: Tue Mar 10, 2020 6:37 am

Re: RMPA Instruction - confusion?

Post by jwhitmore »

potul wrote: Fri Apr 09, 2021 2:51 am delay_r is the base address of your delay memory. This is a circular buffer that rolls at each sample cycle. so if you write ADC to delay_r, and read from delay_r+4000, you get a delay of 4000. If you multiply by the pot value(from 0 to 1), you get a variable delay time, from 0 to 4000
I get the circular buffer, but I think I'm getting the implementation wrong in my head. I've been imagining that the address delay_r is a circular buffer address which is moving sequentially through the buffer. So if on the first sample delay_r points to address 0x0000 then after 200 samples it points to address 0x00c8. That might be the wrong mental representation, perhaps delay_r is always the same address but the underlying arch moves the memory location being address, so it's like a virtual memory address?

Even in a virtual memory address implementation I'm not sure about multiplying it by a POT value. If delay_r address is 0x0000 you can multiply it by what ever you want and get the same value. I'd be happier if you could multiply the POT by the size of the delay buffer and add it to the base address delay_r. That's just the way I'm abstracting this coming from traditional CPU's rather then DSP.

So if you'd a stereo buffer size 4k and you wanted to use the POT for delay you'd want to be reading delay_l + 4k * POT and delay_r + 4K * POT

To add to the confusion you appear to have to scale the address but 256 so it'd be (delay_l * 256) + ( 4k * POT ) and likewise for delay_r.
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Re: RMPA Instruction - confusion?

Post by frank »

jwhitmore wrote: Sun Apr 18, 2021 4:50 am That might be the wrong mental representation, perhaps delay_r is always the same address but the underlying arch moves the memory location being address, so it's like a virtual memory address?
There is a counter that is decremented every sample period that is added to the address in the instruction. This is explained on page 21 of the assembly language PDF.
jwhitmore wrote: Sun Apr 18, 2021 4:50 am Even in a virtual memory address implementation I'm not sure about multiplying it by a POT value. If delay_r address is 0x0000 you can multiply it by what ever you want and get the same value. I'd be happier if you could multiply the POT by the size of the delay buffer and add it to the base address delay_r. That's just the way I'm abstracting this coming from traditional CPU's rather then DSP.
That is what it does, it multiplies by the length and adds it to the delay base address, the comment in the example code is:

or $4000*256 ; length of delay aligned for addressing into acc
mulx pot0 ; mult by pot for adjustable delay
jwhitmore wrote: Sun Apr 18, 2021 4:50 am To add to the confusion you appear to have to scale the address but 256 so it'd be (delay_l * 256) + ( 4k * POT ) and likewise for delay_r.
Yes, there are 8 bits below the address LSB as fractional address bits you could use as interpolation coefficients, etc.
Frank Thomson
Experimental Noize
Post Reply