Device: Add RAD-Gemini
parent
3f3300d677
commit
563c444def
|
|
@ -27,6 +27,7 @@ each of the respective APIs.
|
||||||
- RAD-EpsilonXL
|
- RAD-EpsilonXL
|
||||||
- RAD-Galaxy
|
- RAD-Galaxy
|
||||||
- RAD-Galaxy 2
|
- RAD-Galaxy 2
|
||||||
|
- RAD-Gemini
|
||||||
- RAD-Gigastar
|
- RAD-Gigastar
|
||||||
- RAD-Gigastar 2
|
- RAD-Gigastar 2
|
||||||
- RAD-Moon 2
|
- RAD-Moon 2
|
||||||
|
|
|
||||||
|
|
@ -1076,6 +1076,9 @@ int LegacyDLLExport icsneoGetDeviceSettingsType(void* hObject, EPlasmaIonVnetCha
|
||||||
case NEODEVICE_RADMOON3:
|
case NEODEVICE_RADMOON3:
|
||||||
*pDeviceSettingsType = DeviceRADMoon3SettingsType;
|
*pDeviceSettingsType = DeviceRADMoon3SettingsType;
|
||||||
break;
|
break;
|
||||||
|
case NEODEVICE_RADGEMINI:
|
||||||
|
*pDeviceSettingsType = DeviceRADGeminiSettingsType;
|
||||||
|
break;
|
||||||
case NEODEVICE_RED2:
|
case NEODEVICE_RED2:
|
||||||
*pDeviceSettingsType = DeviceRed2SettingsType;
|
*pDeviceSettingsType = DeviceRed2SettingsType;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,7 @@ void init_chipid(pybind11::module_& m) {
|
||||||
.value("RADCOMET3_ZCHIP", ChipID::RADCOMET3_ZCHIP)
|
.value("RADCOMET3_ZCHIP", ChipID::RADCOMET3_ZCHIP)
|
||||||
.value("Connect_LINUX", ChipID::Connect_LINUX)
|
.value("Connect_LINUX", ChipID::Connect_LINUX)
|
||||||
.value("RADGigastar2_ZYNQ", ChipID::RADGigastar2_ZYNQ)
|
.value("RADGigastar2_ZYNQ", ChipID::RADGigastar2_ZYNQ)
|
||||||
|
.value("RADGemini_MCHIP", ChipID::RADGemini_MCHIP)
|
||||||
.value("Invalid", ChipID::Invalid);
|
.value("Invalid", ChipID::Invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ void init_devicetype(pybind11::module_& m) {
|
||||||
.value("RADEpsilonXL", DeviceType::Enum::RADEpsilonXL)
|
.value("RADEpsilonXL", DeviceType::Enum::RADEpsilonXL)
|
||||||
.value("RADGalaxy2", DeviceType::Enum::RADGalaxy2)
|
.value("RADGalaxy2", DeviceType::Enum::RADGalaxy2)
|
||||||
.value("RADMoon3", DeviceType::Enum::RADMoon3)
|
.value("RADMoon3", DeviceType::Enum::RADMoon3)
|
||||||
|
.value("RADGemini", DeviceType::Enum::RADGemini)
|
||||||
.value("RADComet", DeviceType::Enum::RADComet)
|
.value("RADComet", DeviceType::Enum::RADComet)
|
||||||
.value("FIRE3_FlexRay", DeviceType::Enum::FIRE3_FlexRay)
|
.value("FIRE3_FlexRay", DeviceType::Enum::FIRE3_FlexRay)
|
||||||
.value("FIRE3_T1S_LIN", DeviceType::Enum::FIRE3_T1S_LIN)
|
.value("FIRE3_T1S_LIN", DeviceType::Enum::FIRE3_T1S_LIN)
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,10 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
|
||||||
makeIfSerialMatches<RADMoon3>(dev, newFoundDevices);
|
makeIfSerialMatches<RADMoon3>(dev, newFoundDevices);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __RADGEMINI_H_
|
||||||
|
makeIfSerialMatches<RADGemini>(dev, newFoundDevices);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __RADMOONDUO_H_
|
#ifdef __RADMOONDUO_H_
|
||||||
makeIfSerialMatches<RADMoonDuo>(dev, newFoundDevices);
|
makeIfSerialMatches<RADMoonDuo>(dev, newFoundDevices);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -384,6 +388,10 @@ const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
|
||||||
RADMoon3::DEVICE_TYPE,
|
RADMoon3::DEVICE_TYPE,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __RADGEMINI_H_
|
||||||
|
RADGemini::DEVICE_TYPE,
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __RADMOONDUO_H_
|
#ifdef __RADMOONDUO_H_
|
||||||
RADMoonDuo::DEVICE_TYPE,
|
RADMoonDuo::DEVICE_TYPE,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,7 @@ enum class ChipID : uint8_t {
|
||||||
RADCOMET3_ZCHIP = 125,
|
RADCOMET3_ZCHIP = 125,
|
||||||
Connect_LINUX = 126,
|
Connect_LINUX = 126,
|
||||||
RADGigastar2_ZYNQ = 131,
|
RADGigastar2_ZYNQ = 131,
|
||||||
|
RADGemini_MCHIP = 135,
|
||||||
Invalid = 255
|
Invalid = 255
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,8 @@ public:
|
||||||
Connect = 51,
|
Connect = 51,
|
||||||
RADComet3 = 54,
|
RADComet3 = 54,
|
||||||
RADMoonT1S = 56,
|
RADMoonT1S = 56,
|
||||||
RADGigastar2 = 57
|
RADGigastar2 = 57,
|
||||||
|
RADGemini = 60,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ProductID getProductID() const = 0;
|
virtual ProductID getProductID() const = 0;
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ public:
|
||||||
RADGigastar2 = (0x00000029),
|
RADGigastar2 = (0x00000029),
|
||||||
FIRE3_T1S_LIN = (0x0000002A),
|
FIRE3_T1S_LIN = (0x0000002A),
|
||||||
FIRE3_T1S_SENT = (0x0000002B),
|
FIRE3_T1S_SENT = (0x0000002B),
|
||||||
|
RADGemini = (0x0000002C),
|
||||||
RED = (0x00000040),
|
RED = (0x00000040),
|
||||||
ECU = (0x00000080),
|
ECU = (0x00000080),
|
||||||
IEVB = (0x00000100),
|
IEVB = (0x00000100),
|
||||||
|
|
@ -148,6 +149,8 @@ public:
|
||||||
return "RAD-EpsilonXL";
|
return "RAD-EpsilonXL";
|
||||||
case RADMoon3:
|
case RADMoon3:
|
||||||
return "RAD-Moon 3";
|
return "RAD-Moon 3";
|
||||||
|
case RADGemini:
|
||||||
|
return "RAD-Gemini";
|
||||||
case RADComet:
|
case RADComet:
|
||||||
return "RAD-Comet";
|
return "RAD-Comet";
|
||||||
case RED:
|
case RED:
|
||||||
|
|
@ -271,6 +274,7 @@ private:
|
||||||
#define ICSNEO_DEVICETYPE_RADGIGASTAR2 ((devicetype_t)0x00000029)
|
#define ICSNEO_DEVICETYPE_RADGIGASTAR2 ((devicetype_t)0x00000029)
|
||||||
#define ICSNEO_DEVICETYPE_FIRE3_T1S_LIN ((devicetype_t)0x0000002A)
|
#define ICSNEO_DEVICETYPE_FIRE3_T1S_LIN ((devicetype_t)0x0000002A)
|
||||||
#define ICSNEO_DEVICETYPE_FIRE3_T1S_SENT ((devicetype_t)0x0000002B)
|
#define ICSNEO_DEVICETYPE_FIRE3_T1S_SENT ((devicetype_t)0x0000002B)
|
||||||
|
#define ICSNEO_DEVICETYPE_RADGEMINI ((devicetype_t)0x0000002C)
|
||||||
#define ICSNEO_DEVICETYPE_RED ((devicetype_t)0x00000040)
|
#define ICSNEO_DEVICETYPE_RED ((devicetype_t)0x00000040)
|
||||||
#define ICSNEO_DEVICETYPE_ECU ((devicetype_t)0x00000080)
|
#define ICSNEO_DEVICETYPE_ECU ((devicetype_t)0x00000080)
|
||||||
#define ICSNEO_DEVICETYPE_IEVB ((devicetype_t)0x00000100)
|
#define ICSNEO_DEVICETYPE_IEVB ((devicetype_t)0x00000100)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
#ifndef __RADGEMINI_H_
|
||||||
|
#define __RADGEMINI_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/device/device.h"
|
||||||
|
#include "icsneo/device/devicetype.h"
|
||||||
|
#include "icsneo/device/tree/radgemini/radgeminisettings.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
class RADGemini : public Device {
|
||||||
|
public:
|
||||||
|
// Serial numbers start with GE
|
||||||
|
// USB PID is 0x110E, standard driver is CDCACM
|
||||||
|
ICSNEO_FINDABLE_DEVICE(RADGemini, DeviceType::RADGemini, "GE");
|
||||||
|
|
||||||
|
static const std::vector<Network>& GetSupportedNetworks() {
|
||||||
|
static std::vector<Network> supportedNetworks = {
|
||||||
|
Network::NetID::MDIO_01,
|
||||||
|
};
|
||||||
|
return supportedNetworks;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getEthPhyRegControlSupported() const override { return true; }
|
||||||
|
|
||||||
|
bool isOnlineSupported() const override { return false; }
|
||||||
|
|
||||||
|
bool supportsTC10() const override { return true; }
|
||||||
|
|
||||||
|
ProductID getProductID() const override { return ProductID::RADGemini; }
|
||||||
|
|
||||||
|
BootloaderPipeline getBootloader() override {
|
||||||
|
return BootloaderPipeline()
|
||||||
|
.add<EnterBootloaderPhase>()
|
||||||
|
.add<FlashPhase>(ChipID::RADGemini_MCHIP, BootloaderCommunication::RED)
|
||||||
|
.add<ReconnectPhase>()
|
||||||
|
.add<WaitPhase>(std::chrono::milliseconds(3000));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
RADGemini(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||||
|
initialize<RADGeminiSettings>(makeDriver);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupPacketizer(Packetizer& packetizer) override {
|
||||||
|
Device::setupPacketizer(packetizer);
|
||||||
|
packetizer.align16bit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupEncoder(Encoder& encoder) override {
|
||||||
|
Device::setupEncoder(encoder);
|
||||||
|
encoder.supportEthPhy = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
|
||||||
|
for(auto& netid : GetSupportedNetworks())
|
||||||
|
rxNetworks.emplace_back(netid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The supported TX networks are the same as the supported RX networks for this device
|
||||||
|
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif // __RADGEMINI_H_
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef LIBICSNEO_RADGEMINISETTINGS_H
|
||||||
|
#define LIBICSNEO_RADGEMINISETTINGS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "icsneo/device/idevicesettings.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#pragma pack(push, 2)
|
||||||
|
typedef struct {
|
||||||
|
uint16_t perf_en; // 2
|
||||||
|
|
||||||
|
ETHERNET_SETTINGS2 ethernet1; // 16
|
||||||
|
ETHERNET_SETTINGS2 ethernet2; // 16
|
||||||
|
ETHERNET_SETTINGS2 autoEthernet1; // 16
|
||||||
|
ETHERNET_SETTINGS2 autoEthernet2; // 16
|
||||||
|
|
||||||
|
uint16_t network_enabled_on_boot; // 2
|
||||||
|
uint16_t network_enables; // 2
|
||||||
|
uint16_t network_enables_2; // 2
|
||||||
|
uint16_t network_enables_3; // 2
|
||||||
|
uint16_t network_enables_4; // 2
|
||||||
|
uint64_t network_enables_5; // 8
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t enableLatencyTest : 1;
|
||||||
|
uint16_t reserved : 15;
|
||||||
|
} flags; // 2
|
||||||
|
} radgemini_settings_t;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class RADGeminiSettings : public IDeviceSettings {
|
||||||
|
public:
|
||||||
|
RADGeminiSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgemini_settings_t)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
|
||||||
|
#endif // LIBICSNEO_RADGEMINISETTINGS_H
|
||||||
|
|
@ -231,6 +231,7 @@ typedef unsigned __int64 uint64_t;
|
||||||
#define NEODEVICE_GIGASTAR2 (0x00000029)
|
#define NEODEVICE_GIGASTAR2 (0x00000029)
|
||||||
#define NEODEVICE_FIRE3_T1S_LIN (0x0000002A)
|
#define NEODEVICE_FIRE3_T1S_LIN (0x0000002A)
|
||||||
#define NEODEVICE_FIRE3_T1S_SENT (0x0000002B)
|
#define NEODEVICE_FIRE3_T1S_SENT (0x0000002B)
|
||||||
|
#define NEODEVICE_RADGEMINI (0x0000002C)
|
||||||
#define NEODEVICE_RED (0x00000040)
|
#define NEODEVICE_RED (0x00000040)
|
||||||
#define NEODEVICE_ECU (0x00000080)
|
#define NEODEVICE_ECU (0x00000080)
|
||||||
#define NEODEVICE_IEVB (0x00000100)
|
#define NEODEVICE_IEVB (0x00000100)
|
||||||
|
|
@ -1032,6 +1033,11 @@ typedef union _stChipVersions
|
||||||
uint8_t mchip_minor;
|
uint8_t mchip_minor;
|
||||||
} radmoon3_versions;
|
} radmoon3_versions;
|
||||||
struct
|
struct
|
||||||
|
{
|
||||||
|
uint8_t mchip_major;
|
||||||
|
uint8_t mchip_minor;
|
||||||
|
} radgemini_versions;
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
uint8_t mchip_major;
|
uint8_t mchip_major;
|
||||||
uint8_t mchip_minor;
|
uint8_t mchip_minor;
|
||||||
|
|
@ -2842,6 +2848,31 @@ typedef struct _SRADMoon3Settings
|
||||||
|
|
||||||
#define SRADMoon3Settings_SIZE 68
|
#define SRADMoon3Settings_SIZE 68
|
||||||
|
|
||||||
|
typedef struct _SRADGeminiSettings
|
||||||
|
{
|
||||||
|
uint16_t perf_en; // 2
|
||||||
|
|
||||||
|
ETHERNET_SETTINGS2 ethernet1; // 16
|
||||||
|
ETHERNET_SETTINGS2 ethernet2; // 16
|
||||||
|
ETHERNET_SETTINGS2 autoEthernet1; // 16
|
||||||
|
ETHERNET_SETTINGS2 autoEthernet2; // 16
|
||||||
|
|
||||||
|
uint16_t network_enabled_on_boot; // 2
|
||||||
|
uint16_t network_enables; // 2
|
||||||
|
uint16_t network_enables_2; // 2
|
||||||
|
uint16_t network_enables_3; // 2
|
||||||
|
uint16_t network_enables_4; // 2
|
||||||
|
uint64_t network_enables_5; // 8
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t enableLatencyTest : 1;
|
||||||
|
uint16_t reserved : 15;
|
||||||
|
} flags; // 2
|
||||||
|
} SRADGeminiSettings;
|
||||||
|
|
||||||
|
#define SRADGeminiSettings_SIZE 86
|
||||||
|
|
||||||
typedef struct _SRADGigalogSettings
|
typedef struct _SRADGigalogSettings
|
||||||
{
|
{
|
||||||
uint32_t ecu_id;
|
uint32_t ecu_id;
|
||||||
|
|
@ -4626,6 +4657,7 @@ typedef struct _GLOBAL_SETTINGS
|
||||||
SRADEpsilonSettings epsilon;
|
SRADEpsilonSettings epsilon;
|
||||||
SRADBMSSettings rad_bms;
|
SRADBMSSettings rad_bms;
|
||||||
SRADMoon3Settings radmoon3;
|
SRADMoon3Settings radmoon3;
|
||||||
|
SRADGeminiSettings radgemini;
|
||||||
SRADCometSettings radcomet;
|
SRADCometSettings radcomet;
|
||||||
// Make sure SDeviceSettings matches this
|
// Make sure SDeviceSettings matches this
|
||||||
};
|
};
|
||||||
|
|
@ -4676,6 +4708,11 @@ typedef enum _EDeviceSettingsType
|
||||||
DeviceFire3FlexraySettingsType,
|
DeviceFire3FlexraySettingsType,
|
||||||
DeviceRADCometSettingsType,
|
DeviceRADCometSettingsType,
|
||||||
DeviceRed2OemSettingsType,
|
DeviceRed2OemSettingsType,
|
||||||
|
DeviceRADComet3SettingsType,
|
||||||
|
DeviceRADGalaxy2SettingsType,
|
||||||
|
DeviceRADGigastar2SettingsType,
|
||||||
|
DeviceRADMoonT1SSettingsType,
|
||||||
|
DeviceRADGeminiSettingsType,
|
||||||
// add new settings type here
|
// add new settings type here
|
||||||
DeviceSettingsTypeMax,
|
DeviceSettingsTypeMax,
|
||||||
DeviceSettingsNone = 0xFFFFFFFF // just wanted to reserve this
|
DeviceSettingsNone = 0xFFFFFFFF // just wanted to reserve this
|
||||||
|
|
@ -4726,6 +4763,7 @@ typedef struct _SDeviceSettings
|
||||||
SRADEpsilonSettings epsilon;
|
SRADEpsilonSettings epsilon;
|
||||||
SRADBMSSettings rad_bms;
|
SRADBMSSettings rad_bms;
|
||||||
SRADMoon3Settings radmoon3;
|
SRADMoon3Settings radmoon3;
|
||||||
|
SRADGeminiSettings radgemini;
|
||||||
SFire3FlexraySettings fire3Flexray;
|
SFire3FlexraySettings fire3Flexray;
|
||||||
SRADCometSettings radcomet;
|
SRADCometSettings radcomet;
|
||||||
// Make sure GLOBAL_SETTINGS matches this
|
// Make sure GLOBAL_SETTINGS matches this
|
||||||
|
|
@ -5558,6 +5596,7 @@ CHECK_STRUCT_SIZE(SRADEpsilonSettings);
|
||||||
CHECK_STRUCT_SIZE(RAD_GPTP_SETTINGS);
|
CHECK_STRUCT_SIZE(RAD_GPTP_SETTINGS);
|
||||||
CHECK_STRUCT_SIZE(SRADBMSSettings);
|
CHECK_STRUCT_SIZE(SRADBMSSettings);
|
||||||
CHECK_STRUCT_SIZE(SRADMoon3Settings);
|
CHECK_STRUCT_SIZE(SRADMoon3Settings);
|
||||||
|
CHECK_STRUCT_SIZE(SRADGeminiSettings);
|
||||||
CHECK_STRUCT_SIZE(SFire3FlexraySettings);
|
CHECK_STRUCT_SIZE(SFire3FlexraySettings);
|
||||||
CHECK_STRUCT_SIZE(CANHubSettings);
|
CHECK_STRUCT_SIZE(CANHubSettings);
|
||||||
CHECK_STRUCT_SIZE(SRADCometSettings);
|
CHECK_STRUCT_SIZE(SRADCometSettings);
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include "icsneo/device/tree/radmoon2/radmoon2.h"
|
#include "icsneo/device/tree/radmoon2/radmoon2.h"
|
||||||
#include "icsneo/device/tree/radmoon2/radmoon2zl.h"
|
#include "icsneo/device/tree/radmoon2/radmoon2zl.h"
|
||||||
#include "icsneo/device/tree/radmoon3/radmoon3.h"
|
#include "icsneo/device/tree/radmoon3/radmoon3.h"
|
||||||
|
#include "icsneo/device/tree/radgemini/radgemini.h"
|
||||||
#include "icsneo/device/tree/radmoonduo/radmoonduo.h"
|
#include "icsneo/device/tree/radmoonduo/radmoonduo.h"
|
||||||
#include "icsneo/device/tree/radpluto/radpluto.h"
|
#include "icsneo/device/tree/radpluto/radpluto.h"
|
||||||
#include "icsneo/device/tree/radstar2/radstar2.h"
|
#include "icsneo/device/tree/radstar2/radstar2.h"
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include "icsneo/device/tree/radmoon2/radmoon2.h"
|
#include "icsneo/device/tree/radmoon2/radmoon2.h"
|
||||||
#include "icsneo/device/tree/radmoon2/radmoon2zl.h"
|
#include "icsneo/device/tree/radmoon2/radmoon2zl.h"
|
||||||
#include "icsneo/device/tree/radmoon3/radmoon3.h"
|
#include "icsneo/device/tree/radmoon3/radmoon3.h"
|
||||||
|
#include "icsneo/device/tree/radgemini/radgemini.h"
|
||||||
#include "icsneo/device/tree/radmoonduo/radmoonduo.h"
|
#include "icsneo/device/tree/radmoonduo/radmoonduo.h"
|
||||||
#include "icsneo/device/tree/radpluto/radpluto.h"
|
#include "icsneo/device/tree/radpluto/radpluto.h"
|
||||||
#include "icsneo/device/tree/radstar2/radstar2.h"
|
#include "icsneo/device/tree/radstar2/radstar2.h"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue