Spin Semiconductor Forum Index Spin Semiconductor
Support forum
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

tap tempo snippet
Goto page 1, 2, 3, 4, 5, 6  Next
 
Post new topic   Reply to topic    Spin Semiconductor Forum Index -> Algorithm development
View previous topic :: View next topic  
Author Message
slacker



Joined: 01 Feb 2011
Posts: 115

PostPosted: Sat Jul 23, 2011 7:34 am    Post subject: tap tempo snippet Reply with quote

If anyone's interested here's some taptempo code I came up with. I tested it out by hacking it into some existing delay code and it works. It measures the time between two consecutive taps and outputs a value between 0 and 1 proportional to the time between them up to a max of 1 second. I need to add a timeout if the time between taps is too long.

The code up to "ENDSWITCH" can be used on its own to create a momentary and latching switch from a tap input.

Hopefully the comments explain how it works, if not just ask. If anyone's got any ideas for improvements, or alternative ways of doing it feel free to post them.

Code:
;tap tempo
;pot 2 tap input
;output is a value between 0 and 1 written to taptempo register,
;corresponding to a delay of 0 to 1000ms if using the full delay memory

equ  db reg0              ;debounce
equ  mom reg1      ;momentary output of switch +1 high, -1 Low
equ  latch reg2      ;latched output of switch +1 high, -1 low
equ ramp reg3              ;current value of rmpo, scaled to 0 to 1
equ taptempo reg4           ;taptempo value, 0 to 1

equ count 0.01      ;debounce counter

skp run,START
wldr rmp0,0.064,4096   ;set up rmp0
sof 0,0.999      
wrax latch,0              ;set latch = 1 high

START:

;Switch Debouncing and pot filtering work around

ldax   pot2             ;read pot2
sof 1,-0.5                     ;level shift to -0.5 to 0.5
skp neg,DOWN     ;if negative jump to DOWN
ldax db                ;else high, read db
sof 1,count             ;add count
wrax db,0             ;write new value to db
skp zro,ENDDB     ;jump to ENDDB
DOWN:
ldax db                 ;read db
sof 1,-count               ;deduct count
wrax db,0             ;write new value to db

ENDDB:

;latching switch, falling edge triggered flipflop
;Output of debounce routine of < -0.9 is low, > 0.9 is high, values in between
;are ignored and the switch does nothing, Schmitt trigger action.


ldax db                  ;read db
absa                  ;get absolute value
sof 1,-0.9                       ;deduct 0.9 so only values < -0.9 or > 0.9 give a positive result
skp neg,ENDSWITCH   ;if negative then jump to ENDSWITCH
ldax db                 ;read db
sof 1,-0.9                      ;deduct 0.9
skp neg,LO              ;if negative jump to LO, output of debounce is low
sof 0,0.999                  ;else output of debounce is high
wrax mom,0              ;set mom to 1 (high)
skp zro,ENDSWITCH   ;jump to ENDSWITCH
LO:
ldax mom                      ;read mom
skp neg,ENDSWITCH   ;if it's negative then debounce was already low last time so do nothing, jump to ENDSWITCH
sof 0,-0.999               ;else mom was high last time so switch has only just been pressed (falling edge)
wrax mom,0               ;set mom to -1 (low)
ldax latch                      ;read latch
sof -1,0                  ;invert, high becomes low, low becomes high
wrax latch,0                 ;write to value to latch

ENDSWITCH:

;tap tempo, uses rmp0 as a 1 Hz rising ramp, runs whilst latch is low and is sampled and held when latch is high

ldax latch                   ;read latch
skp neg,LOW           ;if negative jump to LOW
jam rmp0                    ;else latch is high, jam rmp0 (reset to 0)
ldax ramp            ;read ramp, will contain last value of rmp0 before latch went high   
wrax taptempo,0      ;write to taptempo
skp zro,ENDTT      ;jump to ENDTT
LOW:
sof 0,0.064      
wrax rmp0_rate,1      ;set rmp0 rate to 1Hz
cho rdal,rmp0               ;read value of rmp0
sof -2,0.999                ;level shift to 0 to 1 rising ramp
wrax ramp,0               ;write to ramp
ENDTT:

ldax taptempo
wrax dacl,0
Back to top
View user's profile Send private message
Sweetalk



Joined: 15 Oct 2009
Posts: 95

PostPosted: Sat Jul 30, 2011 7:36 am    Post subject: Reply with quote

Great!!! anyway easy to test it with a delay?.
Back to top
View user's profile Send private message
slacker



Joined: 01 Feb 2011
Posts: 115

PostPosted: Sat Jul 30, 2011 11:39 am    Post subject: Reply with quote

To add to exiting delay code change pot2 in this line to the pot that your delay code uses to set the delay time.

Code:
ldax   pot2             ;read pot2


Then add your delay code after
Code:
ENDTT:
where your delay code reads from a pot replace the pot name with taptempo so for example

Code:
rdax pot2,1
becomes
Code:
rdax taptempo,1


I tested it by hacking it into the simple delay here http://www.spinsemi.com/forum/viewtopic.php?t=124
Back to top
View user's profile Send private message
Sweetalk



Joined: 15 Oct 2009
Posts: 95

PostPosted: Sat Jul 30, 2011 1:29 pm    Post subject: Reply with quote

Thank you for the super fast answer!!! I'll try it asap!!
Back to top
View user's profile Send private message
Sweetalk



Joined: 15 Oct 2009
Posts: 95

PostPosted: Mon Aug 01, 2011 11:55 am    Post subject: Reply with quote

One last question before I try it. In the taptempo code there are to lines in the end:

Code:
ldax taptempo
wrax dacl,0


You said that I paste the delay code after the ENDTT: , so, I erase those two lines or where should I put them?
Back to top
View user's profile Send private message
slacker



Joined: 01 Feb 2011
Posts: 115

PostPosted: Mon Aug 01, 2011 12:55 pm    Post subject: Reply with quote

You can delete those 2 lines, sorry for not explaining that earlier.
I've written a simple delay using the code, I'll post it sometime this week. I'm still working on making it reset if the time between taps is too long, I thought I had it figured out but it's not working right.
Back to top
View user's profile Send private message
Sweetalk



Joined: 15 Oct 2009
Posts: 95

PostPosted: Mon Aug 01, 2011 1:58 pm    Post subject: Reply with quote

Great, i'm working on that too. Also thinking some way to have a flashing led on the tempo. Maybe a square wave lfo in the left out?.
Back to top
View user's profile Send private message
slacker



Joined: 01 Feb 2011
Posts: 115

PostPosted: Wed Aug 03, 2011 1:33 pm    Post subject: Reply with quote

Here's an updated version of the code, including a simple delay. The taptempo code now times out if the time between taps is too long, it's still not working 100% correctly though, I need to start a new thread about the issues I'm having with it.
It also includes a tap tempo indicator on the right DAC, it flashes the clipping LED at the current tempo, but it could be modified to flash an external LED instead.

Code:

;tap tempo delay
;pot 2 = tap input
;pot 0 = feedback
;pot 1 = delay level

equ  db reg0      ;debounce
equ  mom reg1      ;momentary output of switch +1 high, -1 Low
equ  latch reg2      ;latched output of switch +1 high, -1 low
equ ramp reg3      ;current value of rmpo, scaled to 0 to 1
equ taptempo reg4   ;taptempo value, 0 to 1
equ fback reg5      ;feedback
equ delayout reg6      ;delay output
equ clip reg7      ;clipping

equ count 0.01      ;debounce counter


mem delay 32767

skp run,START
wldr rmp0,0.064,4096   ;set up rmp0
wldr rmp1,0.064,4096   ;set up rmp1
sof 0,0.999      
wrax latch,0      ;set latch = 1 high

START:

;Switch Debouncing and pot filtering work around

ldax   pot2   ;read pot2
sof 1,-0.5   ;level shift to -0.5 to 0.5
skp neg,DOWN   ;if negative jump to DOWN
ldax db      ;else high, read db
sof 1,count   ;add count
wrax db,0   ;write new value to db
skp zro,ENDDB   ;jump to ENDDB
DOWN:
ldax db      ;read db
sof 1,-count   ;deduct count
wrax db,0   ;write new value to db

ENDDB:

;latching switch, falling edge triggered flipflop
;Output of debounce routine of < -0.9 is low, > 0.9 is high, values in between
;are ignored and the switch does nothing, Schmitt trigger action.


