Created
May 4, 2021 10:36
-
-
Save metroid2010/181fe451a6c6c1c53389178d9ce85ff6 to your computer and use it in GitHub Desktop.
4-channel discrete note selector with PWM output for an analog sequencer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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 ¬e) { | |
| note = ( note < MAX_NOTES-1 )? note + 1 : note; | |
| }; | |
| void decrement_note(uint8_t ¬e) { | |
| 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 ¬e, 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