9
9
10
10
See file LICENSE.txt for further informations on licensing terms.
11
11
12
- Last updated January 7th , 2017
12
+ Last updated January 8th , 2017
13
13
*/
14
14
15
15
#include " SPIFirmata.h"
16
16
17
17
SPIFirmata::SPIFirmata ()
18
+ {
19
+ init ();
20
+ }
21
+
22
+ void SPIFirmata::init ()
18
23
{
19
24
mDeviceId = 0 ;
20
25
mCsPin = -1 ;
26
+ mCsActiveState = SPI_CS_ACTIVE_LOW; // default
21
27
}
22
28
23
- boolean SPIFirmata::handlePinMode (byte pin, int mode)
29
+ bool SPIFirmata::handlePinMode (uint8_t pin, int mode)
24
30
{
25
- // ignore SS pin for now
26
- if (mode == PIN_MODE_SPI && pin != SS) {
27
- Firmata.setPinMode (pin, PIN_MODE_SPI);
28
- return true ;
29
- }
31
+ // There is no reason for a user to manually set the SPI pin modes
30
32
return false ;
31
33
}
32
34
33
- void SPIFirmata::handleCapability (byte pin)
35
+ void SPIFirmata::handleCapability (uint8_t pin)
34
36
{
35
37
// ignore SS pin for now
36
38
if (IS_PIN_SPI (pin) && pin != SS) {
@@ -41,30 +43,43 @@ void SPIFirmata::handleCapability(byte pin)
41
43
}
42
44
}
43
45
44
- boolean SPIFirmata::handleSysex (byte command, byte argc, byte *argv)
46
+ bool SPIFirmata::handleSysex (uint8_t command, uint8_t argc, uint8_t *argv)
45
47
{
46
48
if (command == SPI_DATA) {
47
- byte mode = argv[0 ];
49
+ uint8_t mode = argv[0 ];
48
50
// not using channel yet
49
- byte channel = argv[1 ] & SPI_CHANNEL_MASK;
51
+ uint8_t channel = argv[1 ] & SPI_CHANNEL_MASK;
50
52
51
53
switch (mode) {
52
54
case SPI_CONFIG:
53
55
SPI.begin ();
56
+ // SPI pin states are configured by SPI.begin, but we still register them with Firmata.
57
+ Firmata.setPinMode (MOSI, PIN_MODE_SPI);
58
+ Firmata.setPinMode (MISO, PIN_MODE_SPI);
59
+ Firmata.setPinMode (SCK, PIN_MODE_SPI);
60
+ // ignore SS for now
61
+ // Firmata.setPinMode(SS, PIN_MODE_SPI);
54
62
break ;
55
63
case SPI_BEGIN_TRANSACTION:
56
64
{
57
65
mDeviceId = argv[1 ] >> 2 ;
58
66
uint8_t bitOrder = argv[2 ] & SPI_BIT_ORDER_MASK;
59
67
uint8_t dataMode = argv[2 ] >> 1 ;
60
- uint32_t clockSpeed = (uint32_t )argv[3 ] | ((uint32_t )argv[4 ] << 7 ) | (( uint32_t )argv[ 5 ] << 14 ) |
61
- ((uint32_t )argv[6 ] << 21 ) | ((uint32_t )argv[7 ] << 28 );
68
+ uint32_t clockSpeed = (uint32_t )argv[3 ] | ((uint32_t )argv[4 ] << 7 ) |
69
+ (( uint32_t )argv[ 5 ] << 14 ) | ((uint32_t )argv[6 ] << 21 ) | ((uint32_t )argv[7 ] << 28 );
62
70
63
71
if (argc > 8 ) {
64
72
mCsPin = argv[8 ];
65
73
pinMode (mCsPin , OUTPUT);
66
- // TODO - need to know if the device is active LOW or active HIGH at this time.
67
- digitalWrite (mCsPin , HIGH);
74
+
75
+ if (argv[9 ] != END_SYSEX) {
76
+ mCsActiveState = argv[9 ];
77
+ } else {
78
+ // set default
79
+ mCsActiveState = SPI_CS_ACTIVE_LOW;
80
+ }
81
+ // set CS pin to opposite of active state
82
+ digitalWrite (mCsPin , !mCsActiveState );
68
83
69
84
// protect the CS pin
70
85
// TODO - decide if this is the best approach. If PIN_MODE_SPI is set, the user cannot
@@ -81,34 +96,28 @@ boolean SPIFirmata::handleSysex(byte command, byte argc, byte *argv)
81
96
break ;
82
97
case SPI_TRANSFER:
83
98
{
84
- byte transferOptions = argv[2 ] & SPI_TRANSFER_OPTS_MASK ;
85
- byte numBytes = argv[3 ];
99
+ uint8_t transferOptions = argv[2 ] & SPI_TRANSFER_MODES_MASK ;
100
+ uint8_t numBytes = argv[3 ];
86
101
87
- boolean csIsActive = true ;
88
- byte csStartVal = LOW;
89
- byte csEndVal = HIGH;
90
- boolean csStartOnly = false ;
91
- boolean csEndOnly = false ;
102
+ bool csIsActive = true ;
103
+ bool csStartOnly = false ;
104
+ bool csEndOnly = false ;
92
105
93
- // boolean csToggle = false;
106
+ // bool csToggle = false;
94
107
95
108
if (mCsPin >= 0 ) {
96
109
if (argv[2 ] & SPI_CS_DISABLE_MASK) {
97
110
csIsActive = false ;
98
111
} else {
99
112
if (argv[2 ] & SPI_CS_START_ONLY_MASK) csStartOnly = true ;
100
113
if (argv[2 ] & SPI_CS_END_ONLY_MASK) csEndOnly = true ;
101
- if (argv[2 ] & SPI_CS_ACTIVE_EDGE_MASK) {
102
- csStartVal = HIGH;
103
- csStartVal = LOW;
104
- }
105
114
// TODO - handle csToggle
106
115
// if (argv[2] & SPI_CS_TOGGLE_MASK) csToggle = true;
107
116
}
108
117
}
109
118
110
- if ((csIsActive || csStartOnly) && !csEndOnly) {
111
- digitalWrite (mCsPin , csStartVal );
119
+ if (mCsPin >= 0 && csIsActive && !csEndOnly) {
120
+ digitalWrite (mCsPin , mCsActiveState );
112
121
}
113
122
114
123
if (transferOptions == SPI_READ_WRITE) {
@@ -122,8 +131,9 @@ boolean SPIFirmata::handleSysex(byte command, byte argc, byte *argv)
122
131
Firmata.sendString (" No transferOptions set" );
123
132
}
124
133
125
- if ((csIsActive || csEndOnly) && !csStartOnly) {
126
- digitalWrite (mCsPin , csEndVal);
134
+ // TODO - ideally this should be called before the SPI_REPLY message is sent.
135
+ if (mCsPin >= 0 && csIsActive && !csStartOnly) {
136
+ digitalWrite (mCsPin , !mCsActiveState );
127
137
}
128
138
break ; // SPI_TRANSFER
129
139
}
@@ -138,20 +148,19 @@ boolean SPIFirmata::handleSysex(byte command, byte argc, byte *argv)
138
148
139
149
void SPIFirmata::reset ()
140
150
{
141
- mCsPin = -1 ;
142
- mDeviceId = 0 ;
151
+ init ();
143
152
}
144
153
145
- void SPIFirmata::readWrite (byte channel, byte numBytes, byte argc, byte *argv)
154
+ void SPIFirmata::readWrite (uint8_t channel, uint8_t numBytes, uint8_t argc, uint8_t *argv)
146
155
{
147
- byte offset = 4 ; // mode + channel + opts + numBytes
148
- byte buffer[numBytes];
149
- byte bufferIndex = 0 ;
156
+ uint8_t offset = 4 ; // mode + channel + opts + numBytes
157
+ uint8_t buffer[numBytes];
158
+ uint8_t bufferIndex = 0 ;
150
159
if (numBytes * 2 != argc - offset) {
151
160
// TODO - handle error
152
161
Firmata.sendString (" fails numBytes test" );
153
162
}
154
- for (byte i = 0 ; i < numBytes * 2 ; i += 2 ) {
163
+ for (uint8_t i = 0 ; i < numBytes * 2 ; i += 2 ) {
155
164
bufferIndex = (i + 1 ) / 2 ;
156
165
buffer[bufferIndex] = argv[i + offset + 1 ] << 7 | argv[i + offset];
157
166
}
@@ -160,38 +169,38 @@ void SPIFirmata::readWrite(byte channel, byte numBytes, byte argc, byte *argv)
160
169
reply (channel, numBytes, buffer);
161
170
}
162
171
163
- void SPIFirmata::writeOnly (byte channel, byte numBytes, byte argc, byte *argv)
172
+ void SPIFirmata::writeOnly (uint8_t channel, uint8_t numBytes, uint8_t argc, uint8_t *argv)
164
173
{
165
- byte offset = 4 ;
166
- byte txValue;
174
+ uint8_t offset = 4 ;
175
+ uint8_t txValue;
167
176
if (numBytes * 2 != argc - offset) {
168
177
// TODO - handle error
169
178
Firmata.sendString (" fails numBytes test" );
170
179
}
171
- for (byte i = 0 ; i < numBytes * 2 ; i += 2 ) {
180
+ for (uint8_t i = 0 ; i < numBytes * 2 ; i += 2 ) {
172
181
txValue = argv[i + offset + 1 ] << 7 | argv[i + offset];
173
182
SPI.transfer (txValue);
174
183
}
175
184
}
176
185
177
- void SPIFirmata::readOnly (byte channel, byte numBytes)
186
+ void SPIFirmata::readOnly (uint8_t channel, uint8_t numBytes)
178
187
{
179
- byte replyData[numBytes];
180
- for (byte i = 0 ; i < numBytes; i++) {
188
+ uint8_t replyData[numBytes];
189
+ for (uint8_t i = 0 ; i < numBytes; i++) {
181
190
replyData[i] = SPI.transfer (0x00 );
182
191
}
183
192
reply (channel, numBytes, replyData);
184
193
}
185
194
186
- void SPIFirmata::reply (byte channel, byte numBytes, byte *buffer)
195
+ void SPIFirmata::reply (uint8_t channel, uint8_t numBytes, uint8_t *buffer)
187
196
{
188
197
Firmata.write (START_SYSEX);
189
198
Firmata.write (SPI_DATA);
190
199
Firmata.write (SPI_REPLY);
191
200
Firmata.write (mDeviceId << 2 | channel);
192
201
Firmata.write (numBytes);
193
202
194
- for (byte i = 0 ; i < numBytes; i++) {
203
+ for (uint8_t i = 0 ; i < numBytes; i++) {
195
204
Firmata.write (buffer[i] & 0x7F );
196
205
Firmata.write (buffer[i] >> 7 & 0x7F );
197
206
}
0 commit comments