ldax db         ;read db
absa         ;get absolute value
sof 1,-0.9      ;deduct 0.9 so only values < -0.9 or > 0.9 give a positive result
skp neg,ENDSWITCH   ;if negative then jump to ENDSWITCH
ldax db         ;read db
sof 1,-0.9      ;deduct 0.9
skp neg,LO      ;if negative jump to LO, output of debounce is low
sof 0,0.999      ;else output of debounce is high
wrax mom,0      ;set mom to 1 (high)
skp zro,ENDSWITCH   ;jump to ENDSWITCH
LO:
ldax mom      ;read mom
skp neg,ENDSWITCH   ;if it's negative then debounce was already low last time so do nothing, jump to ENDSWITCH
sof 0,-0.999      ;else mom was high last time so switch has only just been pressed (falling edge)
wrax mom,0      ;set mom to -1 (low)
ldax latch      ;read latch
sof -1,0         ;invert, high becomes low, low becomes high
wrax latch,0      ;write to value to latch

ENDSWITCH:

;tap tempo, uses rmp0 as a 1 Hz rising ramp, runs whilst latch is low and is sampled and held when latch is high

ldax latch      ;read latch
skp neg,LOW      ;if negative jump to LOW
jam rmp0      ;else latch is high, jam rmp0 (reset to 0)
ldax ramp      ;read ramp, will contain last value of rmp0 before latch went high   
wrax taptempo,0      ;write to taptempo
skp zro,ENDTT      ;jump to ENDTT
LOW:
sof 0,0.064      
wrax rmp0_rate,1      ;set rmp0 rate to 1Hz
cho rdal,rmp0      ;read value of rmp0
sof -2,0.999
sof 1,0.001      ;level shift to 0 to 1 rising ramp
wrax ramp,1      ;write to ramp
sof 1,-0.85
skp neg,ENDTT
ldax taptempo
wrax ramp,0
sof 0,0.999
wrax latch,0
ENDTT:

;tap tempo indicator, flashes clipping LED at tap tempo

clr
wrax dacr,0
sof 0,0.064      
wrax rmp1_rate,1      ;set rmp1 rate to 1Hz
cho rdal,rmp1      ;read value of rmp1
sof -2,0.999
sof 1,0.001
rdax taptempo,-0.5
skp neg,ENDLED
jam rmp1
sof 0,0.999
wrax dacr,0
ENDLED:

ldax fback
rdax adcl,1
wra delay,0

ldax taptempo
wrax addr_ptr,0

rmpa 1
wrax delayout,1

mulx pot0
wrax clip,-0.33333
mulx clip
mulx clip
rdax clip,1

wrax fback,0

rdax delayout,1
mulx pot1
rdax adcl,1

wrax dacl,0
Back to top
View user's profile Send private message
frank



Joined: 19 Oct 2005
Posts: 958

PostPosted: Sat Aug 06, 2011 4:58 pm    Post subject: Reply with quote

slacker wrote:
I need to start a new thread about the issues I'm having with it.


I've been waiting for you to start the new thread to learn how things are going, please keep posting, I enjoy reading other people code and how they solved an issue.
_________________
Frank Thomson
Experimental Noize
Back to top
View user's profile Send private message Visit poster's website
slacker



Joined: 01 Feb 2011
Posts: 115

PostPosted: Mon Aug 08, 2011 8:57 am    Post subject: Reply with quote

Sorry Frank, I was busy with other things and didn't get round to posting about the problems I was having. I got some time yesterday and figured out what the problem was, turns out it was a user error on my part. Here's the bit of code that wasn't working properly.

Code:

sof 0,0.064       
wrax rmp0_rate,1      ;set rmp0 rate to 1Hz
cho rdal,rmp0      ;read value of rmp0
sof -2,0.999
sof 1,0.001      ;level shift to 0 to 1 rising ramp
wrax ramp,1      ;write to ramp
sof 1,-0.998
skp neg,ENDTT
ldax taptempo
wrax ramp,0
sof 0,0.999
wrax latch,0


The idea of this is to start a 1Hz ramp on the first press of the tap tempo switch, convert that from a value between 0 and 0.5 into a value to between 0 and 1, a second tap of the switch then grabs that value and writes it to a register that can be used to generate a taptempo control of a delay or whatever. That appeared to work, except that if a second tap wasn't received within 1 second, the ramp started again so the second bit of the code starting with the sof 1,-0.998 line was supposed to reset the system once the ramp reached 1 second. The problem was it didn't do anything, it was as though the ramp was never getting to 1.

