parent
63c81b1c3d
commit
3ddb832708
|
|
@ -10,3 +10,4 @@ third-party/concurrentqueue/tests
|
|||
*.bak
|
||||
.vs
|
||||
.cache
|
||||
*.wav
|
||||
|
|
@ -69,7 +69,7 @@ A2BDecoder::A2BDecoder(
|
|||
) : A2BDecoder(std::make_unique<std::ifstream>(filename, std::ios::binary), chSize16, chMap) { }
|
||||
|
||||
A2BDecoder::operator bool() const {
|
||||
return initialized && *stream;
|
||||
return initialized && stream->good() && !stream->eof();
|
||||
}
|
||||
|
||||
void A2BDecoder::initializeFromHeader() {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ option(LIBICSNEO_BUILD_CPP_SIMPLE_EXAMPLE "Build the simple C++ example." ON)
|
|||
option(LIBICSNEO_BUILD_CPP_INTERACTIVE_EXAMPLE "Build the command-line interactive C++ example." ON)
|
||||
option(LIBICSNEO_BUILD_CPP_A2B_EXAMPLE "Build the A2B example." ON)
|
||||
option(LIBICSNEO_BUILD_CPP_LIN_EXAMPLE "Build the LIN example." ON)
|
||||
option(LIBICSNEO_BUILD_CPP_COREMINI_EXAMPLE "Build the Coremini example." ON)
|
||||
|
||||
# Disabled until we properly build these in-tree
|
||||
# option(LIBICSNEO_BUILD_CSHARP_INTERACTIVE_EXAMPLE "Build the command-line interactive C# example." OFF)
|
||||
# option(LIBICSNEO_BUILD_JAVA_INTERACTIVE_EXAMPLE "Build the command-line interactive Java example." OFF)
|
||||
|
|
@ -36,6 +38,11 @@ endif()
|
|||
if(LIBICSNEO_BUILD_CPP_LIN_EXAMPLE)
|
||||
add_subdirectory(cpp/lin)
|
||||
endif()
|
||||
|
||||
if(LIBICSNEO_BUILD_CPP_COREMINI_EXAMPLE)
|
||||
add_subdirectory(cpp/coremini)
|
||||
endif()
|
||||
|
||||
# if(LIBICSNEO_BUILD_CSHARP_INTERACTIVE_EXAMPLE)
|
||||
# add_subdirectory(csharp)
|
||||
# endif()
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
# libicsneo C++ Example
|
||||
|
||||
This is an example console application which uses libicsneo to connect to an Intrepid Control Systems hardware device. It has both interactive and simple examples for sending and receiving CAN & CAN FD traffic.
|
||||
|
||||
## Building
|
||||
|
||||
This example shows how to use the C++ version of libicsneo with CMake. It will build libicsneo along with your project.
|
||||
|
||||
First, you need to clone the repository onto your local machine. Run:
|
||||
|
||||
```shell
|
||||
git clone https://github.com/intrepidcs/libicsneo-examples --recursive
|
||||
```
|
||||
|
||||
Alternatively, if you cloned without the `--recursive flag`, you must enter the `libicsneo-examples` folder and run the following:
|
||||
|
||||
```shell
|
||||
git submodule update --recursive --init
|
||||
```
|
||||
|
||||
If you haven't done this, `third-party/libicsneo` will be empty and you won't be able to build!
|
||||
|
||||
### Windows using Visual Studio 2017+
|
||||
|
||||
1. Launch Visual Studio and open the `libicsneo-examples` folder.
|
||||
2. Choose `File->Open->CMake...`
|
||||
3. Navigate to the `libicsneocpp-example` folder and select the `CMakeLists.txt` there.
|
||||
4. Visual Studio will process the CMake project.
|
||||
5. Choose the dropdown attached to the green play button (labelled "select startup item...") in the toolbar.
|
||||
6. Select `libicsneocpp-simple-example.exe`
|
||||
7. Press the green play button to compile and run the example.
|
||||
|
||||
### Ubuntu 18.04 LTS
|
||||
|
||||
1. Install dependencies with `sudo apt update` then `sudo apt install build-essential cmake libusb-1.0-0-dev libpcap0.8-dev`
|
||||
2. Change directories to your `libicsneo-examples/libicsneocpp-example` folder and create a build directory by running `mkdir -p build`
|
||||
3. Enter the build directory with `cd build`
|
||||
4. Run `cmake ..` to generate your Makefile.
|
||||
* Hint! Running `cmake -DCMAKE_BUILD_TYPE=Debug ..` will generate the proper scripts to build debug, and `cmake -DCMAKE_BUILD_TYPE=Release ..` will generate the proper scripts to build with all optimizations on.
|
||||
5. Run `make libicsneocpp-interactive-example` to build.
|
||||
* Hint! Speed up your build by using multiple processors! Use `make libicsneocpp-interactive-example -j#` where `#` is the number of cores/threads your system has plus one. For instance, on a standard 8 thread Intel i7, you might use `-j9` for an ~8x speedup.
|
||||
6. Now run `sudo ./libicsneocpp-interactive-example` to run the example.
|
||||
* Hint! In order to run without sudo, you will need to set up the udev rules. Copy `libicsneo-examples/third-party/libicsneo/99-intrepidcs.rules` to `/etc/udev/rules.d`, then run `udevadm control --reload-rules && udevadm trigger` afterwards. While the program will still run without setting up these rules, it will fail to open any devices.
|
||||
7. If you wish to run the simple example instead, replace any instances of "interactive" with "simple" in steps 5 and 6.
|
||||
|
||||
### macOS
|
||||
|
||||
Instructions coming soon™
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
#include <icsneo/device/tree/rada2b/rada2bsettings.h>
|
||||
#include <icsneo/communication/message/callback/streamoutput/a2bdecoder.h>
|
||||
#include <string>
|
||||
#include <math.h>
|
||||
|
||||
static constexpr size_t numFramesInWave = 48;
|
||||
|
||||
|
|
@ -70,7 +71,7 @@ void example0(std::shared_ptr<icsneo::Device>& rada2b) {
|
|||
|
||||
decoder.outputAll(rada2b); // Output entire wave file
|
||||
|
||||
elapsedTime += ((double)numFramesInWave) * 1.0/48000.0;
|
||||
elapsedTime += (static_cast<double>(numFramesInWave)) * 1.0/48000.0;
|
||||
|
||||
decoder.stream->clear();
|
||||
decoder.stream->seekg(0, std::ios::beg);
|
||||
|
|
@ -78,7 +79,7 @@ void example0(std::shared_ptr<icsneo::Device>& rada2b) {
|
|||
while(decoder && elapsedTime < 5.0) {
|
||||
auto msg = decoder.decode();
|
||||
rada2b->transmit(msg);
|
||||
elapsedTime += ((double)msg->getNumFrames())*1.0/48000.0;
|
||||
elapsedTime += (static_cast<double>(msg->getNumFrames()))*1.0/48000.0;
|
||||
}
|
||||
|
||||
decoder.stream->clear();
|
||||
|
|
@ -105,11 +106,11 @@ void example1(std::shared_ptr<icsneo::Device>& rada2b) {
|
|||
|
||||
// Example 2: RADA2B settings
|
||||
void example2(std::shared_ptr<icsneo::Device>& rada2b) {
|
||||
uint32_t tdm;
|
||||
uint8_t numChannels;
|
||||
{
|
||||
// Get device settings
|
||||
auto* settings = rada2b->settings.get();
|
||||
auto* rada2bSettings = (icsneo::RADA2BSettings*)settings;
|
||||
auto* rada2bSettings = static_cast<icsneo::RADA2BSettings*>(settings);
|
||||
|
||||
// Check if monitor mode is enabled
|
||||
auto type = rada2bSettings->getNodeType(icsneo::RADA2BSettings::RADA2BDevice::Monitor);
|
||||
|
|
@ -121,9 +122,9 @@ void example2(std::shared_ptr<icsneo::Device>& rada2b) {
|
|||
}
|
||||
|
||||
// Get current tdm mode
|
||||
tdm = rada2bSettings->getTDMModeInt(icsneo::RADA2BSettings::RADA2BDevice::Node);
|
||||
numChannels = rada2bSettings->getNumChannels(icsneo::RADA2BSettings::RADA2BDevice::Node);
|
||||
|
||||
std::cout << "Current tdm mode: " << tdm << std::endl;
|
||||
std::cout << "Current num channels: " << static_cast<uint32_t>(numChannels) << std::endl;
|
||||
// Set node type to master node.
|
||||
rada2bSettings->setNodeType(icsneo::RADA2BSettings::RADA2BDevice::Node, icsneo::RADA2BSettings::NodeType::Master);
|
||||
|
||||
|
|
@ -174,6 +175,68 @@ void example3() {
|
|||
std::cout << "Was received from monitor: " << msg.isMonitorMsg() << std::endl;
|
||||
}
|
||||
|
||||
// Example 4: Packaging and transmitting sine wave using A2BMessage API
|
||||
void example4(std::shared_ptr<icsneo::Device>& rada2b) {
|
||||
std::cout << "Transmitting a 1000 hz sine wave." << std::endl;
|
||||
|
||||
float deltaTime = static_cast<float>(1.0/48000.0);
|
||||
float elapsedTime = 0.0;
|
||||
float twoPI = static_cast<float>(2.0*atan(1.0)*4.0);
|
||||
float frequency = 1000;
|
||||
float amplitude = static_cast<float>((1 << 23) - 1);
|
||||
|
||||
uint8_t icsChannel = 0; // Play audio on channel 2, upstream, see docs for details
|
||||
|
||||
|
||||
// Play for roughly 5 seconds
|
||||
while(elapsedTime < 5.0) {
|
||||
// Allocate message
|
||||
std::shared_ptr<icsneo::A2BMessage> a2bmsgPtr = std::make_shared<icsneo::A2BMessage>(static_cast<uint8_t>(4), false, static_cast<size_t>(2048));
|
||||
|
||||
icsneo::A2BMessage& a2bmsg = *a2bmsgPtr.get();
|
||||
a2bmsg.network = icsneo::Network(icsneo::Network::NetID::A2B2);
|
||||
|
||||
for(size_t frame = 0; frame < a2bmsg.getNumFrames(); frame++) {
|
||||
|
||||
// Sine wave sample, amplitude 1000, frequency 1000 hz
|
||||
|
||||
float contSample = amplitude*sin(twoPI*frequency*elapsedTime);
|
||||
icsneo::A2BPCMSample sample = static_cast<icsneo::A2BPCMSample>(contSample);
|
||||
|
||||
// Set sample for each frame in message
|
||||
a2bmsg[frame][icsChannel] = sample;
|
||||
|
||||
elapsedTime+=deltaTime;
|
||||
}
|
||||
|
||||
// Transmit message to device
|
||||
|
||||
if(!rada2b->transmit(a2bmsgPtr)) {
|
||||
std::cout << "Failed to transmit." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Example 5: Wave loop back
|
||||
void example5(std::shared_ptr<icsneo::Device>& rada2b) {
|
||||
|
||||
auto listener = [&rada2b]() {
|
||||
auto handler = rada2b->addMessageCallback(std::make_shared<icsneo::A2BWAVOutput>("looped.wav", 48000));
|
||||
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||
rada2b->removeMessageCallback(handler);
|
||||
};
|
||||
|
||||
// Listen on another thread
|
||||
std::thread listenerThread{listener};
|
||||
|
||||
// Transmit wave file using example0
|
||||
|
||||
example0(rada2b);
|
||||
listenerThread.join();
|
||||
}
|
||||
|
||||
void displayUsage() {
|
||||
std::cout << "libicsneo A2B example" << std::endl;
|
||||
|
|
@ -187,8 +250,10 @@ void displayUsage() {
|
|||
std::cout << "Example options:" << std::endl;
|
||||
std::cout << "0\ttx" << std::endl;
|
||||
std::cout << "1\trx" << std::endl;
|
||||
std::cout << "2\trx split channel" << std::endl;
|
||||
std::cout << "2\tSet RADA2B settings" << std::endl;
|
||||
std::cout << "3\tA2BMessage API" << std::endl;
|
||||
std::cout << "4\tPackaging and transmitting sine wave using A2BMessage API" << std::endl;
|
||||
std::cout << "5\tWave loopback" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
|
@ -212,7 +277,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
int option = atoi(arguments[2].c_str());
|
||||
|
||||
if(option < 0 || option > 3) {
|
||||
if(option < 0 || option > 5) {
|
||||
std::cerr << "Invalid usage." << std::endl;
|
||||
displayUsage();
|
||||
return EXIT_FAILURE;
|
||||
|
|
@ -274,6 +339,12 @@ int main(int argc, char **argv) {
|
|||
case 3:
|
||||
example3();
|
||||
break;
|
||||
case 4:
|
||||
example4(rada2b);
|
||||
break;
|
||||
case 5:
|
||||
example5(rada2b);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
cmake_minimum_required(VERSION 3.2)
|
||||
project(libicsneocpp-coremini VERSION 0.2.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED 11)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Add an include directory like so if desired
|
||||
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
# Enable Warnings
|
||||
if(MSVC)
|
||||
# Force to always compile with W4
|
||||
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
endif()
|
||||
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
|
||||
endif()
|
||||
|
||||
# Add libicsneo, usually a git submodule within your project works well
|
||||
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libicsneo ${CMAKE_CURRENT_BINARY_DIR}/third-party/libicsneo)
|
||||
|
||||
add_executable(libicsneocpp-coremini src/coremini.cpp)
|
||||
target_link_libraries(libicsneocpp-coremini icsneocpp)
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// Usage:
|
||||
// ./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH]
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <icsneo/icsneocpp.h>
|
||||
|
||||
void displayUsage() {
|
||||
std::cout << "Usage:\n";
|
||||
std::cout << "./libicsneocpp-coremini [DEVICE_SERIAL] [COREMINI_SCRIPT_PATH]\n";
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::vector<std::string> arguments(argv, argv + argc);
|
||||
|
||||
if(arguments.size() != 3) {
|
||||
displayUsage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
std::cout << icsneo::GetVersion() << std::endl;
|
||||
|
||||
const auto& devices = icsneo::FindAllDevices();
|
||||
|
||||
auto it = std::find_if(
|
||||
devices.begin(),
|
||||
devices.end(),
|
||||
[&arguments](const auto &d)
|
||||
{ return d->getSerial() == arguments[1]; });
|
||||
|
||||
if(it == devices.end()) {
|
||||
std::cout << "Failed to find device." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<icsneo::Device> device = *it;
|
||||
if(!device->open()) {
|
||||
std::cout << "Failed to open device." << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(!device->goOnline()) {
|
||||
std::cout << "Failed to go online." << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!device->uploadCoremini(std::make_unique<std::ifstream>(arguments[2], std::ios::binary), icsneo::Disk::MemoryType::Flash))
|
||||
{
|
||||
std::cout << "Failed to upload coremini" << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;
|
||||
}
|
||||
|
||||
if (!device->startScript(icsneo::Disk::MemoryType::Flash))
|
||||
{
|
||||
std::cout << "Failed to start script" << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl;
|
||||
}
|
||||
|
||||
device->goOffline();
|
||||
device->close();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -125,10 +125,10 @@ public:
|
|||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
return (TDMMode)(deviceSettings.tdmMode);
|
||||
return static_cast<TDMMode>(deviceSettings.tdmMode);
|
||||
}
|
||||
|
||||
uint8_t getTDMModeInt(RADA2BDevice device) const {
|
||||
uint8_t getNumChannels(RADA2BDevice device) const {
|
||||
return tdmModeToChannelNum(getTDMMode(device));
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ public:
|
|||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
return (ChannelSize)(~(deviceSettings.flags & a2bSettingsFlag16bit));
|
||||
return static_cast<ChannelSize>(~(deviceSettings.flags & a2bSettingsFlag16bit));
|
||||
}
|
||||
|
||||
uint8_t getChannelOffset(RADA2BDevice device, A2BMessage::A2BDirection dir) const {
|
||||
|
|
@ -154,7 +154,7 @@ public:
|
|||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
return (NodeType)(deviceSettings.nodeType);
|
||||
return static_cast<NodeType>(deviceSettings.nodeType);
|
||||
}
|
||||
|
||||
void setNodeType(RADA2BDevice device, NodeType newType) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue