Controlling two attiny85s with one footswitch

Started by patrick398, December 12, 2020, 03:44:52 AM

Previous topic - Next topic

patrick398


I've spent most of the day trying to work this out and can't find exactly the information i'm after and i can't figure it out myself so hoping someone can give me a hand.

I'm using two ATtiny85s currently which are part of a larger circuit. tiny #1 is a strange noise maker, tiny #2 is controlling a relay which switches in/out tiny #1 into a larger guitar effect. It's all working well but i started thinking that it would be cool if the footswitch connected to tiny #2 which bypasses/unbypasses could also change the 'mode' of tiny #1 which is making the noise. So that the footswitch would bypass/unbypass tiny #2 with a short press (as it does currently), but select between two modes in tiny #1 when there's a long press.

So i need to change the code for tiny #2 so that it toggles on button release rather than press, and it also needs to ignore long presses so that it won't bypass tiny #1 when you're trying to change the mode.

Then i need to have tiny #1 read the same footswitch as tiny #2 and change between two different pieces of code (noise makers) only when it detects a long press. So i guess tiny #1 only deals with short presses and tiny #2 only deals with long presses.

This is an attempt at the code for tiny #2 largely based on an arduinogetstarted tutorial.

#include <ezButton.h>
int buttonPin = 3;
int relayPin = 0;
const int SHORT_PRESS_TIME = 1000; // 1000 milliseconds
const int LONG_PRESS_TIME  = 1000; // 1000 milliseconds

ezButton button(buttonPin);  // create ezButton object that attach to buttonPin;

int relayState = LOW;
unsigned long pressedTime  = 0;
unsigned long releasedTime = 0;
bool isPressing = false;
bool isLongDetected = false;

void setup() {
  button.setDebounceTime(50); // set debounce time to 50 milliseconds
  pinMode (buttonPin, INPUT_PULLUP);
  pinMode (relayPin, OUTPUT);
  digitalWrite (relayPin, relayState);
}

void loop() {
  button.loop(); // MUST call the loop() function first


  if (button.isPressed()) {
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  }

  if (button.isReleased()) {
    isPressing = false;
    releasedTime = millis();

    long pressDuration = releasedTime - pressedTime;

    if ( pressDuration < SHORT_PRESS_TIME ) {
      relayState = !relayState;
      digitalWrite (relayPin, relayState);


    }

    if (isPressing == true && isLongDetected == false) {
      long pressDuration = millis() - pressedTime;

      if ( pressDuration > LONG_PRESS_TIME ) {

        isLongDetected = true;
      }
    }
  }


I'm not sure that's the best way to go about it but that's where i'm at.
I'm really stumped on how to use long presses only to toggle between modes on tiny #1. I thought about using the same approach here but i can't think how to select between two different bits of code.

Sorry for the info-dump! Any help would be greatly appreciated

Patrick

pruttelherrie

#1
Quote from: patrick398 on December 12, 2020, 03:44:52 AM
I'm really stumped on how to use long presses only to toggle between modes on tiny #1. I thought about using the same approach here but i can't think how to select between two different bits of code.

Use a boolean variable to choose between two code-paths (the two modes), and have a detected long-press toggle this boolean.


boolean UseModeOne = true;

main {
  <some code to read the Bounce object>

  if(longpress) {
    UseModeOne = !UseModeOne; // invert boolean when longpress is detected
    <unset the longpress variable to prevent inverting on every loop!>
  }

  if(UseModeOne) {
    <code for mode one>
  } else {
    <code for mode two>
  }
}


... or I might totally misunderstand your question.

patrick398

Thanks for the reply! I think i understand what you're saying, implementing it may take some doing.
I've decided to split this into two problems to make it simpler. The easier of the two is having the tiny that is bypassing/unbypassing only triggering on detection of a short press. I have this so far: It does indeed trigger on the short press as intended but it also triggers on a long press. I have no code in the section for the long press so i'm not sure why it's doing that.

#include <ezButton.h>
const int buttonPin = 3; //2
int relayPin = 0;// 5
int noisePin = 1; //6

const int SHORT_PRESS_TIME = 1000; // 1000 milliseconds
const int LONG_PRESS_TIME  = 1000; // 1000 milliseconds

ezButton button(buttonPin);  // create ezButton object that attach to pin 7;

int noiseState = LOW;
int relayState = LOW;
unsigned long pressedTime  = 0;
unsigned long releasedTime = 0;
bool isPressing = false;
bool isLongDetected = false;

void setup() {
  pinMode (buttonPin, INPUT_PULLUP);
  pinMode (relayPin, OUTPUT);
  pinMode (noisePin, OUTPUT);
  button.setDebounceTime(30); // set debounce time to 30 milliseconds
  digitalWrite (relayPin, relayState);
  digitalWrite (noisePin, noiseState);

}

void loop() {
  button.loop(); // MUST call the loop() function first

  if (button.isPressed()) {
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  }

  if (button.isReleased()) {
    isPressing = false;
    releasedTime = millis();

    long pressDuration = releasedTime - pressedTime;

    if ( pressDuration < SHORT_PRESS_TIME )
      noiseState = !noiseState;
    digitalWrite (noisePin, noiseState);

    relayState = !relayState;
    digitalWrite(relayPin, relayState);

  }

  if (isPressing == true && isLongDetected == false) {
    long pressDuration = millis() - pressedTime;

    if ( pressDuration > LONG_PRESS_TIME ) {}

      isLongDetected = true;
   
  }
}



Anything jumping out?
I think i'll try and tackle the boolean variable once i've got this part working.

patrick398

For the boolean variable section, or mode selection i tried implementing something as per your advice, or what i understood it to be. It kind of works, I'm just using LEDs to see if it's working. LED 2 flashes after 3 seconds but LED 1 lights straight away and only turns off when LED 2 flashes. When i press the button again LED 2 flashes straight away then turns off when LED 1 turns on after 3 seconds.

boolean mode1 = true;

const int BUTTON_PIN = 3; // the number of the pushbutton pin
const int LONG_PRESS_TIME  = 3000; // 1000 milliseconds
int LED1 = 0;
int LED2 = 1;
int LED1State;


// Variables will change:
int lastState = LOW;  // the previous state from the input pin
int currentState;     // the current reading from the input pin
unsigned long pressedTime  = 0;
bool isPressing = false;
bool isLongDetected = false;

void setup() {

  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode (LED1, OUTPUT);
  digitalWrite (LED1, LOW);
  pinMode (LED2, OUTPUT);
  digitalWrite (LED2, LOW);
}

void loop() {
  // read the state of the switch/button:
  currentState = digitalRead(BUTTON_PIN);

  if (lastState == HIGH && currentState == LOW) {       // button is pressed
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  } else if (lastState == LOW && currentState == HIGH) { // button is released
    isPressing = false;
  }

  if (isPressing == true && isLongDetected == false) {
    long pressDuration = millis() - pressedTime;

    if ( pressDuration > LONG_PRESS_TIME ) {
      mode1 = !mode1;
      isLongDetected = true;

    }
    if (mode1) {
      LED1State = !LED1State;
      digitalWrite (LED1, LED1State);
     
    }
    else {
      digitalWrite (LED2, HIGH);
      delay (100);
      digitalWrite (LED2, LOW);
      delay (100);
      digitalWrite (LED2, HIGH);
      delay (100);
      digitalWrite (LED2, LOW);
     


    }

  }

  lastState = currentState;
}

pruttelherrie

Quote from: patrick398 on December 13, 2020, 03:01:30 AM
LED 2 flashes after 3 seconds but LED 1 lights straight away and only turns off when LED 2 flashes. When i press the button again LED 2 flashes straight away then turns off when LED 1 turns on after 3 seconds.

I think that's how it's supposed to work; only at the end of the press will you know if it's a longpress or not.

But I see that now the mode-decision is inside the if(isPressed && !longDetected) block, however it should be called on every loop. The longDuration = ... can move into the "button is released" part, like so:


bool mode1 = true;

const int BUTTON_PIN = 3; // the number of the pushbutton pin
const int LONG_PRESS_TIME  = 3000; // 1000 milliseconds
int LED1 = 0;
int LED2 = 1;
int LED1State;

// Variables will change:
int lastState = LOW;  // the previous state from the input pin
int currentState;     // the current reading from the input pin
unsigned long pressedTime  = 0;
long pressDuration;
bool isPressing = false;
bool isLongDetected = false;

void setup() {

  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode (LED1, OUTPUT);
  digitalWrite (LED1, LOW);
  pinMode (LED2, OUTPUT);
  digitalWrite (LED2, LOW);
}

void loop() {
  // read the state of the switch/button:
  currentState = digitalRead(BUTTON_PIN);

  if (lastState == HIGH && currentState == LOW) {       // button is pressed
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  } else if (lastState == LOW && currentState == HIGH) { // button is released
    isPressing = false;
    pressDuration = millis() - pressedTime;
    if ( pressDuration > LONG_PRESS_TIME ) {
      mode1 = !mode1;
      isLongDetected = true;
    }
  }

  if (mode1) {
      LED1State = !LED1State;
      digitalWrite (LED1, LED1State);
  }  else {
      digitalWrite (LED2, HIGH);
      delay (100);
      digitalWrite (LED2, LOW);
      delay (100);
      digitalWrite (LED2, HIGH);
      delay (100);
      digitalWrite (LED2, LOW);
  }

  lastState = currentState;
}


Please note that "LED1State = !LED1State;" will be called on every loop(), so it will toggle very fast and it will look as if it is lit all the time. Also, if you need to do some setup of variables when you toggle modes, this should be put in the if(pressDuration > LONG_PRESS_TIME) block.



potul

Quote from: patrick398 on December 12, 2020, 10:02:18 AM


Anything jumping out?
I think i'll try and tackle the boolean variable once i've got this part working.

Aren't you missing some brackets here:

    if ( pressDuration < SHORT_PRESS_TIME )
      noiseState = !noiseState;
    digitalWrite (noisePin, noiseState);

    relayState = !relayState;
    digitalWrite(relayPin, relayState);

  }


