Skip to content

Instantly share code, notes, and snippets.

@metroid2010
Created May 4, 2021 10:36
Show Gist options
  • Select an option

  • Save metroid2010/181fe451a6c6c1c53389178d9ce85ff6 to your computer and use it in GitHub Desktop.

Select an option

Save metroid2010/181fe451a6c6c1c53389178d9ce85ff6 to your computer and use it in GitHub Desktop.
4-channel discrete note selector with PWM output for an analog sequencer
#define BUTTON_PRESSED LOW
#define BUTTON_NOT_PRESSED HIGH
//#define DEBUG 1 // uncomment to enable serial output
#ifdef DEBUG
#define _PL(a) Serial.println(a)
#define _PP(a) Serial.print(a)
#else
#define _PL(a)
#define _PP(a)
#endif
#define SERIAL_BPS 9600
#define BUTTON_UP_SEQ1 1 // input button pins, pullup configuration
#define BUTTON_DOWN_SEQ1 2
#define BUTTON_UP_SEQ2 3
#define BUTTON_DOWN_SEQ2 4
#define BUTTON_UP_SEQ3 5
#define BUTTON_DOWN_SEQ3 6
#define BUTTON_UP_SEQ4 7
#define BUTTON_DOWN_SEQ4 8
#define PWM_OUT_SEQ1 10 // output pwm
#define PWM_OUT_SEQ2 11
#define PWM_OUT_SEQ3 12
#define PWM_OUT_SEQ4 13
typedef enum button_e {
BUTTON_UP = 0,
BUTTON_DOWN
} button_t;
#define MAX_NOTES 7 // remember to set this when adding or removing notes
const char notes_name[MAX_NOTES][3] {
// human readable note names
"C1",
"D1",
"E1",
"F1",
"G1",
"A1",
"B1"
};
const uint8_t notes_pwm[MAX_NOTES] {
// pwm output values for each note in array above
1, // C1
2,
3,
4,
5,
6,
7 // B1
};
void setup() {
pinMode(BUTTON_UP_SEQ1, INPUT_PULLUP);
pinMode(BUTTON_DOWN_SEQ1, INPUT_PULLUP);
pinMode(BUTTON_UP_SEQ2, INPUT_PULLUP);
pinMode(BUTTON_DOWN_SEQ2, INPUT_PULLUP);
pinMode(BUTTON_UP_SEQ3, INPUT_PULLUP);
pinMode(BUTTON_DOWN_SEQ3, INPUT_PULLUP);
pinMode(BUTTON_UP_SEQ4, INPUT_PULLUP);
pinMode(BUTTON_DOWN_SEQ4, INPUT_PULLUP);
pinMode(PWM_OUT_SEQ1, OUTPUT);
pinMode(PWM_OUT_SEQ2, OUTPUT);
pinMode(PWM_OUT_SEQ3, OUTPUT);
pinMode(PWM_OUT_SEQ4, OUTPUT);
Serial.begin(SERIAL_BPS);
}
uint8_t button_state_up_seq1 = BUTTON_NOT_PRESSED;
uint8_t button_state_down_seq1 = BUTTON_NOT_PRESSED;
uint8_t button_state_up_seq2 = BUTTON_NOT_PRESSED;
uint8_t button_state_down_seq2 = BUTTON_NOT_PRESSED;
uint8_t button_state_up_seq3 = BUTTON_NOT_PRESSED;
uint8_t button_state_down_seq3 = BUTTON_NOT_PRESSED;
uint8_t button_state_up_seq4 = BUTTON_NOT_PRESSED;
uint8_t button_state_down_seq4 = BUTTON_NOT_PRESSED;
uint8_t last_button_state_up_seq1 = BUTTON_NOT_PRESSED;
uint8_t last_button_state_down_seq1 = BUTTON_NOT_PRESSED;
uint8_t last_button_state_up_seq2 = BUTTON_NOT_PRESSED;
uint8_t last_button_state_down_seq2 = BUTTON_NOT_PRESSED;
uint8_t last_button_state_up_seq3 = BUTTON_NOT_PRESSED;
uint8_t last_button_state_down_seq3 = BUTTON_NOT_PRESSED;
uint8_t last_button_state_up_seq4 = BUTTON_NOT_PRESSED;
uint8_t last_button_state_down_seq4 = BUTTON_NOT_PRESSED;
uint8_t note_seq1 = 0;
uint8_t note_seq2 = 0;
uint8_t note_seq3 = 0;
uint8_t note_seq4 = 0;
void increment_note(uint8_t &note) {
note = ( note < MAX_NOTES-1 )? note + 1 : note;
};
void decrement_note(uint8_t &note) {
note = ( note > 0 )? note - 1 : note;
};
void check_button(uint8_t &button_state, const uint8_t button_pin, uint8_t &last_button_state, uint8_t &note, const button_t button_type) {
button_state = digitalRead(button_pin);
if (button_state == BUTTON_PRESSED && button_state != last_button_state) {
if ( button_type == BUTTON_UP ) {
increment_note(note);
_PP("BUTTON "); _PP(button_pin); _PP("; note++ -> "); _PL(notes_name[note]);
} else if ( button_type == BUTTON_DOWN ) {
decrement_note(note);
_PP("BUTTON "); _PP(button_pin); _PP("; note-- -> "); _PL(notes_name[note]);
};
last_button_state = BUTTON_PRESSED;
} else if (button_state == BUTTON_NOT_PRESSED) {
last_button_state = BUTTON_NOT_PRESSED;
};
}
void loop() {
check_button(button_state_up_seq1, BUTTON_UP_SEQ1, last_button_state_up_seq1, note_seq1, BUTTON_UP);
check_button(button_state_down_seq1, BUTTON_DOWN_SEQ1, last_button_state_down_seq1, note_seq1, BUTTON_DOWN);
check_button(button_state_up_seq2, BUTTON_UP_SEQ2, last_button_state_up_seq2, note_seq2, BUTTON_UP);
check_button(button_state_down_seq2, BUTTON_DOWN_SEQ2, last_button_state_down_seq2, note_seq2, BUTTON_DOWN);
check_button(button_state_up_seq3, BUTTON_UP_SEQ3, last_button_state_up_seq3, note_seq3, BUTTON_UP);
check_button(button_state_down_seq3, BUTTON_DOWN_SEQ3, last_button_state_down_seq3, note_seq3, BUTTON_DOWN);
check_button(button_state_up_seq4, BUTTON_UP_SEQ4, last_button_state_up_seq4, note_seq4, BUTTON_UP);
check_button(button_state_down_seq4, BUTTON_DOWN_SEQ4, last_button_state_down_seq4, note_seq4, BUTTON_DOWN);
digitalWrite(PWM_OUT_SEQ1, notes_pwm[note_seq1]);
digitalWrite(PWM_OUT_SEQ2, notes_pwm[note_seq2]);
digitalWrite(PWM_OUT_SEQ3, notes_pwm[note_seq3]);
digitalWrite(PWM_OUT_SEQ4, notes_pwm[note_seq4]);
delay(10); // needed to stabilize button behaviour
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment