Skip to content

Commit d0bef9e

Browse files
committed
sendExtendedAnalog
includes support function transformByteStreamToMessageBytes(), which replaces sendValueAsTwo7bitBytes()
1 parent 2e09889 commit d0bef9e

File tree

4 files changed

+67
-19
lines changed

4 files changed

+67
-19
lines changed

Firmata.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ systemCallbackFunction FirmataClass::currentSystemResetCallback = (systemCallbac
5050
*/
5151
void FirmataClass::sendValueAsTwo7bitBytes(int value)
5252
{
53-
marshaller.sendValueAsTwo7bitBytes(value);
53+
marshaller.transformByteStreamToMessageBytes(sizeof(value), reinterpret_cast<uint8_t *>(&value), sizeof(value));
5454
}
5555

5656
/**
@@ -196,7 +196,7 @@ void FirmataClass::printFirmwareVersion(void)
196196
FirmataStream->write(firmwareVersionVector[0]); // major version number
197197
FirmataStream->write(firmwareVersionVector[1]); // minor version number
198198
for (i = 2; i < firmwareVersionCount; ++i) {
199-
marshaller.sendValueAsTwo7bitBytes(firmwareVersionVector[i]);
199+
sendValueAsTwo7bitBytes(firmwareVersionVector[i]);
200200
}
201201
endSysex();
202202
}

Firmata.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class FirmataClass
128128

129129
/* private methods ------------------------------ */
130130
void strobeBlinkPin(byte pin, int count, int onInterval, int offInterval);
131-
friend void FirmataMarshaller::sendValueAsTwo7bitBytes(uint16_t value) const;
131+
friend void FirmataMarshaller::transformByteStreamToMessageBytes (size_t bytec, uint8_t * bytev, size_t max_bytes = 0) const;
132132

133133
/* callback functions */
134134
static callbackFunction currentAnalogCallback;

FirmataMarshaller.cpp

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,57 @@ const
6666
}
6767

6868
/**
69-
* Split a 16-bit integer into two 7-bit values and write each value.
70-
* @param value The 16-bit value to be split and written separately.
69+
* An alternative to the normal analog message, this extended version allows addressing beyond
70+
* pin 15 and supports sending analog values with any number of bits.
71+
* @param pin The analog pin to which the value is sent.
72+
* @param bytec The size of the storage for the analog value
73+
* @param bytev The pointer to the location of the analog value
7174
*/
72-
void FirmataMarshaller::sendValueAsTwo7bitBytes(uint16_t value)
75+
void FirmataMarshaller::sendExtendedAnalog(uint8_t pin, size_t bytec, uint8_t * bytev)
7376
const
7477
{
75-
FirmataStream->write(value & 0x7F); // LSB
76-
FirmataStream->write(value >> 7 & 0x7F); // MSB
78+
if ( (Stream *)NULL == FirmataStream ) { return; }
79+
FirmataStream->write(START_SYSEX);
80+
FirmataStream->write(EXTENDED_ANALOG);
81+
FirmataStream->write(pin);
82+
transformByteStreamToMessageBytes(bytec, bytev, bytec);
83+
FirmataStream->write(END_SYSEX);
84+
}
85+
86+
/**
87+
* Transform 8-bit stream into 7-bit message
88+
* @param bytec The number of data bytes in the message.
89+
* @param bytev A pointer to the array of data bytes to send in the message.
90+
* @param max_bytes Force message to be n bytes, regardless of data bits.
91+
*/
92+
void FirmataMarshaller::transformByteStreamToMessageBytes (size_t bytec, uint8_t * bytev, size_t max_bytes)
93+
const
94+
{
95+
static const size_t transmit_bits = 7;
96+
static const uint8_t transmit_mask = ((1 << transmit_bits) - 1);
97+
98+
size_t bytes_sent = 0;
99+
size_t outstanding_bits = 0;
100+
uint8_t outstanding_bit_cache = *bytev;
101+
102+
if ( !max_bytes ) { max_bytes = static_cast<size_t>(-1); }
103+
for (size_t i = 0 ; (i < bytec) && (bytes_sent < max_bytes) ; ++i) {
104+
uint8_t transmit_byte = (outstanding_bit_cache|(bytev[i] << outstanding_bits));
105+
FirmataStream->write(transmit_mask & transmit_byte);
106+
++bytes_sent;
107+
outstanding_bit_cache = (bytev[i] >> (transmit_bits - outstanding_bits));
108+
outstanding_bits = (outstanding_bits + (8 - transmit_bits));
109+
for ( ; (outstanding_bits >= transmit_bits) && (bytes_sent < max_bytes) ; ) {
110+
transmit_byte = outstanding_bit_cache;
111+
FirmataStream->write(transmit_mask & transmit_byte);
112+
++bytes_sent;
113+
outstanding_bit_cache >>= transmit_bits;
114+
outstanding_bits -= transmit_bits;
115+
}
116+
}
117+
if ( outstanding_bits && (bytes_sent < max_bytes) ) {
118+
FirmataStream->write(static_cast<uint8_t>((1 << outstanding_bits) - 1) & outstanding_bit_cache);
119+
}
77120
}
78121