Shouldn't it be:

    if ( pressDuration < SHORT_PRESS_TIME ){
      noiseState = !noiseState;
    digitalWrite (noisePin, noiseState);

    relayState = !relayState;
    digitalWrite(relayPin, relayState);
}
  }

patrick398

Quote from: pruttelherrie on December 13, 2020, 04:35:04 AM
Quote from: patrick398 on December 13, 2020, 03:01:30 AM
LED 2 flashes after 3 seconds but LED 1 lights straight away and only turns off when LED 2 flashes. When i press the button again LED 2 flashes straight away then turns off when LED 1 turns on after 3 seconds.

I think that's how it's supposed to work; only at the end of the press will you know if it's a longpress or not.

But I see that now the mode-decision is inside the if(isPressed && !longDetected) block, however it should be called on every loop. The longDuration = ... can move into the "button is released" part, like so:


bool mode1 = true;

const int BUTTON_PIN = 3; // the number of the pushbutton pin
const int LONG_PRESS_TIME  = 3000; // 1000 milliseconds
int LED1 = 0;
int LED2 = 1;
int LED1State;

// Variables will change:
int lastState = LOW;  // the previous state from the input pin
int currentState;     // the current reading from the input pin
unsigned long pressedTime  = 0;
long pressDuration;
bool isPressing = false;
bool isLongDetected = false;

void setup() {

  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode (LED1, OUTPUT);
  digitalWrite (LED1, LOW);
  pinMode (LED2, OUTPUT);
  digitalWrite (LED2, LOW);
}

