Codes for Flakes
parent
04a5ea7823
commit
121e8465e8
@ -0,0 +1,180 @@
|
||||
// Chaos on Trigger
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include "sample.h"
|
||||
|
||||
#define LED_PIN 13
|
||||
#define SPEAKER_PIN 11
|
||||
|
||||
#define KNOB_1 (0)
|
||||
#define KNOB_2 (1)
|
||||
#define KNOB_3 (2)
|
||||
#define INPUT3_PIN A3 // gate trigger
|
||||
|
||||
volatile uint16_t sample;
|
||||
volatile uint16_t loop_start;
|
||||
volatile uint16_t loop_length;
|
||||
volatile uint16_t index_bounds;
|
||||
volatile uint16_t loop_overflow;
|
||||
|
||||
volatile boolean gate;
|
||||
volatile boolean gate_prev;
|
||||
volatile boolean is_playing;
|
||||
|
||||
volatile uint16_t time_since_gate;
|
||||
|
||||
bool triggered;
|
||||
|
||||
int i=0;
|
||||
|
||||
byte lastSample;
|
||||
|
||||
void startPlayback()
|
||||
|
||||
{
|
||||
pinMode(SPEAKER_PIN, OUTPUT);
|
||||
|
||||
// Set up Timer 2 to do pulse width modulation on the speaker pin.
|
||||
// Use internal clock (datasheet p.160)
|
||||
ASSR &= ~(_BV(EXCLK) | _BV(AS2));
|
||||
|
||||
// Set fast PWM mode (p.157)
|
||||
TCCR2A |= _BV(WGM21) | _BV(WGM20);
|
||||
TCCR2B &= ~_BV(WGM22);
|
||||
|
||||
// Do non-inverting PWM on pin OC2A (p.155)
|
||||
// On the Arduino this is pin 11.
|
||||
TCCR2A = (TCCR2A | _BV(COM2A1)) & ~_BV(COM2A0);
|
||||
TCCR2A &= ~(_BV(COM2B1) | _BV(COM2B0));
|
||||
// No prescaler (p.158)
|
||||
TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
|
||||
|
||||
// Set initial pulse width to the first sample.
|
||||
OCR2A = pgm_read_byte(&sound_data[0]);
|
||||
|
||||
// Set up Timer 1 to send a sample every interrupt.
|
||||
cli();
|
||||
|
||||
// Set CTC mode (Clear Timer on Compare Match) (p.133)
|
||||
// Have to set OCR1A *after*, otherwise it gets reset to 0!
|
||||
TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
|
||||
TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));
|
||||
|
||||
// No prescaler (p.134)
|
||||
TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
|
||||
|
||||
// Set the compare register (OCR1A).
|
||||
// OCR1A is a 16-bit register, so we have to do this with
|
||||
// interrupts disabled to be safe.
|
||||
OCR1A = F_CPU / SAMPLE_RATE; // 16e6 / 8000 = 2000
|
||||
|
||||
// Enable interrupt when TCNT1 == OCR1A (p.136)
|
||||
TIMSK1 |= _BV(OCIE1A);
|
||||
|
||||
lastSample = pgm_read_byte(&sound_data[sound_length - 1]);
|
||||
sample = 0;
|
||||
sei();
|
||||
}
|
||||
|
||||
void stopPlayback()
|
||||
{
|
||||
TIMSK1 &= ~_BV(OCIE1A); // Disable playback per-sample interrupt.
|
||||
TCCR1B &= ~_BV(CS10); // Disable the per-sample timer completely.
|
||||
TCCR2B &= ~_BV(CS10); // Disable the PWM timer.
|
||||
digitalWrite(SPEAKER_PIN, LOW);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
|
||||
startPlayback();
|
||||
|
||||
loop_start = 0;
|
||||
loop_length = sound_length;
|
||||
gate = false;
|
||||
gate_prev = false;
|
||||
is_playing = false;
|
||||
time_since_gate = 0;
|
||||
}
|
||||
|
||||
// This is called at 8000 Hz to load the next sample.
|
||||
ISR(TIMER1_COMPA_vect)
|
||||
{
|
||||
|
||||
if (gate == true && gate_prev == false)
|
||||
|
||||
{
|
||||
time_since_gate = 0;
|
||||
sample = loop_start;
|
||||
is_playing = true;
|
||||
}
|
||||
|
||||
gate_prev = gate;
|
||||
time_since_gate++;
|
||||
|
||||
if (time_since_gate >= 8000 * 20)
|
||||
{
|
||||
|
||||
is_playing = false;
|
||||
}
|
||||
|
||||
if (is_playing)
|
||||
{
|
||||
|
||||
OCR2A = pgm_read_byte(&sound_data[sample % sound_length]);
|
||||
sample++;
|
||||
|
||||
if(sample >= index_bounds)
|
||||
{
|
||||
sample = loop_start;
|
||||
}
|
||||
else if((sample < loop_start) &&
|
||||
(sample >= loop_overflow))
|
||||
{
|
||||
sample = loop_start;}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
OCR2A = pgm_read_byte(&sound_data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
|
||||
{
|
||||
gate = analogRead(A3) << 9;
|
||||
if (gate && !triggered)
|
||||
{
|
||||
loop_start = random(0,1023) / 1024.0 * random(100,11461);
|
||||
delay(500);
|
||||
loop_length = (analogRead(KNOB_2) + 1) / 1024.0 * sound_length;
|
||||
OCR1A = (512.0 / (analogRead(KNOB_3) + 1)) * (F_CPU / SAMPLE_RATE);
|
||||
gate = analogRead(3) ;
|
||||
|
||||
triggered=true;
|
||||
}
|
||||
|
||||
else if(!gate && triggered)
|
||||
{triggered=false;}
|
||||
|
||||
|
||||
// can be up to 2x sound length. the more you know.
|
||||
index_bounds = loop_start + loop_length;
|
||||
//Serial.println(loop_length);
|
||||
// this will set the overflow length. take the loop overflow into account when checking the loop boundaries
|
||||
if(index_bounds > sound_length)
|
||||
{
|
||||
loop_overflow = index_bounds - sound_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
loop_overflow = 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
//Deep Flakes
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include "sample.h"
|
||||
|
||||
#define LED_PIN 13
|
||||
#define SPEAKER_PIN 11
|
||||
|
||||
#define KNOB_1 (0)
|
||||
#define KNOB_2 (1)
|
||||
#define KNOB_3 (2)
|
||||
#define INPUT_3 (3)
|
||||
|
||||
volatile uint16_t sample;
|
||||
volatile uint16_t loop_start;
|
||||
volatile uint16_t loop_length;
|
||||
volatile uint16_t index_bounds;
|
||||
volatile uint16_t loop_overflow;
|
||||
|
||||
volatile boolean gate;
|
||||
volatile boolean gate_prev;
|
||||
|
||||
byte lastSample;
|
||||
|
||||
void startPlayback()
|
||||
{
|
||||
pinMode(SPEAKER_PIN, OUTPUT);
|
||||
|
||||
// Set up Timer 2 to do pulse width modulation on the speaker pin.
|
||||
// Use internal clock (datasheet p.160)
|
||||
ASSR &= ~(_BV(EXCLK) | _BV(AS2));
|
||||
|
||||
// Set fast PWM mode (p.157)
|
||||
TCCR2A |= _BV(WGM21) | _BV(WGM20);
|
||||
TCCR2B &= ~_BV(WGM22);
|
||||
|
||||
// Do non-inverting PWM on pin OC2A (p.155)
|
||||
// On the Arduino this is pin 11.
|
||||
TCCR2A = (TCCR2A | _BV(COM2A1)) & ~_BV(COM2A0);
|
||||
TCCR2A &= ~(_BV(COM2B1) | _BV(COM2B0));
|
||||
// No prescaler (p.158)
|
||||
TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
|
||||
|
||||
// Set initial pulse width to the first sample.
|
||||
OCR2A = pgm_read_byte(&sound_data[0]);
|
||||
|
||||
// Set up Timer 1 to send a sample every interrupt.
|
||||
cli();
|
||||
|
||||
// Set CTC mode (Clear Timer on Compare Match) (p.133)
|
||||
// Have to set OCR1A *after*, otherwise it gets reset to 0!
|
||||
TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
|
||||
TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));
|
||||
|
||||
// No prescaler (p.134)
|
||||
TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
|
||||
|
||||
// Set the compare register (OCR1A).
|
||||
// OCR1A is a 16-bit register, so we have to do this with
|
||||
// interrupts disabled to be safe.
|
||||
OCR1A = F_CPU / SAMPLE_RATE; // 16e6 / 8000 = 2000
|
||||
|
||||
// Enable interrupt when TCNT1 == OCR1A (p.136)
|
||||
TIMSK1 |= _BV(OCIE1A);
|
||||
|
||||
lastSample = pgm_read_byte(&sound_data[sound_length - 1]);
|
||||
sample = 0;
|
||||
sei();
|
||||
}
|
||||
|
||||
void stopPlayback()
|
||||
{
|
||||
TIMSK1 &= ~_BV(OCIE1A); // Disable playback per-sample interrupt.
|
||||
TCCR1B &= ~_BV(CS10); // Disable the per-sample timer completely.
|
||||
TCCR2B &= ~_BV(CS10); // Disable the PWM timer.
|
||||
digitalWrite(SPEAKER_PIN, LOW);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
digitalWrite(LED_PIN, HIGH);
|
||||
|
||||
startPlayback();
|
||||
|
||||
loop_start = 0;
|
||||
loop_length = sound_length;
|
||||
gate = false;
|
||||
gate_prev = false;
|
||||
}
|
||||
|
||||
// This is called at 8000 Hz to load the next sample.
|
||||
ISR(TIMER1_COMPA_vect)
|
||||
{
|
||||
if(sample >= index_bounds)
|
||||
{
|
||||
sample = loop_start;
|
||||
}
|
||||
else if((sample < loop_start) &&
|
||||
(sample >= loop_overflow))
|
||||
{
|
||||
sample = loop_start;
|
||||
}
|
||||
else if((gate == true) &&
|
||||
(gate_prev == false))
|
||||
{
|
||||
sample = loop_start;
|
||||
}
|
||||
else
|
||||
{
|
||||
OCR2A = pgm_read_byte(&sound_data[sample % sound_length]);
|
||||
}
|
||||
gate_prev = gate;
|
||||
sample++;
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
loop_start = analogRead(KNOB_1) / 1024.0 * sound_length;
|
||||
loop_length = (analogRead(KNOB_2) + 1) / 1024.0 * sound_length;
|
||||
OCR1A = (512.0 / (analogRead(KNOB_3) + 1)) * (F_CPU / SAMPLE_RATE);
|
||||
gate = analogRead(3) >> 9; // 10 bits in. gate < 512 == off, gate >= 512 == on
|
||||
// change to gate = analogRead(3) << 9; if trigger doesn't work)
|
||||
|
||||
// can be up to 2x sound length. the more you know.
|
||||
index_bounds = loop_start + loop_length;
|
||||
Serial.println(loop_length);
|
||||
// this will set the overflow length. take the loop overflow into account when checking the loop boundaries
|
||||
if(index_bounds > sound_length)
|
||||
{
|
||||
loop_overflow = index_bounds - sound_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
loop_overflow = 0;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue