| 
				
			 | 
			
			
				
				@@ -1,11 +1,15 @@ 
			 | 
		
		
	
		
			
			| 
				1
			 | 
			
				1
			 | 
			
			
				
				 """ 
			 | 
		
		
	
		
			
			| 
				2
			 | 
			
				2
			 | 
			
			
				
				 Spectroshaker by The Dod: 
			 | 
		
		
	
		
			
			| 
				3
			 | 
			
				3
			 | 
			
			
				
				 Adafruit CircuitPlayground Bluefruit dual-mode "bling" 
			 | 
		
		
	
		
			
			| 
				4
			 | 
			
				
			 | 
			
			
				
				-(selectable via the slider switch). 
			 | 
		
		
	
		
			
			| 
				5
			 | 
			
				4
			 | 
			
			
				
				 The RGB levels of neopixels around the circuit indicate: 
			 | 
		
		
	
		
			
			| 
				6
			 | 
			
				5
			 | 
			
			
				
				 - Low/Mid/High sound levels (spectrogram mode) 
			 | 
		
		
	
		
			
			| 
				7
			 | 
			
				6
			 | 
			
			
				
				 - X/Y/Z acceleration (shaker mode) 
			 | 
		
		
	
		
			
			| 
				8
			 | 
			
				
			 | 
			
			
				
				-TO BE CONTINUED ... 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				7
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				8
			 | 
			
			
				
				+Controls: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				9
			 | 
			
			
				
				+    slider switch: normal/standby mode 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				10
			 | 
			
			
				
				+    button a: toggle between spectrogram/shaker mode 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				11
			 | 
			
			
				
				+    button b: cycle between 4 brightness levels 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				12
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				9
			 | 
			
				13
			 | 
			
			
				
				 """ 
			 | 
		
		
	
		
			
			| 
				10
			 | 
			
				14
			 | 
			
			
				
				 import math 
			 | 
		
		
	
		
			
			| 
				11
			 | 
			
				15
			 | 
			
			
				
				 import time 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -21,48 +25,77 @@ LED_ANGLES = [ 
			 | 
		
		
	
		
			
			| 
				21
			 | 
			
				25
			 | 
			
			
				
				 minx = miny = minz = -5.0 
			 | 
		
		
	
		
			
			| 
				22
			 | 
			
				26
			 | 
			
			
				
				 maxx = maxy = maxz = 5.0 
			 | 
		
		
	
		
			
			| 
				23
			 | 
			
				27
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				24
			 | 
			
				
			 | 
			
			
				
				-fft_size = 8 # power of 2 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				28
			 | 
			
			
				
				+fft_size = 8  # power of 2 
			 | 
		
		
	
		
			
			| 
				25
			 | 
			
				29
			 | 
			
			
				
				 samples = [0.0+0.0j]*fft_size 
			 | 
		
		
	
		
			
			| 
				26
			 | 
			
				
			 | 
			
			
				
				-MAX_2FREQ = 10.0 # After testing this a bit in the wild 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				30
			 | 
			
			
				
				+MAX_2FREQ = 10.0  # After testing this a bit in the wild 
			 | 
		
		
	
		
			
			| 
				27
			 | 
			
				31
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				28
			 | 
			
				32
			 | 
			
			
				
				 cp.pixels.brightness = 0.1 
			 | 
		
		
	
		
			
			| 
				29
			 | 
			
				33
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				34
			 | 
			
			
				
				+MODE_SPECTRO = 1 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				35
			 | 
			
			
				
				+MODE_SHAKER = 2 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				36
			 | 
			
			
				
				+current_mode = MODE_SHAKER 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				37
			 | 
			
			
				
				+is_standby = cp.switch 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				38
			 | 
			
			
				
				+last_click = 0 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				39
			 | 
			
			
				
				+DEBOUNCE = 0.25 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				40
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				30
			 | 
			
				41
			 | 
			
			
				
				 def angles2level(led, val): 
			 | 
		
		
	
		
			
			| 
				31
			 | 
			
				42
			 | 
			
			
				
				     led_angle = LED_ANGLES[led] 
			 | 
		
		
	
		
			
			| 
				32
			 | 
			
				43
			 | 
			
			
				
				     val_angle = val * 2.0 * math.pi 
			 | 
		
		
	
		
			
			| 
				33
			 | 
			
				44
			 | 
			
			
				
				     angle = led_angle - val_angle 
			 | 
		
		
	
		
			
			| 
				34
			 | 
			
				
			 | 
			
			
				
				-    while angle>2*math.pi: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				45
			 | 
			
			
				
				+    while angle > 2 * math.pi: 
			 | 
		
		
	
		
			
			| 
				35
			 | 
			
				46
			 | 
			
			
				
				         angle -= 2*math.pi 
			 | 
		
		
	
		
			
			| 
				36
			 | 
			
				47
			 | 
			
			
				
				     # the pow() makes sin() values sharper 
			 | 
		
		
	
		
			
			| 
				37
			 | 
			
				48
			 | 
			
			
				
				     return int(255*pow(math.sin(angle/2), 4)) 
			 | 
		
		
	
		
			
			| 
				38
			 | 
			
				49
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				39
			 | 
			
				50
			 | 
			
			
				
				 while True: 
			 | 
		
		
	
		
			
			| 
				40
			 | 
			
				
			 | 
			
			
				
				-    if cp.button_a: 
			 | 
		
		
	
		
			
			| 
				41
			 | 
			
				
			 | 
			
			
				
				-        cp.pixels.brightness = max(0.05, cp.pixels.brightness*0.9) 
			 | 
		
		
	
		
			
			| 
				42
			 | 
			
				
			 | 
			
			
				
				-    elif cp.button_b: 
			 | 
		
		
	
		
			
			| 
				43
			 | 
			
				
			 | 
			
			
				
				-        cp.pixels.brightness = min(0.95, 1.0-(1.0-cp.pixels.brightness)*0.9) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				51
			 | 
			
			
				
				+    if time.monotonic() > last_click+DEBOUNCE: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				52
			 | 
			
			
				
				+        if is_standby != cp.switch: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				53
			 | 
			
			
				
				+            is_standby = cp.switch 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				54
			 | 
			
			
				
				+            last_click = time.monotonic() 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				55
			 | 
			
			
				
				+            if is_standby: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				56
			 | 
			
			
				
				+                for i in range(NUM_PIXELS): 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				57
			 | 
			
			
				
				+                    cp.pixels[i] = (0, 0, 0) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				58
			 | 
			
			
				
				+        if cp.button_a: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				59
			 | 
			
			
				
				+            last_click = time.monotonic() 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				60
			 | 
			
			
				
				+            current_mode = ( 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				61
			 | 
			
			
				
				+                current_mode == MODE_SHAKER and MODE_SPECTRO 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				62
			 | 
			
			
				
				+                or MODE_SHAKER) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				63
			 | 
			
			
				
				+        elif cp.button_b: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				64
			 | 
			
			
				
				+            last_click = time.monotonic() 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				65
			 | 
			
			
				
				+            is_standby = False 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				66
			 | 
			
			
				
				+            if cp.pixels.brightness >= 0.4: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				67
			 | 
			
			
				
				+                cp.pixels.brightness = 0.1 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				68
			 | 
			
			
				
				+            else: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				69
			 | 
			
			
				
				+                cp.pixels.brightness += 0.1 
			 | 
		
		
	
		
			
			| 
				44
			 | 
			
				70
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				45
			 | 
			
				
			 | 
			
			
				
				-    samples.pop(0) 
			 | 
		
		
	
		
			
			| 
				46
			 | 
			
				
			 | 
			
			
				
				-    samples.append(cp.sound_level+0.0j) 
			 | 
		
		
	
		
			
			| 
				47
			 | 
			
				
			 | 
			
			
				
				-    x, y, z = cp.acceleration 
			 | 
		
		
	
		
			
			| 
				48
			 | 
			
				
			 | 
			
			
				
				-    if x<minx: minx = x 
			 | 
		
		
	
		
			
			| 
				49
			 | 
			
				
			 | 
			
			
				
				-    if y<miny: miny = y 
			 | 
		
		
	
		
			
			| 
				50
			 | 
			
				
			 | 
			
			
				
				-    if z<minz: minz = z 
			 | 
		
		
	
		
			
			| 
				51
			 | 
			
				
			 | 
			
			
				
				-    if x>maxx: maxx = x 
			 | 
		
		
	
		
			
			| 
				52
			 | 
			
				
			 | 
			
			
				
				-    if y>maxy: maxy = y 
			 | 
		
		
	
		
			
			| 
				53
			 | 
			
				
			 | 
			
			
				
				-    if z>maxx: maxz = z 
			 | 
		
		
	
		
			
			| 
				54
			 | 
			
				
			 | 
			
			
				
				-    if cp.switch: # accelerometer mode 
			 | 
		
		
	
		
			
			| 
				55
			 | 
			
				
			 | 
			
			
				
				-        vals = ( 
			 | 
		
		
	
		
			
			| 
				56
			 | 
			
				
			 | 
			
			
				
				-            (x-minx)/(maxx-minx), 
			 | 
		
		
	
		
			
			| 
				57
			 | 
			
				
			 | 
			
			
				
				-            (y-miny)/(maxy-miny), 
			 | 
		
		
	
		
			
			| 
				58
			 | 
			
				
			 | 
			
			
				
				-            (z-minz)/(maxz-minz)) 
			 | 
		
		
	
		
			
			| 
				59
			 | 
			
				
			 | 
			
			
				
				-    else: # spectrogram mode 
			 | 
		
		
	
		
			
			| 
				60
			 | 
			
				
			 | 
			
			
				
				-        raw_freqs = spectrogram(samples) 
			 | 
		
		
	
		
			
			| 
				61
			 | 
			
				
			 | 
			
			
				
				-        pairs = [raw_freqs[i]+raw_freqs[i+1] for i in range(fft_size//2)] 
			 | 
		
		
	
		
			
			| 
				62
			 | 
			
				
			 | 
			
			
				
				-        vals = [min(1.0, abs(x/MAX_2FREQ)) for x in pairs[:3]] 
			 | 
		
		
	
		
			
			| 
				63
			 | 
			
				
			 | 
			
			
				
				-    for i in range(NUM_PIXELS): 
			 | 
		
		
	
		
			
			| 
				64
			 | 
			
				
			 | 
			
			
				
				-        cp.pixels[i] = ( 
			 | 
		
		
	
		
			
			| 
				65
			 | 
			
				
			 | 
			
			
				
				-            angles2level(i, vals[0]), 
			 | 
		
		
	
		
			
			| 
				66
			 | 
			
				
			 | 
			
			
				
				-            angles2level(i, vals[1]), 
			 | 
		
		
	
		
			
			| 
				67
			 | 
			
				
			 | 
			
			
				
				-            angles2level(i, vals[2])) 
			 | 
		
		
	
		
			
			| 
				68
			 | 
			
				
			 | 
			
			
				
				-    time.sleep(0.01) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				71
			 | 
			
			
				
				+    if not is_standby: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				72
			 | 
			
			
				
				+        samples.pop(0) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				73
			 | 
			
			
				
				+        samples.append(cp.sound_level+0.0j) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				74
			 | 
			
			
				
				+        x, y, z = cp.acceleration 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				75
			 | 
			
			
				
				+        if x < minx: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				76
			 | 
			
			
				
				+            minx = x 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				77
			 | 
			
			
				
				+        if y < miny: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				78
			 | 
			
			
				
				+            miny = y 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				79
			 | 
			
			
				
				+        if z < minz: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				80
			 | 
			
			
				
				+            minz = z 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				81
			 | 
			
			
				
				+        if x > maxx: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				82
			 | 
			
			
				
				+            maxx = x 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				83
			 | 
			
			
				
				+        if y > maxy: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				84
			 | 
			
			
				
				+            maxy = y 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				85
			 | 
			
			
				
				+        if z > maxz: 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				86
			 | 
			
			
				
				+            maxz = z 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				87
			 | 
			
			
				
				+        if current_mode == MODE_SHAKER:  # accelerometer mode 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				88
			 | 
			
			
				
				+            vals = ( 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				89
			 | 
			
			
				
				+                (x-minx)/(maxx-minx), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				90
			 | 
			
			
				
				+                (y-miny)/(maxy-miny), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				91
			 | 
			
			
				
				+                (z-minz)/(maxz-minz)) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				92
			 | 
			
			
				
				+        else:  # spectrogram mode 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				93
			 | 
			
			
				
				+            raw_freqs = spectrogram(samples) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				94
			 | 
			
			
				
				+            pairs = [raw_freqs[i]+raw_freqs[i+1] for i in range(fft_size//2)] 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				95
			 | 
			
			
				
				+            vals = [min(1.0, abs(x/MAX_2FREQ)) for x in pairs[:3]] 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				96
			 | 
			
			
				
				+        for i in range(NUM_PIXELS): 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				97
			 | 
			
			
				
				+            cp.pixels[i] = ( 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				98
			 | 
			
			
				
				+                angles2level(i, vals[0]), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				99
			 | 
			
			
				
				+                angles2level(i, vals[1]), 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				100
			 | 
			
			
				
				+                angles2level(i, vals[2])) 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				101
			 | 
			
			
				
				+    time.sleep(0.01) 
			 |