void loop() {
  // read the state of the switch/button:
  currentState = digitalRead(BUTTON_PIN);

  if (lastState == HIGH && currentState == LOW) {       // button is pressed
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  } else if (lastState == LOW && currentState == HIGH) { // button is released
    isPressing = false;
    pressDuration = millis() - pressedTime;
    if ( pressDuration > LONG_PRESS_TIME ) {
      mode1 = !mode1;
      isLongDetected = true;
    }
  }

  if (mode1) {
      LED1State = !LED1State;
      digitalWrite (LED1, LED1State);
  }  else {
      digitalWrite (LED2, HIGH);
      delay (100);
      digitalWrite (LED2, LOW);
      delay (100);
      digitalWrite (LED2, HIGH);
      delay (100);
      digitalWrite (LED2, LOW);
  }

  lastState = currentState;
}


Please note that "LED1State = !LED1State;" will be called on every loop(), so it will toggle very fast and it will look as if it is lit all the time. Also, if you need to do some setup of variables when you toggle modes, this should be put in the if(pressDuration > LONG_PRESS_TIME) block.

Thanks a lot for checking it over. So the variables associated with the two pieces of code for the two modes should be placed in the if(pressDuration... Part?
What do you mean LED1State... will be called on every loop? It runs even when mode two is selected? It needs to work like a toggle between the two modes that only activates after a 3 second button press. I'll worry about led indicators later haha

Quote from: potul on December 13, 2020, 05:46:05 AM
Quote from: patrick398 on December 12, 2020, 10:02:18 AM


Anything jumping out?
I think i'll try and tackle the boolean variable once i've got this part working.

Aren't you missing some brackets here:

    if ( pressDuration < SHORT_PRESS_TIME )
      noiseState = !noiseState;
    digitalWrite (noisePin, noiseState);

    relayState = !relayState;
    digitalWrite(relayPin, relayState);

  }


Shouldn't it be:

    if ( pressDuration < SHORT_PRESS_TIME ){
      noiseState = !noiseState;
    digitalWrite (noisePin, noiseState);

    relayState = !relayState;
    digitalWrite(relayPin, relayState);
}
  }


Yes I think you're right, I'll try that and see where it gets me. Thanks!

niektb

Can't you write a little communication system between the two ATTiny's? Using I2C?

patrick398

Quote from: niektb on December 13, 2020, 10:32:32 AM
Can't you write a little communication system between the two ATTiny's? Using I2C?

I think learning how to do that would take me even further away from a solution ha

pruttelherrie

