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
152
153
154
155
156
157
158
159
160
161
162
163
|
/*
Firmata.h - Firmata library
Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See file LICENSE.txt for further informations on licensing terms.
*/
#ifndef Firmata_h
#define Firmata_h
#include "Boards.h" /* Hardware Abstraction Layer + Wiring/Arduino */
/* Version numbers for the protocol. The protocol is still changing, so these
* version numbers are important. This number can be queried so that host
* software can test whether it will be compatible with the currently
* installed firmware. */
#define FIRMATA_MAJOR_VERSION 2 // for non-compatible changes
#define FIRMATA_MINOR_VERSION 3 // for backwards compatible changes
#define FIRMATA_BUGFIX_VERSION 1 // for bugfix releases
#define MAX_DATA_BYTES 32 // max number of data bytes in non-Sysex messages
// message command bytes (128-255/0x80-0xFF)
#define DIGITAL_MESSAGE 0x90 // send data for a digital pin
#define ANALOG_MESSAGE 0xE0 // send data for an analog pin (or PWM)
#define REPORT_ANALOG 0xC0 // enable analog input by pin #
#define REPORT_DIGITAL 0xD0 // enable digital input by port pair
//
#define SET_PIN_MODE 0xF4 // set a pin to INPUT/OUTPUT/PWM/etc
//
#define REPORT_VERSION 0xF9 // report protocol version
#define SYSTEM_RESET 0xFF // reset from MIDI
//
#define START_SYSEX 0xF0 // start a MIDI Sysex message
#define END_SYSEX 0xF7 // end a MIDI Sysex message
// extended command set using sysex (0-127/0x00-0x7F)
/* 0x00-0x0F reserved for user-defined commands */
#define SERVO_CONFIG 0x70 // set max angle, minPulse, maxPulse, freq
#define STRING_DATA 0x71 // a string message with 14-bits per char
#define SHIFT_DATA 0x75 // a bitstream to/from a shift register
#define I2C_REQUEST 0x76 // send an I2C read/write request
#define I2C_REPLY 0x77 // a reply to an I2C read request
#define I2C_CONFIG 0x78 // config I2C settings such as delay times and power pins
#define EXTENDED_ANALOG 0x6F // analog write (PWM, Servo, etc) to any pin
#define PIN_STATE_QUERY 0x6D // ask for a pin's current mode and value
#define PIN_STATE_RESPONSE 0x6E // reply with pin's current mode and value
#define CAPABILITY_QUERY 0x6B // ask for supported modes and resolution of all pins
#define CAPABILITY_RESPONSE 0x6C // reply with supported modes and resolution
#define ANALOG_MAPPING_QUERY 0x69 // ask for mapping of analog to pin numbers
#define ANALOG_MAPPING_RESPONSE 0x6A // reply with mapping info
#define REPORT_FIRMWARE 0x79 // report name and version of the firmware
#define SAMPLING_INTERVAL 0x7A // set the poll rate of the main loop
#define SYSEX_NON_REALTIME 0x7E // MIDI Reserved for non-realtime messages
#define SYSEX_REALTIME 0x7F // MIDI Reserved for realtime messages
// these are DEPRECATED to make the naming more consistent
#define FIRMATA_STRING 0x71 // same as STRING_DATA
#define SYSEX_I2C_REQUEST 0x76 // same as I2C_REQUEST
#define SYSEX_I2C_REPLY 0x77 // same as I2C_REPLY
#define SYSEX_SAMPLING_INTERVAL 0x7A // same as SAMPLING_INTERVAL
// pin modes
//#define INPUT 0x00 // defined in wiring.h
//#define OUTPUT 0x01 // defined in wiring.h
#define ANALOG 0x02 // analog pin in analogInput mode
#define PWM 0x03 // digital pin in PWM output mode
#define SERVO 0x04 // digital pin in Servo output mode
#define SHIFT 0x05 // shiftIn/shiftOut mode
#define I2C 0x06 // pin included in I2C setup
#define TOTAL_PIN_MODES 7
extern "C" {
// callback function types
typedef void (*callbackFunction)(byte, int);
typedef void (*systemResetCallbackFunction)(void);
typedef void (*stringCallbackFunction)(char*);
typedef void (*sysexCallbackFunction)(byte command, byte argc, byte*argv);
}
// TODO make it a subclass of a generic Serial/Stream base class
class FirmataClass
{
public:
FirmataClass(Stream &s);
/* Arduino constructors */
void begin();
void begin(long);
void begin(Stream &s);
/* querying functions */
void printVersion(void);
void blinkVersion(void);
void printFirmwareVersion(void);
//void setFirmwareVersion(byte major, byte minor); // see macro below
void setFirmwareNameAndVersion(const char *name, byte major, byte minor);
/* serial receive handling */
int available(void);
void processInput(void);
/* serial send handling */
void sendAnalog(byte pin, int value);
void sendDigital(byte pin, int value); // TODO implement this
void sendDigitalPort(byte portNumber, int portData);
void sendString(const char* string);
void sendString(byte command, const char* string);
void sendSysex(byte command, byte bytec, byte* bytev);
/* attach & detach callback functions to messages */
void attach(byte command, callbackFunction newFunction);
void attach(byte command, systemResetCallbackFunction newFunction);
void attach(byte command, stringCallbackFunction newFunction);
void attach(byte command, sysexCallbackFunction newFunction);
void detach(byte command);
private:
Stream &FirmataSerial;
/* firmware name and version */
byte firmwareVersionCount;
byte *firmwareVersionVector;
/* input message handling */
byte waitForData; // this flag says the next serial input will be data
byte executeMultiByteCommand; // execute this after getting multi-byte data
byte multiByteChannel; // channel data for multiByteCommands
byte storedInputData[MAX_DATA_BYTES]; // multi-byte data
/* sysex */
boolean parsingSysex;
int sysexBytesRead;
/* callback functions */
callbackFunction currentAnalogCallback;
callbackFunction currentDigitalCallback;
callbackFunction currentReportAnalogCallback;
callbackFunction currentReportDigitalCallback;
callbackFunction currentPinModeCallback;
systemResetCallbackFunction currentSystemResetCallback;
stringCallbackFunction currentStringCallback;
sysexCallbackFunction currentSysexCallback;
/* private methods ------------------------------ */
void processSysexMessage(void);
void systemReset(void);
void pin13strobe(int count, int onInterval, int offInterval);
void sendValueAsTwo7bitBytes(int value);
void startSysex(void);
void endSysex(void);
};
extern FirmataClass Firmata;
/*==============================================================================
* MACROS
*============================================================================*/
/* shortcut for setFirmwareNameAndVersion() that uses __FILE__ to set the
* firmware name. It needs to be a macro so that __FILE__ is included in the
* firmware source file rather than the library source file.
*/
#define setFirmwareVersion(x, y) setFirmwareNameAndVersion(__FILE__, x, y)
#endif /* Firmata_h */
|