#include "ScexUartReader.h" #include // Contains file controls like O_RDWR #include #include #include #include #include #include // write(), read(), close() #include // Error integer and strerror() function #include #include "OBSWConfig.h" ScexUartReader::ScexUartReader(object_id_t objectId) : SystemObject(objectId), ringBuffer(200 * 2048, true), sizesQueue(200) { semaphore = SemaphoreFactory::instance()->createBinarySemaphore(); semaphore->acquire(); lock = MutexFactory::instance()->createMutex(); } // void ScexUartRead::start() { /* semaphore->give(); */ } ReturnValue_t ScexUartReader::performOperation(uint8_t operationCode) { lock->lockMutex(); state = States::IDLE; lock->unlockMutex(); while (true) { semaphore->acquire(); std::cout << "task was started" << std::endl; int bytesRead = 0; do { bytesRead = read(serialPort, reinterpret_cast(recBuf.data()), static_cast(recBuf.size())); if (bytesRead == 0) { MutexGuard mg(lock); States currentState = state; if (currentState == States::FINISH) { state = States::IDLE; break; } } else if (bytesRead < 0) { sif::warning << "ScexUartReader::performOperation: read call failed with error [" << errno << ", " << strerror(errno) << "]" << std::endl; break; } else if (bytesRead >= static_cast(recBuf.size())) { sif::error << "ScexUartReader::performOperation: Receive buffer too small" << std::endl; } else if (bytesRead > 0) { MutexGuard mg(lock); sizesQueue.insert(bytesRead); ReturnValue_t result = ringBuffer.writeData(recBuf.data(), bytesRead); if (result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "ScexUartReader::performOperation: Writing into ring buffer failed" << std::endl; } if (debugMode) { sif::info << "Received " << bytesRead << " bytes from the Solar Cell Experiment:" << std::endl; arrayprinter::print(recBuf.data(), bytesRead, OutputType::HEX, false); } break; } } while (bytesRead > 0); // task block comes here std::cout << "done" << std::endl; } return RETURN_OK; } ReturnValue_t ScexUartReader::initializeInterface(CookieIF *cookie) { UartCookie *uartCookie = dynamic_cast(cookie); if (uartCookie) { return RETURN_FAILED; } std::string devname = uartCookie->getDeviceFile(); /* Get file descriptor */ serialPort = open(devname.c_str(), O_RDWR); if (serialPort < 0) { sif::warning << "open call failed with error [" << errno << ", " << strerror(errno) << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } // Setting up UART parameters tty.c_cflag &= ~PARENB; // Clear parity bit tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication tty.c_cflag &= ~CSIZE; // Clear all the size bits tty.c_cflag |= CS8; // 8 bits per byte tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1) // Use non-canonical mode and clear echo flag tty.c_lflag &= ~(ICANON | ECHO); // Non-blocking mode, read until either line is 0.1 second idle or maximum of 255 bytes are // received in one go tty.c_cc[VTIME] = 20; // Read for up to 2 seconds tty.c_cc[VMIN] = 0; // Read as much as there is available // Q7S UART Lite has fixed baud rate. For other linux systems, set baud rate here. #if !defined(XIPHOS_Q7S) if (cfsetispeed(&tty, B57600) != 0) { sif::warning << "ScexUartReader::initializeInterface: Setting baud rate failed" << std::endl; } #endif if (tcsetattr(serialPort, TCSANOW, &tty) != 0) { sif::warning << "tcsetattr call failed with error [" << errno << ", " << strerror(errno) << std::endl; } // Flush received and unread data tcflush(serialPort, TCIFLUSH); return RETURN_OK; } ReturnValue_t ScexUartReader::sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) { lock->lockMutex(); if (state == States::NOT_READY or state == States::RUNNING) { lock->unlockMutex(); return HasReturnvaluesIF::RETURN_FAILED; } state = States::RUNNING; lock->unlockMutex(); size_t encodedLen = 0; ReturnValue_t result = dleEncoder.encode(sendData, sendLen, cmdbuf.data(), cmdbuf.size(), &encodedLen, true); if (result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "UartTestClass::scexInit: Encoding failed" << std::endl; return RETURN_FAILED; } size_t bytesWritten = write(serialPort, cmdbuf.data(), encodedLen); if (bytesWritten != encodedLen) { sif::warning << "Sending ping command to solar experiment failed" << std::endl; return RETURN_FAILED; } result = semaphore->release(); if (result != HasReturnvaluesIF::RETURN_OK) { std::cout << "ScexUartReader::sendMessag: Releasing semaphore failed" << std::endl; } return RETURN_OK; } ReturnValue_t ScexUartReader::getSendSuccess(CookieIF *cookie) { return RETURN_OK; } ReturnValue_t ScexUartReader::requestReceiveMessage(CookieIF *cookie, size_t requestLen) { return RETURN_OK; } void ScexUartReader::setDebugMode(bool enable) { this->debugMode = enable; } ReturnValue_t ScexUartReader::finish() { MutexGuard mg(lock); if (state == States::IDLE) { return HasReturnvaluesIF::RETURN_FAILED; } state = States::FINISH; return RETURN_OK; } ReturnValue_t ScexUartReader::readReceivedMessage(CookieIF *cookie, uint8_t **buffer, size_t *size) { MutexGuard mg(lock); if (sizesQueue.empty()) { *size = 0; return RETURN_OK; } *size = sizesQueue.pop(); *buffer = ipcBuffer.data(); ReturnValue_t result = ringBuffer.readData(ipcBuffer.data(), *size, true); if (result != RETURN_OK) { sif::warning << "ScexUartReader::readReceivedMessage: Reading RingBuffer failed" << std::endl; } return RETURN_OK; }