Quote from: patrick398 on December 13, 2020, 10:22:44 AM
So the variables associated with the two pieces of code for the two modes should be placed in the if(pressDuration... Part?

Only if you need to do some initialisation of these variables when you switch to that mode.

QuoteWhat do you mean LED1State... will be called on every loop? It runs even when mode two is selected? It needs to work like a toggle between the two modes that only activates after a 3 second button press.
Yes, the code above will call "LED1State = !LED1State; " on EVERY loop(), so the LED will flash really fast. You should move this inverting into the block above it. But the normal algorithm should stay in the lower code blocks, like this:


   if (lastState == HIGH && currentState == LOW) {       // button is pressed
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  } else if (lastState == LOW && currentState == HIGH) { // button is released
    isPressing = false;
    pressDuration = millis() - pressedTime;
    if ( pressDuration > LONG_PRESS_TIME ) {
      mode1 = !mode1;
      if(mode1) {
        LED1State = true;
        digitalWrite(LED1, HIGH);
        LED2State = false;
        digitalWrite(LED2, LOW);
      } else {
          LED1State = false;
          digitalWrite(LED1, LOW);
          LED2State = true;
          digitalWrite(LED2, HIGH);
      }
      isLongDetected = true;
    }
  }

  if(mode1) {

     < do algorithm 1 stuff here >

  } else {

     < do algorithm 2 stuff here >

  }





But proably you want to do more in mode1, so I would suggest:


if (lastState == HIGH && currentState == LOW) {       // button is pressed
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  } else if (lastState == LOW && currentState == HIGH) { // button is released
    isPressing = false;
    pressDuration = millis() - pressedTime;
    if ( pressDuration > LONG_PRESS_TIME ) {
      mode1 = !mode1;
      isLongDetected = true;
    }
  }

niektb

Quote from: patrick398 on December 13, 2020, 11:16:02 AM
Quote from: niektb on December 13, 2020, 10:32:32 AM
Can't you write a little communication system between the two ATTiny's? Using I2C?

I think learning how to do that would take me even further away from a solution ha

If you ever feel bored hahah  :icon_mrgreen:
https://www.instructables.com/Communication-Between-Two-Arduinos-I2C/
The upside is that you can separate the functionality of the attiny's much better, makes it much more elegant  8) ;)

patrick398

#11
This seems to be working quite well now with the LEDs, so thank you so much. I feel like i'm about to run into a lot of problems trying to get the different bits of actual code instead of the LEDs going.
I've tried replacing one of the 'mode' sections with the noise code. I can see the LED flashing erratically as expected, but when holding the switch for 3 seconds the the LED just turns on rather than flashing.

Also, i've realised the other 'mode' i want to include does everything in the setup and nothing in the loop, am i going to have to rethink how i do this?

Here's where i'm at so far:

boolean mode1 = true;

const int BUTTON_PIN = 3; // the number of the pushbutton pin
const int LONG_PRESS_TIME  = 3000; // 3000 milliseconds
int PWM_pin = 0;
int LED2 = 1; // LED2 Pin
int LED1State; // track state of LED1
int LED2State; // track state of LED2


// Variables will change:
int lastState = LOW; 
int currentState;     
unsigned long pressedTime  = 0;
bool isPressing = false;
bool isLongDetected = false;
void setup() {
 
  pinMode(BUTTON_PIN, INPUT_PULLUP);

  pinMode (LED2, OUTPUT);
  digitalWrite (LED2, LOW);
}

void loop() {
  // read the state of the switch/button:
  currentState = digitalRead(BUTTON_PIN);

  // button is pressed
   if (lastState == HIGH && currentState == LOW) {     
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;

    // button is released
  } else if (lastState == LOW && currentState == HIGH) {
    isPressing = false;
  }
 
  if (isPressing == true && isLongDetected == false) {
   
  long  pressDuration = millis() - pressedTime;


    if ( pressDuration > LONG_PRESS_TIME ) {
      mode1 = !mode1;
     
      isLongDetected = true;
    }
  }

  if(mode1) {

   int potVal2 = analogRead(2);
  int sensorReading = analogRead(1)*14 ; //6
  int thisPitch = map(sensorReading, 10, 65, potVal2, 100);

     tone(LED2, thisPitch); // 5

  } else {

    digitalWrite (LED2, HIGH);
    delay (50);
    digitalWrite (LED2, LOW);
    delay (50);
     digitalWrite (LED2, HIGH);
    delay (50);
    digitalWrite (LED2, LOW);
    delay (50);
     digitalWrite (LED2, HIGH);
    delay (50);
    digitalWrite (LED2, LOW);
    delay (50);
  }
// track state of the button
     lastState = currentState;
}


And here is the pitch shifting code i would like to use as 'mode 2'. I have changed it so i'm no longer using buttons to change the pitch shift, it's set at a constant down tune...beyond that i have basically no idea how it works  :icon_redface:


volatile uint8_t Buffer[256];             // Circular buffer
volatile uint8_t ReadPtr, WritePtr, LastPtr, New;

// Everything done by interrupts **********************************

// ADC conversion complete - save sample in buffer
ISR (ADC_vect) {
  Buffer[LastPtr] = New;
  New = ADCH + 128;
  Buffer[WritePtr] = (Buffer[WritePtr] + New)>>1;
  LastPtr = WritePtr;
  WritePtr = (WritePtr + 1) & 0xFF;
}

// Timer interrupt - read from buffer and output to DAC
ISR (TIMER0_COMPA_vect) {
  OCR1A = Buffer[ReadPtr];
  ReadPtr = (ReadPtr + 1) & 0xFF;
}

// Pin change interrupt adjusts shift
ISR (PCINT0_vect) {
  int Buttons = PINB;
  if ((Buttons & 0x01) == 0) OCR0A++;
  else if ((Buttons & 0x04) == 0) OCR0A--;
}

// Setup **********************************************
 
void setup () {
  // Enable 64 MHz PLL and use as source for Timer1
  PLLCSR = 1<<PCKE | 1<<PLLE;     

  // Set up Timer/Counter1 for PWM output
  TIMSK = 0;                              // Timer interrupts OFF
  TCCR1 = 1<<PWM1A | 2<<COM1A0 | 1<<CS10; // PWM OCR1A, clear on match, 1:1 prescale
  OCR1A = 128;
  pinMode(1, OUTPUT);                     // Enable OC1A PWM output pin

  // Set up Timer/Counter0 to generate 20kHz interrupt
  TCCR0A = 2<<WGM00;                      // CTC mode
  TCCR0B = 2<<CS00;                       // /8 prescaler
  OCR0A = 60;                             // 17.9kHz interrupt
  TIMSK = TIMSK | 1<<OCIE0A;              // Enable interrupt
 
  // Set up ADC
  ADMUX = 2<<REFS0 | 1<<ADLAR | 7<<MUX0;  // Internal 1.1V ref, ADC2 vs ADC3, x20
  // Enable, auto trigger, interrupt, 250kHz ADC clock:
  ADCSRA = 1<<ADEN | 1<<ADSC | 1<<ADATE | 1<<ADIE | 5<<ADPS0; 
  ADCSRB = 1<<7 | 0<<ADTS0;               // Bipolar, free-running

  // Set up buttons on PB0 and PB2
  pinMode(0, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  PCMSK = 1<<PINB0 | 1<<PINB2;            // Pin change interrupts on PB0 and PB2
  GIMSK = GIMSK | 1<<PCIE;                // Enable pin change interrupt
}

void loop () {
}



ElectricDruid

Quote from: patrick398 on December 14, 2020, 08:14:16 AM
And here is the pitch shifting code i would like to use as 'mode 2'. I have changed it so i'm no longer using buttons to change the pitch shift, it's set at a constant down tune...beyond that i have basically no idea how it works  :icon_redface:

I can't help with some of the other stuff, but I think I can tell you how the pitch shift works. Here goes!

It looks like it sets up a 20KHz sample rate for the ADC and an interrupt at that rate. That interrupt puts samples into a circular buffer.

At the same time, there's another interrupt at a different rate for the DAC (17.9KHz is mentioned for starters) which takes a sample out of the circular buffer and spits it out.

Since they're going at different rates, there'll be a pitch shift. Since there's no crossfading or any other efforts made to hide the points where the two pointers cross or jump from newer data to older or whatever, there'll also be lots of glitches.

The next-simplest alternative is some kind of cross-fading to hide the joins, like the FV-1 uses. That removes any clicks, but instead gives you volume variations. This happens because the two signals for the crossfade are either in phase (no problem) or out of phase, in which case you get partial or total cancellation and a drop in volume. This wouldn't be so bad except that it happens regularly, so you get a pitch shift, but with a pulsing tremolo.

pruttelherrie

Next to ElectricDruid's nice explanation, you have to keep in mind that the mode2 pitchshifter runs in the interrupts, so to switch back to mode1 you'll have to turn off those interrupts (in the "setup" part of the mode switching).

patrick398

Quote from: ElectricDruid on December 14, 2020, 10:52:50 AM
Quote from: patrick398 on December 14, 2020, 08:14:16 AM
And here is the pitch shifting code i would like to use as 'mode 2'. I have changed it so i'm no longer using buttons to change the pitch shift, it's set at a constant down tune...beyond that i have basically no idea how it works  :icon_redface:

I can't help with some of the other stuff, but I think I can tell you how the pitch shift works. Here goes!

It looks like it sets up a 20KHz sample rate for the ADC and an interrupt at that rate. That interrupt puts samples into a circular buffer.

At the same time, there's another interrupt at a different rate for the DAC (17.9KHz is mentioned for starters) which takes a sample out of the circular buffer and spits it out.

Since they're going at different rates, there'll be a pitch shift. Since there's no crossfading or any other efforts made to hide the points where the two pointers cross or jump from newer data to older or whatever, there'll also be lots of glitches.

The next-simplest alternative is some kind of cross-fading to hide the joins, like the FV-1 uses. That removes any clicks, but instead gives you volume variations. This happens because the two signals for the crossfade are either in phase (no problem) or out of phase, in which case you get partial or total cancellation and a drop in volume. This wouldn't be so bad except that it happens regularly, so you get a pitch shift, but with a pulsing tremolo.

Thanks for that Tom! I've been messing with some of the numbers in the code, it gets pretty whacky which is fun. You can get bonkers modulation and fierce ring modulation sounds. The clicking is quite present in the down tuned sound I had originally and trying to make more of the tremolo sound did occur to me. Not sure how useful a tremolo with no speed control is though...probably a damn sight more useful than the strange noises I currently have it make ha.

Quote from: pruttelherrie on December 14, 2020, 03:28:04 PM
Next to ElectricDruid's nice explanation, you have to keep in mind that the mode2 pitchshifter runs in the interrupts, so to switch back to mode1 you'll have to turn off those interrupts (in the "setup" part of the mode switching).
I had a feeling that was going to cause me troubles. Is this something I might be able to work out how to do on my own? I can brew some strong coffee and go Mano a Mano with Google (duckduckgo)
If I can't figure it out I can always use two tiny chips and have one mode on each...but that would feel like such a fail.

niektb

I might be wrong but does the first code work as expected in mode2? Seems that it takes a long time before CurrentState is updated?

pruttelherrie

Quote from: patrick398 on December 14, 2020, 05:08:24 PM
Quote from: pruttelherrie on December 14, 2020, 03:28:04 PM
Next to ElectricDruid's nice explanation, you have to keep in mind that the mode2 pitchshifter runs in the interrupts, so to switch back to mode1 you'll have to turn off those interrupts (in the "setup" part of the mode switching).
I had a feeling that was going to cause me troubles. Is this something I might be able to work out how to do on my own? I can brew some strong coffee and go Mano a Mano with Google (duckduckgo)
If I can't figure it out I can always use two tiny chips and have one mode on each...but that would feel like such a fail.
It's already in the comments of the code: all lines that say "Enable" should be countered with a "Disable"  :icon_wink:


patrick398

#18
Quote from: pruttelherrie on December 15, 2020, 03:20:42 AM
Quote from: patrick398 on December 14, 2020, 05:08:24 PM
Quote from: pruttelherrie on December 14, 2020, 03:28:04 PM
Next to ElectricDruid's nice explanation, you have to keep in mind that the mode2 pitchshifter runs in the interrupts, so to switch back to mode1 you'll have to turn off those interrupts (in the "setup" part of the mode switching).
I had a feeling that was going to cause me troubles. Is this something I might be able to work out how to do on my own? I can brew some strong coffee and go Mano a Mano with Google (duckduckgo)
If I can't figure it out I can always use two tiny chips and have one mode on each...but that would feel like such a fail.
It's already in the comments of the code: all lines that say "Enable" should be countered with a "Disable"  :icon_wink:

Just had a chance to have a proper look at this and i'm not sure i understand what you mean. I see a lot of the code is commented 'enable' but not sure how i go about enabling/disabling it using the mode two code

EDIT: Actually, the output for this code is physical pin 6 on the ATtiny, which the other code isn't using...so is it as simple as enabling this pin as an output in the mode 2 code?

pruttelherrie

Actually, you could try that first yeah!  After all the setup, the modeswitching could be as simple as

if(mode1) {
  pinMode(1, INPUT);
} else {
  pinMode(1, OUTPUT);
}

If that doesn't work, you'll have to turn off the interrupts in mode1 and then turn them on in mode2, something like

if(mode1) {
  TIMSK = TIMSK & ~(1<<OCIE0A);              // Disable interrupt
  GIMSK = GIMSK & ~(1<<PCIE);                // Disable pin change interrupt
} else {
  TIMSK = TIMSK | 1<<OCIE0A;              // Enable interrupt
  GIMSK = GIMSK | 1<<PCIE;                // Enable pin change interrupt
}


Read up on 'bit manipulation' to learn how & why this works! For example (quick google) https://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101