2 #include <avr/interrupt.h>
6 volatile int16_t midisync_clocked
= 0;
9 volatile uint8_t midi_q
[MIDI_Q_SIZE
]; // cyclic queue for midi msgs
10 volatile static uint8_t head_idx
= 0;
11 volatile static uint8_t tail_idx
= 0;
13 #define MIDI_BAUDRATE 31250UL // the MIDI spec baudrate
15 // interrupt on receive char
16 ISR(SIG_USART0_RECV
) {
19 midi_q
[tail_idx
++] = c
; // place at end of q
20 tail_idx
%= MIDI_Q_SIZE
;
22 if( tail_idx
== head_idx
) {
23 // i.e. there are too many msgs in the q
24 // drop the oldest msg?
26 head_idx
%= MIDI_Q_SIZE
;
30 void midi_init(void) {
31 /* setup the MIDI UART */
32 uint16_t ubbr
= (F_CPU
/ (16 * MIDI_BAUDRATE
)) - 1; // formula in datasheet
33 UCSR0B
|= (1<<RXEN0
) | (1<<TXEN0
)| (1<<RXCIE0
); // read and write, interrupt on recv.
34 UBRR0L
= (uint8_t)ubbr
; // set baudrate
35 UBRR0H
= (uint8_t)(ubbr
>>8);
38 int midi_putchar(uint8_t c
) {
39 loop_until_bit_is_set(UCSR0A
, UDRE0
);
44 int midi_getch(void) { // checks if there is a character waiting!
45 if (head_idx
!= tail_idx
)
50 int midi_getchar(void) {
53 while (head_idx
== tail_idx
);
56 c
= midi_q
[head_idx
++];
57 head_idx
%= MIDI_Q_SIZE
;
64 static uint8_t SYSEX_snd_checksum
;
65 void sysex_start(uint8_t command
) {
67 SYSEX_snd_checksum
= 0;
69 // Send SYSEX start, manufacturer ID, model number and command
70 midi_putchar(MD_SYSEX_START
);
71 midi_putchar(MD_MF_ID_1
);
72 midi_putchar(MD_MF_ID_2
);
73 midi_putchar(MD_MF_ID_3
);
74 midi_putchar(MD_SYNTH_ID
);
75 midi_putchar(command
);
78 void sysex_data(uint8_t data
) {
79 // split one byte of data in two
80 uint8_t msb
= data
>> 7;
81 uint8_t lsb
= data
& 0x7f;
85 SYSEX_snd_checksum
= (SYSEX_snd_checksum
+ msb
+ lsb
) % 128;
88 void sysex_end(void) {
90 midi_putchar(SYSEX_snd_checksum
);
93 midi_putchar(MD_SYSEX_END
);