#include #include #include #define LED 13 /* built-in LED */ #define BTN_UP 2 #define BTN_DOWN 3 #define BTN_PRINT 4 #define PIN_PRINT 5 #define BTNS_COUNT 3 #define UP 0 #define DOWN 1 #define PRINT 2 #define DEBOUNCE_DELAY 100 /* ms */ #if 0 /* can't delay by dynamic steps like this */ #define PRINTING_PULSE_MIN 5 /* 0.5us */ #define PRINTING_PULSE_MAX 255 /* 25.5us */ #define PRINTING_PULSE_STEP 5 /* 0.5us */ #define PRINTING_PULSE_DELAY 1000 /* 1ms -- better more and be safe */ #else /* calculated for 16MHz -- 1 = 0.1875us */ #define PRINTING_PULSE_MIN 4 /* 0.75us */ #define PRINTING_PULSE_MAX 132 /* 24.75us */ #define PRINTING_PULSE_STEP 4 /* 0.75us */ /* = 32 steps */ #endif struct s_debounce { uint8_t state; /** current state: pressed/not pressed */ uint8_t previous_state; /** previous state: pressed/not pressed */ uint8_t lasting; /** how long current state lasts */ }; /* * PLAN * * - step up/down pulse width (once per click) * - repeat printing while pressed * = send a pulse (block the software) and end it * = do not allow more pulses within a certain delay */ int main(void) { /* calculate bits for the PINs */ uint8_t led_pin = _BV(LED % 8); uint8_t btn_pin[BTNS_COUNT]; uint8_t print_pin = _BV(PIN_PRINT); struct s_debounce debounced[BTNS_COUNT]; uint8_t printing_pulse = PRINTING_PULSE_MIN; /*uint16_t printing_delay = PRINTING_PULSE_DELAY;*/ /* init: can print */ /* initialise arrays */ memset(debounced, 0x0, BTNS_COUNT * sizeof(struct s_debounce)); btn_pin[UP] = _BV(BTN_UP); btn_pin[DOWN] = _BV(BTN_DOWN); btn_pin[PRINT] = _BV(BTN_PRINT); /* set LED's PIN to output (= 1); default is off */ DDRB |= led_pin; PORTB &= ~led_pin; /* set the reading PINs to input (= 0) */ DDRD &= ~btn_pin[UP] & ~btn_pin[DOWN] & ~btn_pin[PRINT]; /* set the buttons to use the internal pull-up resistors */ PORTD |= btn_pin[UP] | btn_pin[DOWN] | btn_pin[PRINT]; /* set the printing PIN to output (= 1); default is off */ DDRD |= print_pin; PORTD &= ~print_pin; for (;;) { /* UP and DOWN are mutually exclusive */ /* BTN: increase pulse width */ if (debounced[DOWN].state) { debounced[UP].state = PIND & btn_pin[UP]; if (debounced[UP].state == debounced[UP].previous_state) { if (debounced[UP].lasting < DEBOUNCE_DELAY) { debounced[UP].lasting++; } } else { debounced[UP].lasting = 0; } if (debounced[UP].lasting == DEBOUNCE_DELAY) { /* button pushed => increase pulse width */ if (!debounced[UP].state && printing_pulse < PRINTING_PULSE_MAX) { printing_pulse += PRINTING_PULSE_STEP; } /* prevent repeating the action */ debounced[UP].lasting++; } debounced[UP].previous_state = debounced[UP].state; } /* BTN: decrease pulse width */ if (debounced[UP].state) { debounced[DOWN].state = PIND & btn_pin[DOWN]; if (debounced[DOWN].state == debounced[DOWN].previous_state) { if (debounced[DOWN].lasting < DEBOUNCE_DELAY) { debounced[DOWN].lasting++; } } else { debounced[DOWN].lasting = 0; } if (debounced[DOWN].lasting == DEBOUNCE_DELAY) { /* button pushed => decrease pulse */ if (!debounced[DOWN].state && printing_pulse > PRINTING_PULSE_MIN) { printing_pulse -= PRINTING_PULSE_STEP; } /* prevent repeating the action */ debounced[DOWN].lasting++; } debounced[DOWN].previous_state = debounced[DOWN].state; } /* BTN: print */ /*if (printing_delay == PRINTING_PULSE_DELAY) {*/ debounced[PRINT].state = PIND & btn_pin[PRINT]; if (debounced[PRINT].state == debounced[PRINT].previous_state) { if (debounced[PRINT].lasting < DEBOUNCE_DELAY) { debounced[PRINT].lasting++; } } else { debounced[PRINT].lasting = 0; } if (debounced[PRINT].lasting == DEBOUNCE_DELAY) { /* button pushed => fire! */ if (!debounced[PRINT].state) { PORTD |= print_pin; _delay_loop_1(printing_pulse); PORTD &= ~print_pin; /* make sure the nozzle gets its rest */ /*printing_delay = 0;*/ } } debounced[PRINT].previous_state = debounced[PRINT].state; /* } else { printing_delay++; } */ _delay_ms(1); } return 0; }