added memphis code with reverse playbakc option

master
dennisdebel 5 years ago
parent 2ca81bdd4b
commit 0ebfb91487

@ -0,0 +1,161 @@
#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;
byte firstSample;
int forwardOrReverse;
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]);
firstSample = pgm_read_byte(&sound_data[sound_length]);
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);
forwardOrReverse = 600;
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
{
if(forwardOrReverse < 500){ //analogread to slow messes with 'pitch timer'!?
//OCR2A = pgm_read_byte(&sound_data[(sample*(analogRead(KNOB_3)/100)) % sound_length]); // normal playback + 'pitch control (number of samples played percycl ish)'
OCR2A = pgm_read_byte(&sound_data[sample % sound_length]); // normal playback
//OCR2A = pgm_read_byte(&sound_data[sound_length - sample]); // reverse playback
//OCR2A = pgm_read_byte(&sound_data[sound_length % sample]); //backspin
}
if(forwardOrReverse > 500){
//OCR2A = pgm_read_byte(&sound_data[sample % sound_length]); // normal playback
//OCR2A = pgm_read_byte(&sound_data[sound_length - (sample*(analogRead(KNOB_3)/100))]); // reverse playback
OCR2A = pgm_read_byte(&sound_data[sound_length - sample]); // reverse playback
//OCR2A = pgm_read_byte(&sound_data[sound_length % sample]); //backspin
}
}
gate_prev = gate;
sample++; //just a counter, the 'playhead'
}
void loop()
{
//loop_start = analogRead(KNOB_1) / 1024.0 * sound_length;
loop_start = 0;
loop_length = sound_length;
forwardOrReverse = analogRead(KNOB_1); //play reverse or not
// loop_length = (analogRead(KNOB_2) + 1) / 1024.0 * sound_length;
OCR1A = (512.0 / (analogRead(KNOB_3) + 1)) * (F_CPU / SAMPLE_RATE);// pitch control cpu speed div by samplerate
// OCR1A = 1; //pitch control >> ah for reversed playback this also has to be reversed some how!
//16e6 / 8000 = 2000
gate = analogRead(3) >> 9; // 10 bits in. gate < 512 == off, gate >= 512 == on
// can be up to 2x sound length. the more you know.
index_bounds = loop_start + 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save