Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
786 lines (656 sloc) 24 KB
/*
KASTLE DRUM
The Kastle Drum is a special edition of Bastl’s classic mini modular synth focusing on algorithmic industrial glitchy drums
How do you generate rhythm on a patchable drum machine that has neither buttons, nor a programmable sequencer? You discover it!
Drum sound synthesis with a unique dynamic acceleration charged envelope makes this rhythm box surprisingly versatile and extremely fun to play.
The built-in VC clock generator with a stepped pattern sequencer can either run on its own or it can be synchronized to analog clock,
while retaining the triangle LFO for parameter modulation.
The Kastle Drum is a mini modular synthesizer with a headphone output,
2 in/out ports for interfacing other gear, and it runs on just 3 AA batteries. It is ideal for beginners in modular synthesis,
but it will add some quite unique functionality to any modular synthesizer system. It delivers the fun of modular synthesis at a
low price and fits into your pocket so you can play it anywhere!
Kastle Drum Features
-8 drum synthesis styles
-”noises” output for less tonal content
-DRUM selects drum sounds
-acceleration charge dynamic envelope
-decay time
-PITCH control with offset and CV input with attenuator
-voltage-controllable clock with square and triangle output
-stepped voltage generator with random, 8 step and 16 step loop mode
-2 I/O CV ports that can be routed to any patch point
-the main output can drive headphones
-3x AA battery operation or USB power selectable by a switch
-open source
-durable black & gold PCB enclosure
Writen by Vaclav Pelousek 2020
based on the earlier kastle v1.5
open source license: CC BY SA
http://www.bastl-instruments.com
-this is the code for the VCO chip of the Kastle
-software written in Arduino 1.8.12 - used to flash ATTINY 85 running at 8mHz
http://highlowtech.org/?p=1695
-created with help of the heavenly powers of internet and several tutorials that you can google out
-i hope somebody finds this code usefull (i know it is a mess :( )
thanks to
-Lennart Schierling for making some work on the register access
-Uwe Schuller for explaining the capacitance of zener diodes
-Peter Edwards for making the inspireing bitRanger
-Ondrej Merta for being the best boss
-and the whole bastl crew that made this project possible
-Arduino community and the forums for picking ups bits of code to setup the timers & interrupts
-v1.5 and kastle drum uses bits of code from miniMO DCO http://www.minimosynth.com/
*/
#define F_CPU 8000000 // This is used by delay.h library
#include <stdlib.h>
#include <avr/interrupt.h>
#include <avr/io.h> // Adds useful constants
#include <util/delay.h>
//#include <CB_AT.h>
//#include <CB2_AT.h>
//#include <CB3_AT.h>
//#include <CB4_AT.h>
//#include <GB_BLIP_AT.h>
//#include <GB_BZZ_AT.h>
//#include <GB_GLITCH_AT.h>
//#include <GB_HH_AT.h>
//#include <GB_KICK_AT.h>
//#include <GB_SNARE_AT.h>
//#include <GB_TUI_AT.h>
//#include <GL_A_AT.h>
//#include <GL_B_AT.h>
//#include <GL_C_AT.h>
//#include <GL_D_AT.h>
//#include <GL_E_AT.h>
//#include <GL_F_AT.h>
//#include <GL_G_AT.h>
//#include <GL_H_AT.h>
//#include <GL_I_AT.h>
//#include <HAT_AT.h>
//#include <HAT2_AT.h>
//#include <KICK_AT.h>
//#include <KICK2_AT.h>
//#include <RIDE_AT.h>
//#include <SNARE_AT.h>
//#include <SNARE2_AT.h>
//#include <TR_CB_AT.h>
//#include <TR_CLAP_AT.h>
//#include <TR_KICK_AT.h>
//#include <TR_OH_AT.h>
//#include <TR_RIM_AT.h>
//#include <TR_SNARE_AT.h>
//#include <TR_TOM_AT.h>
//#include "SINE.h" //sinewave wavetable - modified but originnaly from the Mozzi library
#include "TR_HH_AT.h"
//#include <SAW.h>
//#include <CHEB4.h>
//for debugging purposes
//#include "SoftwareSerial.h"
//const int Rx = 8;
//const int Tx = 3;
//SoftwareSerial mySerial(Rx, Tx); //use only for debugging
//global variables
#define WSMAP_POINTS 5
uint16_t wsMap[10] = {
0, 63, 127, 191, 234, 15, 100, 160, 210, 254
};
uint8_t _out;
uint16_t time;
uint8_t mode;
uint8_t analogChannelRead = 1;
uint8_t analogValues[4];
uint8_t lastAnalogValues[4];
uint8_t out;
uint8_t pwmCounter;
//uint8_t mapLookup[256];
uint8_t _clocks;
bool flop;
uint8_t incr = 6, _incr = 6;
uint8_t lastOut;
uint8_t bitShift = 3;
uint16_t osc2offset = 255;
uint8_t lastAnalogChannelRead;
bool firstRead = false;
uint8_t pwmIncrement, _upIncrement, _downIncrement, upIncrement, downIncrement;
bool quantizer;
const uint8_t analogToDigitalPinMapping[4] = {
PORTB5, PORTB2, PORTB4, PORTB3
};
//defines for synth types
//all are dual oscillator setups -
#define NOISE 1 // phase distortion -
#define FM 0 //aka phase modulation
#define TAH 2 //aka track & hold modulation (downsampling with T&H)
#define LOW_THRES 150
#define HIGH_THRES 162
#define LOW_MIX 300
#define HIGH_MIX 900
//defines for synth parameters
#define PITCH 3
#define WS_1 2
#define WS_2 1
const char PROGMEM sinetable[128] = {
0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76, 79, 82, 85, 88, 90, 93, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124,
128, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 162, 165, 167, 170, 173, 176, 179, 182, 185, 188, 190, 193, 196, 198, 201, 203, 206, 208, 211, 213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 238, 240, 241, 243, 244, 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255,
};
//the actual table that is read to generate the sound
unsigned char wavetable[256];
uint32_t curveMap(uint8_t value, uint8_t numberOfPoints, uint16_t * tableMap) {
uint32_t inMin = 0, inMax = 255, outMin = 0, outMax = 255;
for (int i = 0; i < numberOfPoints - 1; i++) {
if (value >= tableMap[i] && value <= tableMap[i + 1]) {
inMax = tableMap[i + 1];
inMin = tableMap[i];
outMax = tableMap[numberOfPoints + i + 1];
outMin = tableMap[numberOfPoints + i];
i = numberOfPoints + 10;
}
}
return map(value, inMin, inMax, outMin, outMax);
}
void createLookup() {
for (uint16_t i = 0; i < 256; i++) {
// mapLookup[i]=curveMap(i,WSMAP_POINTS,wsMap);
}
}
bool XYmode;
uint8_t startupRead = 0;
uint8_t decayVolume;
uint16_t decayTime = 50;
uint8_t _sample;
uint8_t _saw, _lastSaw;
uint8_t decayVolume2 = 0;
void setup() { //happends at the startup
writeWave(0);
digitalWrite(5, HIGH); //turn on pull up resistor for the reset pin
// createLookup(); //mapping of knob values is done thru a lookuptable which is generated at startup from defined values
//set outputs
pinMode(0, OUTPUT);
pinMode(1, OUTPUT);
//serial for debugging only
//mySerial.begin(9600);
setTimers(); //setup interrupts
//setup ADC and run it in interrupt
init();
connectChannel(analogChannelRead);
startConversion();
//long _time=millis();
/*
while(millis()-_time<4){
loop();
}
*/
_delay_us(100);
while (startupRead < 12) {
loop();
}
// } //read voltages
XYmode = true; //if all pots are hight and mode is HIGH than render XY mode instead
if (analogValues[0] < HIGH_THRES) XYmode = false;
for (uint8_t i = 1; i < 4; i++) if (analogValues[i] < 200) XYmode = false; //HIGH_THRES
}
void setTimers(void)
{
/*
TCCR0A=0;
TCCR0B=0;
bitWrite(TCCR0A,COM0A0,0);
bitWrite(TCCR0A,COM0A1,1);
bitWrite(TCCR0A,COM0B0,0);
bitWrite(TCCR0A,COM0B1,1);
bitWrite(TCCR0A,WGM00,1);
bitWrite(TCCR0A,WGM01,1);
bitWrite(TCCR0B,WGM02,0);
bitWrite(TCCR0B,CS00,1);
*/
PLLCSR |= (1 << PLLE); // Enable PLL (64 MHz)
_delay_us(100); // Wait for a steady state
while (!(PLLCSR & (1 << PLOCK))); // Ensure PLL lock
PLLCSR |= (1 << PCKE); // Enable PLL as clock source for timer 1
PLLCSR |= (1 << LSM); //low speed mode 32mhz
cli(); // Interrupts OFF (disable interrupts globally)
TCCR0A = 2 << COM0A0 | 2 << COM0B0 | 3 << WGM00;
TCCR0B = 0 << WGM02 | 1 << CS00;
// setup timer 0 to run fast for audiorate interrupt
TCCR1 = 0; //stop the timer
TCNT1 = 0; //zero the timer
GTCCR = _BV(PSR1); //reset the prescaler
OCR1A = 255; //set the compare value
OCR1C = 255;
// OCR1C = 31;
TIMSK = _BV(OCIE1A);// | _BV(TOIE0); //TOIE0 //interrupt on Compare Match A
//start timer, ctc mode, prescaler clk/1
TCCR1 = _BV(CTC1) | _BV(CS12);// | _BV(CS10) ;//| _BV(CS11);// | _BV(CS11) ;// //| _BV(CS13) | _BV(CS12) | _BV(CS11) |
// GTCCR = (1 << PWM1B) | (1 << COM1B1); // PWM, output on pb4, compare with OCR1B (see interrupt below), reset on match with OCR1C
//OCR1C = 0xff; // 255
// TCCR1 = (1 << CS10); // no prescale
sei();
// TIMSK |=_BV(TOIE0);
}
uint16_t clocks() {
//return _clocks;
return TCNT0 | (_clocks << 8);
}
void writeWave(int wave) {
switch (wave) {
case 0:
sineWave();
break;
case 1:
triangleWave();
break;
case 2:
squareWave();
break;
case 3:
sawtoothWave();
break;
case 4:
digitalWrite(0, LOW);
zeroWave();
break;
}
}
//functions to populate the wavetable
void sineWave() { //too costly to calculate on the fly, so it reads from the sine table. We use 128 values, then mirror them to get the whole cycle
for (int i = 0; i < 128; ++i) {
wavetable[i] = pgm_read_byte_near(sinetable + i);
}
wavetable[128] = 255;
for (int i = 129; i < 256; ++i) {
wavetable[i] = wavetable[256 - i] ;
}
}
void sawtoothWave() {
for (int i = 0; i < 256; ++i) {
wavetable[i] = i; // sawtooth
}
}
void triangleWave() {
for (int i = 0; i < 128; ++i) {
wavetable[i] = i * 2;
}
int value = 255;
for (int i = 128; i < 256; ++i) {
wavetable[i] = value;
value -= 2;
}
}
void squareWave() {
for (int i = 0; i < 128; ++i) {
wavetable[i] = 255;
}
for (int i = 128; i < 256; ++i) {
wavetable[i] = 1; //0 gives problems (offset and different freq), related to sample = ((wavetable[phase >> 8]*amplitude)>>8);
}
}
void zeroWave() {
for (int i = 0; i < 256; ++i) {
wavetable[i] = 1; //0 gives problems
}
}
/*
ISR(TIMER0_OVF_vect){ // increment _clocks at PWM interrupt overflow - this gives 16bit time consciousnes to the chip (aproxx 2 seconds before overflow)
_clocks++;
}
*/
byte sample, sample90;
unsigned int _phase, _lastPhase;
unsigned int frequency;
byte sample2;
unsigned int _phase2, _phase4, _phase5, _phase6;
unsigned int frequency2, frequency4, frequency5, frequency6;
uint8_t _phs, _phs90;
uint8_t _phase3;
uint8_t pitchEnv;
/*
ISR(TIMER0_OVF_vect){ //not used //Timer 0 interruption - changes the width of timer 1's pulse to generate waves
// OCR1B
// analogValues[WS_2]
//phase accumulator
}
*/
ISR(TIMER1_COMPA_vect) // render primary oscillator in the interupt
{
OCR0A = sample;//(sample+sample2)>>1;
OCR0B = sample2;//_phs;// sample90;
//_lastPhase=_phase;
if (pitchEnv) {
_phase += (frequency + (decayVolume));
_phase3 += (frequency + (decayVolume)); //frequency;//
_phase2 += (frequency2 + (decayVolume));
}
else {
_phase += frequency;
_phase3 += frequency;
_phase2 += frequency2;
}
if(!(_phase%4) )_phase4 += frequency4;
//_phase5 += frequency5;
// _phase5 += frequency5;
if (mode) { // other than FM, FM=0
// _phase3 = _phase2 >> 5;
//(frequency2+1)<<1;
//(frequency2-1)*3;
// _phase6 += frequency6;
}
else {
_phs = (_phase + (analogValues[WS_2] * wavetable[_phase2 >> 8])) >> 6;
sample = ((wavetable[_phs] ) * decayVolume) >> 8;
}
/*
out+=incr; // increment the oscillator saw core
if((analogValues[WS_2])<pwmCounter) OCR0B=255; //render pulse oscillator output
else OCR0B=0;
pwmCounter=out<<1; // speed up the frequency of the square wave output twice
TCNT1 = 0; //reset interupt couter
*/
}
uint16_t sampleEnd;
const uint8_t multiplier[24] = {
2, 2, 2, 3, 1, 2, 4, 4, 3, 4, 5, 2, 1, 5, 6, 8, 3, 8, 7, 8, 7, 6, 8, 16
};
void setFrequency2(uint16_t input) {
mode = input >> 7;
if (mode > 6) bitWrite(TCCR0B, CS00, 0), bitWrite(TCCR0B, CS01, 1);
else bitWrite(TCCR0B, CS00, 1), bitWrite(TCCR0B, CS01, 0);
/*
if ( mode == NOISE) frequency2 = (((input - 300) << 2) + 1) / 2; //sampleEnd=map(input,300,1024,0,sampleLength);//
else if ( mode == TAH) {
uint8_t multiplierIndex = analogValues[WS_2] >> 5;
frequency2 = (input << 2) + 1;
frequency4 = (frequency2 + 1) * multiplier[multiplierIndex]; //+analogValues[WS_2]>>4
frequency5 = (frequency2 - 3) * multiplier[multiplierIndex + 8]; //+analogValues[WS_2]>>3
frequency6 = (frequency2 + 7) * multiplier[multiplierIndex + 16]; //+analogValues[WS_2]>>2
}
else {
}
*/
frequency2 = (input << 4) + 1;
frequency4 = 512 - input;
//frequency5 = frequency2;
}
void setLength(uint8_t _length) {
sampleEnd = map(_length, 0, 255, 0, sampleLength);
}
void setFrequency(uint16_t input) {
int addEnv = 0; //((pitchEnv*decayVolume)>>7);
if ( mode == NOISE ) frequency = ((input - 200) << 2) + 1; //NOISE
else if (mode > 3) frequency = (input) + 1;
else frequency = ((input + addEnv) << 2) + 1;
frequency5 = frequency;
/*
coarseVolChange = false; //reset the control condition for volume
if (coarseFreqChange == false) {
byte coarsefreqRead = analogRead(pin) >> 2;
if (coarsefreqRead == potPosFreqRef) {
coarseFreqChange = true;
}
}
if (coarseFreqChange == true) {
int tempRead = analogRead(pin);
byte freqRead = tempRead >> 2;
potPosFreqRef = freqRead;
//frequencymap(tempRead, sensorMin, sensorMax, 1, 3600); //map the calibrated values (by default 0-1023) to the frequency range we want
}
*/
}
int ultimateFold(int _input) {
int _output = _input;
while (_output > 255 || _output < 0) {
if (_output > 255) _output = 255 - (_output - 255);
if (_output < 0) _output = 0 - _output;
}
return _output;
}
uint8_t _sample2, _lastSample2;
#define SAMPLE_PHASE_SHIFT 3
void synthesis() {
if (XYmode) {
sample2=decayVolume;
}
else {
if ((_phase3 >> 2) >= (analogValues[WS_1]) << 4) {
_phase3 = 0;
}
_lastSample2 = sample2;
_sample2 = (char)pgm_read_byte_near(sampleTable + (_phase3) ) + 128; //
// _sample2 = (_sample2 * (wavetable[((_phase2+_phase3)>>8)+sample]>>1)) >> 7;
if (analogValues[PITCH] > wavetable[(_phase4 >> 9) + (_sample2>>5)]) _sample2 = _lastSample2; //128;//_lastSample2;
//+(analogValues[WS_2]<<2)+
else _sample2 = abs(_sample2 - _lastSample2);
sample2 = ((_sample2 * (decayVolume2)) >> 8);
}
if (mode == FM) {
if (XYmode) {
_phs90 = _phs + 64;
// sample2 = (wavetable[_phs90] );
}
else {
/*
_lastSaw = _saw;
_saw = (((255 - (_phase >> 8)) * (analogValues[WS_2])) >> 8);
// uint8_t _p=(_phase4 >> 8)+128;
//sample2 = (((_saw*wavetable[_phase4 >> 8] )>>8)+((wavetable[_phase5 >> 8]*(255-analogValues[WS_2]))>>8)*decayVolume)>>8;
sample2 = (char)pgm_read_byte_near(sampleTable + (_phase >> 2));
sample2 = (sample2 * wavetable[_phase2 >> 8]) >> 8;
sample2 = (sample2 * decayVolume) >> 8;
if (_lastSaw < _saw) _phase4 = 64 << 8; // hard sync for phase distortion
uint8_t shft = abs(_saw - _lastSaw);
if (shft > 3) _phase5 += shft << 8; //soft sync for previous settings of waveshape
*/
}
}
if (mode == NOISE) {
if ((_phase >> 2) >= (analogValues[WS_2] - 100) << 5) {
_phase = 0;
}
_sample = (char)pgm_read_byte_near(sampleTable + (_phase >> 2));
_sample = (_sample * wavetable[_phase2 >> 8]) >> 8;
sample = (_sample * decayVolume) >> 8;
//sample2 = ((wavetable[_phase3 + (_phase >> 8)]) * decayVolume) >> 8;
}
if (mode == TAH) {
if ((_phase2 >> 8) < analogValues[WS_2] + 5) _phs = _phase >> 8, sample = ((wavetable[_phs] ) * decayVolume) >> 8;
if (XYmode) {
_phs90 = _phs + 64;
// sample2 = (wavetable[_phs90] );
}
else {
// sample2 = (((wavetable[_phase2 >> 8] + wavetable[_phase4 >> 8] + wavetable[_phase5 >> 8] + wavetable[_phase6 >> 8]) >> 2) * decayVolume) >> 8;
}
}
if (mode > 2) {
if ((_phase >> 2) >= (analogValues[WS_2] - 100) << 5) {
// _phase=0;
}
}
if (mode == 3) {
if ((_phase >> SAMPLE_PHASE_SHIFT) > sample2Length) _phase = 0;
_sample = (char)pgm_read_byte_near(sample2Table + (_phase >> SAMPLE_PHASE_SHIFT)) + 128;
//_sample = (_sample * wavetable[_phase2 >> 8]) >> 8;
sample = (_sample * decayVolume) >> 8;
//sample2 = ((wavetable[_phase3 + (_phase >> 8)]) * decayVolume) >> 8;
}
if (mode == 4) {
if ((_phase >> SAMPLE_PHASE_SHIFT) > sample3Length) _phase = 0;
_sample = (char)pgm_read_byte_near(sample3Table + (_phase >> SAMPLE_PHASE_SHIFT));
// _sample = (_sample * wavetable[_phase2 >> 8]) >> 8;
sample = (_sample * decayVolume) >> 8;
//sample2 = ((wavetable[_phase3 + (_phase >> 8)]) * decayVolume) >> 8;
}
if (mode == 5) {
if ((_phase >> SAMPLE_PHASE_SHIFT) > sample4Length) _phase = 0;
_sample = (char)pgm_read_byte_near(sample4Table + (_phase >> SAMPLE_PHASE_SHIFT)) + 128;
// _sample = (_sample * wavetable[_phase2 >> 8]) >> 8;
sample = (_sample * decayVolume) >> 8;
// sample2 = ((wavetable[_phase3 + (_phase >> 8)]) * decayVolume) >> 8;
}
if (mode == 6) {
if ((_phase >> SAMPLE_PHASE_SHIFT) > sampleLength) _phase = 0;
_sample = (char)pgm_read_byte_near(sampleTable + (_phase >> SAMPLE_PHASE_SHIFT));
// _sample = (_sample * wavetable[_phase2 >> 8]) >> 8;
sample = (_sample * decayVolume) >> 8;
// sample2 = ((wavetable[_phase3 + (_phase >> 8)]) * decayVolume) >> 8;
}
if (mode == 7) {
if ((_phase >> SAMPLE_PHASE_SHIFT) > sample4Length) _phase = 0;
_sample = (char)pgm_read_byte_near(sample4Table + (_phase >> SAMPLE_PHASE_SHIFT)) + 128;
// _sample = (_sample * wavetable[_phase2 >> 8]) >> 8;
sample = (_sample * decayVolume) >> 8;
// sample2 = ((wavetable[_phase3 + (_phase >> 8)]) * decayVolume) >> 8;
}
}
void loop() {
//if(analogValues[WS_2]<20) analogValues[WS_2]=0;
//FM + PHS DIST
// t&h + chord
// noise sample
synthesis();
renderDecay();
trigDetect();
}
uint8_t trigState = 0;
uint8_t lastTrigState = 0;
void trigDetect() { //rather trigger machine
lastTrigState = trigState;
if (analogValues[0] < LOW_THRES) trigState = 0; //, incr=11,_incr=6, bitShift=2, osc2offset=270;
else if (analogValues[0] > HIGH_THRES) trigState = 2; //, incr=24,_incr=6,bitShift=4,osc2offset=255;
else trigState = 1; //, incr=11,_incr=5,bitShift=4,osc2offset=255;
if (lastTrigState != trigState) trigger(trigState, lastTrigState), _phase = 0;
/*
if(analogValues[0]<LOW_THRES) mode=NOISE; //, incr=11,_incr=6, bitShift=2, osc2offset=270;
else if(analogValues[0]>HIGH_THRES) mode=TAH; //, incr=24,_incr=6,bitShift=4,osc2offset=255;
else mode = FM; //, incr=11,_incr=5,bitShift=4,osc2offset=255;
*/
}
uint8_t trigger(uint8_t intensity_1, uint8_t intensity_2) {
//lastTriggerTime=triggerTime;
//triggerTime=some increment shit
//decayTime=triggerTime-lastTrigerTime;
if (abs(intensity_1 - intensity_2) == 1) decayVolume = 128, decayVolume2 = 255;
else decayVolume = 255, decayVolume2 = 150;
}
uint8_t analogChannelSequence[6] = {0, 1, 0, 2, 0, 3};
uint8_t analogChannelReadIndex;
void setDecay() {
// decayTime2=analogValues[WS_2];
if (analogValues[WS_2] > 100) decayTime = constrain(analogValues[WS_2] - 120, 1, 255), pitchEnv = 0;
else decayTime = (100 - analogValues[WS_2]), pitchEnv = 255; //decayTime;
// decayTime = analogValues[WS_2] + 1
}
ISR(ADC_vect) { // interupt triggered ad completion of ADC counter
startupRead++;
if (!firstRead) { // discard first reading due to ADC multiplexer crosstalk
//update values and remember last values
lastAnalogValues[analogChannelRead] = analogValues[analogChannelRead];
analogValues[analogChannelRead] = getConversionResult() >> 2;
//set ADC MULTIPLEXER to read the next channel
lastAnalogChannelRead = analogChannelRead;
if (!analogChannelRead) trigDetect();
analogChannelReadIndex++;
if (analogChannelReadIndex > 5) analogChannelReadIndex = 0;
analogChannelRead = analogChannelSequence[analogChannelReadIndex];
connectChannel(analogChannelRead);
// set controll values if relevant (value changed)
if (lastAnalogChannelRead == PITCH && lastAnalogValues[PITCH] != analogValues[PITCH]) setFrequency(analogValues[PITCH] << 2), decayVolume2 = constrain(decayVolume2 + ((abs(lastAnalogValues[PITCH] - analogValues[PITCH]) << 3)), 0, 255);; //constrain(mapLookup[,0,1015)); //
if (lastAnalogChannelRead == WS_1 && lastAnalogValues[WS_1] != analogValues[WS_1]) setFrequency2(analogValues[WS_1] << 2), decayVolume = constrain(decayVolume + ((abs(lastAnalogValues[WS_1] - analogValues[WS_1]) << 2)), 0, 255);
if (lastAnalogChannelRead == WS_2 && lastAnalogValues[WS_2] != analogValues[WS_2]) analogValues[WS_2] = analogValues[WS_2], setDecay();
firstRead = true;
//start the ADC - at completion the interupt will be called again
startConversion();
}
else {
/*
at the first reading off the ADX (which will not used)
something else will happen the input pin will briefly turn to output to
discarge charge built up in passive mixing ciruit using zener diodes
because zeners have some higher unpredictable capacitance, various voltages might get stuck on the pin
*/
// if(analogChannelRead!=0) - by mohlo vyresit celou situaci
// if( mode==PHASE_DIST && analogChannelRead!=PITCH){ // //this would somehow make the reset pin trigger because the reset pin is already pulled to ground
if ( mode == NOISE) { // && analogChannelRead!=PITCH){//if(analogChannelRead==0){
// bitWrite(PORTB,analogToDigitalPinMapping[analogChannelRead],1);
// renderDecay();
}
else {
if (analogValues[analogChannelRead] < 200) bitWrite(DDRB, analogToDigitalPinMapping[analogChannelRead], 1);
bitWrite(DDRB, analogToDigitalPinMapping[analogChannelRead], 0);
bitWrite(PORTB, analogToDigitalPinMapping[analogChannelRead], 0);
}
firstRead = false;
startConversion();
}
}
uint16_t decayCounter = 0;
uint16_t decayCounter2 = 0;
void renderDecay() {
if (decayTime != 0) {
if (1) {
decayCounter += 6;
if (decayCounter >= decayTime)
{
decayCounter = 0;
if (decayVolume > 0) decayVolume -= ((decayVolume >> 6) + 1);
//else decayVolume=255;//, _phase=0;
}
}
}
if (decayTime != 0) {
if (1) {
decayCounter2 += 6;
if (decayCounter2 >= (decayTime))
{
decayCounter2 = 0;
if (decayVolume2 > 0) decayVolume2 -= ((decayVolume2 >> 6) + 1);
//else decayVolume=255;//, _phase=0;
}
}
}
}
/*
void setFrequency(int _freq){ //set frequency of the interupt for primary oscillator
_freq=1024-_freq;
uint8_t preScaler=_freq>>7;
preScaler+=2; //*2
pwmIncrement=4;
_upIncrement=pwmIncrement*upIncrement;
_downIncrement=pwmIncrement*downIncrement;
for(uint8_t i=0;i<4;i++) bitWrite(TCCR1,CS10+i,bitRead(preScaler,i));
uint8_t compare=_freq;
bitWrite(compare,7,0);
if(quantizer){ // if quantizer was implemented
//compare=tuneTable[map(compare,0,127,0,6)];
}
OCR1A=compare+128;
}
*/
// #### FUNCTIONS TO ACCES ADC REGISTERS
void init() {
ADMUX = 0;
bitWrite(ADCSRA, ADEN, 1); //adc enabled
bitWrite(ADCSRA, ADPS2, 1); // set prescaler
bitWrite(ADCSRA, ADPS1, 1); // set prescaler
bitWrite(ADCSRA, ADPS0, 1); // set prescaler
bitWrite(ADCSRA, ADIE, 1); //enable conversion finished interupt
bitWrite(SREG, 7, 1);
// prescaler = highest division
}
// channel 8 can be used to measure the temperature of the chip
void connectChannel(uint8_t number) {
ADMUX &= (11110000);
ADMUX |= number;
}
void startConversion() {
bitWrite(ADCSRA, ADSC, 1); //start conversion
}
bool isConversionFinished() {
return (ADCSRA & (1 << ADIF));
}
bool isConversionRunning() {
return !(ADCSRA & (1 << ADIF));
}
uint16_t getConversionResult() {
uint16_t result = ADCL;
return result | (ADCH << 8);
}