The problem, if you haven't already spotted it, was with this line

wrax rmp0_rate,1 ;set rmp0 rate to 1Hz

This was writing 0.064 to the ramp rate, but then leaving it in the accumulator so I guess the following cho command was adding this to the ramp value. So by the time I'd done the sof -2,0.999 instead of getting values between 0 and 1 I was getting values between -0.129 and 0.871 so the ramp never got high enough the trigger the reset. Correcting the line to wrax rmp0_rate,0 solved the problem and it now works properly.
Back to top
View user's profile Send private message
frank



Joined: 19 Oct 2005
Posts: 958

PostPosted: Mon Aug 08, 2011 9:49 am    Post subject: Reply with quote

Yup, been there, left a coefficient at "1" instead of "0" and had it mess up the rest of the code. Glad to see you found it and got it solved, it is one of those problems you can look at 19 times and not see until the 20th review of the code and it's "D'OH!!! How could I miss that???"
_________________
Frank Thomson
Experimental Noize
Back to top
View user's profile Send private message Visit poster's website
slacker



Joined: 01 Feb 2011
Posts: 115

PostPosted: Sun Sep 18, 2011 9:08 am    Post subject: Reply with quote

Just a quick follow up, here's the latest version of the code. This now sets the initial delay time to 333ms, the original started with no delay until one was tapped in. A square wave at the tap tempo rate is sent to DACR, with a suitable driver this will flash an LED.

Code:
;tap tempo delay
;mono input (ADCL) mono output (DACL)
;a 0 - 0.99 square wave at the tap tempo rate is send to DACR. This can be used to flash a LED using a suitable driver.
;Pot 2 is used as a tap tempo switch input. This should be a momentary switch, transition can be high to low or low to high.
;see guitar amp application note for examples of switch hookup. 
;pot 0 = feedback
;pot 1 = delay level

;set up registers and equates

equ  db reg0      ;debounce
equ  mom reg1      ;momentary output of switch +1 high, -1 Low
equ  latch reg2      ;latched output of switch +1 high, -1 low
equ ramp reg3      ;current value of rmpo, scaled to 0 to 1
equ taptempo reg4   ;taptempo value, 0 to 1
equ fback reg5      ;feedback
equ delayout reg6      ;delay output
equ clip reg7      ;clipping
equ led reg8      ;taptempo LED

equ count 0.01      ;debounce counter
equ delaytime 330      ;initial delay time in milli seconds

mem delay 32767

skp run,START
wldr rmp0,0.064,4096   ;set up rmp0
wldr rmp1,0.064,4096   ;set up rmp1
sof 0,0.99      
wrax latch,1      ;set latch = 1 high
wrax led,0      ;set led = 1 high
sof 0,delaytime/1000   ;set initial delay time
wrax ramp,0

START:

;Switch Debouncing and pot filtering work around

ldax   pot2   ;read pot2
sof 1,-0.5   ;level shift to -0.5 to 0.5
skp neg,DOWN   ;if negative jump to DOWN
ldax db      ;else high, read db
sof 1,count   ;add count
wrax db,0   ;write new value to db
skp zro,ENDDB   ;jump to ENDDB
DOWN:
ldax db      ;read db
sof 1,-count   ;deduct count
wrax db,0   ;write new value to db

ENDDB:

;latching switch, falling edge triggered flipflop
;Output of debounce routine of < -0.9 is low, > 0.9 is high, values in between
;are ignored and the switch does nothing, Schmitt trigger action.


ldax db         ;read db
absa         ;get absolute value
sof 1,-0.9      ;deduct 0.9 so only values < -0.9 or > 0.9 give a positive result
skp neg,ENDSWITCH   ;if negative then jump to ENDSWITCH
ldax db         ;read db
sof 1,-0.9      ;deduct 0.9
skp neg,LO      ;if negative jump to LO, output of debounce is low
sof 0,0.999      ;else output of debounce is high
wrax mom,0      ;set mom to 1 (high)
skp zro,ENDSWITCH   ;jump to ENDSWITCH
LO:
ldax mom      ;read mom
skp neg,ENDSWITCH   ;if it's negative then debounce was already low last time so do nothing, jump to ENDSWITCH
sof 0,-0.999      ;else mom was high last time so switch has only just been pressed (falling edge)
wrax mom,0      ;set mom to -1 (low)
ldax latch      ;read latch
sof -1,0         ;invert, high becomes low, low becomes high
wrax latch,0      ;write to value to latch

