/*
   Auduino Lo-Fi granular synthesiser
   by Peter Knight, https://create.arduino.cc/projecthub/GroupGets/5potsynth-b3506d

   Adapted by Anderson Costa for the Wokwi simulator
   https://wokwi.com/arduino/projects/299483632784900621

   Early stage (experimental)

   Analog in 0: Grain 1 pitch
   Analog in 1: Grain 1 decay
   Analog in 2: Grain 2 pitch
   Analog in 3: Grain 2 decay
   Analog in 4: Grain repetition frequency

   Digital in  4: Switch stepped mapping (LOW = chromatic / HIGH = pentatonic)
   Digital in  7: Switch smooth mapping (LOW = logarithmic)

   Digital out 3: Audio signal
   Digital out 5: LED indication of repetition frequency
*/

#include <avr/io.h>
#include <avr/interrupt.h>

// Map Analogue channels
#define GRAIN_FREQ_CONTROL   A0
#define GRAIN_DECAY_CONTROL  A1
#define GRAIN2_FREQ_CONTROL  A2
#define GRAIN2_DECAY_CONTROL A3
#define SYNC_CONTROL         A4

// Map Digital pins
#define PWM_PIN              3
#define LED_BIT              5
#define SW1_PIN              4
#define SW2_PIN              7

#define PWM_VALUE            OCR2B
#define PWM_INTERRUPT        TIMER2_OVF_vect

// Variables
uint16_t syncPhaseAcc;
uint16_t syncPhaseInc;
uint16_t grainPhaseAcc;
uint16_t grainPhaseInc;
uint16_t grainAmp;
uint8_t grainDecay;
uint16_t grain2PhaseAcc;
uint16_t grain2PhaseInc;
uint16_t grain2Amp;
uint8_t grain2Decay;

// Smooth logarithmic mapping
//
uint16_t antilogTable[] = {
  64830, 64132, 63441, 62757, 62081, 61413, 60751, 60097, 59449, 58809, 58176, 57549, 56929, 56316, 55709, 55109,
  54515, 53928, 53347, 52773, 52204, 51642, 51085, 50535, 49991, 49452, 48920, 48393, 47871, 47356, 46846, 46341,
  45842, 45348, 44859, 44376, 43898, 43425, 42958, 42495, 42037, 41584, 41136, 40693, 40255, 39821, 39392, 38968,
  38548, 38133, 37722, 37316, 36914, 36516, 36123, 35734, 35349, 34968, 34591, 34219, 33850, 33486, 33125, 32768
};

uint16_t mapPhaseInc(uint16_t input) {
  return (antilogTable[input & 0x3f]) >> (input >> 6);
}

// Stepped chromatic mapping
//
uint16_t midiTable[] = {
  17, 18, 19, 20, 22, 23, 24, 26, 27, 29, 31, 32, 34, 36, 38, 41, 43, 46, 48, 51, 54, 58, 61, 65, 69, 73,
  77, 82, 86, 92, 97, 103, 109, 115, 122, 129, 137, 145, 154, 163, 173, 183, 194, 206, 218, 231,
  244, 259, 274, 291, 308, 326, 346, 366, 388, 411, 435, 461, 489, 518, 549, 581, 616, 652, 691,
  732, 776, 822, 871, 923, 978, 1036, 1097, 1163, 1232, 1305, 1383, 1465, 1552, 1644, 1742,
  1845, 1955, 2071, 2195, 2325, 2463, 2610, 2765, 2930, 3104, 3288, 3484, 3691, 3910, 4143,
  4389, 4650, 4927, 5220, 5530, 5859, 6207, 6577, 6968, 7382, 7821, 8286, 8779, 9301, 9854,
  10440, 11060, 11718, 12415, 13153, 13935, 14764, 15642, 16572, 17557, 18601, 19708, 20879,
  22121, 23436, 24830, 26306
};

uint16_t mapMidi(uint16_t input) {
  return (midiTable[(1023 - input) >> 3]);
}

// Stepped Pentatonic mapping
//
uint16_t pentatonicTable[54] = {
  0, 19, 22, 26, 29, 32, 38, 43, 51, 58, 65, 77, 86, 103, 115, 129, 154, 173, 206, 231, 259, 308, 346,
  411, 461, 518, 616, 691, 822, 923, 1036, 1232, 1383, 1644, 1845, 2071, 2463, 2765, 3288,
  3691, 4143, 4927, 5530, 6577, 7382, 8286, 9854, 11060, 13153, 14764, 16572, 19708, 22121, 26306
};

