/****************************************************************************************** * button_brd_1.c * * based on hello.ftdi.c by Neil Gershenfeld * and button44 by Rob Hart * set lfuse to 0x5E for 20 MHz xtal * * Debounces button inputs and sends the count over serial * Flag as 1 does the 1-8 inputs * as 0 does the 9,*,0,# and extras * * Brian Plancher * 12/7/16 * ********************************************************************************************/ #include #include #include // helper defs #define output(directions,pin) (directions |= pin) // set port direction for output #define input(directions,pin) (directions &= (~pin)) // set port direction for input #define set(port,pin) (port |= pin) // set port pin #define clear(port,pin) (port &= (~pin)) // clear port pin #define pin_test(pins,pin) (pins & pin) // test for port pin #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set #define bit_delay_time 8.5 // bit delay for 115200 with overhead #define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay #define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay #define char_delay() _delay_ms(10) // char delay // serial port #define serial_port PORTB #define serial_direction DDRB #define serial_pins PINB #define serial_pin_out (1 << PB2) // input devices // Buttons PA0 - PA7 #define input_port PORTA #define input_direction DDRA #define input_pins PINA #define button_0 (1 << PA0) #define button_1 (1 << PA1) #define button_2 (1 << PA2) #define button_3 (1 << PA3) #define button_4 (1 << PA4) #define button_5 (1 << PA5) #define button_6 (1 << PA6) #define button_7 (1 << PA7) // for debounce #define XTAL 20000000L // Crystal frequency in Hz #define OUTER_LOOPS 2000 #define INNER_LOOPS (XTAL / OUTER_LOOPS / 750) #define MAX_COUNT 32767 #define MAX_COUNT_SIZE 15 // define the buttons #define BOARD_FLAG 0 #if BOARD_FLAG #define BUTTON_0_CHAR '1' #define BUTTON_1_CHAR '2' #define BUTTON_2_CHAR '3' #define BUTTON_3_CHAR '4' #define BUTTON_4_CHAR '5' #define BUTTON_5_CHAR '6' #define BUTTON_6_CHAR '7' #define BUTTON_7_CHAR '8' #else #define BUTTON_0_CHAR '9' #define BUTTON_1_CHAR '*' #define BUTTON_2_CHAR '0' #define BUTTON_3_CHAR '#' #define BUTTON_4_CHAR 'B' // backspace #define BUTTON_5_CHAR 'M' // menu #define BUTTON_6_CHAR 'D' // down arrow #define BUTTON_7_CHAR 'E' // enter #endif void put_char(volatile unsigned char *port, unsigned char pin, char txchar) { // // send character in txchar on port pin // assumes line driver (inverts bits) // // start bit // clear(*port,pin); bit_delay(); // // unrolled loop to write data bits // if bit_test(txchar,0) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,1) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,2) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,3) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,4) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,5) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,6) set(*port,pin); else clear(*port,pin); bit_delay(); if bit_test(txchar,7) set(*port,pin); else clear(*port,pin); bit_delay(); // // stop bit // set(*port,pin); bit_delay(); // // char delay // bit_delay(); } int main(void) { // set clock divider to /1 CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // initialize output pins set(serial_port, serial_pin_out); output(serial_direction, serial_pin_out); // initialize buttons set(input_port, button_0|button_1|button_2|button_3|button_4|button_5|button_6|button_7); // turn on pull-up for the buttons input(input_direction, button_0|button_1|button_2|button_3|button_4|button_5|button_6|button_7); // make button input volatile uint16_t inner_loop_cntr = 0; volatile uint16_t outer_loop_cntr = 0; volatile uint8_t btn_state = 0; volatile uint8_t btn_hold = 0; // main loop while (1) { // debounce the button inputs volatile uint8_t btn_flag_0 = !pin_test(input_pins,button_0); // invert b/c pullup volatile uint8_t btn_flag_1 = !pin_test(input_pins,button_1); // invert b/c pullup volatile uint8_t btn_flag_2 = !pin_test(input_pins,button_2); // invert b/c pullup volatile uint8_t btn_flag_3 = !pin_test(input_pins,button_3); // invert b/c pullup volatile uint8_t btn_flag_4 = !pin_test(input_pins,button_4); // invert b/c pullup volatile uint8_t btn_flag_5 = !pin_test(input_pins,button_5); // invert b/c pullup volatile uint8_t btn_flag_6 = !pin_test(input_pins,button_6); // invert b/c pullup volatile uint8_t btn_flag_7 = !pin_test(input_pins,button_7); // invert b/c pullup volatile uint8_t btn_flag = btn_flag_0 | btn_flag_1 | btn_flag_2 | btn_flag_3 | btn_flag_4 | btn_flag_5 | btn_flag_6 | btn_flag_7; if(!btn_flag){ btn_hold = 0; } if(!btn_hold){ if (btn_state != btn_flag){ btn_state = btn_flag; inner_loop_cntr = 0; outer_loop_cntr = 0; } if (outer_loop_cntr == OUTER_LOOPS){ outer_loop_cntr = 0; // see if majority of count was a bttn press if (btn_state){ btn_hold = 1; // notify over serial the appropriate char if(btn_flag_0){ put_char(&serial_port, serial_pin_out, BUTTON_0_CHAR); } else if(btn_flag_1){ put_char(&serial_port, serial_pin_out, BUTTON_1_CHAR); } else if(btn_flag_2){ put_char(&serial_port, serial_pin_out, BUTTON_2_CHAR); } else if(btn_flag_3){ put_char(&serial_port, serial_pin_out, BUTTON_3_CHAR); } else if(btn_flag_4){ put_char(&serial_port, serial_pin_out, BUTTON_4_CHAR); } else if(btn_flag_5){ put_char(&serial_port, serial_pin_out, BUTTON_5_CHAR); } else if(btn_flag_6){ put_char(&serial_port, serial_pin_out, BUTTON_6_CHAR); } else { put_char(&serial_port, serial_pin_out, BUTTON_7_CHAR); } } } else{ if (inner_loop_cntr == INNER_LOOPS){ inner_loop_cntr = 0; outer_loop_cntr += 1; } else{ inner_loop_cntr++; } } } } }