diff --git a/midi_test.c b/midi_test.c new file mode 100644 index 0000000000000000000000000000000000000000..abfff2ebd52e59db6fee9707ac796c6b555f9470 --- /dev/null +++ b/midi_test.c @@ -0,0 +1,163 @@ +// +// sampler.c +// based on hello.ftdi.44.echo.c +// +// 115200 baud FTDI character echo, with flash string +// +// set lfuse to 0x5E for 20 MHz xtal +// +// Neil Gershenfeld +// 12/8/10 +// Erik Strand +// 11/6/2018 +// +// (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 <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 input_pin (1 << PA5) + +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); + } + +#define input_pin (1 << PA5) + +int main(void) { + // Set the clock prescaler to 1. + CLKPR = (1 << CLKPCE); + CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); + + // Set the 8 bit timer's prescaler to 1/1024. + TCCR0B |= 0b00000101; + + // Initialize serial output pins + set(serial_port, serial_pin_out); + output(serial_direction, serial_pin_out); + + // Configure led_pin as an output. + DDRB |= led_pin; + + // Blink the LED with ~1.0s half-period. + // 100 * 200 * 1024 / 20M ~ 2.5s + int count = 0; + while (1) { + // If it's been 10ms, reset the timer and increment count. + if (TCNT0 >= 200) { + TCNT0 = 0; + ++count + + // When count reaches 100, turn the LED on and send a note on command. + if (count == 100) { + PORTB |= led_pin; + put_char(&serial_port, serial_pin_out, 144); // note on + put_char(&serial_port, serial_pin_out, 70); // note (A4) + put_char(&serial_port, serial_pin_out, 100); // velocity + } + + // When count reaches 200, turn the LED off and send a note off command. + else if (++count == 200) { + PORTB &= ~led_pin; + put_char(&serial_port, serial_pin_out, 144); // note off + count = 0; + } + } + } +} +