Exact timing couter

Algorithm development and general DSP issues

Moderator: frank

Post Reply
knutolai
Posts: 65
Joined: Wed Nov 23, 2016 9:43 am
Location: Bergen, Norway

Exact timing couter

Post by knutolai »

Consider a program where an audio snippet is endlessly looped in a 1 second buffer:

Code: Select all

mem   buffer   32767   ; 1 second delay when run w 32768 hz clock
equ   feedback   reg0

ldax   adcl
rdax   feedback
wra   buffer, 0

rda   buffer#, 1
wrax   feedback, 1
wrax   dacl, 0
I wish to store the memory address of one specific sample for the purpose of a timing function I'm working on. By sample I mean an amplitude value that has been read by the adc and stored in the buffer, where it endlessly skips from one address to the next until it loops back around to the start of the buffer via the feedback register.

Code: Select all

equ   ref   reg1
equ   limit   reg2

skp   RUN, start
clr
or   32768*256
wrax   limit, 0
start:

clr
or   256   ; 1 sample
rdax   ref, 1   ; add reference register
wrax   ref, 1   ; store new reference
rdax   limit, -1   ; - limit

skp   NEG, refReset   ; if GEZ (ref >= limit) : 
clr
wrax   ref, 0   ; reset ref register
refReset:
In the code above I'm uncertain of a few things. Am I correct in setting the "limit" register to 32768*256 (instead of 767 or 769)? And will my counter implementation be accurate enough to follow the exact same sample through the buffer indefinitely? Other observations/glaring mistakes?

Thanks!
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

Few things to consider:

1. The assembler allocates N+1 memory locations so you can have separate read and write pointers but you want to use all 32768 locations to get a full second so you will want to read and write to the write address (head of the buffer) but you must read first so you can later overwrite the old data. I.e. in your top code you will want to read from then write to "buffer" and never use "buffer#".

2. Timing, if set up properly, should be fine, every iteration of the code will always work the same so once you set it up it should be good. I think you should load with 32767 since you are doing a "skp neg" which means it will skip on -1 rather than 0.

I do not understand why you are loading limit with 32768*256 since all you want is a counter why multiply by 256? And the "ref" register is never initialized.
Frank Thomson
Experimental Noize
knutolai
Posts: 65
Joined: Wed Nov 23, 2016 9:43 am
Location: Bergen, Norway

Post by knutolai »

Thank you Frank for your reply

I forgot to specify something in my original post. The reason why I'm multiplying by 256 is that I don't just wish a 1 second counter, I wish for the "ref" register to contain a value I can load into the ADDR_PTR register to access the specific sample at any time. Like so:

Code: Select all

ldax   ref
wrax   ADDR_PTR, 0
rmpa   1.0
The idea is to jump to reading from this specific sample whenever some condition is met in the code. That's why I need the counter to run from 0 and upwards. Hope that makes sense.

In response to your first point. Is this what you mean?

Code: Select all

mem   buffer   32767

rda   buffer, 1   ; read from buffer 
wrax   DACL, 1   ; output
rdax   ADCL, 1   ; + input
wra   buffer, 0   ; write to buffer
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

OK that explains the *256.

Yes, read from "buffer" as it will have wrapped around the circular buffer having been delayed for exactly 32768 sample periods then write over it with the new data. This works since you are using the entire memory as a single buffer, if you were splitting the memory into multiple delay blocks then this would not work as the data from the other delay block would be at the buffer write point so reading it would sound wrong.
Frank Thomson
Experimental Noize
knutolai
Posts: 65
Joined: Wed Nov 23, 2016 9:43 am
Location: Bergen, Norway

Post by knutolai »

Ah yes that makes sense.

But shouldn't I set limit to 32768*256 since I want the "ref" register to be in the range of 0 to 32767*256 for writing to the ADDR_PTR register? Since I'm using a NEG skip, if 'ref = 32768*256 = limit' the outcome of the reset function would be 'ref = 0' right?

Code: Select all

clr
or   256
rdax   ref, 1
wrax   ref, 1
rdax   limit, -1
skp   NEG, reset   ; If GEZ (ref >= limit) 
frank
Posts: 1244
Joined: Wed Oct 19, 2005 12:26 pm
Contact:

Post by frank »

This is where things can get a little off depending if you do 'skp neg' versus 'skp gez', where you increment/decrement the offset in the code, trying to use the same value as an address/pointer, etc. I generally recommend simulating it on a piece of paper (just use a 4 sample long memory rather than 32768) to make sure the values are what you need them to be.
Frank Thomson
Experimental Noize
Post Reply