208 lines
7.2 KiB
C++
208 lines
7.2 KiB
C++
/*
|
|
* ArduinoComIF.cpp
|
|
*
|
|
* Created on: 02/06/2021
|
|
* Author: Marco Modè
|
|
*
|
|
*/
|
|
|
|
#include <mission/DeviceHandler/ArduinoComIF.h>
|
|
#include <mission/DeviceHandler/ArduinoCookie.h>
|
|
|
|
#include <fsfw/serialize/SerializeAdapter.h>
|
|
//#include <fsfw/serviceinterface/ServiceInterface.h>
|
|
#include <fsfw/tmtcservices/CommandingServiceBase.h>
|
|
#include <fsfw/tmtcpacket/pus/TmPacketStored.h>
|
|
|
|
// C library headers
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <vector>
|
|
|
|
// Linux headers
|
|
#include <fcntl.h> // Contains file controls like O_RDWR
|
|
#include <errno.h> // Error integer and strerror() function
|
|
#include <termios.h> // Contains POSIX terminal control definitions
|
|
#include <unistd.h> // write(), read(), close()
|
|
|
|
#include <algorithm>
|
|
#include <cstdint>
|
|
|
|
ArduinoComIF::ArduinoComIF(object_id_t objectId) :
|
|
SystemObject(objectId) {
|
|
}
|
|
|
|
ArduinoComIF::~ArduinoComIF() {
|
|
}
|
|
|
|
ReturnValue_t ArduinoComIF::initializeInterface(CookieIF *cookie) {
|
|
ArduinoCookie *Cookie = dynamic_cast<ArduinoCookie*>(cookie);
|
|
|
|
// The Arduino device which manage the sensors of temperature,
|
|
// environmental data and acceleration, sends through serial
|
|
// output these data employing a USB port.
|
|
// Here it is then set-up the interface to manage this communication.
|
|
//
|
|
// In typical UNIX style, serial ports are represented by files
|
|
// within the operating system.
|
|
// These files usually pop-up in /dev/, and begin with the name tty*.
|
|
//
|
|
// To write/read to a serial port, you write/read to the file.
|
|
// Here the serial port parameters are defined exploiting a
|
|
// special tty configuration struct.
|
|
|
|
// Open the serial port. Change device path as needed.
|
|
int serial_port = open("/dev/ttyACM0", O_RDWR);
|
|
|
|
// Create new termios struc, we call it 'tty' for convention.
|
|
struct termios tty;
|
|
|
|
// Read in existing settings, and handle any error.
|
|
if (tcgetattr(serial_port, &tty) != 0) {
|
|
printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
|
|
return 1;
|
|
}
|
|
|
|
// Set-up of the configuration serial port.
|
|
tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
|
|
tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
|
|
tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size
|
|
tty.c_cflag |= CS8; // 8 bits per byte (most common)
|
|
tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
|
|
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)
|
|
|
|
tty.c_lflag &= ~ICANON;
|
|
tty.c_lflag &= ~ECHO; // Disable echo
|
|
tty.c_lflag &= ~ECHOE; // Disable erasure
|
|
tty.c_lflag &= ~ECHONL; // Disable new-line echo
|
|
tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
|
|
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
|
|
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); // Disable any special handling of received bytes
|
|
|
|
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
|
|
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
|
|
|
|
tty.c_cc[VTIME] = 16; // Wait for up to 16 ds (Arduino measurement cycle time), returning as soon as any data is received.
|
|
tty.c_cc[VMIN] = 255; // limit number of bytes which can be read in one time by Linux serial port
|
|
|
|
// Set in/out baud rate to be 115200 bps (same of Arduino)
|
|
cfsetispeed(&tty, B115200);
|
|
cfsetospeed(&tty, B115200);
|
|
|
|
// Save tty settings, also checking for error.
|
|
if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
|
|
printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
|
|
return 1;
|
|
}
|
|
|
|
printf("\nSerial port set. \n");
|
|
|
|
// End of Linux serial port set-up.
|
|
|
|
Cookie->Serial_port_number = serial_port;
|
|
|
|
return RETURN_OK;
|
|
}
|
|
|
|
ReturnValue_t ArduinoComIF::sendMessage(CookieIF *cookie,
|
|
const uint8_t *sendData, size_t sendLen) {
|
|
return RETURN_OK;
|
|
}
|
|
|
|
ReturnValue_t ArduinoComIF::getSendSuccess(CookieIF *cookie) {
|
|
return RETURN_OK;
|
|
}
|
|
|
|
ReturnValue_t ArduinoComIF::requestReceiveMessage(CookieIF *cookie,
|
|
size_t requestLen) {
|
|
return RETURN_OK;
|
|
}
|
|
|
|
ReturnValue_t ArduinoComIF::readReceivedMessage(CookieIF *cookie,
|
|
uint8_t **buffer, size_t *size) {
|
|
ArduinoCookie *Cookie = dynamic_cast<ArduinoCookie*>(cookie);
|
|
|
|
// The buffer array to store the data read are initialized.
|
|
// The whole data packet to be read is 2034 bytes, but
|
|
// the limit for one reading (VMAX) is 255 bytes.
|
|
// Therefore the reading is divided in 8 separate stages
|
|
// which employ 8 different buffer array.
|
|
// At the end these 8 arrays are concatenated in
|
|
// the main buffer array read_buf.
|
|
|
|
uint8_t read_buf[2034]; // 2034 bytes from SPC serial output
|
|
uint8_t read_buf1[255]; // 255 bytes
|
|
uint8_t read_buf2[255]; // 255 bytes
|
|
uint8_t read_buf3[255]; // 255 bytes
|
|
uint8_t read_buf4[255]; // 255 bytes
|
|
uint8_t read_buf5[255]; // 255 bytes
|
|
uint8_t read_buf6[255]; // 255 bytes
|
|
uint8_t read_buf7[255]; // 255 bytes
|
|
uint8_t read_buf8[249]; // 249 bytes
|
|
|
|
// The buffer elements are initially set to 0 so we can call printf() easily.
|
|
memset(&read_buf, '\0', sizeof(read_buf));
|
|
memset(&read_buf1, '\0', sizeof(read_buf));
|
|
memset(&read_buf2, '\0', sizeof(read_buf));
|
|
memset(&read_buf3, '\0', sizeof(read_buf));
|
|
memset(&read_buf4, '\0', sizeof(read_buf));
|
|
memset(&read_buf5, '\0', sizeof(read_buf));
|
|
memset(&read_buf6, '\0', sizeof(read_buf));
|
|
memset(&read_buf7, '\0', sizeof(read_buf));
|
|
memset(&read_buf8, '\0', sizeof(read_buf));
|
|
|
|
// Read bytes. The behaviour of read() (e.g. does it block?, how long does it block for?)
|
|
// depends on the configuration settings above, specifically VMIN and VTIME.
|
|
|
|
int num_bytes1 = read(Cookie->Serial_port_number, &read_buf1,
|
|
sizeof(read_buf1));
|
|
int num_bytes2 = read(Cookie->Serial_port_number, &read_buf2,
|
|
sizeof(read_buf2));
|
|
int num_bytes3 = read(Cookie->Serial_port_number, &read_buf3,
|
|
sizeof(read_buf3));
|
|
int num_bytes4 = read(Cookie->Serial_port_number, &read_buf4,
|
|
sizeof(read_buf4));
|
|
int num_bytes5 = read(Cookie->Serial_port_number, &read_buf5,
|
|
sizeof(read_buf5));
|
|
int num_bytes6 = read(Cookie->Serial_port_number, &read_buf6,
|
|
sizeof(read_buf6));
|
|
int num_bytes7 = read(Cookie->Serial_port_number, &read_buf7,
|
|
sizeof(read_buf7));
|
|
int num_bytes8 = read(Cookie->Serial_port_number, &read_buf8,
|
|
sizeof(read_buf8));
|
|
int num_bytes = num_bytes1 + num_bytes2 + num_bytes3 + num_bytes4
|
|
+ num_bytes5 + num_bytes6 + num_bytes7 + num_bytes8;
|
|
|
|
// The 8 buffer arrays are here concatenated in one single vector.
|
|
std::copy(read_buf1, read_buf1 + 255, read_buf);
|
|
std::copy(read_buf2, read_buf2 + 255, read_buf + 255);
|
|
std::copy(read_buf3, read_buf3 + 255, read_buf + 2 * 255);
|
|
std::copy(read_buf4, read_buf4 + 255, read_buf + 3 * 255);
|
|
std::copy(read_buf5, read_buf5 + 255, read_buf + 4 * 255);
|
|
std::copy(read_buf6, read_buf6 + 255, read_buf + 5 * 255);
|
|
std::copy(read_buf7, read_buf7 + 255, read_buf + 6 * 255);
|
|
std::copy(read_buf8, read_buf8 + 249, read_buf + 7 * 255);
|
|
|
|
// num_bytes is the number of bytes read (n=0: no bytes received, n=-1: error).
|
|
if (num_bytes < 0) {
|
|
printf("Error reading: %s", strerror(errno));
|
|
return 1;
|
|
}
|
|
|
|
printf("Read %i bytes.\n", num_bytes);
|
|
|
|
// Definition of buffer array and buffer size to return after reading.
|
|
|
|
*size = 2034;
|
|
|
|
/*uint8_t *buf_ptr;
|
|
buf_ptr = read_buf;
|
|
buffer = &buf_ptr;*/
|
|
*buffer = read_buf;
|
|
|
|
close(Cookie->Serial_port_number);
|
|
return RETURN_OK;
|
|
|
|
}
|
|
|