uint16_t mapPentatonic(uint16_t input) {
  uint8_t value = (1023 - input) / (1024 / 53);
  return (pentatonicTable[value]);
}

void audioOn() {
  // Set up PWM to 31.25kHz, phase accurate
  TCCR2A = _BV(COM2B1) | _BV(WGM20);
  TCCR2B = _BV(CS20);
  TIMSK2 = _BV(TOIE2);
}

void setup() {
  Serial.begin(9600);
  pinMode(GRAIN_FREQ_CONTROL, INPUT);
  pinMode(GRAIN2_DECAY_CONTROL, INPUT);
  pinMode(GRAIN_DECAY_CONTROL, INPUT);
  pinMode(GRAIN2_FREQ_CONTROL, INPUT);
  pinMode(SYNC_CONTROL, INPUT);
  pinMode(SW1_PIN, INPUT_PULLUP);
  pinMode(SW2_PIN, INPUT_PULLUP);
  pinMode(PWM_PIN, OUTPUT);
  pinMode(LED_BIT, OUTPUT);
  // audioOn();
}

// The loop is pretty simple
// it just updates the parameters for the oscillators
void loop() {
  // Switch stepped mapping (LOW = chromatic / HIGH = pentatonic)
  if (digitalRead(SW1_PIN) == LOW) {
    // Stepped mapping to MIDI notes: C, Db, D, Eb, E, F...
    syncPhaseInc = mapMidi(analogRead(SYNC_CONTROL));
  } else {
    // Stepped pentatonic mapping: D, E, G, A, B
    syncPhaseInc = mapPentatonic(analogRead(SYNC_CONTROL));
  }

  // Switch stepped mapping (LOW = Smooth logarithmic)
  if (digitalRead(SW2_PIN) == LOW) {
    // Smooth frequency mapping
    syncPhaseInc = mapPhaseInc(analogRead(SYNC_CONTROL)) / 4;
  }

  // Updates the phase & decay for the oscillators
  grainPhaseInc  = mapPhaseInc(analogRead(GRAIN_FREQ_CONTROL)) / 2;
  grainDecay     = analogRead(GRAIN_DECAY_CONTROL) / 8;
  grain2PhaseInc = mapPhaseInc(analogRead(GRAIN2_FREQ_CONTROL)) / 2;
  grain2Decay    = analogRead(GRAIN2_DECAY_CONTROL) / 4;

  // Send audio signal to output
  tone(PWM_PIN, signal());
}

// SIGNAL(PWM_INTERRUPT)
uint16_t signal()
{
  uint8_t value;
  uint16_t output;

  syncPhaseAcc += syncPhaseInc;

  if (syncPhaseAcc < syncPhaseInc) {
    // Time to start the next grain
    grainPhaseAcc = 0;
    grainAmp = 0x7fff;
    grain2PhaseAcc = 0;
    grain2Amp = 0x7fff;
    // Faster than using digitalWrite
    PORTD ^= 1 << LED_BIT;
  }

  // Increment the phase of the grain oscillators
  grainPhaseAcc += grainPhaseInc;
  grain2PhaseAcc += grain2PhaseInc;

  // Convert phase into a triangle wave
  value = (grainPhaseAcc >> 7) & 0xff;
  if (grainPhaseAcc & 0x8000) value = ~value;

  // Multiply by current grain amplitude to get sample
  output = value * (grainAmp >> 8);

  // Repeat for second grain
  value = (grain2PhaseAcc >> 7) & 0xff;

  if (grain2PhaseAcc & 0x8000) value = ~value;
  output += value * (grain2Amp >> 8);

  // Make the grain amplitudes decay by a factor every sample (exponential decay)
  grainAmp -= (grainAmp >> 8) * grainDecay;
  grain2Amp -= (grain2Amp >> 8) * grain2Decay;

  // Scale output to the available range, clipping if necessary
  output >>= 9;
  if (output > 255) output = 255;

  // Output to PWM (this is faster than using analogWrite)
  // PWM_VALUE = output;

  return output;
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
pot1:VCC
pot1:SIG
pot1:GND
pot2:VCC
pot2:SIG
pot2:GND
pot3:VCC
pot3:SIG
pot3:GND
pot4:VCC
pot4:SIG
pot4:GND
pot5:VCC
pot5:SIG
pot5:GND
bz1:1
bz1:2
r1:1
r1:2
led:A
led:C
sw1:1
sw1:2
sw1:3
sw2:1
sw2:2
sw2:3