Browse Source

Upload files to 'INPUT_OUTPUT/Flakes/chaos_on_trigger'

master
markvandenheuvel 3 months ago
parent
commit
dff77f8372

+ 180
- 0
INPUT_OUTPUT/Flakes/chaos_on_trigger/chaos_on_trigger.ino View File

@@ -0,0 +1,180 @@
1
+// Chaos on Trigger 
2
+
3
+#include <stdint.h>
4
+#include <avr/interrupt.h>
5
+#include <avr/io.h>
6
+#include <avr/pgmspace.h>
7
+
8
+#include "sample.h"
9
+
10
+#define LED_PIN     13
11
+#define SPEAKER_PIN 11 
12
+
13
+#define KNOB_1  (0)
14
+#define KNOB_2  (1)  
15
+#define KNOB_3  (2)   
16
+#define INPUT3_PIN A3   // gate trigger
17
+
18
+volatile uint16_t sample;
19
+volatile uint16_t loop_start;
20
+volatile uint16_t loop_length;
21
+volatile uint16_t index_bounds;
22
+volatile uint16_t loop_overflow;
23
+
24
+volatile boolean gate;
25
+volatile boolean gate_prev;
26
+volatile boolean is_playing;
27
+
28
+volatile uint16_t time_since_gate;
29
+
30
+bool triggered;
31
+
32
+int i=0;
33
+
34
+byte lastSample;
35
+
36
+void startPlayback()
37
+
38
+{
39
+    pinMode(SPEAKER_PIN, OUTPUT);
40
+
41
+    // Set up Timer 2 to do pulse width modulation on the speaker pin.
42
+    // Use internal clock (datasheet p.160)
43
+    ASSR &= ~(_BV(EXCLK) | _BV(AS2));
44
+
45
+    // Set fast PWM mode  (p.157)
46
+    TCCR2A |= _BV(WGM21) | _BV(WGM20);
47
+    TCCR2B &= ~_BV(WGM22);
48
+
49
+    // Do non-inverting PWM on pin OC2A (p.155)
50
+    // On the Arduino this is pin 11.
51
+    TCCR2A = (TCCR2A | _BV(COM2A1)) & ~_BV(COM2A0);
52
+    TCCR2A &= ~(_BV(COM2B1) | _BV(COM2B0));
53
+    // No prescaler (p.158)
54
+    TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
55
+
56
+    // Set initial pulse width to the first sample.
57
+    OCR2A = pgm_read_byte(&sound_data[0]);
58
+
59
+    // Set up Timer 1 to send a sample every interrupt.
60
+    cli();
61
+
62
+    // Set CTC mode (Clear Timer on Compare Match) (p.133)
63
+    // Have to set OCR1A *after*, otherwise it gets reset to 0!
64
+    TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
65
+    TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));
66
+
67
+    // No prescaler (p.134)
68
+    TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
69
+
70
+    // Set the compare register (OCR1A).
71
+    // OCR1A is a 16-bit register, so we have to do this with
72
+    // interrupts disabled to be safe.
73
+    OCR1A = F_CPU / SAMPLE_RATE; // 16e6 / 8000 = 2000
74
+
75
+    // Enable interrupt when TCNT1 == OCR1A (p.136)
76
+    TIMSK1 |= _BV(OCIE1A);
77
+
78
+    lastSample = pgm_read_byte(&sound_data[sound_length - 1]);
79
+    sample = 0;
80
+    sei();
81
+}
82
+
83
+void stopPlayback()
84
+{
85
+    TIMSK1 &= ~_BV(OCIE1A); // Disable playback per-sample interrupt.
86
+    TCCR1B &= ~_BV(CS10);   // Disable the per-sample timer completely.
87
+    TCCR2B &= ~_BV(CS10);   // Disable the PWM timer.
88
+    digitalWrite(SPEAKER_PIN, LOW);
89
+}
90
+
91
+void setup()
92
+{
93
+    pinMode(LED_PIN, OUTPUT);
94
+    digitalWrite(LED_PIN, HIGH);
95
+
96
+    startPlayback();
97
+
98
+    loop_start = 0; 
99
+    loop_length = sound_length;
100
+    gate = false;
101
+    gate_prev = false;
102
+    is_playing = false;
103
+    time_since_gate = 0;
104
+}
105
+
106
+// This is called at 8000 Hz to load the next sample.
107
+ISR(TIMER1_COMPA_vect)
108
+{
109
+
110
+	if (gate == true && gate_prev == false)
111
+	
112
+	  {
113
+		time_since_gate = 0;
114
+		sample = loop_start;
115
+		is_playing = true;
116
+  	}
117
+
118
+	gate_prev = gate;
119
+	time_since_gate++;
120
+
121
+	if (time_since_gate >= 8000 * 20)
122
+	{
123
+
124
+		is_playing = false;
125
+	}
126
+
127
+	if (is_playing)
128
+	{
129
+
130
+	    OCR2A = pgm_read_byte(&sound_data[sample % sound_length]);
131
+	    sample++;
132
+
133
+	    if(sample >= index_bounds)
134
+	    {
135
+	        sample = loop_start;
136
+	    }
137
+	    else if((sample < loop_start) &&
138
+	            (sample >= loop_overflow))
139
+	    {
140
+	        sample = loop_start;}
141
+	} 
142
+	
143
+	else 
144
+	{
145
+  OCR2A = pgm_read_byte(&sound_data[0]);
146
+	}
147
+}
148
+
149
+void loop()
150
+
151
+{  
152
+  gate = analogRead(A3) << 9;
153
+  if (gate && !triggered)
154
+  {
155
+    loop_start = random(0,1023) / 1024.0 * random(100,11461);  
156
+  delay(500); 
157
+  loop_length = (analogRead(KNOB_2) + 1) / 1024.0 * sound_length;
158
+  OCR1A = (512.0 / (analogRead(KNOB_3) + 1)) * (F_CPU / SAMPLE_RATE);
159
+	gate = analogRead(3) ;
160
+
161
+	triggered=true;
162
+  }
163
+
164
+  else if(!gate && triggered)
165
+  {triggered=false;}
166
+
167
+  
168
+//  can be up to 2x sound length. the more you know.
169
+    index_bounds = loop_start + loop_length;
170
+    //Serial.println(loop_length);
171
+//  this will set the overflow length. take the loop overflow into account when checking the loop boundaries
172
+    if(index_bounds > sound_length)
173
+    {
174
+        loop_overflow = index_bounds - sound_length;
175
+    }
176
+    else
177
+    {
178
+        loop_overflow = 0;
179
+    }
180
+}

+ 1959
- 0
INPUT_OUTPUT/Flakes/chaos_on_trigger/sample.h
File diff suppressed because it is too large
View File


Loading…
Cancel
Save