Skip to content

Commit 967a3f7

Browse files
move csActiveState to spiBeginTransaction and misc refactoring
1 parent 309d86c commit 967a3f7

File tree

3 files changed

+77
-67
lines changed

3 files changed

+77
-67
lines changed

examples/StandardFirmataPlus/StandardFirmataPlus.ino

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
1212
Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
1313
Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
14-
Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
14+
Copyright (C) 2009-2017 Jeff Hoefs. All rights reserved.
1515
1616
This library is free software; you can redistribute it and/or
1717
modify it under the terms of the GNU Lesser General Public
@@ -20,7 +20,7 @@
2020
2121
See file LICENSE.txt for further informations on licensing terms.
2222
23-
Last updated January 7th, 2017
23+
Last updated January 8th, 2017
2424
*/
2525

2626
/*
@@ -384,11 +384,6 @@ void setPinModeCallback(byte pin, int mode)
384384
case PIN_MODE_SERIAL:
385385
#ifdef FIRMATA_SERIAL_FEATURE
386386
serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
387-
#endif
388-
break;
389-
case PIN_MODE_SPI:
390-
#ifdef FIRMATA_SPI_FEATURE
391-
spiFeature.handlePinMode(pin, PIN_MODE_SPI);
392387
#endif
393388
break;
394389
default:

utility/SPIFirmata.cpp

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,30 @@
99
1010
See file LICENSE.txt for further informations on licensing terms.
1111
12-
Last updated January 7th, 2017
12+
Last updated January 8th, 2017
1313
*/
1414

1515
#include "SPIFirmata.h"
1616

1717
SPIFirmata::SPIFirmata()
18+
{
19+
init();
20+
}
21+
22+
void SPIFirmata::init()
1823
{
1924
mDeviceId = 0;
2025
mCsPin = -1;
26+
mCsActiveState = SPI_CS_ACTIVE_LOW; // default
2127
}
2228

23-
boolean SPIFirmata::handlePinMode(byte pin, int mode)
29+
bool SPIFirmata::handlePinMode(uint8_t pin, int mode)
2430
{
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
3032
return false;
3133
}
3234

33-
void SPIFirmata::handleCapability(byte pin)
35+
void SPIFirmata::handleCapability(uint8_t pin)
3436
{
3537
// ignore SS pin for now
3638
if (IS_PIN_SPI(pin) && pin != SS) {
@@ -41,30 +43,43 @@ void SPIFirmata::handleCapability(byte pin)
4143
}
4244
}
4345

44-
boolean SPIFirmata::handleSysex(byte command, byte argc, byte *argv)
46+
bool SPIFirmata::handleSysex(uint8_t command, uint8_t argc, uint8_t *argv)
4547
{
4648
if (command == SPI_DATA) {
47-
byte mode = argv[0];
49+
uint8_t mode = argv[0];
4850
// not using channel yet
49-
byte channel = argv[1] & SPI_CHANNEL_MASK;
51+
uint8_t channel = argv[1] & SPI_CHANNEL_MASK;
5052

5153
switch (mode) {
5254
case SPI_CONFIG:
5355
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);
5462
break;
5563
case SPI_BEGIN_TRANSACTION:
5664
{
5765
mDeviceId = argv[1] >> 2;
5866
uint8_t bitOrder = argv[2] & SPI_BIT_ORDER_MASK;
5967
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);
6270

6371
if (argc > 8) {
6472
mCsPin = argv[8];
6573
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);
6883

6984
// protect the CS pin
7085
// 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)
8196
break;
8297
case SPI_TRANSFER:
8398
{
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];
86101

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;
92105

93-
//boolean csToggle = false;
106+
//bool csToggle = false;
94107

95108
if (mCsPin >= 0) {
96109
if (argv[2] & SPI_CS_DISABLE_MASK) {
97110
csIsActive = false;
98111
} else {
99112
if (argv[2] & SPI_CS_START_ONLY_MASK) csStartOnly = true;
100113
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-
}
105114
// TODO - handle csToggle
106115
// if (argv[2] & SPI_CS_TOGGLE_MASK) csToggle = true;
107116
}
108117
}
109118

110-
if ((csIsActive || csStartOnly) && !csEndOnly) {
111-
digitalWrite(mCsPin, csStartVal);
119+
if (mCsPin >= 0 && csIsActive && !csEndOnly) {
120+
digitalWrite(mCsPin, mCsActiveState);
112121
}
113122

114123
if (transferOptions == SPI_READ_WRITE) {
@@ -122,8 +131,9 @@ boolean SPIFirmata::handleSysex(byte command, byte argc, byte *argv)
122131
Firmata.sendString("No transferOptions set");
123132
}
124133

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);
127137
}
128138
break; // SPI_TRANSFER
129139
}
@@ -138,20 +148,19 @@ boolean SPIFirmata::handleSysex(byte command, byte argc, byte *argv)
138148