ENDSWITCH:

;tap tempo, uses rmp0 as a 1 Hz rising ramp, runs whilst latch is low and is sampled and held when latch is high

ldax latch      ;read latch
skp neg,LOW      ;if negative jump to LOW
jam rmp0      ;else latch is high, jam rmp0 (reset to 0)
ldax ramp      ;read ramp, will contain last value of rmp0 before latch went high   
wrax taptempo,0      ;write to taptempo
skp zro,ENDTT      ;jump to ENDTT
LOW:
sof 0,0.064      
wrax rmp0_rate,0      ;set rmp0 rate to 1Hz
cho rdal,rmp0      ;read value of rmp0
sof -2,0.999
sof 1,0.001      ;level shift to 0 to 1 rising ramp
wrax ramp,1      ;write to ramp
sof 1,-0.999      ;deduct 0.999 from ramp      
skp neg,ENDTT      ;if answer is positive then second tap hasn't happened with 0.999 ms of first         
ldax taptempo      ;so keep last value of taptempo
wrax ramp,0      
sof 0,0.999      ;and reset latch high
wrax latch,0
ENDTT:

;Taptempo rate indicator, creates a square wave at the tap tempo rate
sof 0,0.064      
wrax rmp1_rate,0      ;set rmp1 rate to 1Hz
cho rdal,rmp1      ;read value of rmp1
sof -2,0.999      ;level shift to 0 - 1 rising ramp
sof 1,0.001
rdax taptempo,-0.5   ;deduct half of the taptempo value
skp neg,ENDLED      ;if negative skip to ENDLED
jam rmp1      ;else reset ramp1
ldax led         ;and invert value of led register, creates square wave at taptempo rate
sof -1,0
wrax led,0
ENDLED:

;delay

clr
rdax fback,0.95      ;read feedback register, scaled to 0.95%
rdax adcl,1      ;mix with input from ADCL
wra delay,0      ;write to head of delay
ldax taptempo      ;read taptempo register
wrax addr_ptr,0      ;write to delay address pointer
rmpa 1         ;read from delay address set by pointer
wrax delayout,1      ;write to delayout register

mulx pot0      ;mulx with pot0, feedback level control
wrax clip,-0.33333   ;soft clip, using cube distortion snippet
mulx clip
mulx clip
rdax clip,1
wrax fback,0      ;write to feedback register

rdax delayout,1      ;read delayout register
mulx pot1      ;mulx with pot1, delay level control
rdax adcl,1      ;mix with input from ADCL
wrax dacl,0      ;write to DACL

ldax led         ;read led register
wrax dacr,0      ;write to DACR, flashes LED attached to DACR
Back to top
View user's profile Send private message
Sweetalk



Joined: 15 Oct 2009
Posts: 95

PostPosted: Tue Sep 27, 2011 12:12 pm    Post subject: Reply with quote

Great!! I'll try it this week and post!!
Back to top
View user's profile Send private message
ronaldb



Joined: 03 Dec 2009
Posts: 19

PostPosted: Mon Dec 05, 2011 3:31 am    Post subject: Reply with quote

Hi Slacker,
THanks for this great code, seems to work oke.
But the tap tempo seems to be of tempo. Haven't checked this with a click track but when i tap in and keep counting in my head the delay does not follow.

Did you checked this?

RonaldB
Back to top
View user's profile Send private message
slacker



Joined: 01 Feb 2011
Posts: 115

PostPosted: Mon Dec 05, 2011 11:11 am    Post subject: Reply with quote

Did you use the latest version? The first and second versions I posted have an error in them and the delay doesn't match the tapped tempo.

In the latest one the delay time should match the tap tempo, and it seems to work for me, I haven't tested it though so there might still be some error. I'll see if I can do some tests but if you could try it with a click track and let me know what you find that would be great.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Spin Semiconductor Forum Index -> Algorithm development All times are GMT - 8 Hours
Goto page 1, 2, 3, 4, 5, 6  Next
Page 1 of 6

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group