From dcd2dd87ce8034a46e4150a89dc69f6ba1a22d8d Mon Sep 17 00:00:00 2001 From: Edvin Date: Thu, 10 Apr 2025 11:35:25 +0200 Subject: Implemented code for Slamtec rplidar C1 --- LIDAR/sdk/src/arch/win32/arch_win32.h | 66 +++ LIDAR/sdk/src/arch/win32/net_serial.cpp | 367 +++++++++++++ LIDAR/sdk/src/arch/win32/net_serial.h | 86 +++ LIDAR/sdk/src/arch/win32/net_socket.cpp | 945 ++++++++++++++++++++++++++++++++ LIDAR/sdk/src/arch/win32/timer.cpp | 72 +++ LIDAR/sdk/src/arch/win32/timer.h | 49 ++ LIDAR/sdk/src/arch/win32/winthread.hpp | 144 +++++ 7 files changed, 1729 insertions(+) create mode 100644 LIDAR/sdk/src/arch/win32/arch_win32.h create mode 100644 LIDAR/sdk/src/arch/win32/net_serial.cpp create mode 100644 LIDAR/sdk/src/arch/win32/net_serial.h create mode 100644 LIDAR/sdk/src/arch/win32/net_socket.cpp create mode 100644 LIDAR/sdk/src/arch/win32/timer.cpp create mode 100644 LIDAR/sdk/src/arch/win32/timer.h create mode 100644 LIDAR/sdk/src/arch/win32/winthread.hpp (limited to 'LIDAR/sdk/src/arch/win32') diff --git a/LIDAR/sdk/src/arch/win32/arch_win32.h b/LIDAR/sdk/src/arch/win32/arch_win32.h new file mode 100644 index 0000000..3ae6655 --- /dev/null +++ b/LIDAR/sdk/src/arch/win32/arch_win32.h @@ -0,0 +1,66 @@ +/* + * RPLIDAR SDK + * + * Copyright (c) 2009 - 2014 RoboPeak Team + * http://www.robopeak.com + * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd. + * http://www.slamtec.com + * + */ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#pragma warning (disable: 4996) +#define _CRT_SECURE_NO_WARNINGS + +#ifndef WINVER +#define WINVER 0x0500 +#endif + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif + + +#ifndef _WIN32_IE +#define _WIN32_IE 0x0501 +#endif + +#ifndef _RICHEDIT_VER +#define _RICHEDIT_VER 0x0200 +#endif + + +#include +#include +#include +#include //for memcpy etc.. +#include +#include + + +#include "timer.h" diff --git a/LIDAR/sdk/src/arch/win32/net_serial.cpp b/LIDAR/sdk/src/arch/win32/net_serial.cpp new file mode 100644 index 0000000..f1fe025 --- /dev/null +++ b/LIDAR/sdk/src/arch/win32/net_serial.cpp @@ -0,0 +1,367 @@ +/* + * RPLIDAR SDK + * + * Copyright (c) 2009 - 2014 RoboPeak Team + * http://www.robopeak.com + * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd. + * http://www.slamtec.com + * + */ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdkcommon.h" +#include "net_serial.h" + +namespace rp{ namespace arch{ namespace net{ + +raw_serial::raw_serial() + : rp::hal::serial_rxtx() + , _serial_handle(NULL) + , _baudrate(0) + , _flags(0) +{ + _init(); +} + +raw_serial::~raw_serial() +{ + close(); + + CloseHandle(_ro.hEvent); + CloseHandle(_wo.hEvent); + CloseHandle(_wait_o.hEvent); +} + +bool raw_serial::open() +{ + return open(_portName, _baudrate, _flags); +} + +bool raw_serial::bind(const char * portname, _u32 baudrate, _u32 flags) +{ + strncpy(_portName, portname, sizeof(_portName)); + _baudrate = baudrate; + _flags = flags; + return true; +} + +bool raw_serial::open(const char * portname, _u32 baudrate, _u32 flags) +{ +#ifdef _UNICODE + wchar_t wportname[1024]; + mbstowcs(wportname, portname, sizeof(wportname) / sizeof(wchar_t)); +#endif + + if (isOpened()) close(); + + _serial_handle = CreateFile( +#ifdef _UNICODE + wportname, +#else + portname, +#endif + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL + ); + + if (_serial_handle == INVALID_HANDLE_VALUE) return false; + + if (!SetupComm(_serial_handle, SERIAL_RX_BUFFER_SIZE, SERIAL_TX_BUFFER_SIZE)) + { + close(); + return false; + } + + _dcb.BaudRate = baudrate; + _dcb.ByteSize = 8; + _dcb.Parity = NOPARITY; + _dcb.StopBits = ONESTOPBIT; + _dcb.fDtrControl = DTR_CONTROL_ENABLE; + + if (!SetCommState(_serial_handle, &_dcb)) + { + close(); + return false; + } + + if (!SetCommTimeouts(_serial_handle, &_co)) + { + close(); + return false; + } + + if (!SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR )) + { + close(); + return false; + } + + if (!PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR )) + { + close(); + return false; + } + + Sleep(30); + _is_serial_opened = true; + + //Clear the DTR bit set DTR=high + clearDTR(); + + return true; +} + +void raw_serial::close() +{ + SetCommMask(_serial_handle, 0); + ResetEvent(_wait_o.hEvent); + + CloseHandle(_serial_handle); + _serial_handle = INVALID_HANDLE_VALUE; + + _is_serial_opened = false; +} + +int raw_serial::senddata(const unsigned char * data, size_t size) +{ + DWORD error; + DWORD w_len = 0, o_len = -1; + if (!isOpened()) return ANS_DEV_ERR; + + if (data == NULL || size ==0) return 0; + + if(ClearCommError(_serial_handle, &error, NULL) && error > 0) + PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_TXCLEAR); + + if(!WriteFile(_serial_handle, data, (DWORD)size, &w_len, &_wo)) + if(GetLastError() != ERROR_IO_PENDING) + w_len = ANS_DEV_ERR; + + return w_len; +} + +int raw_serial::recvdata(unsigned char * data, size_t size) +{ + if (!isOpened()) return 0; + DWORD r_len = 0; + + + if(!ReadFile(_serial_handle, data, (DWORD)size, &r_len, &_ro)) + { + if(GetLastError() == ERROR_IO_PENDING) + { + if(!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE)) + { + if(GetLastError() != ERROR_IO_INCOMPLETE) + r_len = 0; + } + } + else + r_len = 0; + } + + return r_len; +} + +void raw_serial::flush( _u32 flags) +{ + PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); +} + +int raw_serial::waitforsent(_u32 timeout, size_t * returned_size) +{ + if (!isOpened() ) return ANS_DEV_ERR; + DWORD w_len = 0; + _word_size_t ans =0; + + if (WaitForSingleObject(_wo.hEvent, timeout) == WAIT_TIMEOUT) + { + ans = ANS_TIMEOUT; + goto _final; + } + if(!GetOverlappedResult(_serial_handle, &_wo, &w_len, FALSE)) + { + ans = ANS_DEV_ERR; + } +_final: + if (returned_size) *returned_size = w_len; + return (int)ans; +} + +int raw_serial::waitforrecv(_u32 timeout, size_t * returned_size) +{ + if (!isOpened() ) return -1; + DWORD r_len = 0; + _word_size_t ans =0; + + if (WaitForSingleObject(_ro.hEvent, timeout) == WAIT_TIMEOUT) + { + ans = ANS_TIMEOUT; + } + if(!GetOverlappedResult(_serial_handle, &_ro, &r_len, FALSE)) + { + ans = ANS_DEV_ERR; + } + if (returned_size) *returned_size = r_len; + return (int)ans; +} + +int raw_serial::waitfordata(size_t data_count, _u32 timeout, size_t * returned_size) +{ + COMSTAT stat; + DWORD error; + DWORD msk,length; + size_t dummy_length; + + if (returned_size==NULL) returned_size=(size_t *)&dummy_length; + + + if ( isOpened()) { + size_t rxqueue_remaining = rxqueue_count(); + if (rxqueue_remaining >= data_count) { + *returned_size = rxqueue_remaining; + return 0; + } + } + + while ( isOpened() ) + { + msk = 0; + SetCommMask(_serial_handle, EV_RXCHAR | EV_ERR ); + if(!WaitCommEvent(_serial_handle, &msk, &_wait_o)) + { + if(GetLastError() == ERROR_IO_PENDING) + { + if (WaitForSingleObject(_wait_o.hEvent, timeout) == WAIT_TIMEOUT) + { + *returned_size =0; + return ANS_TIMEOUT; + } + + GetOverlappedResult(_serial_handle, &_wait_o, &length, TRUE); + + ::ResetEvent(_wait_o.hEvent); + }else + { + ClearCommError(_serial_handle, &error, &stat); + *returned_size = stat.cbInQue; + return ANS_DEV_ERR; + } + } + + if(msk & EV_ERR){ + // FIXME: may cause problem here + ClearCommError(_serial_handle, &error, &stat); + } + + if(msk & EV_RXCHAR){ + ClearCommError(_serial_handle, &error, &stat); + if(stat.cbInQue >= data_count) + { + *returned_size = stat.cbInQue; + return 0; + } + } + } + *returned_size=0; + return ANS_DEV_ERR; +} + +size_t raw_serial::rxqueue_count() +{ + if ( !isOpened() ) return 0; + COMSTAT com_stat; + DWORD error; + DWORD r_len = 0; + + if(ClearCommError(_serial_handle, &error, &com_stat) && error > 0) + { + PurgeComm(_serial_handle, PURGE_RXABORT | PURGE_RXCLEAR); + return 0; + } + return com_stat.cbInQue; +} + +void raw_serial::setDTR() +{ + if ( !isOpened() ) return; + + EscapeCommFunction(_serial_handle, SETDTR); +} + +void raw_serial::clearDTR() +{ + if ( !isOpened() ) return; + + EscapeCommFunction(_serial_handle, CLRDTR); +} + + +void raw_serial::_init() +{ + memset(&_dcb, 0, sizeof(_dcb)); + _dcb.DCBlength = sizeof(_dcb); + _serial_handle = INVALID_HANDLE_VALUE; + memset(&_co, 0, sizeof(_co)); + _co.ReadIntervalTimeout = 0; + _co.ReadTotalTimeoutMultiplier = 0; + _co.ReadTotalTimeoutConstant = 0; + _co.WriteTotalTimeoutMultiplier = 0; + _co.WriteTotalTimeoutConstant = 0; + + memset(&_ro, 0, sizeof(_ro)); + memset(&_wo, 0, sizeof(_wo)); + memset(&_wait_o, 0, sizeof(_wait_o)); + + _ro.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + _wo.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + _wait_o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + _portName[0] = 0; +} + +}}} //end rp::arch::net + + +//begin rp::hal +namespace rp{ namespace hal{ + +serial_rxtx * serial_rxtx::CreateRxTx() +{ + return new rp::arch::net::raw_serial(); +} + +void serial_rxtx::ReleaseRxTx( serial_rxtx * rxtx) +{ + delete rxtx; +} + + +}} //end rp::hal diff --git a/LIDAR/sdk/src/arch/win32/net_serial.h b/LIDAR/sdk/src/arch/win32/net_serial.h new file mode 100644 index 0000000..d43137e --- /dev/null +++ b/LIDAR/sdk/src/arch/win32/net_serial.h @@ -0,0 +1,86 @@ +/* + * RPLIDAR SDK + * + * Copyright (c) 2009 - 2014 RoboPeak Team + * http://www.robopeak.com + * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd. + * http://www.slamtec.com + * + */ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "hal/abs_rxtx.h" + +namespace rp{ namespace arch{ namespace net{ + +class raw_serial : public rp::hal::serial_rxtx +{ +public: + enum{ + SERIAL_RX_BUFFER_SIZE = 512, + SERIAL_TX_BUFFER_SIZE = 128, + SERIAL_RX_TIMEOUT = 2000, + SERIAL_TX_TIMEOUT = 2000, + }; + + raw_serial(); + virtual ~raw_serial(); + virtual bool bind(const char * portname, _u32 baudrate, _u32 flags = 0); + virtual bool open(); + virtual void close(); + virtual void flush( _u32 flags); + + virtual int waitfordata(size_t data_count,_u32 timeout = -1, size_t * returned_size = NULL); + + virtual int senddata(const unsigned char * data, size_t size); + virtual int recvdata(unsigned char * data, size_t size); + + virtual int waitforsent(_u32 timeout = -1, size_t * returned_size = NULL); + virtual int waitforrecv(_u32 timeout = -1, size_t * returned_size = NULL); + + virtual size_t rxqueue_count(); + + virtual void setDTR(); + virtual void clearDTR(); + +protected: + bool open(const char * portname, _u32 baudrate, _u32 flags); + void _init(); + + char _portName[20]; + uint32_t _baudrate; + uint32_t _flags; + + OVERLAPPED _ro, _wo; + OVERLAPPED _wait_o; + volatile HANDLE _serial_handle; + DCB _dcb; + COMMTIMEOUTS _co; +}; + +}}} diff --git a/LIDAR/sdk/src/arch/win32/net_socket.cpp b/LIDAR/sdk/src/arch/win32/net_socket.cpp new file mode 100644 index 0000000..611c9d1 --- /dev/null +++ b/LIDAR/sdk/src/arch/win32/net_socket.cpp @@ -0,0 +1,945 @@ +/* + * RoboPeak Project + * HAL Layer - Socket Interface + * Copyright 2009 - 2013 RoboPeak Project + * + * Win32 Implementation + */ + +#define _WINSOCKAPI_ + +#include "sdkcommon.h" +#include "..\..\hal\socket.h" +#include +#include +#include + +#include +#include +#pragma comment (lib, "Ws2_32.lib") + +namespace rp{ namespace net { + +static volatile bool _isWSAStartupCalled = false; + +static inline bool _checkWSAStartup() { + int iResult; + WSADATA wsaData; + if (!_isWSAStartupCalled) { + iResult = WSAStartup(MAKEWORD(2,2), &wsaData); + if (iResult != 0) { + return false; + } + _isWSAStartupCalled = true; + } + return true; +} + +static const char* _inet_ntop(int af, const void* src, char* dst, int cnt){ + + struct sockaddr_storage srcaddr; + + + memset(dst, 0, cnt); + + memset(&srcaddr, 0, sizeof(struct sockaddr_storage)); + + + srcaddr.ss_family = af; + + switch (af) { + case AF_INET: + { + struct sockaddr_in * ipv4 = reinterpret_cast< struct sockaddr_in *>(&srcaddr); + memcpy(&(ipv4->sin_addr), src, sizeof(ipv4->sin_addr)); + } + break; + case AF_INET6: + { + struct sockaddr_in6 * ipv6 = reinterpret_cast< struct sockaddr_in6 *>(&srcaddr); + memcpy(&(ipv6->sin6_addr), src, sizeof(ipv6->sin6_addr)); + } + break; + } + + if (WSAAddressToStringA((struct sockaddr*) &srcaddr, sizeof(struct sockaddr_storage), 0, dst, (LPDWORD) &cnt) != 0) { + DWORD rv = WSAGetLastError(); + return NULL; + } + return dst; +} + +static int _inet_pton(int Family, const char * pszAddrString, void* pAddrBuf) +{ + struct sockaddr_storage tmpholder; + int actualSize = sizeof(sockaddr_storage); + + int result = WSAStringToAddressA((char *)pszAddrString, Family, NULL, (sockaddr*)&tmpholder, &actualSize); + if (result) return -1; + + switch (Family) { + case AF_INET: + { + struct sockaddr_in * ipv4 = reinterpret_cast< struct sockaddr_in *>(&tmpholder); + memcpy(pAddrBuf, &(ipv4->sin_addr), sizeof(ipv4->sin_addr)); + } + break; + case AF_INET6: + { + struct sockaddr_in6 * ipv6 = reinterpret_cast< struct sockaddr_in6 *>(&tmpholder); + memcpy(pAddrBuf, &(ipv6->sin6_addr), sizeof(ipv6->sin6_addr)); + } + break; + } + return 1; +} + +static inline int _halAddrTypeToOSType(SocketAddress::address_type_t type) +{ + switch (type) { + case SocketAddress::ADDRESS_TYPE_INET: + return AF_INET; + case SocketAddress::ADDRESS_TYPE_INET6: + return AF_INET6; + case SocketAddress::ADDRESS_TYPE_UNSPEC: + return AF_UNSPEC; + + default: + assert(!"should not reach here"); + return AF_UNSPEC; + } +} + + +SocketAddress::SocketAddress() +{ + _checkWSAStartup(); + _platform_data = reinterpret_cast(new sockaddr_storage); + memset(_platform_data, 0, sizeof(sockaddr_storage)); + + reinterpret_cast(_platform_data)->ss_family = AF_INET; +} + +SocketAddress::SocketAddress(const SocketAddress & src) +{ + _platform_data = reinterpret_cast(new sockaddr_storage); + memcpy(_platform_data, src._platform_data, sizeof(sockaddr_storage)); +} + + + +SocketAddress::SocketAddress(const char * addrString, int port, SocketAddress::address_type_t type) +{ + _checkWSAStartup(); + _platform_data = reinterpret_cast(new sockaddr_storage); + memset(_platform_data, 0, sizeof(sockaddr_storage)); + + // default to ipv4 in case the following operation fails + reinterpret_cast(_platform_data)->ss_family = AF_INET; + + setAddressFromString(addrString, type); + setPort(port); +} + +SocketAddress::SocketAddress(void * platform_data) + : _platform_data(platform_data) +{ _checkWSAStartup(); } + +SocketAddress & SocketAddress::operator = (const SocketAddress &src) +{ + memcpy(_platform_data, src._platform_data, sizeof(sockaddr_storage)); + return *this; +} + + +SocketAddress::~SocketAddress() +{ + delete reinterpret_cast(_platform_data); +} + +SocketAddress::address_type_t SocketAddress::getAddressType() const +{ + switch(reinterpret_cast(_platform_data)->ss_family) { + case AF_INET: + return ADDRESS_TYPE_INET; + case AF_INET6: + return ADDRESS_TYPE_INET6; + default: + assert(!"should not reach here"); + return ADDRESS_TYPE_INET; + } +} + +int SocketAddress::getPort() const +{ + switch (getAddressType()) { + case ADDRESS_TYPE_INET: + return (int)ntohs(reinterpret_cast(_platform_data)->sin_port); + case ADDRESS_TYPE_INET6: + return (int)ntohs(reinterpret_cast(_platform_data)->sin6_port); + default: + return 0; + } +} + +u_result SocketAddress::setPort(int port) +{ + switch (getAddressType()) { + case ADDRESS_TYPE_INET: + reinterpret_cast(_platform_data)->sin_port = htons((short)port); + break; + case ADDRESS_TYPE_INET6: + reinterpret_cast(_platform_data)->sin6_port = htons((short)port); + break; + default: + return RESULT_OPERATION_FAIL; + } + return RESULT_OK; +} + +u_result SocketAddress::setAddressFromString(const char * address_string, SocketAddress::address_type_t type) +{ + int ans = 0; + int prevPort = getPort(); + switch (type) { + case ADDRESS_TYPE_INET: + reinterpret_cast(_platform_data)->ss_family = AF_INET; + ans = _inet_pton(AF_INET, + address_string, + &reinterpret_cast(_platform_data)->sin_addr); + break; + + + case ADDRESS_TYPE_INET6: + + reinterpret_cast(_platform_data)->ss_family = AF_INET6; + ans = _inet_pton(AF_INET6, + address_string, + &reinterpret_cast(_platform_data)->sin6_addr); + break; + + default: + return RESULT_INVALID_DATA; + + } + setPort(prevPort); + + return ans<=0?RESULT_INVALID_DATA:RESULT_OK; +} + + +u_result SocketAddress::getAddressAsString(char * buffer, size_t buffersize) const +{ + int net_family = reinterpret_cast(_platform_data)->ss_family; + const char *ans = NULL; + switch (net_family) { + case AF_INET: + ans = _inet_ntop(net_family, &reinterpret_cast(_platform_data)->sin_addr, + buffer, (int)buffersize); + break; + + case AF_INET6: + ans = _inet_ntop(net_family, &reinterpret_cast(_platform_data)->sin6_addr, + buffer, (int)buffersize); + + break; + } + return (ans==NULL)?RESULT_OPERATION_FAIL:RESULT_OK; +} + + + +size_t SocketAddress::LoopUpHostName(const char * hostname, const char * sevicename, std::vector &addresspool , bool performDNS, SocketAddress::address_type_t type) +{ + struct addrinfo hints; + struct addrinfo *result; + int ans; + _checkWSAStartup(); + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = _halAddrTypeToOSType(type); + hints.ai_flags = AI_PASSIVE; + + if (!performDNS) { + hints.ai_family |= AI_NUMERICSERV | AI_NUMERICHOST; + + } + + ans = getaddrinfo(hostname, sevicename, &hints, &result); + + addresspool.clear(); + + if (ans != 0) { + // hostname loopup failed + return 0; + } + + + for (struct addrinfo * cursor = result; cursor != NULL; cursor = cursor->ai_next) { + if (cursor->ai_family == ADDRESS_TYPE_INET || cursor->ai_family == ADDRESS_TYPE_INET6) { + sockaddr_storage * storagebuffer = new sockaddr_storage; + assert(sizeof(sockaddr_storage) >= cursor->ai_addrlen); + memcpy(storagebuffer, cursor->ai_addr, cursor->ai_addrlen); + addresspool.push_back(SocketAddress(storagebuffer)); + } + } + + + freeaddrinfo(result); + + return addresspool.size(); +} + + +u_result SocketAddress::getRawAddress(_u8 * buffer, size_t bufferSize) const +{ + switch (getAddressType()) { + case ADDRESS_TYPE_INET: + if (bufferSize < sizeof(reinterpret_cast(_platform_data)->sin_addr.s_addr)) return RESULT_INSUFFICIENT_MEMORY; + + memcpy(buffer, &reinterpret_cast(_platform_data)->sin_addr.s_addr, sizeof(reinterpret_cast(_platform_data)->sin_addr.s_addr)); + + + break; + case ADDRESS_TYPE_INET6: + if (bufferSize < sizeof(reinterpret_cast(_platform_data)->sin6_addr.s6_addr)) return RESULT_INSUFFICIENT_MEMORY; + memcpy(buffer, reinterpret_cast(_platform_data)->sin6_addr.s6_addr, sizeof(reinterpret_cast(_platform_data)->sin6_addr.s6_addr)); + + break; + default: + return RESULT_OPERATION_FAIL; + } + return RESULT_OK; +} + + +void SocketAddress::setLoopbackAddress(SocketAddress::address_type_t type) +{ + + int prevPort = getPort(); + switch (type) { + case ADDRESS_TYPE_INET: + { + sockaddr_in * addrv4 = reinterpret_cast(_platform_data); + addrv4->sin_family = AF_INET; + addrv4->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } + break; + case ADDRESS_TYPE_INET6: + { + sockaddr_in6 * addrv6 = reinterpret_cast(_platform_data); + addrv6->sin6_family = AF_INET6; + addrv6->sin6_addr = in6addr_loopback; + + } + break; + default: + return; + } + + setPort(prevPort); +} + +void SocketAddress::setBroadcastAddressIPv4() +{ + + int prevPort = getPort(); + sockaddr_in * addrv4 = reinterpret_cast(_platform_data); + addrv4->sin_family = AF_INET; + addrv4->sin_addr.s_addr = htonl(INADDR_BROADCAST); + setPort(prevPort); + +} + +void SocketAddress::setAnyAddress(SocketAddress::address_type_t type) +{ + int prevPort = getPort(); + switch (type) { + case ADDRESS_TYPE_INET: + { + sockaddr_in * addrv4 = reinterpret_cast(_platform_data); + addrv4->sin_family = AF_INET; + addrv4->sin_addr.s_addr = htonl(INADDR_ANY); + } + break; + case ADDRESS_TYPE_INET6: + { + sockaddr_in6 * addrv6 = reinterpret_cast(_platform_data); + addrv6->sin6_family = AF_INET6; + addrv6->sin6_addr = in6addr_any; + + } + break; + default: + return; + } + + setPort(prevPort); + + +} + + +}} + + + +///-------------------------------- + + +namespace rp { namespace arch { namespace net{ + +using namespace rp::net; + +class _single_thread StreamSocketImpl : public StreamSocket +{ +public: + + StreamSocketImpl(SOCKET fd) + : _socket_fd(fd) + { + assert(fd>=0); + int bool_true = 1; + ::setsockopt( _socket_fd, SOL_SOCKET, SO_REUSEADDR , (char *)&bool_true, (int)sizeof(bool_true) ); + + enableNoDelay(true); + this->setTimeout(DEFAULT_SOCKET_TIMEOUT, SOCKET_DIR_BOTH); + } + + virtual ~StreamSocketImpl() + { + closesocket(_socket_fd); + } + + virtual void dispose() + { + delete this; + } + + + virtual u_result bind(const SocketAddress & localaddr) + { + const struct sockaddr * addr = reinterpret_cast(localaddr.getPlatformData()); + assert(addr); + int ans = ::bind(_socket_fd, addr, (int)sizeof(sockaddr_storage)); + if (ans) { + return RESULT_OPERATION_FAIL; + } else { + return RESULT_OK; + } + } + + virtual u_result getLocalAddress(SocketAddress & localaddr) + { + struct sockaddr * addr = reinterpret_cast( const_cast(localaddr.getPlatformData())); //donnot do this at home... + assert(addr); + + int actualsize = sizeof(sockaddr_storage); + int ans = ::getsockname(_socket_fd, addr, &actualsize); + + assert(actualsize <= sizeof(sockaddr_storage)); + assert(addr->sa_family == AF_INET || addr->sa_family == AF_INET6); + + return ans?RESULT_OPERATION_FAIL:RESULT_OK; + } + + virtual u_result setTimeout(_u32 timeout, socket_direction_mask msk) + { + int ans; + timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + if (msk & SOCKET_DIR_RD) { + ans = ::setsockopt( _socket_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, (int)sizeof(tv) ); + if (ans) return RESULT_OPERATION_FAIL; + } + + if (msk & SOCKET_DIR_WR) { + ans = ::setsockopt( _socket_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, (int)sizeof(tv) ); + if (ans) return RESULT_OPERATION_FAIL; + } + + return RESULT_OK; + } + + virtual u_result connect(const SocketAddress & pairAddress) + { + u_long mode_block = 0; + u_long mode_notBlock = 1; + + //set to non block mode + if (SOCKET_ERROR == ioctlsocket(_socket_fd, (long)FIONBIO, &mode_notBlock)) + { + return RESULT_OPERATION_FAIL; + } + + struct timeval tm; + tm.tv_sec = 2; + tm.tv_usec = 0; + int ret = -1; + + const struct sockaddr * addr = reinterpret_cast(pairAddress.getPlatformData()); + int ans = ::connect(_socket_fd, addr, (int)sizeof(sockaddr_storage)); + if (!ans) return RESULT_OK; + + fd_set set; + FD_ZERO(&set); + FD_SET(_socket_fd, &set); + + if (select(-1, NULL, &set, NULL, &tm) <= 0) + { + ret = -1; // error(select error or timeout) + return RESULT_OPERATION_TIMEOUT; + } + + int error = -1; + int optLen = sizeof(int); + getsockopt(_socket_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &optLen); + + if (0 != error) + { + ret = -1; // error + } + else + { + ret = 1; // correct + } + + //set back to block mode + if (SOCKET_ERROR == ioctlsocket(_socket_fd, (long)FIONBIO, &mode_block)) + { + return RESULT_OPERATION_FAIL; + } + if(1 == ret) + { + return RESULT_OK; + } + else + { + return RESULT_OPERATION_FAIL; + } + } + + virtual u_result listen(int backlog) + { + int ans = ::listen( _socket_fd, backlog); + + return ans?RESULT_OPERATION_FAIL:RESULT_OK; + } + + virtual StreamSocket * accept(SocketAddress * pairAddress) + { + int addrsize; + addrsize = sizeof(sockaddr_storage); + SOCKET pair_socket = ::accept( _socket_fd, pairAddress?reinterpret_cast(const_cast(pairAddress->getPlatformData())):NULL + , &addrsize); + + if (pair_socket>=0) { + return new StreamSocketImpl(pair_socket); + } else { + return NULL; + } + } + + virtual u_result waitforIncomingConnection(_u32 timeout) + { + return waitforData(timeout); + } + + virtual u_result send(const void * buffer, size_t len) + { + int ans = ::send( _socket_fd, (const char *)buffer, (int)len, 0); + if (ans != SOCKET_ERROR ) { + assert(ans == (int)len); + + return RESULT_OK; + } else { + switch(WSAGetLastError()) { + case WSAETIMEDOUT: + return RESULT_OPERATION_TIMEOUT; + default: + return RESULT_OPERATION_FAIL; + } + + } + + } + + virtual u_result recv(void *buf, size_t len, size_t & recv_len) + { + int ans = ::recv( _socket_fd, (char *)buf, (int)len, 0); + //::setsockopt(_socket_fd, IPPROTO_TCP, TCP_QUICKACK, (const char *)1, sizeof(int)); + //::setsockopt(_socket_fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){1}, sizeof(int)) + if (ans == SOCKET_ERROR) { + recv_len = 0; + switch(WSAGetLastError()) { + case WSAETIMEDOUT: + return RESULT_OPERATION_TIMEOUT; + default: + return RESULT_OPERATION_FAIL; + } + } else { + recv_len = ans; + return RESULT_OK; + } + } + + virtual u_result getPeerAddress(SocketAddress & peerAddr) + { + struct sockaddr * addr = reinterpret_cast(const_cast(peerAddr.getPlatformData())); //donnot do this at home... + assert(addr); + int actualsize = (int)sizeof(sockaddr_storage); + int ans = ::getpeername(_socket_fd, addr, &actualsize); + + assert(actualsize <= (int)sizeof(sockaddr_storage)); + assert(addr->sa_family == AF_INET || addr->sa_family == AF_INET6); + + return ans?RESULT_OPERATION_FAIL:RESULT_OK; + + } + + virtual u_result shutdown(socket_direction_mask mask) + { + int shutdw_opt ; + + switch (mask) { + case SOCKET_DIR_RD: + shutdw_opt = SD_RECEIVE; + break; + case SOCKET_DIR_WR: + shutdw_opt = SD_SEND; + break; + case SOCKET_DIR_BOTH: + default: + shutdw_opt = SD_BOTH; + } + + int ans = ::shutdown(_socket_fd, shutdw_opt); + return ans?RESULT_OPERATION_FAIL:RESULT_OK; + } + + virtual u_result enableKeepAlive(bool enable) + { + int bool_true = enable?1:0; + return ::setsockopt( _socket_fd, SOL_SOCKET, SO_KEEPALIVE , (const char *)&bool_true, (int)sizeof(bool_true) )?RESULT_OPERATION_FAIL:RESULT_OK; + } + + virtual u_result enableNoDelay(bool enable ) + { + int bool_true = enable?1:0; + return ::setsockopt( _socket_fd, IPPROTO_TCP, TCP_NODELAY, (const char *)&bool_true, (int)sizeof(bool_true) )?RESULT_OPERATION_FAIL:RESULT_OK; + } + + virtual u_result waitforSent(_u32 timeout ) + { + fd_set wrset; + FD_ZERO(&wrset); + FD_SET(_socket_fd, &wrset); + + timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + int ans = ::select(NULL, NULL, &wrset, NULL, &tv); + + switch (ans) { + case 1: + // fired + return RESULT_OK; + case 0: + // timeout + return RESULT_OPERATION_TIMEOUT; + default: + delay(0); //relax cpu + return RESULT_OPERATION_FAIL; + } + } + + virtual u_result waitforData(_u32 timeout ) + { + fd_set rdset; + FD_ZERO(&rdset); + FD_SET(_socket_fd, &rdset); + + timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + int ans = ::select((int)_socket_fd+1, &rdset, NULL, NULL, &tv); + + switch (ans) { + case 1: + // fired + return RESULT_OK; + case 0: + // timeout + return RESULT_OPERATION_TIMEOUT; + default: + delay(0); //relax cpu + return RESULT_OPERATION_FAIL; + } + } + +protected: + + SOCKET _socket_fd; + + +}; + + +class _single_thread DGramSocketImpl : public DGramSocket +{ +public: + + DGramSocketImpl(SOCKET fd) + : _socket_fd(fd) + { + assert(fd>=0); + int bool_true = 1; + ::setsockopt( _socket_fd, SOL_SOCKET, SO_REUSEADDR | SO_BROADCAST , (char *)&bool_true, (int)sizeof(bool_true) ); + setTimeout(DEFAULT_SOCKET_TIMEOUT, SOCKET_DIR_BOTH); + } + + virtual ~DGramSocketImpl() + { + closesocket(_socket_fd); + } + + virtual void dispose() + { + delete this; + } + + + virtual u_result bind(const SocketAddress & localaddr) + { + const struct sockaddr * addr = reinterpret_cast(localaddr.getPlatformData()); + assert(addr); + int ans = ::bind(_socket_fd, addr, (int)sizeof(sockaddr_storage)); + if (ans) { + return RESULT_OPERATION_FAIL; + } else { + return RESULT_OK; + } + } + + virtual u_result getLocalAddress(SocketAddress & localaddr) + { + struct sockaddr * addr = reinterpret_cast(const_cast((localaddr.getPlatformData()))); //donnot do this at home... + assert(addr); + + int actualsize = (int)sizeof(sockaddr_storage); + int ans = ::getsockname(_socket_fd, addr, &actualsize); + + assert(actualsize <= (int)sizeof(sockaddr_storage)); + assert(addr->sa_family == AF_INET || addr->sa_family == AF_INET6); + + return ans?RESULT_OPERATION_FAIL:RESULT_OK; + } + + virtual u_result setTimeout(_u32 timeout, socket_direction_mask msk) + { + int ans; + timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + if (msk & SOCKET_DIR_RD) { + ans = ::setsockopt( _socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, (int)sizeof(tv) ); + if (ans) return RESULT_OPERATION_FAIL; + } + + if (msk & SOCKET_DIR_WR) { + ans = ::setsockopt( _socket_fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv, (int)sizeof(tv) ); + if (ans) return RESULT_OPERATION_FAIL; + } + + return RESULT_OK; + } + + + virtual u_result waitforSent(_u32 timeout ) + { + fd_set wrset; + FD_ZERO(&wrset); + FD_SET(_socket_fd, &wrset); + + timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + int ans = ::select(NULL, NULL, &wrset, NULL, &tv); + + switch (ans) { + case 1: + // fired + return RESULT_OK; + case 0: + // timeout + return RESULT_OPERATION_TIMEOUT; + default: + delay(0); //relax cpu + return RESULT_OPERATION_FAIL; + } + } + + virtual u_result waitforData(_u32 timeout ) + { + fd_set rdset; + FD_ZERO(&rdset); + FD_SET(_socket_fd, &rdset); + + timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + int ans = ::select(NULL, &rdset, NULL, NULL, &tv); + + switch (ans) { + case 1: + // fired + return RESULT_OK; + case 0: + // timeout + return RESULT_OPERATION_TIMEOUT; + default: + delay(0); //relax cpu + return RESULT_OPERATION_FAIL; + } + } + + virtual u_result setPairAddress(const SocketAddress * pairAddress) + { + sockaddr_storage unspecAddr; + unspecAddr.ss_family = AF_UNSPEC; + + const struct sockaddr * addr = pairAddress ? reinterpret_cast(pairAddress->getPlatformData()) : reinterpret_cast(&unspecAddr); + int ans = ::connect(_socket_fd, addr, (int)sizeof(sockaddr_storage)); + return ans? RESULT_OPERATION_FAIL: RESULT_OK; + + } + + virtual u_result sendTo(const SocketAddress * target, const void * buffer, size_t len) + { + + const struct sockaddr * addr = target?reinterpret_cast(target->getPlatformData()): NULL; + int dest_addr_size = (target ? sizeof(sockaddr_storage) : 0); + int ans = ::sendto( _socket_fd, (const char *)buffer, (int)len, 0, addr, dest_addr_size); + if (ans != SOCKET_ERROR) { + assert(ans == (int)len); + return RESULT_OK; + } else { + switch(WSAGetLastError()) { + case WSAETIMEDOUT: + return RESULT_OPERATION_TIMEOUT; + case WSAEMSGSIZE: + return RESULT_INVALID_DATA; + default: + return RESULT_OPERATION_FAIL; + } + } + + } + + virtual u_result clearRxCache() + { + timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + fd_set rdset; + FD_ZERO(&rdset); + FD_SET(_socket_fd, &rdset); + + int res = -1; + char recv_data[2]; + memset(recv_data, 0, sizeof(recv_data)); + while (true) { + res = select(FD_SETSIZE, &rdset, nullptr, nullptr, &tv); + if (res == 0) break; + recv(_socket_fd, recv_data, 1, 0); + } + return RESULT_OK; + } + + + virtual u_result recvFrom(void *buf, size_t len, size_t & recv_len, SocketAddress * sourceAddr) + { + struct sockaddr * addr = (sourceAddr?reinterpret_cast(const_cast(sourceAddr->getPlatformData())):NULL); + int source_addr_size = (sourceAddr?sizeof(sockaddr_storage):0); + + int ans = ::recvfrom( _socket_fd, (char *)buf, (int)len, 0, addr, addr?&source_addr_size:NULL); + if (ans == SOCKET_ERROR) { + recv_len = 0; + int errCode = WSAGetLastError(); + switch(errCode) { + case WSAETIMEDOUT: + return RESULT_OPERATION_TIMEOUT; + default: + return RESULT_OPERATION_FAIL; + } + } else { + recv_len = ans; + return RESULT_OK; + } + + } + + + +protected: + SOCKET _socket_fd; + +}; + + +}}} + + +namespace rp { namespace net{ + + + +static inline int _socketHalFamilyToOSFamily(SocketBase::socket_family_t family) +{ + switch (family) { + case SocketBase::SOCKET_FAMILY_INET: + return AF_INET; + case SocketBase::SOCKET_FAMILY_INET6: + return AF_INET6; + case SocketBase::SOCKET_FAMILY_RAW: + return AF_UNSPEC; //win32 doesn't support RAW Packet + default: + assert(!"should not reach here"); + return AF_INET; // force treating as IPv4 in release mode + } + +} + +StreamSocket * StreamSocket::CreateSocket(SocketBase::socket_family_t family) +{ + _checkWSAStartup(); + if (family == SOCKET_FAMILY_RAW) return NULL; + + + int socket_family = _socketHalFamilyToOSFamily(family); + SOCKET socket_fd = ::socket(socket_family, SOCK_STREAM, 0); + if (socket_fd == -1) return NULL; + StreamSocket * newborn = static_cast(new rp::arch::net::StreamSocketImpl(socket_fd)); + return newborn; + +} + + +DGramSocket * DGramSocket::CreateSocket(SocketBase::socket_family_t family) +{ + _checkWSAStartup(); + int socket_family = _socketHalFamilyToOSFamily(family); + + + SOCKET socket_fd = ::socket(socket_family, (family == SOCKET_FAMILY_RAW) ? SOCK_RAW : SOCK_DGRAM, 0); + if (socket_fd == -1) return NULL; + DGramSocket * newborn = static_cast(new rp::arch::net::DGramSocketImpl(socket_fd)); + return newborn; + +} + + +}} + diff --git a/LIDAR/sdk/src/arch/win32/timer.cpp b/LIDAR/sdk/src/arch/win32/timer.cpp new file mode 100644 index 0000000..d153cc4 --- /dev/null +++ b/LIDAR/sdk/src/arch/win32/timer.cpp @@ -0,0 +1,72 @@ +/* + * RPLIDAR SDK + * + * Copyright (c) 2009 - 2014 RoboPeak Team + * http://www.robopeak.com + * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd. + * http://www.slamtec.com + * + */ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdkcommon.h" +#include +#pragma comment(lib, "Winmm.lib") + +namespace rp{ namespace arch{ + +static LARGE_INTEGER _current_freq; + +void HPtimer_reset() +{ + BOOL ans=QueryPerformanceFrequency(&_current_freq); + _current_freq.QuadPart/=1000ULL; + assert(ans); +} + +_u64 getHDTimer_us() +{ + LARGE_INTEGER current; + QueryPerformanceCounter(¤t); + + return (_u64)(current.QuadPart / (_current_freq.QuadPart/1000ULL)); + +} + +_u64 getHDTimer() +{ + LARGE_INTEGER current; + QueryPerformanceCounter(¤t); + + return (_u64)(current.QuadPart/_current_freq.QuadPart); +} + +BEGIN_STATIC_CODE(timer_cailb) +{ + HPtimer_reset(); +}END_STATIC_CODE(timer_cailb) + +}} diff --git a/LIDAR/sdk/src/arch/win32/timer.h b/LIDAR/sdk/src/arch/win32/timer.h new file mode 100644 index 0000000..27b7a76 --- /dev/null +++ b/LIDAR/sdk/src/arch/win32/timer.h @@ -0,0 +1,49 @@ +/* + * RPLIDAR SDK + * + * Copyright (c) 2009 - 2014 RoboPeak Team + * http://www.robopeak.com + * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd. + * http://www.slamtec.com + * + */ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "hal/types.h" + +#define delay(x) ::Sleep(x) + +namespace rp{ namespace arch{ + void HPtimer_reset(); + _u64 getHDTimer(); + _u64 getHDTimer_us(); + +}} + +#define getms() rp::arch::getHDTimer() +#define getus() rp::arch::getHDTimer_us() diff --git a/LIDAR/sdk/src/arch/win32/winthread.hpp b/LIDAR/sdk/src/arch/win32/winthread.hpp new file mode 100644 index 0000000..590794d --- /dev/null +++ b/LIDAR/sdk/src/arch/win32/winthread.hpp @@ -0,0 +1,144 @@ +/* + * RPLIDAR SDK + * + * Copyright (c) 2009 - 2014 RoboPeak Team + * http://www.robopeak.com + * Copyright (c) 2014 - 2020 Shanghai Slamtec Co., Ltd. + * http://www.slamtec.com + * + */ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdkcommon.h" +#include + +namespace rp{ namespace hal{ + +Thread Thread::create(thread_proc_t proc, void * data) +{ + Thread newborn(proc, data); + + newborn._handle = (_word_size_t)( + _beginthreadex(NULL, 0, (unsigned int (_stdcall * )( void * ))proc, + data, 0, NULL)); + return newborn; +} + +u_result Thread::terminate() +{ + if (!this->_handle) return RESULT_OK; + if (TerminateThread( reinterpret_cast(this->_handle), -1)) + { + CloseHandle(reinterpret_cast(this->_handle)); + this->_handle = NULL; + return RESULT_OK; + }else + { + return RESULT_OPERATION_FAIL; + } +} + +u_result Thread::SetSelfPriority( priority_val_t p) +{ + HANDLE selfHandle = GetCurrentThread(); + + int win_priority = THREAD_PRIORITY_NORMAL; + switch(p) + { + case PRIORITY_REALTIME: + win_priority = THREAD_PRIORITY_TIME_CRITICAL; + break; + case PRIORITY_HIGH: + win_priority = THREAD_PRIORITY_HIGHEST; + break; + case PRIORITY_NORMAL: + win_priority = THREAD_PRIORITY_NORMAL; + break; + case PRIORITY_LOW: + win_priority = THREAD_PRIORITY_LOWEST; + break; + case PRIORITY_IDLE: + win_priority = THREAD_PRIORITY_IDLE; + break; + } + + if (SetThreadPriority(selfHandle, win_priority)) + { + return RESULT_OK; + } + return RESULT_OPERATION_FAIL; +} + +Thread::priority_val_t Thread::getPriority() +{ + if (!this->_handle) return PRIORITY_NORMAL; + int win_priority = ::GetThreadPriority(reinterpret_cast(this->_handle)); + + if (win_priority == THREAD_PRIORITY_ERROR_RETURN) + { + return PRIORITY_NORMAL; + } + + if (win_priority >= THREAD_PRIORITY_TIME_CRITICAL ) + { + return PRIORITY_REALTIME; + } + else if (win_priority=THREAD_PRIORITY_ABOVE_NORMAL) + { + return PRIORITY_HIGH; + } + else if (win_priorityTHREAD_PRIORITY_BELOW_NORMAL) + { + return PRIORITY_NORMAL; + }else if (win_priority<=THREAD_PRIORITY_BELOW_NORMAL && win_priority>THREAD_PRIORITY_IDLE) + { + return PRIORITY_LOW; + }else if (win_priority<=THREAD_PRIORITY_IDLE) + { + return PRIORITY_IDLE; + } + return PRIORITY_NORMAL; +} + +u_result Thread::join(unsigned long timeout) +{ + if (!this->_handle) return RESULT_OK; + switch ( WaitForSingleObject(reinterpret_cast(this->_handle), timeout)) + { + case WAIT_OBJECT_0: + CloseHandle(reinterpret_cast(this->_handle)); + this->_handle = NULL; + return RESULT_OK; + case WAIT_ABANDONED: + return RESULT_OPERATION_FAIL; + case WAIT_TIMEOUT: + return RESULT_OPERATION_TIMEOUT; + } + + return RESULT_OK; +} + +}} -- cgit v1.2.3