139149
void SPIFirmata::reset()
140150
{
141-
mCsPin = -1;
142-
mDeviceId = 0;
151+
init();
143152
}
144153

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)
146155
{
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;
150159
if (numBytes * 2 != argc - offset) {
151160
// TODO - handle error
152161
Firmata.sendString("fails numBytes test");
153162
}
154-
for (byte i = 0; i < numBytes * 2; i += 2) {
163+
for (uint8_t i = 0; i < numBytes * 2; i += 2) {
155164
bufferIndex = (i + 1) / 2;
156165
buffer[bufferIndex] = argv[i + offset + 1] << 7 | argv[i + offset];
157166
}
@@ -160,38 +169,38 @@ void SPIFirmata::readWrite(byte channel, byte numBytes, byte argc, byte *argv)
160169
reply(channel, numBytes, buffer);
161170
}
162171

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)
164173
{
165-
byte offset = 4;
166-
byte txValue;
174+
uint8_t offset = 4;
175+
uint8_t txValue;
167176
if (numBytes * 2 != argc - offset) {
168177
// TODO - handle error
169178
Firmata.sendString("fails numBytes test");
170179
}
171-
for (byte i = 0; i < numBytes * 2; i += 2) {
180+
for (uint8_t i = 0; i < numBytes * 2; i += 2) {
172181
txValue = argv[i + offset + 1] << 7 | argv[i + offset];
173182
SPI.transfer(txValue);
174183
}
175184
}
176185

177-
void SPIFirmata::readOnly(byte channel, byte numBytes)
186+
void SPIFirmata::readOnly(uint8_t channel, uint8_t numBytes)
178187
{
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++) {
181190
replyData[i] = SPI.transfer(0x00);
182191
}
183192
reply(channel, numBytes, replyData);
184193
}
185194

186-
void SPIFirmata::reply(byte channel, byte numBytes, byte *buffer)
195+
void SPIFirmata::reply(uint8_t channel, uint8_t numBytes, uint8_t *buffer)
187196
{
188197
Firmata.write(START_SYSEX);
189198
Firmata.write(SPI_DATA);
190199
Firmata.write(SPI_REPLY);
191200
Firmata.write(mDeviceId << 2 | channel);
192201
Firmata.write(numBytes);
193202

194-
for (byte i = 0; i < numBytes; i++) {
203+
for (uint8_t i = 0; i < numBytes; i++) {
195204
Firmata.write(buffer[i] & 0x7F);
196205
Firmata.write(buffer[i] >> 7 & 0x7F);
197206
}

utility/SPIFirmata.h

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
1010
See file LICENSE.txt for further informations on licensing terms.
1111
12-
Last updated January 7th, 2017
12+
Last updated January 8th, 2017
1313
*/
1414

1515
#ifndef SPIFirmata_h
@@ -35,7 +35,7 @@
3535
#define SPI_END 0x05
3636

3737
// transfer options
38-
#define SPI_TRANSFER_OPTS_MASK 0x03
38+
#define SPI_TRANSFER_MODES_MASK 0x03
3939
#define SPI_READ_WRITE 0x00
4040
#define SPI_READ_ONLY 0x01
4141
#define SPI_WRITE_ONLY 0x02
@@ -44,13 +44,15 @@
4444
#define SPI_CS_DISABLE_MASK 0x04
4545
#define SPI_CS_START_ONLY_MASK 0x08
4646
#define SPI_CS_END_ONLY_MASK 0x10
47-
#define SPI_CS_ACTIVE_EDGE_MASK 0x20
48-
#define SPI_CS_TOGGLE_MASK 0x40
47+
#define SPI_CS_TOGGLE_MASK 0x20
4948

5049
#define SPI_CHANNEL_MASK 0x03
5150
#define SPI_DEVICE_ID_MASK 0x7C
5251
#define SPI_BIT_ORDER_MASK 0x01
5352

53+
#define SPI_CS_ACTIVE_LOW 0x00
54+
#define SPI_CS_ACTIVE_HIGH 0x01
55+
5456
namespace {
5557
// TODO - check Teensy and other non SAM, SAMD or AVR variants
5658
#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
@@ -82,19 +84,23 @@ class SPIFirmata: public FirmataFeature
8284
{
8385
public:
8486
SPIFirmata();
85-
boolean handlePinMode(byte pin, int mode);
86-
void handleCapability(byte pin);
87-
boolean handleSysex(byte command, byte argc, byte *argv);
87+
bool handlePinMode(uint8_t pin, int mode);
88+
void handleCapability(uint8_t pin);
89+
bool handleSysex(uint8_t command, uint8_t argc, uint8_t *argv);
8890
void reset();
8991

9092
private:
91-
signed char mCsPin;
92-
byte mDeviceId;
93+
// TODO - each of these properties should be in an array of channels
94+
int8_t mCsPin;
95+
bool mCsActiveState;
96+
uint8_t mDeviceId;
97+
98+
void init();
9399

94-
void readWrite(byte channel, byte numBytes, byte argc, byte *argv);
95-
void readOnly(byte channel, byte numBytes);
96-
void writeOnly(byte channel, byte numBytes, byte argc, byte *argv);
97-
void reply(byte channel, byte numBytes, byte *buffer);
100+
void readWrite(uint8_t channel, uint8_t numBytes, uint8_t argc, uint8_t *argv);
101+
void readOnly(uint8_t channel, uint8_t numBytes);
102+
void writeOnly(uint8_t channel, uint8_t numBytes, uint8_t argc, uint8_t *argv);
103+
void reply(uint8_t channel, uint8_t numBytes, uint8_t *buffer);
98104
};
99105

100106
#endif /* SPIFirmata_h */

0 commit comments

Comments
 (0)