Private
Public Access
2
0

firmata: Convert mraa FirmataC implementation to work over Uart instead of serial implementation

Signed-off-by: Shiran Ben-Melech <shiran.ben-melech@intel.com>
Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
This commit is contained in:
Shiran Ben-Melech
2016-03-01 15:17:22 +02:00
committed by Brendan Le Foll
parent 4b76fbd14c
commit 04f7cbff5d
6 changed files with 42 additions and 425 deletions

View File

@@ -24,7 +24,7 @@
#pragma once
#include "serial.h"
#include "uart.h"
#define MODE_INPUT 0x00
#define MODE_OUTPUT 0x01
@@ -89,7 +89,7 @@ typedef struct s_pin {
} t_pin;
typedef struct s_firmata {
t_serial* serial;
mraa_uart_context uart;
t_pin pins[128];
int i2cmsg[256][256];
int parse_command_len;

View File

@@ -1,51 +0,0 @@
/*
* 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);

View File

@@ -3,7 +3,6 @@ if (FIRMATA)
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
)

View File

@@ -22,7 +22,6 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "firmata/serial.h"
#include "firmata/firmata.h"
#include <string.h>
@@ -33,6 +32,7 @@ t_firmata*
firmata_new(const char* name)
{
t_firmata* res;
mraa_result_t uart_res = MRAA_ERROR_UNSPECIFIED;
printf("Opening device at: %s\n", name);
res = malloc(sizeof(t_firmata));
@@ -41,14 +41,20 @@ firmata_new(const char* name)
return (NULL);
}
memset(res, 0, sizeof(*res));
res->serial = serial_new();
if (!res->serial) {
perror("firmata_new::Failed malloc");
return (NULL);
res->uart = mraa_uart_init_raw(name);
if (res->uart == NULL) {
fprintf(stderr, "UART failed to setup\n");
return EXIT_FAILURE;
}
serial_open(res->serial, name);
firmata_initPins(res);
serial_setBaud(res->serial, 57600);
uart_res = mraa_uart_set_baudrate(res->uart, 57600);
if (uart_res != MRAA_SUCCESS) {
mraa_result_print(uart_res);
}
firmata_askFirmware(res);
printf("Device opened at: %s\n", name);
return (res);
@@ -60,9 +66,9 @@ firmata_pull(t_firmata* firmata)
uint8_t buff[FIRMATA_MSG_LEN];
int r;
r = serial_waitInput(firmata->serial, 40);
r = mraa_uart_data_available(firmata->uart, 40);
if (r > 0) {
r = serial_read(firmata->serial, buff, sizeof(buff));
r = mraa_uart_read(firmata->uart, buff, sizeof(buff));
if (r < 0) {
return (0);
}
@@ -178,7 +184,7 @@ firmata_endParse(t_firmata* firmata)
buf[len++] = 1;
}
firmata->isReady = 1;
serial_write(firmata->serial, buf, len);
mraa_uart_write(firmata->uart, buf, len);
} else if (firmata->parse_buff[1] == FIRMATA_CAPABILITY_RESPONSE) {
int pin, i, n;
for (pin = 0; pin < 128; pin++) {
@@ -206,7 +212,7 @@ firmata_endParse(t_firmata* firmata)
buf[len++] = pin;
buf[len++] = FIRMATA_END_SYSEX;
}
serial_write(firmata->serial, buf, len);
mraa_uart_write(firmata->uart, buf, len);
}
} else if (firmata->parse_buff[1] == FIRMATA_ANALOG_MAPPING_RESPONSE) {
int pin = 0;
@@ -228,12 +234,12 @@ firmata_endParse(t_firmata* firmata)
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;
}
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;
@@ -265,7 +271,7 @@ firmata_askFirmware(t_firmata* firmata)
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);
res = mraa_uart_write(firmata->uart, buf, 3);
return (res);
}
@@ -280,7 +286,7 @@ firmata_pinMode(t_firmata* firmata, int pin, int 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);
res = mraa_uart_write(firmata->uart, buff, 3);
return (res);
}
@@ -294,7 +300,7 @@ firmata_analogWrite(t_firmata* firmata, int pin, int value)
buff[0] = 0xE0 | pin;
buff[1] = value & 0x7F;
buff[2] = (value >> 7) & 0x7F;
res = serial_write(firmata->serial, buff, 3);
res = mraa_uart_write(firmata->uart, buff, 3);
return (res);
}
@@ -308,7 +314,7 @@ firmata_analogRead(t_firmata *firmata, int 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);
res = mraa_uart_write(firmata->uart, buff, 2);
return res;
}
@@ -336,6 +342,6 @@ firmata_digitalWrite(t_firmata* firmata, int pin, int 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);
res = mraa_uart_write(firmata->uart, buff, 3);
return (res);
}

View File

@@ -28,7 +28,6 @@
#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;
@@ -43,7 +42,7 @@ mraa_firmata_i2c_init_bus_replace(mraa_i2c_context dev)
buff[1] = FIRMATA_I2C_CONFIG;
buff[2] = delay & 0xFF, (delay >> 8) & 0xFF;
buff[3] = FIRMATA_END_SYSEX;
serial_write(firmata_dev->serial, buff, 4);
mraa_uart_write(firmata_dev->uart, buff, 4);
return MRAA_SUCCESS;
}
@@ -80,9 +79,11 @@ mraa_firmata_send_i2c_read_req(mraa_i2c_context dev, int length)
buffer[5] = (length >> 7) & 0x7f;
buffer[6] = FIRMATA_END_SYSEX;
if (serial_write(firmata_dev->serial, buffer, 7) != 7) {
mraa_result_t res = mraa_uart_write(firmata_dev->uart, buffer, 7);
if (res != MRAA_SUCCESS) {
free(buffer);
return MRAA_ERROR_INVALID_RESOURCE;
mraa_result_print(res);
return res;
}
// this needs a lock :)
@@ -112,9 +113,11 @@ mraa_firmata_send_i2c_read_cont_req(mraa_i2c_context dev, uint8_t command, int l
buffer[7] = (length >> 7) & 0x7f;
buffer[8] = FIRMATA_END_SYSEX;
if (serial_write(firmata_dev->serial, buffer, 9) != 9) {
mraa_result_t res = mraa_uart_write(firmata_dev->uart, buffer, 9);
if (res != MRAA_SUCCESS) {
free(buffer);
return MRAA_ERROR_INVALID_RESOURCE;
mraa_result_print(res);
return res;
}
// this needs a lock :)
@@ -218,7 +221,7 @@ mraa_firmata_i2c_write(mraa_i2c_context dev, const uint8_t* data, int bytesToWri
ii = ii+2;
}
buffer[buffer_size-1] = FIRMATA_END_SYSEX;
serial_write(firmata_dev->serial, buffer, buffer_size);
mraa_uart_write(firmata_dev->uart, buffer, buffer_size);
return MRAA_SUCCESS;
}
@@ -233,7 +236,7 @@ mraa_firmata_i2c_write_byte(mraa_i2c_context dev, uint8_t data)
buffer[4] = data & 0x7F;
buffer[5] = (data >> 7) & 0x7F;
buffer[6] = FIRMATA_END_SYSEX;
serial_write(firmata_dev->serial, buffer, 7);
mraa_uart_write(firmata_dev->uart, buffer, 7);
return MRAA_SUCCESS;
}
@@ -250,7 +253,7 @@ mraa_firmata_i2c_write_byte_data(mraa_i2c_context dev, const uint8_t data, const
buffer[6] = data & 0x7F;
buffer[7] = (data >> 7) & 0x7F;
buffer[8] = FIRMATA_END_SYSEX;
serial_write(firmata_dev->serial, buffer, 9);
mraa_uart_write(firmata_dev->uart, buffer, 9);
return MRAA_SUCCESS;
}

View File

@@ -1,340 +0,0 @@
/*
* 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);
}