diff --git a/button_serial.c b/button_serial.c new file mode 100644 index 0000000000000000000000000000000000000000..a8550503768203d30030895bdd38011d379f6644 --- /dev/null +++ b/button_serial.c @@ -0,0 +1,146 @@ +// +// +// serial_button.c +// +// 115200 baud FTDI connection that outputs '0' or '1' depending +// on the state of a physical button +// +// set lfuse to 0x5E for 20 MHz xtal +// +// Neil Gershenfeld +// 12/8/10 +// Erik Strand +// 11/26/2018 +// +#include <avr/io.h> +#include <util/delay.h> +#include <avr/pgmspace.h> + +#define output(directions,pin) (directions |= pin) // set port direction for output +#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 + +#define serial_port PORTA +#define serial_direction DDRA +#define serial_pins PINA +#define serial_pin_in (1 << PA0) +#define serial_pin_out (1 << PA1) + +#define led_pin (1 << PB2) +#define button_pin (1 << PA7) + +#define max_buffer 25 + +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(); +} + +void put_string(volatile unsigned char *port, unsigned char pin, char *str) { + // + // print a null-terminated string + // + static int index; + index = 0; + do { + put_char(port, pin, str[index]); + ++index; + } while (str[index] != 0); +} + +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); + + // Configure led pin as an output. + DDRB |= led_pin; + + // Configure button_pin as an input. + DDRA &= ~button_pin; + + // Activate button_pin's pullup resistor. + PORTA |= button_pin; + + while (1) { + // Turn on the LED when the button is pressed. + if (PINA & button_pin) { + // Turn off the LED. + PORTB &= ~led_pin; + put_char(&serial_port, serial_pin_out, '0'); + } else { + PORTB |= led_pin; + put_char(&serial_port, serial_pin_out, '1'); + } + _delay_us(10000); + } +} +