79122
//******************************************************************************
@@ -173,17 +216,20 @@ const
173216
* when using the ANALOG_MESSAGE. The maximum value of the ANALOG_MESSAGE is limited to 14 bits
174217
* (16384). To increase the pin range or value, see the documentation for the EXTENDED_ANALOG
175218
* message.
176-
* @param pin The analog pin to send the value of (limited to pins 0 - 15).
219+
* @param pin The analog pin to which the value is sent.
177220
* @param value The value of the analog pin (0 - 1024 for 10-bit analog, 0 - 4096 for 12-bit, etc).
178-
* The maximum value is 14-bits (16384).
179221
*/
180222
void FirmataMarshaller::sendAnalog(uint8_t pin, uint16_t value)
181223
const
182224
{
183225
if ( (Stream *)NULL == FirmataStream ) { return; }
184-
// pin can only be 0-15, so chop higher bits
185-
FirmataStream->write(ANALOG_MESSAGE | (pin & 0xF));
186-
sendValueAsTwo7bitBytes(value);
226+
227+
if ( (0xF >= pin) && (0x3FFF >= value) ) {
228+
FirmataStream->write(ANALOG_MESSAGE|pin);
229+
transformByteStreamToMessageBytes(sizeof(value), reinterpret_cast<uint8_t *>(&value), 2);
230+
} else {
231+
sendExtendedAnalog(pin, sizeof(value), reinterpret_cast<uint8_t *>(&value));
232+
}
187233
}
188234

189235
/**
@@ -236,8 +282,9 @@ const
236282
{
237283
if ( (Stream *)NULL == FirmataStream ) { return; }
238284
FirmataStream->write(DIGITAL_MESSAGE | (portNumber & 0xF));
239-
FirmataStream->write((uint8_t)portData % 128); // Tx bits 0-6 (protocol v1 and higher)
240-
FirmataStream->write(portData >> 7); // Tx bits 7-13 (bit 7 only for protocol v2 and higher)
285+
// Tx bits 0-6 (protocol v1 and higher)
286+
// Tx bits 7-13 (bit 7 only for protocol v2 and higher)
287+
transformByteStreamToMessageBytes(sizeof(portData), reinterpret_cast<uint8_t *>(&portData), 2);
241288
}
242289

243290
/**
@@ -284,7 +331,7 @@ const
284331
FirmataStream->write(START_SYSEX);
285332
FirmataStream->write(command);
286333
for (i = 0; i < bytec; ++i) {
287-
sendValueAsTwo7bitBytes(bytev[i]);
334+
transformByteStreamToMessageBytes(sizeof(bytev[i]), reinterpret_cast<uint8_t *>(&bytev[i]), 2);
288335
}
289336
FirmataStream->write(END_SYSEX);
290337
}
@@ -296,7 +343,7 @@ const
296343
void FirmataMarshaller::sendString(const char *string)
297344
const
298345
{
299-
sendSysex(STRING_DATA, strlen(string), (uint8_t *)string);
346+
sendSysex(STRING_DATA, strlen(string), reinterpret_cast<uint8_t *>(const_cast<char *>(string)));
300347
}
301348

302349
/**
@@ -307,5 +354,5 @@ const
307354
void FirmataMarshaller::setSamplingInterval(uint16_t interval_ms)
308355
const
309356
{
310-
sendSysex(SAMPLING_INTERVAL, sizeof(interval_ms), &interval_ms);
357+
sendSysex(SAMPLING_INTERVAL, sizeof(interval_ms), reinterpret_cast<uint8_t *>(&interval_ms));
311358
}

FirmataMarshaller.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ class FirmataMarshaller
5858
/* utility methods */
5959
void reportAnalog(uint8_t pin, bool stream_enable) const;
6060
void reportDigitalPort(uint8_t portNumber, bool stream_enable) const;
61-
void sendValueAsTwo7bitBytes(uint16_t value) const;
61+
void sendExtendedAnalog(uint8_t pin, size_t bytec, uint8_t * bytev) const;
62+
void transformByteStreamToMessageBytes (size_t bytec, uint8_t * bytev, size_t max_bytes = 0) const;
6263

6364
Stream * FirmataStream;
6465
};

0 commit comments

Comments
 (0)