summaryrefslogtreecommitdiff
path: root/tmk_core/protocol/midi/midi_device.h
blob: 693d81a8e214affb491dae77bbde0b6c86e9b49a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// midi for embedded chips,
// Copyright 2010 Alex Norman
//
// This file is part of avr-midi.
//
// avr-midi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
// avr-midi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with avr-midi.  If not, see <http://www.gnu.org/licenses/>.

/**
 * @file
 * @brief Device implementation functions
 */

#ifndef MIDI_DEVICE_H
#define MIDI_DEVICE_H

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @defgroup midi_device Functions used when implementing your own midi device.
 *
 * You use the functions when you are implementing your own midi device.
 *
 * You set a send function to actually send bytes via your device, this method
 * is called when you call a send function with this device, for instance
 * midi_send_cc
 *
 * You use the midi_device_input to process input data from the device and pass
 * it through the device's associated callbacks.
 *
 * You use the midi_device_set_pre_input_process_func if you want to have a
 * function called at the beginning of the device's process function, generally
 * to poll for input and pass that into midi_device_input
 *
 * @{
 */

#include "midi_function_types.h"
#include "bytequeue/bytequeue.h"
#define MIDI_INPUT_QUEUE_LENGTH 192

typedef enum { IDLE, ONE_BYTE_MESSAGE = 1, TWO_BYTE_MESSAGE = 2, THREE_BYTE_MESSAGE = 3, SYSEX_MESSAGE } input_state_t;

typedef void (*midi_no_byte_func_t)(MidiDevice* device);

/**
 * \struct _midi_device
 *
 * @brief This structure represents the input and output functions and
 * processing data for a midi device.
 *
 * A device can represent an actual physical device [serial port, usb port] or
 * something virtual.
 * You should not need to modify this structure directly.
 */
struct _midi_device {
    // output send function
    midi_var_byte_func_t send_func;

    //********input callbacks
    // three byte funcs
    midi_three_byte_func_t input_cc_callback;
    midi_three_byte_func_t input_noteon_callback;
    midi_three_byte_func_t input_noteoff_callback;
    midi_three_byte_func_t input_aftertouch_callback;
    midi_three_byte_func_t input_pitchbend_callback;
    midi_three_byte_func_t input_songposition_callback;
    // two byte funcs
    midi_two_byte_func_t input_progchange_callback;
    midi_two_byte_func_t input_chanpressure_callback;
    midi_two_byte_func_t input_songselect_callback;
    midi_two_byte_func_t input_tc_quarterframe_callback;
    // one byte funcs
    midi_one_byte_func_t input_realtime_callback;
    midi_one_byte_func_t input_tunerequest_callback;

    // sysex
    midi_sysex_func_t input_sysex_callback;

    // only called if more specific callback is not matched
    midi_var_byte_func_t input_fallthrough_callback;
    // called if registered, independent of other callbacks
    midi_var_byte_func_t input_catchall_callback;

    // pre input processing function
    midi_no_byte_func_t pre_input_process_callback;

    // for internal input processing
    uint8_t       input_buffer[3];
    input_state_t input_state;
    uint16_t      input_count;

    // for queueing data between the input and the processing functions
    uint8_t     input_queue_data[MIDI_INPUT_QUEUE_LENGTH];
    byteQueue_t input_queue;
};

/**
 * @brief Process input bytes.  This function parses bytes and calls the
 * appropriate callbacks associated with the given device.  You use this
 * function if you are creating a custom device and you want to have midi
 * input.
 *
 * @param device the midi device to associate the input with
 * @param cnt the number of bytes you are processing
 * @param input the bytes to process
 */
void midi_device_input(MidiDevice* device, uint8_t cnt, uint8_t* input);

/**
 * @brief Set the callback function that will be used for sending output
 * data bytes.  This is only used if you're creating a custom device.
 * You'll most likely want the callback function to disable interrupts so
 * that you can call the various midi send functions without worrying about
 * locking.
 *
 * \param device the midi device to associate this callback with
 * \param send_func the callback function that will do the sending
 */
void midi_device_set_send_func(MidiDevice* device, midi_var_byte_func_t send_func);

/**
 * @brief Set a callback which is called at the beginning of the
 * midi_device_process call.  This can be used to poll for input
 * data and send the data through the midi_device_input function.
 * You'll probably only use this if you're creating a custom device.
 *
 * \param device the midi device to associate this callback with
 * \param midi_no_byte_func_t the actual callback function
 */
void midi_device_set_pre_input_process_func(MidiDevice* device, midi_no_byte_func_t pre_process_func);

/**@}*/

#ifdef __cplusplus
}
#endif

#endif