// // // hello.light.44.c // // phototransistor + button + 2 LEDs // 9600 baud FTDI interface // // Alex Berke // // Modified from code provided by Neil Gershenfeld // // (c) Massachusetts Institute of Technology 2010 // This work may be reproduced, modified, distributed, // performed, and displayed for any purpose. Copyright is // retained and must be preserved. The work is provided // as is; no warranty is provided, and users accept all // liability. // #include #include #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 100 // bit delay for 9600 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 // (Board specific) // RX (serial output) connected to PA1 #define SERIAL_PORT PORTA #define SERIAL_DIRECTION DDRA #define SERIAL_PIN_OUT (1 << PA1) // Button connected to PA0 #define BUTTON_PINS PINA #define BUTTON_PORT PORTA #define BUTTON_DIRECTION DDRA #define BUTTON_PIN (1 << PA0) // LED 1 connected to PB0 // LED 2 connected to PB1 #define LED_PORT PORTB #define LED_DIRECTION DDRB #define LED_PIN_1 (1 << PB0) #define LED_PIN_2 (1 << PB1) 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) { // // main // // // set clock divider to /1 // CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // // Initialize output // // Initialize serial pin (output) set(SERIAL_PORT, SERIAL_PIN_OUT); output(SERIAL_DIRECTION, SERIAL_PIN_OUT); // Initialize LED pins (output) clear(LED_PORT, LED_PIN_1); clear(LED_PORT, LED_PIN_2); output(LED_DIRECTION, LED_PIN_1); output(LED_DIRECTION, LED_PIN_2); // // Initialize input // // Initialize button pin (input) set(BUTTON_PORT, BUTTON_PIN); // Turn on internal pull-up resister input(BUTTON_DIRECTION, BUTTON_PIN); // // Initialize A/D // // Board specific: My phototransistor is connected on ADC2/PA2. ADMUX = (0 << REFS1) | (0 << REFS0) // Vcc ref | (0 << ADLAR) // right adjust | (0 << MUX3) | (0 << MUX2) | (1 << MUX1) | (0 << MUX0); // ADC2 ADCSRA = (1 << ADEN) // enable | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler /128 static char chr; // Used for serial // The light setting alternates between 3 settings: // 0: LED_1 off & LED_2 off // 1: LED_1 on & LED_2 off // 2: LED_1 on & LED_2 on int light_setting = 0; int button_state, last_button_state = 0; while (1) { // // main loop // // // Handle button and LEDs // check if button state has been toggled button_state = pin_test(BUTTON_PINS, BUTTON_PIN); if (button_state != last_button_state) { // the button has been toggled last_button_state = button_state; // Remember this for next loop. // if it is toggled unpressed, keep the settings as they are // otherwise, update the settings if (!button_state) { // Increment the light setting (modular 3 because there are 3 settings) light_setting = (light_setting + 1) % 3; if (light_setting == 0) { clear(LED_PORT, LED_PIN_1); clear(LED_PORT, LED_PIN_2); } if (light_setting == 1) { set(LED_PORT, LED_PIN_1); clear(LED_PORT, LED_PIN_2); } if (light_setting == 2) { set(LED_PORT, LED_PIN_1); set(LED_PORT, LED_PIN_2); } } } // Handle reading from phototransistor // // send framing // put_char(&SERIAL_PORT, SERIAL_PIN_OUT, 1); char_delay(); put_char(&SERIAL_PORT, SERIAL_PIN_OUT, 2); char_delay(); put_char(&SERIAL_PORT, SERIAL_PIN_OUT, 3); char_delay(); put_char(&SERIAL_PORT, SERIAL_PIN_OUT, 4); char_delay(); // // initiate conversion // ADCSRA |= (1 << ADSC); // // wait for completion // while (ADCSRA & (1 << ADSC)); // // send result // // Send ADC low chr = ADCL; put_char(&SERIAL_PORT, SERIAL_PIN_OUT, chr); char_delay(); // Send ADC high chr = ADCH; put_char(&SERIAL_PORT, SERIAL_PIN_OUT, chr); char_delay(); } }