代码拉取完成,页面将自动刷新
同步操作将从 gastonfeng/firmata 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
/*
FirmataMarshaller.cpp
Copyright (c) 2006-2008 Hans-Christoph Steiner. All rights reserved.
Copyright (C) 2009-2016 Jeff Hoefs. 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.
*/
//******************************************************************************
//* Includes
//******************************************************************************
#include "FirmataMarshaller.h"
#if defined(__cplusplus) && !defined(ARDUINO)
#include <cstring>
#else
#endif
#include <cstring>
#include <cassert>
#include <logger_rte.h>
#include "FirmataConstants.h"
using namespace firmata;
//******************************************************************************
//* Support Functions
//******************************************************************************
/**
* Request or halt a nStream of analog readings from the Firmata host application. The range of pins is
* limited to [0..15] when using the REPORT_ANALOG. The maximum result of the REPORT_ANALOG is limited to 14 bits
* (16384). To increase the pin range or value, see the documentation for the EXTENDED_ANALOG
* message.
* @param pin The analog pin for which to request the value (limited to pins 0 - 15).
* @param stream_enable A zero value will disable the nStream, a non-zero will enable the nStream
* @note The maximum resulting value is 14-bits (16384).
*/
void FirmataMarshaller::reportAnalog(nStream *FirmataStream, uint8_t pin, bool stream_enable) {
// pin can only be 0-15, so chop higher bits
FirmataStream->write(REPORT_ANALOG | (pin & 0xF));
FirmataStream->write(stream_enable);
}
/**
* Request or halt an 8-bit port nStream from the Firmata host application (protocol v2 and later).
* Send 14-bits in a single digital message (protocol v1).
* @param portNumber The port number for which to request the value. Note that this is not the same as a "port" on the
* physical microcontroller. Ports are defined in order per every 8 pins in ascending order
* of the Arduino digital pin numbering scheme. Port 0 = pins D0 - D7, port 1 = pins D8 - D15, etc.
* @param stream_enable A zero value will disable the nStream, a non-zero will enable the nStream
*/
void FirmataMarshaller::reportDigitalPort(nStream *FirmataStream, uint8_t portNumber, bool stream_enable) {
FirmataStream->write(REPORT_DIGITAL | (portNumber & 0xF));
FirmataStream->write(stream_enable);
}
/**
* An alternative to the normal analog message, this extended version allows addressing beyond
* pin 15 and supports sending analog values with any number of bits.
* @param pin The analog pin to which the value is sent.
* @param bytec The size of the storage for the analog value
* @param bytev The pointer to the location of the analog value
*/
void FirmataMarshaller::sendExtendedAnalog(nStream *FirmataStream, uint8_t pin, size_t bytec, uint8_t *bytev) {
FirmataStream->write(START_SYSEX);
FirmataStream->write(EXTENDED_ANALOG);
FirmataStream->write(pin);
encodeByteStream(FirmataStream, bytec, bytev);
FirmataStream->write(END_SYSEX);
FirmataStream->flush();
}
/**
* Transform 8-bit nStream into 7-bit message
* @param bytec The number of data bytes in the message.
* @param bytev A pointer to the array of data bytes to send in the message.
* @param max_bytes Force message to be n bytes, regardless of data bits.
*/
extern "C" u16 crc_16(u8 *buf, int cnt, u16 init);
void FirmataMarshaller::encodeByteStream(nStream *FirmataStream, size_t bytec, uint8_t *bytev, size_t max_bytes) {
if (FirmataStream == nullptr) {
return;
}
// logger.debug("encodeByteStream:%p bytec=%d,bytev=%p, max_bytes=%d", FirmataStream, bytec, bytev, max_bytes);
static const size_t transmit_bits = 7;
static const uint8_t transmit_mask = ((1 << transmit_bits) - 1);
size_t bytes_sent = 0;
size_t outstanding_bits = 0;
uint8_t outstanding_bit_cache = *bytev;
u16 crc = 0;
u8 v;
if ((int) bytev < 0x30000000) {
// logger.debug("encodeByteStream:%p bytec=%d,bytev=%p, max_bytes=%d", FirmataStream, bytec, bytev, max_bytes);
return;
}
if (max_bytes == 0) {
max_bytes = FIRMATA_BUFFER_SZ;
}
if (bytec > max_bytes) {
// logger.error("encodeByteStream: bytec %d > max_bytes %d", bytec, max_bytes);
return;
}
for (size_t i = 0; (i < bytec) && (bytes_sent < max_bytes); ++i) {
auto transmit_byte = (uint8_t) (outstanding_bit_cache | (bytev[i] << outstanding_bits));
v = transmit_mask & transmit_byte;
FirmataStream->write(v);
crc = crc_16(&v, 1, crc);
++bytes_sent;
outstanding_bit_cache = (bytev[i] >> (transmit_bits - outstanding_bits));
outstanding_bits = (outstanding_bits + (8 - transmit_bits));
while ((outstanding_bits >= transmit_bits) && (bytes_sent < max_bytes)) {
transmit_byte = outstanding_bit_cache;
v = transmit_mask & transmit_byte;
FirmataStream->write(v);
crc = crc_16(&v, 1, crc);
++bytes_sent;
outstanding_bit_cache >>= transmit_bits;
outstanding_bits -= transmit_bits;
}
}
if (outstanding_bits && (bytes_sent < max_bytes)) {
v = (uint8_t) ((1 << outstanding_bits) - 1) & outstanding_bit_cache;
FirmataStream->write(v);
crc = crc_16(&v, 1, crc);
}
#ifdef FIRMATA_USE_CRC
FirmataStream->write(crc & 0x7f);
FirmataStream->write((crc >> 7) & 0x7f);
FirmataStream->write((crc >> 14) & 0x7f);
#endif
}
//******************************************************************************
//* Constructors
//******************************************************************************
/**
* The FirmataMarshaller class.
*/
FirmataMarshaller::FirmataMarshaller() = default;
//******************************************************************************
//* Public Methods
//******************************************************************************
/**
* Reassign the Firmata nStream transport.
* @param s A reference to the nStream transport object. This can be any type of
* transport that implements the nStream interface. Some examples include Ethernet, WiFi
* and other UARTs on the board (Serial1, Serial2, etc).
*/
void FirmataMarshaller::begin() {
//
}
/**
* Closes the FirmataMarshaller nStream by setting its nStream reference to `(nStream *)NULL`
*/
void FirmataMarshaller::end() {
//
}
//******************************************************************************
//* Output nStream Handling
//******************************************************************************
/**
* Query the target's firmware name and version
*/
void FirmataMarshaller::queryFirmwareVersion(nStream *FirmataStream) {
if ((nStream *) nullptr == FirmataStream) {
return;
}
FirmataStream->write(START_SYSEX);
FirmataStream->write(REPORT_FIRMWARE);
FirmataStream->write(END_SYSEX);
FirmataStream->flush();
}
/**
* Query the target's Firmata protocol version
*/
void FirmataMarshaller::queryVersion(nStream *FirmataStream) {
FirmataStream->write(REPORT_VERSION);
}
/**
* Halt the nStream of analog readings from the Firmata host application. The range of pins is
* limited to [0..15] when using the REPORT_ANALOG. The maximum result of the REPORT_ANALOG is limited to 14 bits
* (16384). To increase the pin range or value, see the documentation for the EXTENDED_ANALOG
* message.
* @param pin The analog pin for which to request the value (limited to pins 0 - 15).
*/
void FirmataMarshaller::reportAnalogDisable(nStream *FirmataStream, uint8_t pin) {
reportAnalog(FirmataStream, pin, false);
}
/**
* Request a nStream of analog readings from the Firmata host application. The range of pins is
* limited to [0..15] when using the REPORT_ANALOG. The maximum result of the REPORT_ANALOG is limited to 14 bits
* (16384). To increase the pin range or value, see the documentation for the EXTENDED_ANALOG
* message.
* @param pin The analog pin for which to request the value (limited to pins 0 - 15).
*/
void FirmataMarshaller::reportAnalogEnable(nStream *FirmataStream, uint8_t pin) {
reportAnalog(FirmataStream, pin, true);
}
/**
* Halt an 8-bit port nStream from the Firmata host application (protocol v2 and later).
* Send 14-bits in a single digital message (protocol v1).
* @param portNumber The port number for which to request the value. Note that this is not the same as a "port" on the
* physical microcontroller. Ports are defined in order per every 8 pins in ascending order
* of the Arduino digital pin numbering scheme. Port 0 = pins D0 - D7, port 1 = pins D8 - D15, etc.
*/
void FirmataMarshaller::reportDigitalPortDisable(nStream *FirmataStream, uint8_t portNumber) {
reportDigitalPort(FirmataStream, portNumber, false);
}
/**
* Request an 8-bit port nStream from the Firmata host application (protocol v2 and later).
* Send 14-bits in a single digital message (protocol v1).
* @param portNumber The port number for which to request the value. Note that this is not the same as a "port" on the
* physical microcontroller. Ports are defined in order per every 8 pins in ascending order
* of the Arduino digital pin numbering scheme. Port 0 = pins D0 - D7, port 1 = pins D8 - D15, etc.
*/
void FirmataMarshaller::reportDigitalPortEnable(nStream *FirmataStream, uint8_t portNumber) {
reportDigitalPort(FirmataStream, portNumber, true);
}
/**
* Send an analog message to the Firmata host application. The range of pins is limited to [0..15]
* when using the ANALOG_MESSAGE. The maximum value of the ANALOG_MESSAGE is limited to 14 bits
* (16384). To increase the pin range or value, see the documentation for the EXTENDED_ANALOG
* message.
* @param pin The analog pin to which the value is sent.
* @param value The value of the analog pin (0 - 1024 for 10-bit analog, 0 - 4096 for 12-bit, etc).
* @note The maximum value is 14-bits (16384).
*/
void FirmataMarshaller::sendAnalog(nStream *FirmataStream, uint8_t pin, int16_t value) {
#ifdef FIRMATA_INSTANT
if ((0xF >= pin) && (0x3FFF >= value))
{
FirmataStream->write(ANALOG_MESSAGE | pin);
encodeByteStream(FirmataStream, sizeof(value), (uint8_t *)(&value), sizeof(value));
}
else
#endif
{
sendExtendedAnalog(FirmataStream, pin, sizeof(value), (uint8_t *) (&value));
}
}
/**
* Send an analog mapping query to the Firmata host application. The resulting sysex message will
* have an ANALOG_MAPPING_RESPONSE command byte, followed by a list of pins [0-n]; where each
* pin will specify its corresponding analog pin number or 0x7F (127) if not applicable.
*/
void FirmataMarshaller::sendAnalogMappingQuery(nStream *FirmataStream) {
sendSysex(FirmataStream, ANALOG_MAPPING_QUERY, 0, nullptr);
}
/**
* Send a capability query to the Firmata host application. The resulting sysex message will have
* a CAPABILITY_RESPONSE command byte, followed by a list of byte tuples (mode and mode resolution)
* for each pin; where each pin list is terminated by 0x7F (127).
*/
void FirmataMarshaller::sendCapabilityQuery(nStream *FirmataStream) {
sendSysex(FirmataStream, CAPABILITY_QUERY, 0, nullptr);
}
/**
* Send a single digital pin value to the Firmata host application.
* @param pin The digital pin to send the value of.
* @param value The value of the pin.
*/
void FirmataMarshaller::sendDigital(nStream *FirmataStream, uint8_t pin, uint8_t value) {
FirmataStream->write(SET_DIGITAL_PIN_VALUE);
FirmataStream->write(pin & 0x7F);
FirmataStream->write(value != 0);
}
/**
* Send an 8-bit port in a single digital message (protocol v2 and later).
* Send 14-bits in a single digital message (protocol v1).
* @param portNumber The port number to send. Note that this is not the same as a "port" on the
* physical microcontroller. Ports are defined in order per every 8 pins in ascending order
* of the Arduino digital pin numbering scheme. Port 0 = pins D0 - D7, port 1 = pins D8 - D15, etc.
* @param portData The value of the port. The value of each pin in the port is represented by a bit.
*/
void FirmataMarshaller::sendDigitalPort(nStream *FirmataStream, uint8_t portNumber, uint16_t portData) {
FirmataStream->write(DIGITAL_MESSAGE | (portNumber & 0xF));
// Tx bits 0-6 (protocol v1 and higher)
// Tx bits 7-13 (bit 7 only for protocol v2 and higher)
encodeByteStream(FirmataStream, sizeof(portData), (uint8_t *) (&portData), sizeof(portData));
}
/**
* Sends the firmware name and version to the Firmata host application.
* @param major The major verison number
* @param minor The minor version number
* @param bytec The length of the firmware name
* @param bytev The firmware name array
*/
void FirmataMarshaller::sendFirmwareVersion(nStream *FirmataStream, uint8_t major, uint8_t minor, size_t bytec,
uint8_t *bytev) {
FirmataStream->write(START_SYSEX);
FirmataStream->write(REPORT_FIRMWARE);
FirmataStream->write(major);
FirmataStream->write(minor);
for (int i = 0; i < bytec; ++i) {
encodeByteStream(FirmataStream, sizeof(bytev[i]), (&bytev[i]));
}
FirmataStream->write(END_SYSEX);
FirmataStream->flush();
}
/**
* Send the Firmata protocol version to the Firmata host application.
* @param major The major verison number
* @param minor The minor version number
*/
void FirmataMarshaller::sendVersion(nStream *FirmataStream, uint8_t major, uint8_t minor) {
FirmataStream->write(REPORT_VERSION);
FirmataStream->write(major);
FirmataStream->write(minor);
}
/**
* Send the pin mode/configuration. The pin configuration (or mode) in Firmata represents the
* current function of the pin. Examples are digital input or output, analog input, pwm, i2c,
* serial (uart), etc.
* @param pin The pin to configure.
* @param config The configuration value for the specified pin.
*/
void FirmataMarshaller::sendPinMode(nStream *FirmataStream, uint8_t pin, uint8_t config) {
FirmataStream->write(SET_PIN_MODE);
FirmataStream->write(pin);
FirmataStream->write(config);
}
/**
* Send a pin state query to the Firmata host application. The resulting sysex message will have
* a PIN_STATE_RESPONSE command byte, followed by the pin number, the pin mode and a nStream of
* bits to indicate any *data* written to the pin (pin state).
* @param pin The pin to query
* @note The pin state is any data written to the pin (i.e. pin state != pin value)
*/
void FirmataMarshaller::sendPinStateQuery(nStream *FirmataStream, uint8_t pin) {
FirmataStream->write(START_SYSEX);
FirmataStream->write(PIN_STATE_QUERY);
FirmataStream->write(pin);
FirmataStream->write(END_SYSEX);
FirmataStream->flush();
}
/**
* Send a sysex message where all values after the command byte are packet as 2 7-bit bytes
* (this is not always the case so this function is not always used to send sysex messages).
* @param command The sysex command byte.
* @param bytec The number of data bytes in the message (excludes start, command and end bytes).
* @param bytev A pointer to the array of data bytes to send in the message.
*/
void FirmataMarshaller::sendSysex(nStream *FirmataStream, uint8_t command, size_t bytec, uint8_t *bytev) {
assert(FirmataStream);
if (bytec > FIRMATA_BUFFER_SZ) {
// core_debug("FirmataMarshaller byte limit");
return;
}
if (FirmataStream->lock)
rtos::mutex_lock(FirmataStream->lock);
FirmataStream->flag |= FLAG_SYSEX;
FirmataStream->write(START_SYSEX);
FirmataStream->write(command);
if (bytec > 0)
encodeByteStream(FirmataStream, bytec, bytev);
FirmataStream->write(END_SYSEX);
FirmataStream->flush();
if (FirmataStream->lock)
rtos::mutex_unlock(FirmataStream->lock);
}
/**
* Send a string to the Firmata host application.
* @param string A pointer to the char string
*/
void FirmataMarshaller::sendString(nStream *FirmataStream, const char *string) {
sendSysex(FirmataStream, STRING_DATA, strlen(string), (uint8_t *) (const_cast<char *>(string)));
}
/**
* The sampling interval sets how often analog data and i2c data is reported to the client.
* @param interval_ms The interval (in milliseconds) at which to sample
* @note The default sampling interval is 19ms
*/
void FirmataMarshaller::setSamplingInterval(nStream *FirmataStream, uint16_t interval_ms) {
sendSysex(FirmataStream, SAMPLING_INTERVAL, sizeof(interval_ms), (uint8_t *) (&interval_ms));
}
/**
* Perform a software reset on the target. For example, StandardFirmata.ino will initialize
* everything to a known state and reset the parsing buffer.
*/
void FirmataMarshaller::systemReset(nStream *FirmataStream) {
FirmataStream->write(SYSTEM_RESET);
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。