firmata: initial work
Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
This commit is contained in:
@@ -274,7 +274,10 @@ int mraa_get_sub_platform_id(int pin_or_bus_index);
|
||||
*/
|
||||
int mraa_get_sub_platform_index(int pin_or_bus_id);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
mraa_result_t mraa_add_subplatform(mraa_platform_t subplatformtype, const char* uart_dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -288,4 +288,19 @@ getDefaultI2cBus(int platform_offset=MRAA_MAIN_PLATFORM_OFFSET)
|
||||
{
|
||||
return mraa_get_default_i2c_bus(platform_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add mraa subplatform
|
||||
*
|
||||
* @param subplatformtype the type of subplatform to add
|
||||
* (e.g. MRAA_GENERIC_FIRMATA)
|
||||
* @param uart_dev subplatform device string (e.g. "/dev/ttyACM0")
|
||||
* @return Result of operation
|
||||
*/
|
||||
inline Result
|
||||
addSubplatform(Platform subplatformtype, std::string uart_dev)
|
||||
{
|
||||
return (Result) mraa_add_subplatform((mraa_platform_t) subplatformtype, uart_dev.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,6 +54,9 @@ typedef enum {
|
||||
// USB platform extenders start at 256
|
||||
MRAA_FTDI_FT4222 = 256, /**< FTDI FT4222 USB to i2c bridge */
|
||||
|
||||
// contains bit 9 so is subplatform
|
||||
MRAA_GENERIC_FIRMATA = 1280, /**< Firmata uart platform/bridge */
|
||||
|
||||
MRAA_NULL_PLATFORM = 98, /**< Platform with no capabilities that hosts a sub platform */
|
||||
MRAA_UNKNOWN_PLATFORM =
|
||||
99 /**< An unknown platform type, typically will load INTEL_GALILEO_GEN1 */
|
||||
|
||||
@@ -47,13 +47,13 @@ typedef enum {
|
||||
BEAGLEBONE = 6, /**< The different BeagleBone Black Modes B/C */
|
||||
BANANA = 7, /**< Allwinner A20 based Banana Pi and Banana Pro */
|
||||
INTEL_NUC5 = 8, /**< The Intel 5th generations Broadwell NUCs */
|
||||
96BOARDS = 9, /**< Linaro 96boards */
|
||||
A96BOARDS = 9, /**< Linaro 96boards, A prefix for 'ARM' since not allowed numerical */
|
||||
INTEL_SOFIA_3GR = 10, /**< The Intel SoFIA 3GR */
|
||||
INTEL_CHERRYHILLS = 11, /**< The Intel Braswell Cherryhills */
|
||||
|
||||
FTDI_FT4222 = 256, /**< FTDI FT4222 USB to i2c bridge */
|
||||
|
||||
FIRMATA = 1024, /**< Firmata uart platform/bridge */
|
||||
GENERIC_FIRMATA = 1280, /**< Firmata uart platform/bridge */
|
||||
|
||||
NULL_PLATFORM = 98,
|
||||
UNKNOWN_PLATFORM =
|
||||
|
||||
111
include/firmata/firmata.h
Normal file
111
include/firmata/firmata.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2015 Jules Dourlens (jdourlens@gmail.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "serial.h"
|
||||
|
||||
#define MODE_INPUT 0x00
|
||||
#define MODE_OUTPUT 0x01
|
||||
#define MODE_ANALOG 0x02
|
||||
#define MODE_PWM 0x03
|
||||
#define MODE_SERVO 0x04
|
||||
#define MODE_SHIFT 0x05
|
||||
#define MODE_I2C 0x06
|
||||
|
||||
#define LOW 0
|
||||
#define HIGH 1
|
||||
|
||||
#define FIRMATA_START_SYSEX 0xF0 // start a MIDI Sysex message
|
||||
#define FIRMATA_END_SYSEX 0xF7 // end a MIDI Sysex message
|
||||
#define FIRMATA_PIN_MODE_QUERY 0x72 // ask for current and supported pin modes
|
||||
#define FIRMATA_PIN_MODE_RESPONSE 0x73 // reply with current and supported pin modes
|
||||
#define FIRMATA_PIN_STATE_QUERY 0x6D
|
||||
#define FIRMATA_PIN_STATE_RESPONSE 0x6E
|
||||
#define FIRMATA_CAPABILITY_QUERY 0x6B
|
||||
#define FIRMATA_CAPABILITY_RESPONSE 0x6C
|
||||
#define FIRMATA_ANALOG_MAPPING_QUERY 0x69
|
||||
#define FIRMATA_ANALOG_MAPPING_RESPONSE 0x6A
|
||||
|
||||
#define FIRMATA_DIGITAL_MESSAGE 0x90 // send data for a digital pin
|
||||
#define FIRMATA_ANALOG_MESSAGE 0xE0 // send data for an analog pin (or PWM)
|
||||
#define FIRMATA_ANALOG_MESSAGE 0xE0 // send data for an analog pin (or PWM)
|
||||
#define FIRMATA_REPORT_ANALOG 0xC0 // enable analog input by pin #
|
||||
#define FIRMATA_REPORT_DIGITAL 0xD0 // enable digital input by port pair
|
||||
|
||||
#define FIRMATA_I2C_CONFIG 0x78
|
||||
#define FIRMATA_I2C_REPLY 0x77
|
||||
#define FIRMATA_I2C_REQUEST 0x76
|
||||
|
||||
#define I2C_MODE_WRITE 0x00
|
||||
#define I2C_MODE_READ 0x01
|
||||
#define I2C_CONTINUOUSREAD 0x02
|
||||
#define I2C_STOP_READING 0x03
|
||||
|
||||
#define FIRMATA_SET_PIN_MODE 0xF4 // set a pin to INPUT/OUTPUT/PWM/etc
|
||||
|
||||
#define FIRMATA_REPORT_VERSION 0xF9 // report protocol version
|
||||
#define FIRMATA_SYSTEM_RESET 0xFF // reset from MIDI
|
||||
|
||||
#define FIRMATA_START_SYSEX 0xF0 // start a MIDI Sysex message
|
||||
#define FIRMATA_END_SYSEX 0xF7 // end a MIDI Sysex message
|
||||
|
||||
// extended command set using sysex (0-127/0x00-0x7F)
|
||||
/* 0x00-0x0F reserved for custom commands */
|
||||
#define FIRMATA_SERVO_CONFIG 0x70 // set max angle, minPulse, maxPulse, freq
|
||||
#define FIRMATA_STRING 0x71 // a string message with 14-bits per char
|
||||
#define FIRMATA_REPORT_FIRMWARE 0x79 // report name and version of the firmware
|
||||
#define FIRMATA_SYSEX_NON_REALTIME 0x7E // MIDI Reserved for non-realtime messages
|
||||
#define FIRMATA_SYSEX_REALTIME 0x7F // MIDI Reserved for realtime messages
|
||||
|
||||
#define FIRMATA_MSG_LEN 1024
|
||||
|
||||
typedef struct s_pin {
|
||||
uint8_t mode;
|
||||
uint8_t analog_channel;
|
||||
uint64_t supported_modes;
|
||||
uint32_t value;
|
||||
} t_pin;
|
||||
|
||||
typedef struct s_firmata {
|
||||
t_serial* serial;
|
||||
t_pin pins[128];
|
||||
int i2cmsg[256][256];
|
||||
int parse_command_len;
|
||||
int parse_count;
|
||||
uint8_t parse_buff[FIRMATA_MSG_LEN];
|
||||
int isReady;
|
||||
char firmware[140];
|
||||
} t_firmata;
|
||||
|
||||
t_firmata* firmata_new(const char* name);
|
||||
void firmata_initPins(t_firmata* firmata);
|
||||
int firmata_askFirmware(t_firmata* firmata);
|
||||
int firmata_pinMode(t_firmata* firmata, int pin, int mode);
|
||||
int firmata_digitalWrite(t_firmata* firmata, int pin, int value);
|
||||
int firmata_analogWrite(t_firmata* firmata, int pin, int value);
|
||||
int firmata_analogRead(t_firmata* firmata, int pin);
|
||||
int firmata_pull(t_firmata* firmata);
|
||||
void firmata_parse(t_firmata* firmata, const uint8_t* buf, int len);
|
||||
void firmata_endParse(t_firmata* firmata);
|
||||
38
include/firmata/firmata_mraa.h
Normal file
38
include/firmata/firmata_mraa.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Author: Brendan Le Foll <brendan.le.foll@intel.com>
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mraa_internal.h"
|
||||
|
||||
mraa_platform_t mraa_firmata_platform(mraa_board_t* board, const char* uart_dev);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
51
include/firmata/serial.h
Normal file
51
include/firmata/serial.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2015 Jules Dourlens (jdourlens@gmail.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <termios.h>
|
||||
|
||||
typedef struct s_serial {
|
||||
int port_is_open;
|
||||
const char* port_name;
|
||||
int baud_rate;
|
||||
char* error_msg;
|
||||
|
||||
int port_fd;
|
||||
struct termios settings_orig;
|
||||
struct termios settings;
|
||||
int tx;
|
||||
int rx;
|
||||
} t_serial;
|
||||
|
||||
t_serial* serial_new();
|
||||
int serial_open(t_serial* serial, const char* name);
|
||||
int serial_setBaud(t_serial* serial, int baud);
|
||||
int serial_read(t_serial* serial, void* ptr, int count);
|
||||
int serial_write(t_serial* serial, void* ptr, int len);
|
||||
int serial_waitInput(t_serial* serial, int msec);
|
||||
int serial_discardInput(t_serial* serial);
|
||||
void serial_flushOutput(t_serial* serial);
|
||||
int serial_setControl(t_serial* serial, int dtr, int rts);
|
||||
35
include/firmata/servo.h
Normal file
35
include/firmata/servo.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2015 Jules Dourlens (jdourlens@gmail.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "firmata.h"
|
||||
|
||||
typedef struct s_servo {
|
||||
t_firmata* firmata;
|
||||
int pin;
|
||||
} t_servo;
|
||||
|
||||
t_servo* servo_attach(t_firmata* firmata, int pin);
|
||||
int servo_write(t_servo* servo, int value);
|
||||
@@ -73,6 +73,8 @@ typedef struct {
|
||||
mraa_result_t (*i2c_write_word_data_replace) (mraa_i2c_context dev, const uint16_t data, const uint8_t command);
|
||||
mraa_result_t (*i2c_stop_replace) (mraa_i2c_context dev);
|
||||
|
||||
mraa_result_t (*aio_init_internal_replace) (mraa_aio_context dev, int pin);
|
||||
mraa_result_t (*aio_read_replace) (mraa_aio_context dev);
|
||||
mraa_result_t (*aio_get_valid_fp) (mraa_aio_context dev);
|
||||
mraa_result_t (*aio_init_pre) (unsigned int aio);
|
||||
mraa_result_t (*aio_init_post) (mraa_aio_context dev);
|
||||
|
||||
@@ -106,6 +106,11 @@ if (USBPLAT)
|
||||
add_subdirectory(usb)
|
||||
endif ()
|
||||
|
||||
if (FIRMATA)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFIRMATA=1")
|
||||
add_subdirectory (firmata)
|
||||
endif ()
|
||||
|
||||
set (mraa_LIB_SRCS
|
||||
${mraa_LIB_PLAT_SRCS_NOAUTO}
|
||||
# autogenerated version file
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Author: Nandkishor Sonar
|
||||
* Author: Brendan Le Foll <brendan.le.foll@intel.com>
|
||||
* Copyright (c) 2014, 2015 Intel Corporation.
|
||||
* Copyright (c) 2014-2016 Intel Corporation.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@@ -56,7 +56,7 @@ aio_get_valid_fp(mraa_aio_context dev)
|
||||
}
|
||||
|
||||
static mraa_aio_context
|
||||
mraa_aio_init_internal(mraa_adv_func_t* func_table)
|
||||
mraa_aio_init_internal(mraa_adv_func_t* func_table, int aio)
|
||||
{
|
||||
mraa_aio_context dev = calloc(1, sizeof(struct _aio));
|
||||
if (dev == NULL) {
|
||||
@@ -64,6 +64,20 @@ mraa_aio_init_internal(mraa_adv_func_t* func_table)
|
||||
}
|
||||
dev->advance_func = func_table;
|
||||
|
||||
if (IS_FUNC_DEFINED(dev, aio_init_internal_replace)) {
|
||||
if (dev->advance_func->aio_init_internal_replace(dev, aio) == MRAA_SUCCESS) {
|
||||
return dev;
|
||||
}
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Open valid analog input file and get the pointer.
|
||||
if (MRAA_SUCCESS != aio_get_valid_fp(dev)) {
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
@@ -83,16 +97,37 @@ mraa_aio_init(unsigned int aio)
|
||||
syslog(LOG_ERR, "aio: Sub platform Not Initialised");
|
||||
return NULL;
|
||||
}
|
||||
pin = mraa_get_sub_platform_index(aio);
|
||||
aio = mraa_get_sub_platform_index(aio);
|
||||
}
|
||||
|
||||
// aio are always past the gpio_count in the pin array
|
||||
pin = aio + board->gpio_count;
|
||||
|
||||
if (pin < 0 || pin >= board->phy_pin_count) {
|
||||
syslog(LOG_ERR, "aio: pin %i beyond platform definition", pin);
|
||||
return NULL;
|
||||
}
|
||||
if (aio > board->aio_count) {
|
||||
syslog(LOG_ERR, "aio: requested channel out of range");
|
||||
return NULL;
|
||||
}
|
||||
if (board->pins[pin].capabilites.aio != 1) {
|
||||
syslog(LOG_ERR, "aio: pin %i not capable of aio", pin);
|
||||
return NULL;
|
||||
}
|
||||
if (board->pins[pin].aio.mux_total > 0) {
|
||||
if (mraa_setup_mux_mapped(board->pins[pin].aio) != MRAA_SUCCESS) {
|
||||
syslog(LOG_ERR, "aio: unable to setup multiplexers for pin");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Create ADC device connected to specified channel
|
||||
mraa_aio_context dev = mraa_aio_init_internal(board->adv_func);
|
||||
mraa_aio_context dev = mraa_aio_init_internal(board->adv_func, aio);
|
||||
if (dev == NULL) {
|
||||
syslog(LOG_ERR, "aio: Insufficient memory for specified input channel %d", aio);
|
||||
return NULL;
|
||||
}
|
||||
pin = aio + board->gpio_count;
|
||||
dev->channel = board->pins[pin].aio.pinmap;
|
||||
dev->value_bit = DEFAULT_BITS;
|
||||
|
||||
@@ -103,32 +138,6 @@ mraa_aio_init(unsigned int aio)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (aio > board->aio_count) {
|
||||
syslog(LOG_ERR, "aio: requested channel out of range");
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (board->pins[pin].capabilites.aio != 1) {
|
||||
syslog(LOG_ERR, "aio: pin uncapable of aio");
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (board->pins[pin].aio.mux_total > 0) {
|
||||
if (mraa_setup_mux_mapped(board->pins[pin].aio) != MRAA_SUCCESS) {
|
||||
free(dev);
|
||||
syslog(LOG_ERR, "aio: unable to setup multiplexers for pin");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Open valid analog input file and get the pointer.
|
||||
if (MRAA_SUCCESS != aio_get_valid_fp(dev)) {
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
raw_bits = mraa_adc_raw_bits();
|
||||
|
||||
if (IS_FUNC_DEFINED(dev, aio_init_post)) {
|
||||
mraa_result_t ret = dev->advance_func->aio_init_post(dev);
|
||||
@@ -138,12 +147,18 @@ mraa_aio_init(unsigned int aio)
|
||||
}
|
||||
}
|
||||
|
||||
raw_bits = mraa_adc_raw_bits();
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
mraa_aio_read(mraa_aio_context dev)
|
||||
{
|
||||
if (IS_FUNC_DEFINED(dev, aio_read_replace)) {
|
||||
return dev->advance_func->aio_read_replace(dev);
|
||||
}
|
||||
|
||||
char buffer[17];
|
||||
unsigned int shifter_value = 0;
|
||||
|
||||
|
||||
11
src/firmata/CMakeLists.txt
Normal file
11
src/firmata/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
if (FIRMATA)
|
||||
message (STATUS "INFO - Adding firmata backend support")
|
||||
set (mraa_LIB_PLAT_SRCS_NOAUTO ${mraa_LIB_PLAT_SRCS_NOAUTO}
|
||||
${PROJECT_SOURCE_DIR}/src/firmata/firmata.c
|
||||
${PROJECT_SOURCE_DIR}/src/firmata/servo.c
|
||||
${PROJECT_SOURCE_DIR}/src/firmata/serial.c
|
||||
${PROJECT_SOURCE_DIR}/src/firmata/firmata_mraa.c
|
||||
PARENT_SCOPE
|
||||
)
|
||||
message (${mraa_LIB_PLAT_SRCS_NOAUTO})
|
||||
endif ()
|
||||
341
src/firmata/firmata.c
Normal file
341
src/firmata/firmata.c
Normal file
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2015 Jules Dourlens (jdourlens@gmail.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "firmata/serial.h"
|
||||
#include "firmata/firmata.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
t_firmata*
|
||||
firmata_new(const char* name)
|
||||
{
|
||||
t_firmata* res;
|
||||
|
||||
printf("Opening device at: %s\n", name);
|
||||
res = malloc(sizeof(t_firmata));
|
||||
if (!res) {
|
||||
perror("firmata_new::Failed malloc");
|
||||
return (NULL);
|
||||
}
|
||||
memset(res, 0, sizeof(*res));
|
||||
res->serial = serial_new();
|
||||
if (!res->serial) {
|
||||
perror("firmata_new::Failed malloc");
|
||||
return (NULL);
|
||||
}
|
||||
serial_open(res->serial, name);
|
||||
firmata_initPins(res);
|
||||
serial_setBaud(res->serial, 57600);
|
||||
firmata_askFirmware(res);
|
||||
printf("Device opened at: %s\n", name);
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
firmata_pull(t_firmata* firmata)
|
||||
{
|
||||
uint8_t buff[FIRMATA_MSG_LEN];
|
||||
int r;
|
||||
|
||||
r = serial_waitInput(firmata->serial, 40);
|
||||
if (r > 0) {
|
||||
r = serial_read(firmata->serial, buff, sizeof(buff));
|
||||
if (r < 0) {
|
||||
return (0);
|
||||
}
|
||||
if (r > 0) {
|
||||
firmata_parse(firmata, buff, r);
|
||||
return (r);
|
||||
}
|
||||
} else if (r < 0) {
|
||||
return (r);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
firmata_parse(t_firmata* firmata, const uint8_t* buf, int len)
|
||||
{
|
||||
const uint8_t* p;
|
||||
const uint8_t* end;
|
||||
|
||||
p = buf;
|
||||
end = p + len;
|
||||
for (p = buf; p < end; p++) {
|
||||
uint8_t msn = *p & 0xF0;
|
||||
if (msn == 0xE0 || msn == 0x90 || *p == 0xF9) {
|
||||
firmata->parse_command_len = 3;
|
||||
firmata->parse_count = 0;
|
||||
} else if (msn == 0xC0 || msn == 0xD0) {
|
||||
firmata->parse_command_len = 2;
|
||||
firmata->parse_count = 0;
|
||||
} else if (*p == FIRMATA_START_SYSEX) {
|
||||
firmata->parse_count = 0;
|
||||
firmata->parse_command_len = sizeof(firmata->parse_buff);
|
||||
} else if (*p == FIRMATA_END_SYSEX) {
|
||||
firmata->parse_command_len = firmata->parse_count + 1;
|
||||
} else if (*p & 0x80) {
|
||||
firmata->parse_command_len = 1;
|
||||
firmata->parse_count = 0;
|
||||
}
|
||||
if (firmata->parse_count < (int) sizeof(firmata->parse_buff)) {
|
||||
firmata->parse_buff[firmata->parse_count] = (uint8_t)(*p);
|
||||
firmata->parse_count++;
|
||||
}
|
||||
if (firmata->parse_count == firmata->parse_command_len) {
|
||||
firmata_endParse(firmata);
|
||||
firmata->parse_count = 0;
|
||||
firmata->parse_command_len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
firmata_endParse(t_firmata* firmata)
|
||||
{
|
||||
uint8_t cmd = (firmata->parse_buff[0] & 0xF0);
|
||||
int pin;
|
||||
|
||||
if (cmd == 0xE0 && firmata->parse_count == 3) {
|
||||
int analog_ch = (firmata->parse_buff[0] & 0x0F);
|
||||
int analog_val = firmata->parse_buff[1] | (firmata->parse_buff[2] << 7);
|
||||
for (pin = 0; pin < 128; pin++) {
|
||||
if (firmata->pins[pin].analog_channel == analog_ch) {
|
||||
firmata->pins[pin].value = analog_val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (cmd == 0x90 && firmata->parse_count == 3) {
|
||||
int port_num = (firmata->parse_buff[0] & 0x0F);
|
||||
int port_val = firmata->parse_buff[1] | (firmata->parse_buff[2] << 7);
|
||||
int pin = port_num * 8;
|
||||
int mask;
|
||||
for (mask = 1; mask & 0xFF; mask <<= 1, pin++) {
|
||||
if (firmata->pins[pin].mode == MODE_INPUT) {
|
||||
uint32_t val = (port_val & mask) ? 1 : 0;
|
||||
firmata->pins[pin].value = val;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (firmata->parse_buff[0] == FIRMATA_START_SYSEX &&
|
||||
firmata->parse_buff[firmata->parse_count - 1] == FIRMATA_END_SYSEX) {
|
||||
if (firmata->parse_buff[1] == FIRMATA_REPORT_FIRMWARE) {
|
||||
int len = 0;
|
||||
int i;
|
||||
for (i = 4; i < firmata->parse_count - 2; i += 2) {
|
||||
firmata->firmware[len++] =
|
||||
(firmata->parse_buff[i] & 0x7F) | ((firmata->parse_buff[i + 1] & 0x7F) << 7);
|
||||
}
|
||||
firmata->firmware[len++] = '-';
|
||||
firmata->firmware[len++] = firmata->parse_buff[2] + '0';
|
||||
firmata->firmware[len++] = '.';
|
||||
firmata->firmware[len++] = firmata->parse_buff[3] + '0';
|
||||
firmata->firmware[len++] = 0;
|
||||
printf("Name :: %s\n", firmata->firmware);
|
||||
// query the board's capabilities only after hearing the
|
||||
// REPORT_FIRMWARE message. For boards that reset when
|
||||
// the port open (eg, Arduino with reset=DTR), they are
|
||||
// not ready to communicate for some time, so the only
|
||||
// way to reliably query their capabilities is to wait
|
||||
// until the REPORT_FIRMWARE message is heard.
|
||||
uint8_t buf[80];
|
||||
len = 0;
|
||||
buf[len++] = FIRMATA_START_SYSEX;
|
||||
buf[len++] = FIRMATA_ANALOG_MAPPING_QUERY; // read analog to pin # info
|
||||
buf[len++] = FIRMATA_END_SYSEX;
|
||||
buf[len++] = FIRMATA_START_SYSEX;
|
||||
buf[len++] = FIRMATA_CAPABILITY_QUERY; // read capabilities
|
||||
buf[len++] = FIRMATA_END_SYSEX;
|
||||
for (i = 0; i < 16; i++) {
|
||||
buf[len++] = 0xC0 | i; // report analog
|
||||
buf[len++] = 1;
|
||||
buf[len++] = 0xD0 | i; // report digital
|
||||
buf[len++] = 1;
|
||||
}
|
||||
firmata->isReady = 1;
|
||||
serial_write(firmata->serial, buf, len);
|
||||
} else if (firmata->parse_buff[1] == FIRMATA_CAPABILITY_RESPONSE) {
|
||||
int pin, i, n;
|
||||
for (pin = 0; pin < 128; pin++) {
|
||||
firmata->pins[pin].supported_modes = 0;
|
||||
}
|
||||
for (i = 2, n = 0, pin = 0; i < firmata->parse_count; i++) {
|
||||
if (firmata->parse_buff[i] == 127) {
|
||||
pin++;
|
||||
n = 0;
|
||||
continue;
|
||||
}
|
||||
if (n == 0) {
|
||||
// first byte is supported mode
|
||||
firmata->pins[pin].supported_modes |= (1 << firmata->parse_buff[i]);
|
||||
}
|
||||
n = n ^ 1;
|
||||
}
|
||||
// send a state query for for every pin with any modes
|
||||
for (pin = 0; pin < 128; pin++) {
|
||||
uint8_t buf[512];
|
||||
int len = 0;
|
||||
if (firmata->pins[pin].supported_modes) {
|
||||
buf[len++] = FIRMATA_START_SYSEX;
|
||||
buf[len++] = FIRMATA_PIN_STATE_QUERY;
|
||||
buf[len++] = pin;
|
||||
buf[len++] = FIRMATA_END_SYSEX;
|
||||
}
|
||||
serial_write(firmata->serial, buf, len);
|
||||
}
|
||||
} else if (firmata->parse_buff[1] == FIRMATA_ANALOG_MAPPING_RESPONSE) {
|
||||
int pin = 0;
|
||||
int i;
|
||||
for (i = 2; i < firmata->parse_count - 1; i++) {
|
||||
firmata->pins[pin].analog_channel = firmata->parse_buff[i];
|
||||
pin++;
|
||||
}
|
||||
return;
|
||||
} else if (firmata->parse_buff[1] == FIRMATA_PIN_STATE_RESPONSE && firmata->parse_count >= 6) {
|
||||
int pin = firmata->parse_buff[2];
|
||||
firmata->pins[pin].mode = firmata->parse_buff[3];
|
||||
firmata->pins[pin].value = firmata->parse_buff[4];
|
||||
if (firmata->parse_count > 6)
|
||||
firmata->pins[pin].value |= (firmata->parse_buff[5] << 7);
|
||||
if (firmata->parse_count > 7)
|
||||
firmata->pins[pin].value |= (firmata->parse_buff[6] << 14);
|
||||
} else if (firmata->parse_buff[1] == FIRMATA_I2C_REPLY) {
|
||||
printf("got an i2c reply with count %d!!\n", firmata->parse_count);
|
||||
int addr = (firmata->parse_buff[2] & 0x7f) | ((firmata->parse_buff[3] & 0x7f) << 7);
|
||||
int reg = (firmata->parse_buff[4] & 0x7f) | ((firmata->parse_buff[5] & 0x7f) << 7);
|
||||
int i = 6;
|
||||
int ii = 0;
|
||||
for (ii; ii < (firmata->parse_count - 7) / 2; ii++) {
|
||||
firmata->i2cmsg[addr][reg+ii] = (firmata->parse_buff[i] & 0x7f) | ((firmata->parse_buff[i+1] & 0x7f) << 7);;
|
||||
i = i+2;
|
||||
}
|
||||
printf("i2c reply is %d\n", firmata->i2cmsg[addr][reg]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
firmata_initPins(t_firmata* firmata)
|
||||
{
|
||||
int i;
|
||||
|
||||
firmata->parse_count = 0;
|
||||
firmata->parse_command_len = 0;
|
||||
firmata->isReady = 0;
|
||||
for (i = 0; i < 128; i++) {
|
||||
firmata->pins[i].mode = 255;
|
||||
firmata->pins[i].analog_channel = 127;
|
||||
firmata->pins[i].supported_modes = 0;
|
||||
firmata->pins[i].value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
firmata_askFirmware(t_firmata* firmata)
|
||||
{
|
||||
uint8_t buf[3];
|
||||
int res;
|
||||
|
||||
buf[0] = FIRMATA_START_SYSEX;
|
||||
buf[1] = FIRMATA_REPORT_FIRMWARE; // read firmata name & version
|
||||
buf[2] = FIRMATA_END_SYSEX;
|
||||
res = serial_write(firmata->serial, buf, 3);
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
firmata_pinMode(t_firmata* firmata, int pin, int mode)
|
||||
{
|
||||
int res;
|
||||
uint8_t buff[4];
|
||||
|
||||
firmata->pins[pin].mode = mode;
|
||||
buff[0] = FIRMATA_SET_PIN_MODE;
|
||||
buff[1] = pin;
|
||||
buff[2] = mode;
|
||||
printf("Setting pinMode at: %i with value: %i\n", pin, mode);
|
||||
res = serial_write(firmata->serial, buff, 3);
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
firmata_analogWrite(t_firmata* firmata, int pin, int value)
|
||||
{
|
||||
int res;
|
||||
|
||||
uint8_t buff[3];
|
||||
printf("Writting analogWrite at: %i with value: %i\n", pin, value);
|
||||
buff[0] = 0xE0 | pin;
|
||||
buff[1] = value & 0x7F;
|
||||
buff[2] = (value >> 7) & 0x7F;
|
||||
res = serial_write(firmata->serial, buff, 3);
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
firmata_analogRead(t_firmata *firmata, int pin)
|
||||
{
|
||||
int res;
|
||||
int value = 1;
|
||||
uint8_t buff[2];
|
||||
printf("Writting analogRead at: %i\n", pin);
|
||||
buff[0] = FIRMATA_REPORT_ANALOG | pin;
|
||||
buff[1] = value;
|
||||
printf("192 == %d, pinval == %d, pin %d", buff[0], buff[1], pin);
|
||||
res = serial_write(firmata->serial, buff, 2);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
firmata_digitalWrite(t_firmata* firmata, int pin, int value)
|
||||
{
|
||||
int i;
|
||||
int res;
|
||||
uint8_t buff[4];
|
||||
|
||||
if (pin < 0 || pin > 127)
|
||||
return (0);
|
||||
firmata->pins[pin].value = value;
|
||||
int port_num = pin / 8;
|
||||
int port_val = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
int p = port_num * 8 + i;
|
||||
if (firmata->pins[p].mode == MODE_OUTPUT || firmata->pins[p].mode == MODE_INPUT) {
|
||||
if (firmata->pins[p].value) {
|
||||
port_val |= (1 << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Writting digitalWrite at: %i with value: %i\n", pin, value);
|
||||
buff[0] = FIRMATA_DIGITAL_MESSAGE | port_num;
|
||||
buff[1] = port_val & 0x7F;
|
||||
buff[2] = (port_val >> 7) & 0x7F;
|
||||
res = serial_write(firmata->serial, buff, 3);
|
||||
return (res);
|
||||
}
|
||||
507
src/firmata/firmata_mraa.c
Normal file
507
src/firmata/firmata_mraa.c
Normal file
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
* Author: Brendan Le Foll <brendan.le.foll@intel.com>
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mraa_internal.h"
|
||||
#include "firmata/firmata_mraa.h"
|
||||
#include "firmata/firmata.h"
|
||||
#include "firmata/serial.h"
|
||||
|
||||
static t_firmata* firmata_dev;
|
||||
static pthread_t thread_id;
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_i2c_init_bus_replace(mraa_i2c_context dev)
|
||||
{
|
||||
int delay = 1; // this should be either 1 or 0, I don't know :)
|
||||
uint8_t buff[4];
|
||||
printf("i2c init\n");
|
||||
buff[0] = FIRMATA_START_SYSEX;
|
||||
buff[1] = FIRMATA_I2C_CONFIG;
|
||||
buff[2] = delay & 0xFF, (delay >> 8) & 0xFF;
|
||||
buff[3] = FIRMATA_END_SYSEX;
|
||||
serial_write(firmata_dev->serial, buff, 4);
|
||||
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_i2c_address(mraa_i2c_context dev, uint8_t addr)
|
||||
{
|
||||
// only thing needed and it's already done
|
||||
//dev->addr = (int) addr;
|
||||
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_i2c_frequency(mraa_i2c_context dev, mraa_i2c_mode_t mode)
|
||||
{
|
||||
return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_send_i2c_read_req(mraa_i2c_context dev, int length)
|
||||
{
|
||||
uint8_t* buffer = calloc(7, 0);
|
||||
if (buffer == NULL) {
|
||||
return MRAA_ERROR_NO_RESOURCES;
|
||||
}
|
||||
buffer[0] = FIRMATA_START_SYSEX;
|
||||
buffer[1] = FIRMATA_I2C_REQUEST;
|
||||
buffer[2] = dev->addr;
|
||||
buffer[3] = I2C_MODE_READ << 3;
|
||||
|
||||
// number of bytes
|
||||
buffer[4] = length & 0x7f;
|
||||
buffer[5] = (length >> 7) & 0x7f;
|
||||
buffer[6] = FIRMATA_END_SYSEX;
|
||||
|
||||
if (serial_write(firmata_dev->serial, buffer, 7) != 7) {
|
||||
free(buffer);
|
||||
return MRAA_ERROR_INVALID_RESOURCE;
|
||||
}
|
||||
|
||||
// this needs a lock :)
|
||||
memset(&firmata_dev->i2cmsg[dev->addr][0], -1, sizeof(int)*length);
|
||||
|
||||
free(buffer);
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_send_i2c_read_cont_req(mraa_i2c_context dev, uint8_t command, int length)
|
||||
{
|
||||
uint8_t* buffer = calloc(9, 0);
|
||||
if (buffer == NULL) {
|
||||
return MRAA_ERROR_NO_RESOURCES;
|
||||
}
|
||||
buffer[0] = FIRMATA_START_SYSEX;
|
||||
buffer[1] = FIRMATA_I2C_REQUEST;
|
||||
buffer[2] = dev->addr;
|
||||
buffer[3] = I2C_MODE_READ << 3;
|
||||
|
||||
// register to read from
|
||||
buffer[4] = command & 0x7f;
|
||||
buffer[5] = (command >> 7) & 0x7f;
|
||||
// number of bytes
|
||||
buffer[6] = length & 0x7f;
|
||||
buffer[7] = (length >> 7) & 0x7f;
|
||||
buffer[8] = FIRMATA_END_SYSEX;
|
||||
|
||||
if (serial_write(firmata_dev->serial, buffer, 9) != 9) {
|
||||
free(buffer);
|
||||
return MRAA_ERROR_INVALID_RESOURCE;
|
||||
}
|
||||
|
||||
// this needs a lock :)
|
||||
memset(&firmata_dev->i2cmsg[dev->addr][command], -1, sizeof(int)*length);
|
||||
|
||||
free(buffer);
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
mraa_firmata_i2c_read_byte(mraa_i2c_context dev)
|
||||
{
|
||||
if (mraa_firmata_send_i2c_read_req(dev, 1) == MRAA_SUCCESS) {
|
||||
while (firmata_dev->i2cmsg[dev->addr][0] == -1) {
|
||||
usleep(500);
|
||||
}
|
||||
return firmata_dev->i2cmsg[dev->addr][0];
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
mraa_firmata_i2c_read_word_data(mraa_i2c_context dev, uint8_t command)
|
||||
{
|
||||
if (mraa_firmata_send_i2c_read_cont_req(dev, command, 2) == MRAA_SUCCESS) {
|
||||
while (firmata_dev->i2cmsg[dev->addr][command] == -1) {
|
||||
usleep(500);
|
||||
}
|
||||
|
||||
uint8_t* rawdata[2];
|
||||
rawdata[0] = firmata_dev->i2cmsg[dev->addr][command];
|
||||
rawdata[1] = firmata_dev->i2cmsg[dev->addr][command+1];
|
||||
uint16_t data = (uint16_t) rawdata;
|
||||
uint8_t high = (data & 0xFF00) >> 8;
|
||||
data = (data << 8) & 0xFF00;
|
||||
data |= high;
|
||||
|
||||
return data;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mraa_firmata_i2c_read_bytes_data(mraa_i2c_context dev, uint8_t command, uint8_t* data, int length)
|
||||
{
|
||||
if (mraa_firmata_send_i2c_read_cont_req(dev, command, length) == MRAA_SUCCESS) {
|
||||
while (firmata_dev->i2cmsg[dev->addr][command] == -1) {
|
||||
usleep(500);
|
||||
}
|
||||
|
||||
memcpy(data, &firmata_dev->i2cmsg[dev->addr][command], sizeof(int)*length);
|
||||
return length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mraa_firmata_i2c_read(mraa_i2c_context dev, uint8_t* data, int length)
|
||||
{
|
||||
if (mraa_firmata_send_i2c_read_req(dev, length) == MRAA_SUCCESS) {
|
||||
while (firmata_dev->i2cmsg[dev->addr][0] == -1) {
|
||||
usleep(500);
|
||||
}
|
||||
int i = 0;
|
||||
for (i = 0; i < length; i++) {
|
||||
data[i] = firmata_dev->i2cmsg[dev->addr][i];
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
mraa_firmata_i2c_read_byte_data(mraa_i2c_context dev, uint8_t command)
|
||||
{
|
||||
if (mraa_firmata_send_i2c_read_cont_req(dev, command, 1) == MRAA_SUCCESS) {
|
||||
while (firmata_dev->i2cmsg[dev->addr][command] == -1) {
|
||||
usleep(500);
|
||||
}
|
||||
|
||||
return firmata_dev->i2cmsg[dev->addr][command];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_i2c_write(mraa_i2c_context dev, const uint8_t* data, int bytesToWrite)
|
||||
{
|
||||
// buffer needs 5 bytes for firmata, and 2 bytes for every byte of data
|
||||
int buffer_size = (bytesToWrite*2) + 5;
|
||||
uint8_t* buffer = calloc(buffer_size, 0);
|
||||
int i = 0;
|
||||
int ii = 4;
|
||||
buffer[0] = FIRMATA_START_SYSEX;
|
||||
buffer[1] = FIRMATA_I2C_REQUEST;
|
||||
buffer[2] = dev->addr;
|
||||
buffer[3] = I2C_MODE_WRITE << 3;
|
||||
// we need to write until FIRMATA_END_SYSEX
|
||||
for (i; i < (buffer_size-1); i++) {
|
||||
buffer[ii] = data[i] & 0x7F;
|
||||
buffer[ii+1] = (data[i] >> 7) & 0x7f;
|
||||
ii = ii+2;
|
||||
}
|
||||
buffer[buffer_size-1] = FIRMATA_END_SYSEX;
|
||||
serial_write(firmata_dev->serial, buffer, buffer_size);
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_i2c_write_byte(mraa_i2c_context dev, uint8_t data)
|
||||
{
|
||||
uint8_t* buffer = calloc(7, 0);
|
||||
buffer[0] = FIRMATA_START_SYSEX;
|
||||
buffer[1] = FIRMATA_I2C_REQUEST;
|
||||
buffer[2] = dev->addr;
|
||||
buffer[3] = I2C_MODE_WRITE << 3;
|
||||
buffer[4] = data & 0x7F;
|
||||
buffer[5] = (data >> 7) & 0x7F;
|
||||
buffer[6] = FIRMATA_END_SYSEX;
|
||||
serial_write(firmata_dev->serial, buffer, 7);
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_i2c_write_byte_data(mraa_i2c_context dev, const uint8_t data, const uint8_t command)
|
||||
{
|
||||
uint8_t* buffer = calloc(9, 0);
|
||||
buffer[0] = FIRMATA_START_SYSEX;
|
||||
buffer[1] = FIRMATA_I2C_REQUEST;
|
||||
buffer[2] = dev->addr;
|
||||
buffer[3] = I2C_MODE_WRITE << 3;
|
||||
buffer[4] = command & 0x7F;
|
||||
buffer[5] = (command >> 7) & 0x7F;
|
||||
buffer[6] = data & 0x7F;
|
||||
buffer[7] = (data >> 7) & 0x7F;
|
||||
buffer[8] = FIRMATA_END_SYSEX;
|
||||
serial_write(firmata_dev->serial, buffer, 9);
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_i2c_write_word_data(mraa_i2c_context dev, const uint16_t data, const uint8_t command)
|
||||
{
|
||||
return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_i2c_stop(mraa_i2c_context dev)
|
||||
{
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
mraa_firmata_aio_read(mraa_aio_context dev)
|
||||
{
|
||||
// careful, whilst you need to enable '0' for A0 you then need to read 14
|
||||
// in t_firmata because well that makes sense doesn't it...
|
||||
return (unsigned int) firmata_dev->pins[dev->channel].value;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_aio_init_internal_replace(mraa_aio_context dev, int aio)
|
||||
{
|
||||
// firmata considers A0 pin0 as well as actual pin0 :/
|
||||
firmata_pinMode(firmata_dev, aio, MODE_ANALOG);
|
||||
// register for updates on that ADC channel
|
||||
firmata_analogRead(firmata_dev, aio);
|
||||
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_gpio_init_internal_replace(mraa_gpio_context dev, int pin)
|
||||
{
|
||||
dev->pin = pin;
|
||||
dev->phy_pin = pin;
|
||||
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_gpio_mode_replace(mraa_gpio_context dev, mraa_gpio_mode_t mode)
|
||||
{
|
||||
return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
static int
|
||||
mraa_firmata_gpio_read_replace(mraa_gpio_context dev)
|
||||
{
|
||||
return firmata_dev->pins[dev->pin].value;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_gpio_write_replace(mraa_gpio_context dev, int write_value)
|
||||
{
|
||||
if (write_value == 0) {
|
||||
firmata_digitalWrite(firmata_dev, dev->phy_pin, LOW);
|
||||
} else {
|
||||
firmata_digitalWrite(firmata_dev, dev->phy_pin, HIGH);
|
||||
}
|
||||
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static mraa_result_t
|
||||
mraa_firmata_gpio_dir_replace(mraa_gpio_context dev, mraa_gpio_dir_t dir)
|
||||
{
|
||||
switch (dir) {
|
||||
case MRAA_GPIO_IN:
|
||||
firmata_pinMode(firmata_dev, dev->phy_pin, MODE_INPUT);
|
||||
break;
|
||||
case MRAA_GPIO_OUT:
|
||||
firmata_pinMode(firmata_dev, dev->phy_pin, MODE_OUTPUT);
|
||||
break;
|
||||
case MRAA_GPIO_OUT_LOW:
|
||||
firmata_pinMode(firmata_dev, dev->phy_pin, MODE_OUTPUT);
|
||||
firmata_digitalWrite(firmata_dev, dev->phy_pin, LOW);
|
||||
break;
|
||||
case MRAA_GPIO_OUT_HIGH:
|
||||
firmata_pinMode(firmata_dev, dev->phy_pin, MODE_OUTPUT);
|
||||
firmata_digitalWrite(firmata_dev, dev->phy_pin, HIGH);
|
||||
break;
|
||||
default:
|
||||
return MRAA_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
mraa_firmata_pull_handler(void)
|
||||
{
|
||||
while(1) {
|
||||
firmata_pull(firmata_dev);
|
||||
usleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
mraa_board_t*
|
||||
mraa_firmata_init(const char* uart_dev)
|
||||
{
|
||||
mraa_board_t* b = (mraa_board_t*) calloc(1, sizeof(mraa_board_t));
|
||||
if (b == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
firmata_dev = firmata_new(uart_dev);
|
||||
|
||||
// if this isn't working then we have an issue with our uart
|
||||
while (!firmata_dev->isReady) {
|
||||
firmata_pull(firmata_dev);
|
||||
}
|
||||
|
||||
pthread_create(&thread_id, NULL, mraa_firmata_pull_handler, NULL);
|
||||
|
||||
b->platform_name = "firmata";
|
||||
// do we support 2.5? Or are we more 2.3?
|
||||
// or should we return the flashed sketch name?
|
||||
b->platform_version = firmata_dev->firmware;
|
||||
b->gpio_count = 14;
|
||||
b->aio_count = 6;
|
||||
b->adc_supported = 10;
|
||||
b->phy_pin_count = 20;
|
||||
b->i2c_bus_count = 1;
|
||||
b->def_i2c_bus = 0;
|
||||
b->i2c_bus[0].bus_id = 0;
|
||||
|
||||
b->pins = (mraa_pininfo_t*) calloc(b->phy_pin_count, sizeof(mraa_pininfo_t));
|
||||
if (b->pins == NULL) {
|
||||
free(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(b->pins[0].name, "IO0", 8);
|
||||
b->pins[0].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[0].gpio.pinmap = 0;
|
||||
strncpy(b->pins[1].name, "IO1", 8);
|
||||
b->pins[1].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[1].gpio.pinmap = 1;
|
||||
strncpy(b->pins[2].name, "IO2", 8);
|
||||
b->pins[2].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[2].gpio.pinmap = 2;
|
||||
strncpy(b->pins[3].name, "IO3", 8);
|
||||
b->pins[3].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[3].gpio.pinmap = 3;
|
||||
strncpy(b->pins[4].name, "IO4", 8);
|
||||
b->pins[4].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[4].gpio.pinmap = 4;
|
||||
strncpy(b->pins[5].name, "IO5", 8);
|
||||
b->pins[5].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[5].gpio.pinmap = 5;
|
||||
strncpy(b->pins[6].name, "IO6", 8);
|
||||
b->pins[6].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[6].gpio.pinmap = 6;
|
||||
strncpy(b->pins[7].name, "IO7", 8);
|
||||
b->pins[7].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[7].gpio.pinmap = 7;
|
||||
strncpy(b->pins[8].name, "IO8", 8);
|
||||
b->pins[8].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[8].gpio.pinmap = 8;
|
||||
strncpy(b->pins[9].name, "IO9", 8);
|
||||
b->pins[9].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[9].gpio.pinmap = 9;
|
||||
strncpy(b->pins[10].name, "IO10", 8);
|
||||
b->pins[10].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[10].gpio.pinmap = 10;
|
||||
strncpy(b->pins[11].name, "IO11", 8);
|
||||
b->pins[11].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[11].gpio.pinmap = 11;
|
||||
strncpy(b->pins[12].name, "IO12", 8);
|
||||
b->pins[12].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[12].gpio.pinmap = 12;
|
||||
strncpy(b->pins[13].name, "IO13", 8);
|
||||
b->pins[13].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 };
|
||||
b->pins[13].gpio.pinmap = 13;
|
||||
strncpy(b->pins[10].name, "A0", 8);
|
||||
b->pins[14].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 1, 0 };
|
||||
b->pins[14].gpio.pinmap = 14;
|
||||
b->pins[14].aio.pinmap = 14;
|
||||
strncpy(b->pins[11].name, "A1", 8);
|
||||
b->pins[15].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 1, 0 };
|
||||
b->pins[15].gpio.pinmap = 15;
|
||||
b->pins[15].aio.pinmap = 15;
|
||||
strncpy(b->pins[12].name, "A2", 8);
|
||||
b->pins[16].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 1, 0 };
|
||||
b->pins[16].gpio.pinmap = 16;
|
||||
b->pins[16].aio.pinmap = 16;
|
||||
strncpy(b->pins[13].name, "A3", 8);
|
||||
b->pins[17].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 1, 0 };
|
||||
b->pins[17].gpio.pinmap = 17;
|
||||
b->pins[17].aio.pinmap = 17;
|
||||
strncpy(b->pins[13].name, "A4", 8);
|
||||
b->pins[18].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 1, 0 };
|
||||
b->pins[18].gpio.pinmap = 18;
|
||||
b->pins[18].aio.pinmap = 18;
|
||||
strncpy(b->pins[13].name, "A5", 8);
|
||||
b->pins[19].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 1, 0 };
|
||||
b->pins[19].gpio.pinmap = 19;
|
||||
b->pins[19].aio.pinmap = 19;
|
||||
|
||||
b->adv_func = (mraa_adv_func_t*) calloc(1, sizeof(mraa_adv_func_t));
|
||||
if (b->adv_func == NULL) {
|
||||
free(b->pins);
|
||||
free(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b->adv_func->gpio_init_internal_replace = &mraa_firmata_gpio_init_internal_replace;
|
||||
b->adv_func->gpio_mode_replace = &mraa_firmata_gpio_mode_replace;
|
||||
b->adv_func->gpio_dir_replace = &mraa_firmata_gpio_dir_replace;
|
||||
b->adv_func->gpio_read_replace = &mraa_firmata_gpio_read_replace;
|
||||
b->adv_func->gpio_write_replace = &mraa_firmata_gpio_write_replace;
|
||||
|
||||
b->adv_func->aio_init_internal_replace = &mraa_firmata_aio_init_internal_replace;
|
||||
b->adv_func->aio_read_replace = &mraa_firmata_aio_read;
|
||||
|
||||
b->adv_func->i2c_init_bus_replace = &mraa_firmata_i2c_init_bus_replace;
|
||||
b->adv_func->i2c_set_frequency_replace = &mraa_firmata_i2c_frequency;
|
||||
b->adv_func->i2c_address_replace = &mraa_firmata_i2c_address;
|
||||
b->adv_func->i2c_read_replace = &mraa_firmata_i2c_read;
|
||||
b->adv_func->i2c_read_byte_replace = &mraa_firmata_i2c_read_byte;
|
||||
b->adv_func->i2c_read_byte_data_replace = &mraa_firmata_i2c_read_byte_data;
|
||||
b->adv_func->i2c_read_word_data_replace = &mraa_firmata_i2c_read_word_data;
|
||||
b->adv_func->i2c_read_bytes_data_replace = &mraa_firmata_i2c_read_bytes_data;
|
||||
b->adv_func->i2c_write_replace = &mraa_firmata_i2c_write;
|
||||
b->adv_func->i2c_write_byte_replace = &mraa_firmata_i2c_write_byte;
|
||||
b->adv_func->i2c_write_byte_data_replace = &mraa_firmata_i2c_write_byte_data;
|
||||
b->adv_func->i2c_write_word_data_replace = &mraa_firmata_i2c_write_word_data;
|
||||
b->adv_func->i2c_stop_replace = &mraa_firmata_i2c_stop;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
mraa_platform_t
|
||||
mraa_firmata_platform(mraa_board_t* board, const char* uart_dev)
|
||||
{
|
||||
/**
|
||||
* Firmata boards are not something we can detect so we just trust the user
|
||||
* to initialise them themselves and is the only platform type not to be
|
||||
* initialised from mraa_init(). Good luck!
|
||||
*/
|
||||
mraa_board_t* sub_plat = NULL;
|
||||
|
||||
sub_plat = mraa_firmata_init(uart_dev);
|
||||
if (sub_plat != NULL) {
|
||||
sub_plat->platform_type = MRAA_GENERIC_FIRMATA;
|
||||
board->sub_platform = sub_plat;
|
||||
return sub_plat->platform_type;
|
||||
}
|
||||
|
||||
return MRAA_NULL_PLATFORM;
|
||||
}
|
||||
340
src/firmata/serial.c
Normal file
340
src/firmata/serial.c
Normal file
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2015 Jules Dourlens (jdourlens@gmail.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "firmata/serial.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/select.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/serial.h>
|
||||
|
||||
t_serial*
|
||||
serial_new()
|
||||
{
|
||||
t_serial* res;
|
||||
|
||||
res = malloc(sizeof(t_serial));
|
||||
if (!res) {
|
||||
return (NULL);
|
||||
}
|
||||
res->port_is_open = 0;
|
||||
res->baud_rate = 57600;
|
||||
res->tx = 0;
|
||||
res->rx = 0;
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
serial_open(t_serial* serial, const char* name)
|
||||
{
|
||||
struct serial_struct kernel_serial_settings;
|
||||
int bits;
|
||||
|
||||
serial->port_fd = open(name, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
if (serial->port_fd < 0) {
|
||||
if (errno == EACCES) {
|
||||
perror("Unable to access, insufficient permission");
|
||||
} else if (errno == EISDIR) {
|
||||
perror("Unable to open, Object is a directory, not a serial port");
|
||||
} else if (errno == ENODEV || errno == ENXIO) {
|
||||
perror("Unable to open, Serial port hardware not installed");
|
||||
} else if (errno == ENOENT) {
|
||||
perror("Unable to open, Device name does not exist");
|
||||
} else {
|
||||
perror("Unable to open: Unknown error.");
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
memset(&(serial->settings), 0, sizeof(struct termios));
|
||||
#if 0
|
||||
if (ioctl(serial->port_fd, TIOCMGET, &bits) < 0) {
|
||||
close(serial->port_fd);
|
||||
perror("Unable to query serial port signals");
|
||||
return (-1);
|
||||
}
|
||||
bits &= ~(TIOCM_DTR | TIOCM_RTS);
|
||||
if (ioctl(serial->port_fd, TIOCMSET, &bits) < 0) {
|
||||
close(serial->port_fd);
|
||||
perror("Unable to control serial port signals");
|
||||
return (-1);
|
||||
}
|
||||
if (tcgetattr(serial->port_fd, &(serial->settings_orig)) != 0) {
|
||||
close(serial->port_fd);
|
||||
perror("Unable to query serial port settings (perhaps not a serial port)");
|
||||
return (-1);
|
||||
}
|
||||
memset(&(serial->settings), 0, sizeof(struct termios));
|
||||
serial->settings.c_iflag = IGNBRK | IGNPAR;
|
||||
serial->settings.c_cflag = CS8 | CREAD | HUPCL | CLOCAL;
|
||||
serial_setBaud(serial, serial->baud_rate);
|
||||
if (ioctl(serial->port_fd, TIOCGSERIAL, &kernel_serial_settings) == 0) {
|
||||
kernel_serial_settings.flags |= ASYNC_LOW_LATENCY;
|
||||
ioctl(serial->port_fd, TIOCSSERIAL, &kernel_serial_settings);
|
||||
}
|
||||
tcflush(serial->port_fd, TCIFLUSH);
|
||||
#endif
|
||||
serial->port_name = name;
|
||||
serial->port_is_open = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
serial_setBaud(t_serial* serial, int baud)
|
||||
{
|
||||
speed_t spd;
|
||||
switch (baud) {
|
||||
case 230400:
|
||||
spd = B230400;
|
||||
break;
|
||||
case 115200:
|
||||
spd = B115200;
|
||||
break;
|
||||
case 57600:
|
||||
spd = B57600;
|
||||
break;
|
||||
case 38400:
|
||||
spd = B38400;
|
||||
break;
|
||||
case 19200:
|
||||
spd = B19200;
|
||||
break;
|
||||
case 9600:
|
||||
spd = B9600;
|
||||
break;
|
||||
case 4800:
|
||||
spd = B4800;
|
||||
break;
|
||||
case 2400:
|
||||
spd = B2400;
|
||||
break;
|
||||
case 1800:
|
||||
spd = B1800;
|
||||
break;
|
||||
case 1200:
|
||||
spd = B1200;
|
||||
break;
|
||||
case 600:
|
||||
spd = B600;
|
||||
break;
|
||||
case 300:
|
||||
spd = B300;
|
||||
break;
|
||||
case 200:
|
||||
spd = B200;
|
||||
break;
|
||||
case 150:
|
||||
spd = B150;
|
||||
break;
|
||||
case 134:
|
||||
spd = B134;
|
||||
break;
|
||||
case 110:
|
||||
spd = B110;
|
||||
break;
|
||||
case 75:
|
||||
spd = B75;
|
||||
break;
|
||||
case 50:
|
||||
spd = B50;
|
||||
break;
|
||||
#ifdef B460800
|
||||
case 460800:
|
||||
spd = B460800;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B500000
|
||||
case 500000:
|
||||
spd = B500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B576000
|
||||
case 576000:
|
||||
spd = B576000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B921600
|
||||
case 921600:
|
||||
spd = B921600;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B1000000
|
||||
case 1000000:
|
||||
spd = B1000000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B1152000
|
||||
case 1152000:
|
||||
spd = B1152000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B1500000
|
||||
case 1500000:
|
||||
spd = B1500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B2000000
|
||||
case 2000000:
|
||||
spd = B2000000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B2500000
|
||||
case 2500000:
|
||||
spd = B2500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B3000000
|
||||
case 3000000:
|
||||
spd = B3000000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B3500000
|
||||
case 3500000:
|
||||
spd = B3500000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B4000000
|
||||
case 4000000:
|
||||
spd = B4000000;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B7200
|
||||
case 7200:
|
||||
spd = B7200;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B14400
|
||||
case 14400:
|
||||
spd = B14400;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B28800
|
||||
case 28800:
|
||||
spd = B28800;
|
||||
break;
|
||||
#endif
|
||||
#ifdef B76800
|
||||
case 76800:
|
||||
spd = B76800;
|
||||
break;
|
||||
#endif
|
||||
default: {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
cfsetospeed(&(serial->settings), spd);
|
||||
cfsetispeed(&(serial->settings), spd);
|
||||
if (tcsetattr(serial->port_fd, TCSANOW, &(serial->settings)) < 0)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
serial_read(t_serial* serial, void* ptr, int count)
|
||||
{
|
||||
int n, bits;
|
||||
|
||||
if (!serial->port_is_open)
|
||||
return (-1);
|
||||
if (count <= 0)
|
||||
return (0);
|
||||
n = read(serial->port_fd, ptr, count);
|
||||
if (n < 0 && (errno == EAGAIN || errno == EINTR))
|
||||
return (0);
|
||||
if (n == 0 && ioctl(serial->port_fd, TIOCMGET, &bits) < 0)
|
||||
return (-99);
|
||||
serial->rx += n;
|
||||
return (n);
|
||||
}
|
||||
|
||||
int
|
||||
serial_write(t_serial* serial, void* ptr, int len)
|
||||
{
|
||||
//printf("Write %d\n", len);
|
||||
write(serial->port_fd, (const char *)ptr, len);
|
||||
return (len);
|
||||
}
|
||||
|
||||
int
|
||||
serial_waitInput(t_serial* serial, int msec)
|
||||
{
|
||||
if (!serial->port_is_open)
|
||||
return -1;
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = msec / 1000;
|
||||
tv.tv_usec = (msec % 1000) * 1000;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(serial->port_fd, &rfds);
|
||||
return (select(serial->port_fd + 1, &rfds, NULL, NULL, &tv));
|
||||
}
|
||||
|
||||
int
|
||||
serial_discardInput(t_serial* serial)
|
||||
{
|
||||
if (!serial->port_is_open)
|
||||
return;
|
||||
// does this really work properly (and is it thread safe) on Linux??
|
||||
tcflush(serial->port_fd, TCIFLUSH);
|
||||
}
|
||||
|
||||
void
|
||||
serial_flushOutput(t_serial* serial)
|
||||
{
|
||||
if (!serial->port_is_open)
|
||||
return;
|
||||
tcdrain(serial->port_fd);
|
||||
}
|
||||
|
||||
int
|
||||
serial_setControl(t_serial* serial, int dtr, int rts)
|
||||
{
|
||||
if (!serial->port_is_open)
|
||||
return -1;
|
||||
int bits;
|
||||
if (ioctl(serial->port_fd, TIOCMGET, &bits) < 0)
|
||||
return -1;
|
||||
if (dtr == 1) {
|
||||
bits |= TIOCM_DTR;
|
||||
} else if (dtr == 0) {
|
||||
bits &= ~TIOCM_DTR;
|
||||
}
|
||||
if (rts == 1) {
|
||||
bits |= TIOCM_RTS;
|
||||
} else if (rts == 0) {
|
||||
bits &= ~TIOCM_RTS;
|
||||
}
|
||||
if (ioctl(serial->port_fd, TIOCMSET, &bits) < 0)
|
||||
return -1;
|
||||
;
|
||||
return (0);
|
||||
}
|
||||
55
src/firmata/servo.c
Normal file
55
src/firmata/servo.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2015 Jules Dourlens (jdourlens@gmail.com)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "firmata/servo.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
t_servo*
|
||||
servo_attach(t_firmata* firmata, int pin)
|
||||
{
|
||||
t_servo* res;
|
||||
|
||||
if (!firmata || !firmata->isReady) {
|
||||
perror("servo_new::Firmata is not ready");
|
||||
return (NULL);
|
||||
}
|
||||
res = malloc(sizeof(t_servo));
|
||||
if (!res) {
|
||||
perror("servo_new::malloc failed");
|
||||
return (NULL);
|
||||
}
|
||||
res->firmata = firmata;
|
||||
res->pin = pin;
|
||||
firmata_pinMode(res->firmata, pin, MODE_SERVO);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
servo_write(t_servo* servo, int value)
|
||||
{
|
||||
return (firmata_analogWrite(servo->firmata, servo->pin, value));
|
||||
}
|
||||
20
src/mraa.c
20
src/mraa.c
@@ -42,6 +42,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mraa_internal.h"
|
||||
#include "firmata/firmata_mraa.h"
|
||||
#include "gpio.h"
|
||||
#include "version.h"
|
||||
|
||||
@@ -141,6 +142,10 @@ mraa_init()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FIRMATA)
|
||||
// look for USB id 8087:0aba -> genuino/arduino 101
|
||||
#endif
|
||||
|
||||
// Look for IIO devices
|
||||
mraa_iio_detect();
|
||||
|
||||
@@ -941,3 +946,18 @@ mraa_get_iio_device_count()
|
||||
{
|
||||
return plat_iio->iio_device_count;
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
mraa_add_subplatform(mraa_platform_t subplatformtype, const char* uart_dev)
|
||||
{
|
||||
#ifdef FIRMATA
|
||||
if (subplatformtype == MRAA_GENERIC_FIRMATA) {
|
||||
if (mraa_firmata_platform(plat, uart_dev) == MRAA_GENERIC_FIRMATA) {
|
||||
syslog(LOG_NOTICE, "mraa: Added firmata subplatform");
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return MRAA_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user