Page 1 of 1
Exact timing couter
Posted: Sun Oct 15, 2017 3:38 am
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!
Posted: Mon Oct 16, 2017 10:33 am
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.
Posted: Mon Oct 16, 2017 12:50 pm
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
Posted: Mon Oct 16, 2017 1:29 pm
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.
Posted: Tue Oct 17, 2017 1:28 am
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)
Posted: Tue Oct 17, 2017 9:10 am
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.