Initial commit

This commit is contained in:
Paul Hollinsky
2018-09-10 20:28:29 -04:00
commit e2e5017331
133 changed files with 24597 additions and 0 deletions
+156
View File
@@ -0,0 +1,156 @@
#include "include/device.h"
#include "communication/include/messagecallback.h"
#include <string.h>
#include <iostream>
#include <sstream>
using namespace icsneo;
static const uint8_t fromBase36Table[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 };
static const char toBase36Table[36] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
static const uint32_t toBase36Powers[7] = { 1, 36, 1296, 46656, 1679616, 60466176, 2176782336 };
#define MIN_BASE36_SERIAL (16796160)
#define MAX_SERIAL (2176782335)
std::string Device::SerialNumToString(uint32_t serial) {
if(serial == 0 || serial > MAX_SERIAL)
return "0";
std::stringstream ss;
if(serial >= MIN_BASE36_SERIAL) {
for (auto i = 5; i >= 0; i--) {
ss << toBase36Table[serial / toBase36Powers[i]];
serial = serial % toBase36Powers[i];
}
} else {
ss << serial;
}
return ss.str();
}
uint32_t Device::SerialStringToNum(const std::string& serial) {
if(Device::SerialStringIsNumeric(serial)) {
try {
return std::stoi(serial);
} catch(...) {
return 0;
}
}
if(serial.length() != 6)
return 0; // Non-numeric serial numbers should be 6 characters
uint32_t ret = 0;
for (auto i = 0; i < 6; i++) {
ret *= 36;
ret += fromBase36Table[(unsigned char)serial[i]];
}
return ret;
}
bool Device::SerialStringIsNumeric(const std::string& serial) {
if(serial.length() == 0)
return false;
if(serial.length() == 1)
return isdigit(serial[0]);
// Check the first two characters, at least one should be a character if we need to do a base36 conversion
return isdigit(serial[0]) && isdigit(serial[1]);
}
void Device::enableMessagePolling() {
if(messagePollingCallbackID != 0) // We are already polling
return;
messagePollingCallbackID = com->addMessageCallback(MessageCallback([this](std::shared_ptr<Message> message) {
pollingContainer.enqueue(message);
enforcePollingMessageLimit();
}));
}
bool Device::disableMessagePolling() {
if(messagePollingCallbackID == 0)
return true; // Not currently polling
auto ret = com->removeMessageCallback(messagePollingCallbackID);
getMessages(); // Flush any messages still in the container
messagePollingCallbackID = 0;
return ret;
}
std::vector<std::shared_ptr<Message>> Device::getMessages() {
std::vector<std::shared_ptr<Message>> ret;
getMessages(ret);
return ret;
}
bool Device::getMessages(std::vector<std::shared_ptr<Message>>& container, size_t limit) {
// A limit of zero indicates no limit
auto oglimit = limit;
if(limit == 0)
limit = (size_t)-1;
if(limit > (pollingContainer.size_approx() + 4))
limit = (pollingContainer.size_approx() + 4);
if(container.capacity() < limit)
container.resize(limit);
size_t actuallyRead = pollingContainer.try_dequeue_bulk(container.data(), limit);
container.resize(actuallyRead);
return actuallyRead <= oglimit;
}
void Device::enforcePollingMessageLimit() {
while(pollingContainer.size_approx() > pollingMessageLimit) {
std::shared_ptr<Message> throwAway;
pollingContainer.try_dequeue(throwAway);
// TODO Flag an error for the user!
}
}
bool Device::open() {
if(!com)
return false;
return com->open();
}
bool Device::close() {
if(!com)
return false;
return com->close();
}
bool Device::goOnline() {
if(!com->sendCommand(Communication::Command::EnableNetworkCommunication, true))
return false;
if(!com->sendCommand(Communication::Command::RequestSerialNumber))
return false;
com->addMessageCallback(CANMessageCallback([](std::shared_ptr<Message> message) {
std::shared_ptr<CANMessage> canMessage = std::static_pointer_cast<CANMessage>(message);
std::cout << "CAN 0x" << std::hex << canMessage->arbid << std::dec << " [" << canMessage->data.size() << "] " << std::hex;
for(const auto& b : canMessage->data)
std::cout << (int)b << ' ';
std::cout << std::dec << std::endl;
}));
return online = true;
}
bool Device::goOffline() {
return com->sendCommand(Communication::Command::EnableNetworkCommunication, false);
}
+34
View File
@@ -0,0 +1,34 @@
#include "device/include/devicefinder.h"
#include "device/neovifire/include/neovifire.h"
#include "device/neovifire2/include/neovifire2.h"
#include "device/plasion/include/neoviion.h"
#include "device/plasion/include/neoviplasma.h"
#include "device/radstar2/include/radstar2.h"
#include "device/radsupermoon/include/radsupermoon.h"
#include "device/valuecan3/include/valuecan3.h"
#include "device/valuecan4/include/valuecan4.h"
#include "device/vividcan/include/vividcan.h"
using namespace icsneo;
std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
std::vector<std::shared_ptr<Device>> foundDevices;
std::vector<std::vector<std::shared_ptr<Device>>> findResults;
findResults.push_back(NeoVIFIRE::Find());
findResults.push_back(NeoVIFIRE2::Find());
findResults.push_back(NeoVIION::Find());
findResults.push_back(NeoVIPLASMA::Find());
findResults.push_back(RADStar2::Find());
findResults.push_back(RADSupermoon::Find());
findResults.push_back(ValueCAN3::Find());
findResults.push_back(ValueCAN4::Find());
findResults.push_back(VividCAN::Find());
for(auto& results : findResults) {
if(results.size())
foundDevices.insert(foundDevices.end(), std::make_move_iterator(results.begin()), std::make_move_iterator(results.end()));
}
return foundDevices;
}
+75
View File
@@ -0,0 +1,75 @@
#ifndef __DEVICE_H__
#define __DEVICE_H__
#include <vector>
#include <memory>
#include <cstring>
#include "device/include/neodevice.h"
#include "communication/include/communication.h"
#include "third-party/concurrentqueue/concurrentqueue.h"
namespace icsneo {
class Device {
public:
Device(neodevice_t neodevice = {}) {
data = neodevice;
data.device = this;
setProductName("undefined");
}
virtual ~Device() {
disableMessagePolling();
close();
}
static std::string SerialNumToString(uint32_t serial);
static uint32_t SerialStringToNum(const std::string& serial);
static bool SerialStringIsNumeric(const std::string& serial);
std::string getProductName() const { return data.type; }
uint16_t getUSBProductId() const { return usbProductId; }
std::string getSerial() const { return data.serial; }
uint32_t getSerialNumber() const { return Device::SerialStringToNum(getSerial()); }
const neodevice_t& getNeoDevice() const { return data; }
virtual bool open();
virtual bool close();
virtual bool isOnline() const { return online; }
virtual bool goOnline();
virtual bool goOffline();
// Message polling related functions
void enableMessagePolling();
bool disableMessagePolling();
std::vector<std::shared_ptr<Message>> getMessages();
bool getMessages(std::vector<std::shared_ptr<Message>>& container, size_t limit = 0);
size_t getPollingMessageLimit() { return pollingMessageLimit; }
void setPollingMessageLimit(size_t newSize) {
pollingMessageLimit = newSize;
enforcePollingMessageLimit();
}
protected:
uint16_t usbProductId = 0;
bool online = false;
int messagePollingCallbackID = 0;
std::shared_ptr<Communication> com;
neodevice_t& getWritableNeoDevice() { return data; }
void setProductName(const std::string& newName) {
#pragma warning( disable : 4996 )
auto copied = newName.copy(data.type, sizeof(data.type) - 1);
data.type[copied] = '\0';
}
private:
neodevice_t data;
size_t pollingMessageLimit = 20000;
moodycamel::ConcurrentQueue<std::shared_ptr<Message>> pollingContainer;
void enforcePollingMessageLimit();
};
};
#endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef __DEVICEFINDER_H_
#define __DEVICEFINDER_H_
#include "device/include/device.h"
#include <vector>
#include <memory>
namespace icsneo {
class DeviceFinder {
public:
static std::vector<std::shared_ptr<Device>> FindAll();
};
};
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef __NEODEVICE_H_
#define __NEODEVICE_H_
#include <stdint.h>
#ifdef __cplusplus
// A forward declaration is needed as there is a circular dependency
namespace icsneo {
class Device;
};
typedef icsneo::Device* devicehandle_t;
#else
typedef void* devicehandle_t;
#endif
typedef int32_t neodevice_handle_t;
typedef struct {
devicehandle_t device;
neodevice_handle_t handle;
char serial[7];
char type[64];
} neodevice_t;
#endif
+55
View File
@@ -0,0 +1,55 @@
#ifndef __NEOVIFIRE_H_
#define __NEOVIFIRE_H_
#include "device/include/device.h"
#include "platform/include/ftdi.h"
namespace icsneo {
class NeoVIFIRE : public Device {
public:
static constexpr const char* PRODUCT_NAME = "neoVI FIRE";
static constexpr const uint16_t USB_PRODUCT_ID = 0x0701;
NeoVIFIRE(neodevice_t neodevice) : Device(neodevice) {
com = std::make_shared<Communication>(std::make_shared<FTDI>(getWritableNeoDevice()));
setProductName(PRODUCT_NAME);
usbProductId = USB_PRODUCT_ID;
}
enum class Mode : char {
Application = 'A',
Bootloader = 'B'
};
bool goOnline() {
// Enter mode is only needed on very old FIRE devices, will be ignored by newer devices
if(!enterMode(Mode::Application))
return false;
return Device::goOnline();
}
bool enterMode(Mode mode) {
// Included for compatibility with bootloaders on very old FIRE devices
// Mode will be a uppercase char like 'A'
if(!com->rawWrite({ (uint8_t)mode }))
return false;
// We then expect to see that same mode back in lowercase
// This won't happen in the case of new devices, though, so we assume it worked
return true;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(USB_PRODUCT_ID))
found.push_back(std::make_shared<NeoVIFIRE>(neodevice));
return found;
}
};
};
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef __NEOVIFIRE2_H_
#define __NEOVIFIRE2_H_
#include "device/include/device.h"
#include "platform/include/ftdi.h"
namespace icsneo {
class NeoVIFIRE2 : public Device {
public:
static constexpr const char* PRODUCT_NAME = "neoVI FIRE 2";
static constexpr const uint16_t USB_PRODUCT_ID = 0x1000;
NeoVIFIRE2(neodevice_t neodevice) : Device(neodevice) {
com = std::make_shared<Communication>(std::make_shared<FTDI>(getWritableNeoDevice()));
setProductName(PRODUCT_NAME);
usbProductId = USB_PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(USB_PRODUCT_ID))
found.push_back(std::make_shared<NeoVIFIRE2>(neodevice));
return found;
}
};
};
#endif
+30
View File
@@ -0,0 +1,30 @@
#ifndef __NEOVIION_H_
#define __NEOVIION_H_
#include "device/plasion/include/plasion.h"
#include "platform/include/ftdi.h"
namespace icsneo {
class NeoVIION : public Plasion {
public:
static constexpr const char* PRODUCT_NAME = "neoVI ION";
static constexpr const uint16_t USB_PRODUCT_ID = 0x0901;
NeoVIION(neodevice_t neodevice) : Plasion(neodevice) {
setProductName(PRODUCT_NAME);
usbProductId = USB_PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(USB_PRODUCT_ID))
found.push_back(std::make_shared<NeoVIION>(neodevice));
return found;
}
};
};
#endif
+30
View File
@@ -0,0 +1,30 @@
#ifndef __NEOVIPLASMA_H_
#define __NEOVIPLASMA_H_
#include "device/plasion/include/plasion.h"
#include "platform/include/ftdi.h"
namespace icsneo {
class NeoVIPLASMA : public Plasion {
public:
static constexpr const char* PRODUCT_NAME = "neoVI PLASMA";
static constexpr const uint16_t USB_PRODUCT_ID = 0x0801;
NeoVIPLASMA(neodevice_t neodevice) : Plasion(neodevice) {
setProductName(PRODUCT_NAME);
usbProductId = USB_PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(USB_PRODUCT_ID))
found.push_back(std::make_shared<NeoVIPLASMA>(neodevice));
return found;
}
};
};
#endif
+19
View File
@@ -0,0 +1,19 @@
#ifndef __PLASION_H_
#define __PLASION_H_
#include "device/include/device.h"
#include "communication/include/multichannelcommunication.h"
#include "platform/include/ftdi.h"
namespace icsneo {
class Plasion : public Device {
public:
Plasion(neodevice_t neodevice) : Device(neodevice) {
com = std::make_shared<MultiChannelCommunication>(std::make_shared<FTDI>(getWritableNeoDevice()));
}
};
};
#endif
+32
View File
@@ -0,0 +1,32 @@
#ifndef __RADSTAR2_H_
#define __RADSTAR2_H_
#include "device/include/device.h"
#include "platform/include/ftdi.h"
namespace icsneo {
class RADStar2 : public Device {
public:
// Serial numbers start with RS
static constexpr const char* PRODUCT_NAME = "RADStar 2";
static constexpr const uint16_t USB_PRODUCT_ID = 0x0005;
RADStar2(neodevice_t neodevice) : Device(neodevice) {
com = std::make_shared<Communication>(std::make_shared<FTDI>(getWritableNeoDevice()));
setProductName(PRODUCT_NAME);
usbProductId = USB_PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(USB_PRODUCT_ID))
found.push_back(std::make_shared<RADStar2>(neodevice));
return found;
}
};
};
#endif
@@ -0,0 +1,34 @@
#ifndef __RADSUPERMOON_H_
#define __RADSUPERMOON_H_
#include "device/include/device.h"
#include "platform/include/ftdi.h"
namespace icsneo {
class RADSupermoon : public Device {
public:
// Serial numbers start with VV
static constexpr const char* PRODUCT_NAME = "RADSupermoon";
static constexpr const uint16_t USB_PRODUCT_ID = 0x1201;
RADSupermoon(neodevice_t neodevice) : Device(neodevice) {
com = std::make_shared<Communication>(std::make_shared<FTDI>(getWritableNeoDevice()));
com->setAlign16Bit(false);
setProductName(PRODUCT_NAME);
usbProductId = USB_PRODUCT_ID;
}
// RSM does not connect at all yet (needs FTDI D3xx driver, not the 2xx compatible one)
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(USB_PRODUCT_ID))
found.push_back(std::make_shared<RADSupermoon>(neodevice));
return found;
}
};
};
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef __VALUECAN3_H_
#define __VALUECAN3_H_
#include "device/include/device.h"
#include "platform/include/ftdi.h"
namespace icsneo {
class ValueCAN3 : public Device {
public:
static constexpr const char* PRODUCT_NAME = "ValueCAN 3";
static constexpr const uint16_t USB_PRODUCT_ID = 0x0601;
ValueCAN3(neodevice_t neodevice) : Device(neodevice) {
com = std::make_shared<Communication>(std::make_shared<FTDI>(getWritableNeoDevice()));
setProductName(PRODUCT_NAME);
usbProductId = USB_PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(USB_PRODUCT_ID))
found.push_back(std::make_shared<ValueCAN3>(neodevice));
return found;
}
};
};
#endif
+32
View File
@@ -0,0 +1,32 @@
#ifndef __VALUECAN4_H_
#define __VALUECAN4_H_
#include "device/include/device.h"
#include "platform/include/stm32.h"
namespace icsneo {
class ValueCAN4 : public Device {
public:
// Serial numbers are V0 for 4-4, VE for 4-2EL, V2 for 4-2, and V1 for 4-1
static constexpr const char* PRODUCT_NAME = "ValueCAN 4";
static constexpr const uint16_t USB_PRODUCT_ID = 0x1101;
ValueCAN4(neodevice_t neodevice) : Device(neodevice) {
com = std::make_shared<Communication>(std::make_shared<STM32>(getWritableNeoDevice()));
setProductName(PRODUCT_NAME);
usbProductId = USB_PRODUCT_ID;
}
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : STM32::FindByProduct(USB_PRODUCT_ID))
found.push_back(std::make_shared<ValueCAN4>(neodevice));
return found;
}
};
};
#endif
+34
View File
@@ -0,0 +1,34 @@
#ifndef __VIVIDCAN_H_
#define __VIVIDCAN_H_
#include "device/include/device.h"
#include "platform/include/stm32.h"
namespace icsneo {
class VividCAN : public Device {
public:
// Serial numbers start with VV
static constexpr const char* PRODUCT_NAME = "VividCAN";
static constexpr const uint16_t USB_PRODUCT_ID = 0x1102;
VividCAN(neodevice_t neodevice) : Device(neodevice) {
com = std::make_shared<Communication>(std::make_shared<STM32>(getWritableNeoDevice()));
setProductName(PRODUCT_NAME);
usbProductId = USB_PRODUCT_ID;
}
bool goOnline() { return false; }
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : STM32::FindByProduct(USB_PRODUCT_ID))
found.push_back(std::make_shared<VividCAN>(neodevice));
return found;
}
};
};
#endif