commit 695418eb85dba45a0d6ba5093e137cf3dee3ea75 Author: zhaohe Date: Sun Jul 2 15:28:12 2023 +0800 v1.0 diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..45866f9 --- /dev/null +++ b/.clang-format @@ -0,0 +1,9 @@ +# Defines the Chromium style for automatic reformatting. +# http://clang.llvm.org/docs/ClangFormatStyleOptions.html +Language: Cpp +BasedOnStyle: Google +ColumnLimit: 160 +AlignConsecutiveMacros: true +AlignConsecutiveDeclarations: true +AlignConsecutiveAssignments: true +AlignOperands: true \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af3a880 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +build +out +.cache +./libs +libs/ +buildpc +buildhost \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..b690ade --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "${workspaceFolder}/", + "${workspaceFolder}/dep" + ], + "compilerPath": "/usr/bin/g++", + "cStandard": "gnu11", + "cppStandard": "gnu++14", + "intelliSenseMode": "linux-gcc-x64", + "compileCommands": "${workspaceFolder}/build/compile_commands.json" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..94aa104 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,111 @@ +{ + "files.associations": { + "__locale": "cpp", + "array": "cpp", + "atomic": "cpp", + "hash_map": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "forward_list": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "semaphore": "cpp", + "shared_mutex": "cpp", + "span": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cfenv": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp", + "__nullptr": "cpp", + "locale": "cpp", + "__bit_reference": "cpp", + "__functional_base": "cpp", + "__node_handle": "cpp", + "__memory": "cpp", + "filesystem": "cpp", + "__functional_base_03": "cpp", + "__hash_table": "cpp", + "__tree": "cpp", + "__tuple": "cpp", + "*.ipp": "cpp", + "complex": "cpp", + "csetjmp": "cpp", + "cuchar": "cpp", + "unordered_set": "cpp", + "rope": "cpp", + "slist": "cpp", + "scoped_allocator": "cpp", + "netdb.h": "c", + "aiui_cjson.h": "c", + "string.h": "c", + "aiui_base64.h": "c", + "aiui_wsclient.h": "c", + "aiui_sha256.h": "c", + "socket.h": "c", + "unistd.h": "c", + "err.h": "c", + "cerrno": "c", + "stdio.h": "c", + "any": "cpp" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e92c2d6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,72 @@ +cmake_minimum_required(VERSION 3.13) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_BUILD_TYPE Debug) +set(CMAKE_SKIP_BUILD_RPATH FALSE) +set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +project(rk3588sdk) + +set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc") +set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++") + +set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/) +# 设置ccache加速C++编译速度 +set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) +set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) + +# 设置通用编译选项 +set(C_CPP_FLAGS "${C_CPP_FLAGS} -Wno-format-overflow") +set(C_CPP_FLAGS "${C_CPP_FLAGS} -Wno-unused-local-typedefs") +set(C_CPP_FLAGS "${C_CPP_FLAGS} -Wno-unused-but-set-variable") +set(C_CPP_FLAGS "${C_CPP_FLAGS} -Wno-deprecated-declarations") +set(C_CPP_FLAGS "${C_CPP_FLAGS} -Werror=return-type") +set(C_CPP_FLAGS "${C_CPP_FLAGS} -Werror=parentheses") +set(C_CPP_FLAGS "${C_CPP_FLAGS} -Wfatal-errors") +set(C_CPP_FLAGS "${C_CPP_FLAGS} -Wno-unused-result") +set(C_CPP_FLAGS "${C_CPP_FLAGS} -Wno-comment") + +set(C_CPP_FLAGS "${C_CPP_FLAGS} -O3") +set(C_CPP_FLAGS "${C_CPP_FLAGS} -g3") +set(C_CPP_FLAGS "${C_CPP_FLAGS} -fPIC") +set(C_CPP_FLAGS "${C_CPP_FLAGS} -Wall") + +# 设置C编译选项 +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CPP_FLAGS}") + +# 设置CPP编译选项 +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_CPP_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pessimizing-move") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + +message("CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") +message("PROJECT_NAME: ${PROJECT_NAME}") + +# LINK_DIRECTORIES(/home/zwsd/Desktop/minhang/rk3588sdk/demo/ac_sound_capture1/libspisound/) + +find_library(LIBSPI libspisound.so ./demo/ac_sound_capture1/libspisound/) + + +add_executable(ac_sound_capture1 demo/ac_sound_capture1/ac_sound_capture1.cpp) +target_link_libraries(ac_sound_capture1 ${LIBSPI} pthread) +install(TARGETS ac_sound_capture1 DESTINATION ./app/) + + +add_executable(test_uart_232_1 demo/uart/test_uart232_1.cpp demo/uart/uart.cpp) +target_link_libraries(test_uart_232_1 pthread) +install(TARGETS test_uart_232_1 DESTINATION ./app/) + +add_executable(test_uart_232_2 demo/uart/test_uart232_2.cpp demo/uart/uart.cpp) +target_link_libraries(test_uart_232_2 pthread) +install(TARGETS test_uart_232_2 DESTINATION ./app/) + +add_executable(test_uart485 demo/uart/test_uart485.cpp demo/uart/uart.cpp) +target_link_libraries(test_uart485 pthread) +install(TARGETS test_uart485 DESTINATION ./app/) + +add_executable(test_usbuart demo/uart/test_usbuart.cpp demo/uart/uart.cpp) +target_link_libraries(test_usbuart pthread) +install(TARGETS test_usbuart DESTINATION ./app/) + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..804c0bb --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# rk3588sdk + +``` +编译环境准备: + ubuntu20.04 + sudo apt install gcc-aarch64-linux-gnu + sudo apt install g++-aarch64-linux-gnu + +无密码登陆: + ssh-copy-id iflytop@板子IP + +编译: + ./build.sh + +部署: + ./sh/deploy.sh username ip +``` diff --git a/demo/ac_sound_capture1/ac_sound_capture1.cpp b/demo/ac_sound_capture1/ac_sound_capture1.cpp new file mode 100644 index 0000000..eb272f1 --- /dev/null +++ b/demo/ac_sound_capture1/ac_sound_capture1.cpp @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "libspisound/spisound.h" +} + +using namespace std; + +class WAVHeader { + public: + /** + * @brief WAV 文件头部信息的二进制格式 + * + * WAV 文件头部信息包含了如下字段: + * - 固定为 "RIFF" 的 4 字节 chunk_id + * - 文件总大小 - 8 的 4 字节 chunk_size + * - 固定为 "WAVE" 的 4 字节 format + * - 固定为 "fmt " 的 4 字节 subchunk1_id + * - 固定为 16 的 4 字节 subchunk1_size + * - 编码格式,1 表示 PCM 编码的 2 字节 audio_format + * - 声道数,1 为单声道,2 为立体声的 2 字节 num_channels + * - 采样率,如 44100 的 4 字节 sample_rate + * - 数据传输速率,即采样率 * 声道数 * 位数 / 8 的 4 字节 byte_rate + * - 数据块对齐,即每个采样点占用的字节数,如 2 表示 16 位,即 2 字节的 2 字节 block_align + * - 位数,如 8、16、24、32 的 2 字节 bits_per_sample + * - 固定为 "data" 的 4 字节 subchunk2_id + * - 数据长度,即文件总大小 - 44 的 4 字节 subchunk2_size + */ + struct WAVHeaderBinary { + char chunk_id[4]; // 固定为 "RIFF" + uint32_t chunk_size; // 文件总大小 - 8 + char format[4]; // 固定为 "WAVE" + char subchunk1_id[4]; // 固定为 "fmt " + uint32_t subchunk1_size; // 固定为 16 + uint16_t audio_format; // 编码格式,1 表示 PCM 编码 + uint16_t num_channels; // 声道数,1 为单声道,2 为立体声 + uint32_t sample_rate; // 采样率,如 44100 + uint32_t byte_rate; // 数据传输速率,即采样率 * 声道数 * 位数 / 8 + uint16_t block_align; // 数据块对齐,即每个采样点占用的字节数,如 2 表示 16 位,即 2 字节 + uint16_t bits_per_sample; // 位数,如 8、16、24、32 + char subchunk2_id[4]; // 固定为 "data" + uint32_t subchunk2_size; // 数据长度,即文件总大小 - 44 + }; + WAVHeaderBinary header; + + public: + WAVHeader() {} + void initialize(uint32_t sample_rate, uint16_t bits_per_sample, uint16_t num_channels, uint32_t wavbinsize) { + // 填充 RIFF 头 + memcpy(header.chunk_id, "RIFF", 4); + header.chunk_size = wavbinsize + 44 - 8; + memcpy(header.format, "WAVE", 4); + + // 填充 fmt 子块 + memcpy(header.subchunk1_id, "fmt ", 4); + header.subchunk1_size = 16; + header.audio_format = 1; // PCM 编码 + header.num_channels = num_channels; + header.sample_rate = sample_rate; + header.byte_rate = sample_rate * num_channels * bits_per_sample / 8; + header.block_align = num_channels * bits_per_sample / 8; + header.bits_per_sample = bits_per_sample; + + // 填充 data 子块 + memcpy(header.subchunk2_id, "data", 4); + header.subchunk2_size = wavbinsize; + } + void resize(uint32_t wavbinsize) { + header.chunk_size = wavbinsize + 44 - 8; + header.subchunk2_size = wavbinsize; + } + + void dump() { + printf("chunk_id: %s\n", string(header.chunk_id, 4).c_str()); + printf("chunk_size: %d\n", header.chunk_size); + printf("format: %s\n", string(header.format, 4).c_str()); + printf("subchunk1_id: %s\n", string(header.subchunk1_id, 4).c_str()); + printf("subchunk1_size: %d\n", header.subchunk1_size); + printf("audio_format: %d\n", header.audio_format); + printf("num_channels: %d\n", header.num_channels); + printf("sample_rate: %d\n", header.sample_rate); + printf("byte_rate: %d\n", header.byte_rate); + printf("block_align: %d\n", header.block_align); + printf("bits_per_sample: %d\n", header.bits_per_sample); + printf("subchunk2_id: %s\n", header.subchunk2_id); + printf("subchunk2_size: %d\n", header.subchunk2_size); + } + + WAVHeader(uint32_t sample_rate, uint16_t bits_per_sample, uint16_t num_channels, uint32_t num_samples) { + initialize(sample_rate, bits_per_sample, num_channels, num_samples); + } + uint8_t* data() { return (uint8_t*)&header; } + size_t size() { return sizeof(header); } +}; + +void wavWriteVoice(string filename, uint32_t sample_rate, uint16_t bits_per_sample, uint16_t num_channels, const char* data, uint32_t size) { + fstream file; + WAVHeader wavHeader; + // logger->info("writeVoice filename:{} {} {} {} {}", filename, sample_rate, bits_per_sample, num_channels, size); + file.open(filename, fstream::in | fstream::out | fstream::binary); + if (!file.is_open()) { + file.open(filename, fstream::out | fstream::binary | fstream::trunc); + wavHeader.initialize(sample_rate, bits_per_sample, num_channels, 0); + file.seekp(0, ios::beg); + file.write((char*)wavHeader.data(), wavHeader.size()); + file.close(); + file.open(filename, fstream::in | fstream::out | fstream::binary); + } + + // file.write(data, size); +#if 1 + /** + * @brief 判断文件大小,文件大小大于等于44字节,说明文件已经存在,不需要写入头部 + */ + file.seekp(0, ios::end); + file.write(data, size); + /** + * @brief 更新头部信息 + */ + uint32_t filesize = file.tellp(); + file.seekp(4, ios::beg); + uint32_t chunk_size = filesize - 8; + file.write((char*)&chunk_size, 4); + file.seekp(40, ios::beg); + uint32_t subchunk2_size = filesize - 44; + file.write((char*)&subchunk2_size, 4); +#endif + + file.close(); +} + +void sound_capture_callback(int32_t* voicedata, uint32_t len) { + printf("sound_capture_callback:%d\n", len); + wavWriteVoice("record.wav", 48000, 32, 1, (char*)voicedata, len * sizeof(int32_t)); +} + +int main(int argc, char const* argv[]) { + system("rm -rf record.wav"); + + error_code_t erro_code = spisound_init("/dev/spidev1.0", 59, sound_capture_callback); + if (erro_code != ksp_success) { + spisound_dump_last_error(); + return -1; + } + + erro_code = spisound_start_capture(); + if (erro_code != ksp_success) { + spisound_dump_last_error(); + return -1; + } + + while (true) sleep(1); + return 0; +} diff --git a/demo/ac_sound_capture1/libspisound/README.md b/demo/ac_sound_capture1/libspisound/README.md new file mode 100644 index 0000000..9164880 --- /dev/null +++ b/demo/ac_sound_capture1/libspisound/README.md @@ -0,0 +1,7 @@ +``` +注意事项: + +1. libspisound.so仅仅是为了编译使用,不需要拷贝到目标设备上,目标设备已经有了这个库。 +2. 当前音频格式为48K,32bit,LittleEnd + +``` \ No newline at end of file diff --git a/demo/ac_sound_capture1/libspisound/libspisound.so b/demo/ac_sound_capture1/libspisound/libspisound.so new file mode 100644 index 0000000..a6d9a97 Binary files /dev/null and b/demo/ac_sound_capture1/libspisound/libspisound.so differ diff --git a/demo/ac_sound_capture1/libspisound/spisound.h b/demo/ac_sound_capture1/libspisound/spisound.h new file mode 100644 index 0000000..2fd3c82 --- /dev/null +++ b/demo/ac_sound_capture1/libspisound/spisound.h @@ -0,0 +1,66 @@ +#pragma once +#include + +#ifdef cplusplus +extern "C" { +#endif +/** + * @brief 上报48k音频数据32位音频数据 + * + * @param data 音频数据 + * @param len 音频数据长度 + * + */ +typedef void (*spisound_cb_t)(int32_t *data, uint32_t len); + +typedef enum { + ksp_success, + ksp_module_not_inited, + ksp_module_has_started, + ksp_create_thread_fail, + ksp_init_spi_cs_pin_open_fail, + ksp_init_spi_error_open_fail, + ksp_init_spi_error_set_speed_fail, + ksp_init_spi_error_set_nbits_fail, + ksp_init_spi_error_set_mode_fail, +} error_code_t; + +static inline const char *error_code_to_string(error_code_t code) { + switch (code) { + case ksp_success: + return "success"; + case ksp_module_not_inited: + return "module not inited"; + case ksp_module_has_started: + return "module has started"; + case ksp_create_thread_fail: + return "create thread fail"; + case ksp_init_spi_cs_pin_open_fail: + return "init spi cs pin open fail"; + case ksp_init_spi_error_open_fail: + return "init spi error open fail"; + case ksp_init_spi_error_set_speed_fail: + return "init spi error set speed fail"; + case ksp_init_spi_error_set_nbits_fail: + return "init spi error set nbits fail"; + case ksp_init_spi_error_set_mode_fail: + return "init spi error set mode fail"; + default: + return "unknown error"; + } +} + +/** + * @brief 初始化声音采集模块 + * + * @param deviceName + * @param callback + */ +error_code_t spisound_init(const char *deviceName, int csgpionId, spisound_cb_t callback); +error_code_t spisound_start_capture(void); +const char *spisound_libversion(); + +void spisound_dump_last_error(); +#ifdef cplusplus +} +#endif \ No newline at end of file diff --git a/demo/uart/test_uart232_1.cpp b/demo/uart/test_uart232_1.cpp new file mode 100644 index 0000000..cdec78c --- /dev/null +++ b/demo/uart/test_uart232_1.cpp @@ -0,0 +1,43 @@ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uart.hpp" +using namespace std; +using namespace iflytop; + +#define UART_NAME "/dev/ttyS0" + +int main(int argc, char const* argv[]) { + Uart uart; + uart.open(UART_NAME, "115200"); + + thread th([&]() { + // + while (true) { + char buf[1024]; + memset(buf, 0, 1024); + int size = uart.receive(buf, 1024, 10); + if (size > 0) { + cout << "receive:" << buf << endl; + } + } + }); + + while (true) { + printf("tx hello\n"); + uart.send("hello", 5); + sleep(1); + } +} \ No newline at end of file diff --git a/demo/uart/test_uart232_2.cpp b/demo/uart/test_uart232_2.cpp new file mode 100644 index 0000000..9edf997 --- /dev/null +++ b/demo/uart/test_uart232_2.cpp @@ -0,0 +1,44 @@ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uart.hpp" +using namespace std; +using namespace iflytop; + +#define UART_NAME "/dev/ttyS5" + +int main(int argc, char const* argv[]) { + Uart uart; + uart.open(UART_NAME, "115200"); + + thread th([&]() { + // + + while (true) { + char buf[1024]; + memset(buf, 0, 1024); + int size = uart.receive(buf, 1024, 10); + if (size > 0) { + cout << "receive:" << buf << endl; + } + } + }); + + while (true) { + printf("tx hello\n"); + uart.send("hello", 5); + sleep(1); + } +} \ No newline at end of file diff --git a/demo/uart/test_uart485.cpp b/demo/uart/test_uart485.cpp new file mode 100644 index 0000000..c693f69 --- /dev/null +++ b/demo/uart/test_uart485.cpp @@ -0,0 +1,44 @@ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uart.hpp" +using namespace std; +using namespace iflytop; + +#define UART_NAME "/dev/ttyS1" + +int main(int argc, char const* argv[]) { + Uart uart; + uart.open(UART_NAME, "115200"); + + thread th([&]() { + // + while (true) { + char buf[1024]; + memset(buf, 0, 1024); + int size = uart.receive(buf, 1024, 10); + if (size > 0) { + cout << "receive:" << buf << endl; + } + } + }); + + while (true) { + const char* txstr = "message from 485\n"; + printf("tx message\n"); + uart.send((char*)txstr, strlen(txstr)); + sleep(1); + } +} \ No newline at end of file diff --git a/demo/uart/test_usbuart.cpp b/demo/uart/test_usbuart.cpp new file mode 100644 index 0000000..5e1a6ff --- /dev/null +++ b/demo/uart/test_usbuart.cpp @@ -0,0 +1,44 @@ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uart.hpp" +using namespace std; +using namespace iflytop; + +#define UART_NAME "/dev/ttyUSB0" + +int main(int argc, char const* argv[]) { + Uart uart; + uart.open(UART_NAME, "115200"); + + thread th([&]() { + // + + while (true) { + char buf[1024]; + memset(buf, 0, 1024); + int size = uart.receive(buf, 1024, 10); + if (size > 0) { + cout << "receive:" << buf << endl; + } + } + }); + + while (true) { + printf("tx hello\n"); + uart.send("hello", 5); + sleep(1); + } +} \ No newline at end of file diff --git a/demo/uart/uart.cpp b/demo/uart/uart.cpp new file mode 100644 index 0000000..794d9b8 --- /dev/null +++ b/demo/uart/uart.cpp @@ -0,0 +1,161 @@ + +/* + * uart.c + */ +#include "uart.hpp" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace iflytop; +using namespace chrono; + +static int64_t getnowms() { return duration_cast(steady_clock::now().time_since_epoch()).count(); } + +static map s_baundmap = { + {"0", 0000000}, {"50", 0000001}, {"75", 0000002}, {"110", 0000003}, // + {"134", 0000004}, {"150", 0000005}, {"200", 0000006}, {"300", 0000007}, // + {"600", 0000010}, {"1200", 0000011}, {"1800", 0000012}, {"2400", 0000013}, // + {"4800", 0000014}, {"9600", 0000015}, {"19200", 0000016}, {"38400", 0000017}, // + {"57600", 0010001}, {"115200", 0010002}, {"230400", 0010003}, {"460800", 0010004}, // + {"500000", 0010005}, {"576000", 0010006}, {"921600", 0010007}, {"1000000", 0010010}, // + {"1152000", 0010011}, {"1500000", 0010012}, {"2000000", 0010013}, {"2500000", 0010014}, // + {"3000000", 0010015}, {"3500000", 0010016}, {"4000000", 0010017}, +}; + +Uart::Uart() {} +Uart::~Uart() {} + +int Uart::open(string path, string ratestr) { + int rc; + + m_name = path; + uint32_t rate = 0; + + m_fd = ::open(path.c_str(), O_RDWR | O_NOCTTY); + if (m_fd < 0) { + // m_error = fmt::format("open {} failed,{}", path, strerror(errno)); + return -1; + } + + if (s_baundmap.find(ratestr) == s_baundmap.end()) { + // m_error = fmt::format("baund {} not support", ratestr); + return -1; + } + rate = s_baundmap[ratestr]; + m_rate = ratestr; + memset(&m_tty, 0, sizeof(m_tty)); + // memset(tty, 0, sizeof(struct termios)); + /* + BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed. + CRTSCTS : output hardware flow control (only used if the cable has + all necessary lines. See sect. 7 of Serial-HOWTO) + CS8 : 8n1 (8bit,no parity,1 stopbit) + CLOCAL : local connection, no modem contol + CREAD : enable receiving characters + */ + // tty->c_cflag = dev->rate | CRTSCTS | CS8 | CLOCAL | CREAD; + m_tty.c_cflag = rate | CS8 | CLOCAL | CREAD; + + // not canonic + /* + IGNPAR : ignore bytes with parity errorsc_cc[VTIME] + */ + m_tty.c_iflag = IGNPAR; + /* set input mode (non-canonical, no echo,...) */ + m_tty.c_lflag = 0; + /* Do not wait for data */ + m_tty.c_cc[VTIME] = 10; /* inter-character timer unused */ + m_tty.c_cc[VMIN] = 0; /* blocking read until 5 chars received */ + + /* + Raw output. + */ + m_tty.c_oflag = 0; + + /* Flush port */ + tcflush(m_fd, TCIFLUSH); + + /* Apply attributes */ + rc = tcsetattr(m_fd, TCSANOW, &m_tty); + if (rc) { + // m_error = fmt::format("tcsetattr {} failed,{}", path, strerror(errno)); + return -1; + } + return 0; +} +int Uart::send(const char *data, int size) { + // if (logger->level() <= level::debug) { + // logger->debug("{} send: {}", m_name, StringUtils().bytesToString((const uint8_t *)data, size)); + // } + int sent = 0; + sent = write(m_fd, data, size); + if (sent < 0) { + // m_error = fmt::format("write {} failed,{}", m_name, strerror(errno)); + } + return sent; +} +int Uart::receive(char *data, int size_max) { + int received = 0; + received = read(m_fd, data, size_max); + if (received < 0) { + // m_error = fmt::format("read {} failed,{}", m_name, strerror(errno)); + } + // if (logger->level() <= level::debug) { + // logger->debug("{} receive: {}", m_name, StringUtils().bytesToString((const uint8_t *)data, received)); + // } + return received; +} +int Uart::receive(char *data, int size, int overtimems) { + if (m_fd < 0) return -1; + + int64_t now = getnowms(); + int64_t end = now + overtimems; + int rc = 0; + int total = 0; + while (getnowms() < end) { + rc = receive(data + total, size - total); + if (rc > 0) { + total += rc; + if (total >= size) break; + } + usleep(333); + } + return total; +} +int Uart::close() { + ::close(m_fd); + m_fd = -1; + return 0; +} +bool Uart::flush_rx() { + if (m_fd < 0) return false; + int rc = tcflush(m_fd, TCIFLUSH); + return rc == 0; +} +bool Uart::flush_tx() { + if (m_fd < 0) return false; + int rc = tcflush(m_fd, TCOFLUSH); + return rc == 0; +} +bool Uart::set_rx_overtime(int n100ms) { + if (m_fd < 0) return false; + m_tty.c_cc[VTIME] = n100ms; + int rc = tcsetattr(this->m_fd, TCSANOW, &m_tty); + return rc == 0; +} \ No newline at end of file diff --git a/demo/uart/uart.hpp b/demo/uart/uart.hpp new file mode 100644 index 0000000..47df0fd --- /dev/null +++ b/demo/uart/uart.hpp @@ -0,0 +1,60 @@ +#pragma once +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace iflytop { +using namespace std; +class Uart { + private: + /* data */ + int m_fd = 0; + string m_name; + string m_rate; + struct termios m_tty; + string m_error; + + public: + Uart(); + ~Uart(); + + /** + * @brief 打开串口 + * + * @param path + * @param rate + * "0" "50" "75" "110" + * "134" "150" "200" "300" + * "600" "1200" "1800" "2400" + * "4800" "9600" "19200" "38400" + * "57600" "115200" "230400" "460800" + * "500000" "576000" "921600" "1000000" + * "1152000" "1500000" "2000000" "2500000" + * "3000000" "3500000" "4000000" + * + * @return int + */ + int open(string path, string rate); + int send(const char *data, int size); + int receive(char *data, int size_max); + int receive(char *data, int size, int overtimems); + int close(); + + string get_error() { return m_error; } + + bool flush_rx(); + bool flush_tx(); + bool set_rx_overtime(int n100ms); +}; + +} // namespace iflytop \ No newline at end of file diff --git a/sh/build.sh b/sh/build.sh new file mode 100755 index 0000000..fd6f9be --- /dev/null +++ b/sh/build.sh @@ -0,0 +1,4 @@ +mkdir -p build +cd build +cmake .. +make -j8 install diff --git a/sh/deploy.sh b/sh/deploy.sh new file mode 100755 index 0000000..e0b4fb6 --- /dev/null +++ b/sh/deploy.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# ./sh/deploy.sh username ip + +set -e + +if [ $# -ne 2 ]; then + echo "Usage: ./sh/deploy.sh username ip" + exit 1 +fi + +# 1. Build +./sh/build.sh + +cd build +make -j8 install +tar -cvf app.tar app + +scp app.tar $1@$2:/home/$1/ +ssh $1@$2 "cd /home/$1/ && tar -xvf app.tar" diff --git a/zcmake/README.md b/zcmake/README.md new file mode 100644 index 0000000..141bb5a --- /dev/null +++ b/zcmake/README.md @@ -0,0 +1,16 @@ +# README + +``` +在工程目录下的CmakeLists.txt,包含此目录下的文件,或者将下面的文件拷贝到工程目录中即可 + +####demo#### + +include(zcmake/zcmake.cmake) + +zadd_executable( + TARGET app.out + SRC src/main.cpp +) + +############ +``` diff --git a/zcmake/zadd_executable.cmake b/zcmake/zadd_executable.cmake new file mode 100644 index 0000000..f1f55c0 --- /dev/null +++ b/zcmake/zadd_executable.cmake @@ -0,0 +1,114 @@ +include(CMakeParseArguments) + +# zadd_executable( +# +# # #################### 目标文件 ################# +# TARGET +# ... +# +# # #################### 依赖 #################### +# DEPENDENCIES +# ... +# +# # #################### 头文件路径 ############### +# INCLUDE_DIRECTORIES +# ... +# +# # #################### 链接的第三方库 ############ +# LINK_LIBRARIES +# ... +# +# # #################### 源文件 ################## +# SRC +# ... +# ) + +function(zadd_executable) + set(oneValueArgs NAME TARGET) + set(multiValueArgs + INSTALL + SRC + DEFINES + DEPENDENCIES + LINK_LIBRARIES + LINK_DIRECTORIES + INCLUDE_DIRECTORIES) + + + cmake_parse_arguments(ZADD_EXECUTABLE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + message("=================================================================") + message("= zadd_executable:${ZADD_EXECUTABLE_TARGET}") + message("=================================================================") + + if(ZADD_EXECUTABLE_TARGET) + message("ADD TARGET: ${ZADD_EXECUTABLE_TARGET}") + else() + message(FATAL_ERROR,"zadd_executable not set target") + endif() + + message("CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}") + message("CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}") + + if(ZADD_EXECUTABLE_INSTALL) + message("INSTALL : ${ZADD_EXECUTABLE_INSTALL}") + endif() + + if(ZADD_EXECUTABLE_SRC) + # message("SRC: ${ZADD_EXECUTABLE_SRC}") + # foreach(EACH ${ZADD_EXECUTABLE_SRC}) + # message(" ${EACH}") + # endforeach(EACH) + else() + message(FATAL_ERROR,"zadd_executable not set src") + endif() + + add_executable(${ZADD_EXECUTABLE_TARGET} ${ZADD_EXECUTABLE_SRC}) + + if(ZADD_EXECUTABLE_DEFINES) + message("DEFINES:") + foreach(EACH ${ZADD_EXECUTABLE_DEFINES}) + message(" ${EACH}") + endforeach(EACH) + target_compile_definitions(${ZADD_EXECUTABLE_TARGET} PRIVATE ${ZADD_EXECUTABLE_DEFINES}) + endif() + + + if(ZADD_EXECUTABLE_DEPENDENCIES) + message("DEPENDENCIES: ") + foreach(EACH ${ZADD_EXECUTABLE_DEPENDENCIES}) + message(" ${EACH}") + endforeach(EACH) + add_dependencies(${ZADD_EXECUTABLE_TARGET} ${ZADD_EXECUTABLE_DEPENDENCIES}) + endif() + + if(ZADD_EXECUTABLE_LINK_LIBRARIES) + message("LINK_LIBRARIES:") + foreach(EACH ${ZADD_EXECUTABLE_LINK_LIBRARIES}) + message(" ${EACH}") + endforeach(EACH) + target_link_libraries(${ZADD_EXECUTABLE_TARGET} ${ZADD_EXECUTABLE_LINK_LIBRARIES}) + endif() + + if(ZADD_EXECUTABLE_LINK_DIRECTORIES) + message("LINK_DIRECTORIES:") + foreach(EACH ${ZADD_EXECUTABLE_LINK_DIRECTORIES}) + message(" ${EACH}") + endforeach(EACH) + target_link_directories(${ZADD_EXECUTABLE_TARGET} PRIVATE ${ZADD_EXECUTABLE_LINK_DIRECTORIES}) + endif() + + if(ZADD_EXECUTABLE_INCLUDE_DIRECTORIES) + message("INCLUDE_DIRECTORIES:") + foreach(EACH ${ZADD_EXECUTABLE_INCLUDE_DIRECTORIES}) + message(" ${EACH}") + endforeach(EACH) + target_include_directories(${ZADD_EXECUTABLE_TARGET} PRIVATE ${ZADD_EXECUTABLE_INCLUDE_DIRECTORIES}) + endif() + message("") + message("") + + if(ZADD_EXECUTABLE_INSTALL) + install(TARGETS ${ZADD_EXECUTABLE_TARGET} DESTINATION ${ZADD_EXECUTABLE_INSTALL}) + endif() +endfunction(zadd_executable) diff --git a/zcmake/zadd_library.cmake b/zcmake/zadd_library.cmake new file mode 100644 index 0000000..e9b7bbe --- /dev/null +++ b/zcmake/zadd_library.cmake @@ -0,0 +1,207 @@ +include(CMakeParseArguments) +# zadd_library( +# +# # #################### 目标文件 ################# +# TARGET +# ... +# +# # #################### 依赖 #################### +# DEPENDENCIES +# ... +# +# # #################### 头文件路径 ############### +# INCLUDE_DIRECTORIES +# ... +# +# # #################### 链接的第三方库 ############ +# LINK_LIBRARIES +# ... +# +# # #################### 源文件 ################## +# SRC +# ... +# ) + +function(zadd_library) + set(oneValueArgs NAME TARGET) + set(multiValueArgs + INSTALL + SRC + DEPENDENCIES + DEFINES + LINK_LIBRARIES + LINK_DIRECTORIES + INCLUDE_DIRECTORIES) + + + + + cmake_parse_arguments(ZAL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + message("=================================================================") + message("= add_library: ${ZAL_TARGET}") + message("=================================================================") + message("CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}") + message("CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}") + if(ZAL_TARGET) + message("ADD TARGET:${ZAL_TARGET}") + else() + message(FATAL_ERROR,"ZAL not set target") + endif() + + if(ZAL_INSTALL) + message("INSTALL : ${ZAL_INSTALL}") + endif() + + if(ZAL_SRC) + # message("SRC: ${ZAL_SRC}") + # message("SRC:") + # foreach(EACH ${ZAL_SRC}) + # message(" ${EACH}") + # endforeach(EACH) + else() + message(FATAL_ERROR,"ZAL not set src") + endif() + + add_library(${ZAL_TARGET} ${ZAL_SRC}) + + + if(ZAL_DEFINES) + message("DEFINES:") + foreach(EACH ${ZAL_DEFINES}) + message(" ${EACH}") + endforeach(EACH) + target_compile_definitions(${ZAL_TARGET} PRIVATE ${ZAL_DEFINES}) + endif() + + if(ZAL_DEPENDENCIES) + message("DEPENDENCIES:") + foreach(EACH ${ZAL_DEPENDENCIES}) + message(" ${EACH}") + endforeach(EACH) + add_dependencies(${ZAL_TARGET} ${ZAL_DEPENDENCIES}) + endif() + + if(ZAL_LINK_LIBRARIES) + message("LINK_LIBRARIES:") + foreach(EACH ${ZAL_LINK_LIBRARIES}) + message(" ${EACH}") + endforeach(EACH) + target_link_libraries(${ZAL_TARGET} ${ZAL_LINK_LIBRARIES}) + endif() + + if(ZAL_LINK_DIRECTORIES) + message("LINK_DIRECTORIES:") + foreach(EACH ${ZAL_LINK_DIRECTORIES}) + message(" ${EACH}") + endforeach(EACH) + target_link_directories(${ZAL_TARGET} PRIVATE ${ZAL_LINK_DIRECTORIES}) + endif() + + if(ZAL_INCLUDE_DIRECTORIES) + message("INCLUDE_DIRECTORIES:") + foreach(EACH ${ZAL_INCLUDE_DIRECTORIES}) + message(" ${EACH}") + endforeach(EACH) + target_include_directories(${ZAL_TARGET} PRIVATE ${ZAL_INCLUDE_DIRECTORIES}) + endif() + + if(ZAL_INSTALL) + install(TARGETS ${ZAL_TARGET} DESTINATION ${ZAL_INSTALL}) + endif() + message("") + message("") + +endfunction(zadd_library) + + + +function(zadd_share_library) + set(oneValueArgs NAME TARGET) + set(multiValueArgs + INSTALL + SRC + DEPENDENCIES + DEFINES + LINK_LIBRARIES + LINK_DIRECTORIES + INCLUDE_DIRECTORIES) + + + + + cmake_parse_arguments(ZAL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + message("=================================================================") + message("= add_library: ${ZAL_TARGET}") + message("=================================================================") + message("CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}") + message("CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}") + if(ZAL_TARGET) + message("ADD TARGET:${ZAL_TARGET}") + else() + message(FATAL_ERROR,"ZAL not set target") + endif() + + if(ZAL_INSTALL) + message("INSTALL : ${ZAL_INSTALL}") + endif() + + if(ZAL_SRC) + # message("SRC: ${ZAL_SRC}") + # message("SRC:") + # foreach(EACH ${ZAL_SRC}) + # message(" ${EACH}") + # endforeach(EACH) + else() + message(FATAL_ERROR,"ZAL not set src") + endif() + + add_library(${ZAL_TARGET} SHARED ${ZAL_SRC}) + + + if(ZAL_DEFINES) + message("DEFINES:") + foreach(EACH ${ZAL_DEFINES}) + message(" ${EACH}") + endforeach(EACH) + target_compile_definitions(${ZAL_TARGET} PRIVATE ${ZAL_DEFINES}) + endif() + + if(ZAL_DEPENDENCIES) + message("DEPENDENCIES:") + foreach(EACH ${ZAL_DEPENDENCIES}) + message(" ${EACH}") + endforeach(EACH) + add_dependencies(${ZAL_TARGET} ${ZAL_DEPENDENCIES}) + endif() + + if(ZAL_LINK_LIBRARIES) + message("LINK_LIBRARIES:") + foreach(EACH ${ZAL_LINK_LIBRARIES}) + message(" ${EACH}") + endforeach(EACH) + target_link_libraries(${ZAL_TARGET} ${ZAL_LINK_LIBRARIES}) + endif() + + if(ZAL_LINK_DIRECTORIES) + message("LINK_DIRECTORIES:") + foreach(EACH ${ZAL_LINK_DIRECTORIES}) + message(" ${EACH}") + endforeach(EACH) + target_link_directories(${ZAL_TARGET} PRIVATE ${ZAL_LINK_DIRECTORIES}) + endif() + + if(ZAL_INCLUDE_DIRECTORIES) + message("INCLUDE_DIRECTORIES:") + foreach(EACH ${ZAL_INCLUDE_DIRECTORIES}) + message(" ${EACH}") + endforeach(EACH) + target_include_directories(${ZAL_TARGET} PRIVATE ${ZAL_INCLUDE_DIRECTORIES}) + endif() + + if(ZAL_INSTALL) + install(TARGETS ${ZAL_TARGET} DESTINATION ${ZAL_INSTALL}) + endif() + message("") + message("") + +endfunction(zadd_share_library) diff --git a/zcmake/zcmake.cmake b/zcmake/zcmake.cmake new file mode 100644 index 0000000..04417a4 --- /dev/null +++ b/zcmake/zcmake.cmake @@ -0,0 +1,4 @@ +include(CMakeParseArguments) +include(zcmake/zadd_library.cmake) +include(zcmake/zadd_executable.cmake) +include(zcmake/zadd_executable_simple.cmake) \ No newline at end of file