// ---------------------------------------------------------------------------- // Copyright (C) 2008, Sealevel Systems // // For help please contact us by email at support@sealevel.com. // // $Id: seamaxlin.h,v 1.11 2009/07/13 19:49:55 kmoody Exp $ // ---------------------------------------------------------------------------- #ifndef PUBLIC_DOCUMENTATION /*! \mainpage Linux SeaMax API Documentation * \section warning Internal Disclaimer * * WARNING! This document is intended for internal use only. */ #else /*! \mainpage Linux SeaMAX API Documentation * * \section intro_sec Introduction * * Sealevel digital and analog I/O modules supported by the SeaMAX software * suite are designed to work with third party applications via the SeaMAX API. * To help simplify application development, the following documentation * details the functions of the SeaMAX API. To help you get started, example * C and C++ source code is provided. * * \section start Getting Started * * There are three modules that are included in the SeaMAX API: * * \li \ref group_seamax_all
* The foundation of SeaMAX with functions for configuring, interfacing, * and modifying supported Sealevel digital I/O modules and devices. * \li \ref group_cethernet_all
* The Ethernet module contains functions related to the discovery and * configuration of Sealevel I/O devices with an Ethernet interface. * \li \ref modbusbreakdown
* The Modbus Specification contains detailed descriptions of all RTU * and TCP Modbus commands applicable to SeaIO and SeaDAC modules. * * The 'Modules' tab above lists all SeaMAX modules and their functions. For * additional information regarding legacy products and technical * specifications, please refer to the 'Related Pages' tab above. * * \section questions Questions & Comments * * Send your questions and comments to Sealevel Systems. For technical * assistance, please include your model or part number and any device * settings that may apply. Technical support is available Monday to * Friday from 8:00AM to 5:00PM (US Eastern Time Zone, UTC-6 hours) by * email (support@sealevel.com) or by phone at +1 (864) 843.4343. */ /// \defgroup group_seamax_all SeaMAX API /// The SeaMAX API consists of the functions outline below, and provides an /// interface for construction, transmission, and reception of Modbus RTU and /// TCP commands. For more information, click a function name below for /// detailed information on function use, parameter types, and return codes. /// /// \note Not every function below may apply to your specific Sealevel I/O /// device. Refer to the \ref modbusbreakdown "modbus breakdown". /// \defgroup group_cethernet_all SeaMAX Ethernet Discovery/Configuration API /// /// The SeaMAX Ethernet Discover API includes functions used for configuration /// and discovery of Ethernet enabled Sealevel I/O devices. For specifics, /// click any of the function names below to view function use, parameters, and /// return code information. /// \ingroup group_seamax_all /// \defgroup group_seamax_oop Object-Oriented SeaMAX Modbus Interface /// This is a C++ wrapper for the standard SeaMAX Modbus interface library. /// This library is designed to aid in the construction, transmission, and /// reception of Modbus RTU and TCP commands. This library is designed for use /// with Sealevel SeaIO modules. /// /// \ingroup group_seamax_all /// \defgroup group_seamax_fun Functional SeaMAX Modbus Interface /// This is a simple C library to aid in the construction, transmission, and /// reception of Modbus RTU and TCP commands. This library is designed for use /// with Sealevel SeaIO modules. /// /// \ingroup group_cethernet_all /// \defgroup group_cethernet_oop Object Oriented CEthernet Interface /// This is a C++ wrapper for the standard CEthernet library. This library is /// designed to aid in the discovery and configuration of Ethernet enabled /// SeaIO modules. /// /// \ingroup group_cethernet_all /// \defgroup group_cethernet_fun Functional CEthernet Interface /// This is a simple C library to aid in the discovery and configuration /// of Ethernet enabled SeaIO modules. /// #endif #ifndef SEAMAXLIN_H__ #define SEAMAXLIN_H__ #include "thirdparty/ftdi.h" // Sealevel vendor ID number #define VENDOR 0x0c52 // This is used for proper inclusion when used with C++ #ifdef __cplusplus extern "C" { #endif // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \typedef SeaMaxLin /// Pointer to a SeaMax object. The data structure this points to is private /// and should not be accessed directly, but through the function calls instead. // ---------------------------------------------------------------------------- typedef long SeaMaxLin; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \typedef HANDLE /// A handle or pointer to another data structure. /// This particular pointer is used to pass the serial communications struct. // ---------------------------------------------------------------------------- typedef int HANDLE; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \typedef slave_address_t /// The slave ID of a device. This value can be from 1 to 247. // ---------------------------------------------------------------------------- typedef unsigned char slave_address_t; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \typedef address_loc_t /// An address specific to your device. Check read/write functions for /// specific use. // ---------------------------------------------------------------------------- typedef unsigned short address_loc_t; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \typedef address_range_t /// The range of address to be used. Check read/write functions for specific /// use. // ---------------------------------------------------------------------------- typedef unsigned short address_range_t; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief The module connection type. /// Currently there is only support for RTU and TCP type connections. // ---------------------------------------------------------------------------- typedef enum { NO_CONNECT = 0, ///< Connection not open. MODBUS_RTU = 1, ///< An RTU type connection. 232, 485, USB. MODBUS_TCP = 2, ///< An ethernet connection. FTDI_DIRECT = 3 ///< An ethernet connection. } seaio_mode_t; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief The current baud rate used by a RTU type module. /// If the module is TCP type, then BR9600, the default, will be used. /// Note these are not the same values used by the termios library. // ---------------------------------------------------------------------------- typedef enum { BRNONE = 0, ///< Default value, no connection, or unkown baud rate. BR1200 = 1, ///< 1200 baud. BR2400 = 2, ///< 2400 baud. BR4800 = 3, ///< 4800 baud. BR9600 = 4, ///< 9600 baud. BR14400 = 5, ///< 14400 baud. BR19200 = 6, ///< 19200 baud. BR28800 = 7, ///< 28800 baud. BR38400 = 8, ///< 38400 baud. BR57600 = 9, ///< 57600 baud. BR115200 = 10 ///< 115200 baud. } baud_rates_t; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief The currently used parity. /// Parity is a quick and simple method of checking for errors. It doesn't /// work all the time, but it is very simple to implement. // ---------------------------------------------------------------------------- typedef enum { P_NONE = 0, ///< No parity (Default). P_ODD = 1, ///< Odd parity. P_EVEN = 2 ///< Even parity. } parity_t; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief The type of read / write to preform. /// Note that not all types can be written. For example an attempt to write to /// D_INPUTS or INPUTREG would cause an EINVAL error. Also you can not directly /// write to SETUPREGS, you must use an appropriate Ioctl. // ---------------------------------------------------------------------------- typedef enum { COILS = 1, ///< Coils are any relay type outputs. D_INPUTS = 2, ///< Digitial inputs. Single bit inputs. HOLDINGREG = 3, ///< Configuration registers. INPUTREG = 4, ///< Registers only used on A/D type devices. SETUPREG = 5, ///< Advanced device configuration registers. SEAMAXPIO = 6 ///< Programmable type I/O. } seaio_type_t; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \ingroup group_seamax_all /// \brief The type of IOCTL operation desired. /// Read the manual carefully when using these. There are some specific /// methods that must be followed to use correctly. // ---------------------------------------------------------------------------- typedef enum { IOCTL_READ_COMM_PARAM = 1, ///< Read communication parameters. IOCTL_SET_ADDRESS = 2, ///< Set device slave ID. IOCTL_SET_COMM_PARAM = 3, ///< Set communication parameters. IOCTL_GET_PIO = 4, ///< Get direction of programmable I/O. IOCTL_SET_PIO = 5, ///< Set direction of programmable I/O. IOCTL_GET_ADDA_CONFIG = 6, ///< Get A/D configuration information. IOCTL_SET_ADDA_CONFIG = 7, ///< Set the A/D configuration. IOCTL_GET_EXT_CONFIG = 8, ///< Extended module id (SeaDAC). IOCTL_GET_ADDA_EXT_CONFIG = 9, ///< Information about D/A jumpers. } IOCTL_t; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief 48 Bit pio configuration. /// This struct is contained within the \a SeaMAX_PIO_ioctl_s struct. It is /// used whenever retrieving or setting port direction on a PIO device with /// 48 bits of I/O. // ---------------------------------------------------------------------------- typedef struct PIO48_config_s { unsigned char channel1; ///< Bits 0-5 map ports 1-6. (0:O, 1:I) } PIO48_config_s; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief 96 Bit pio configuration. /// This struct is contained within the \a SeaMAX_PIO_ioctl_s struct. It is /// used whenever retrieving or setting port direction on a PIO device with /// 96 bits of I/O. // ---------------------------------------------------------------------------- typedef struct PIO96_config_s { unsigned char channel1; ///< Bits 0-5 map ports 1-6. (0:O, 1:I) unsigned char channel2; ///< Bits 0-5 map ports 7-12. (0:O, 1:I) } PIO96_config_s; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief This struct is used to set the address of a particular device. /// In this way, it becomes unnecessary to manually turn the screw terminal to /// configure a particular SeaIO device. It also allows for more devices than /// the physically selectable 15 addresses. // ---------------------------------------------------------------------------- typedef struct seaio_ioctl_address_s { unsigned char new_address; ///< Address value from 1 to 247. } seaio_ioctl_address_s; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief Communication parameters (desired) struct. /// This struct can be used to set a desired communication configuration. /// Note that you must first call get params before you attempt to set params, /// or it will fail. // ---------------------------------------------------------------------------- typedef struct seaio_ioctl_comms_s { baud_rates_t new_baud_rate; ///< Desire baud rate (/a baud_rates_t). parity_t new_parity; ///< Desire parity (/a parity_t). } seaio_ioctl_comms_s; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief Communication parameters (current) struct. /// This struct can be used to store the current communication parameters. /// Note that you will have call get params before you may set a configuration, /// or it will fail. // ---------------------------------------------------------------------------- typedef struct seaio_ioctl_get_params_s { unsigned short model; ///< Device model number (410, 462, ...) unsigned char bridge_type; ///< Bridge type (M, E, U, S, or N). baud_rates_t baud_rate; ///< The device's communication baud rate. parity_t parity; ///< The device's communication parity. unsigned char magic_cookie; ///< \internal Multithread saftey. } seaio_ioctl_get_params_s; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief PIO data/setup struct. /// This struct can be used to read data from a PIO device, or configure a PIO /// device. // ---------------------------------------------------------------------------- typedef struct SeaMAX_PIO_ioctl_s { unsigned short model; ///< Device model number (462, 463, ...) union { PIO48_config_s PIO48; ///< PIO directions /a PIO48_config_s PIO96_config_s PIO96; ///< PIO directions /a PIO96_config_s } config_state; } SeaMAX_PIO_ioctl_s; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief PIO data/setup struct. /// This struct can be used to read data from a PIO device, or configure a PIO /// device. // ---------------------------------------------------------------------------- typedef struct seaio_ioctl_ext_config { unsigned short model; ///< Device model number (SeaDAC) } seaio_ioctl_ext_config; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief The IOCTL struct used in the majority of the IOCTL calls. /// Every call except the three involving A/D and D/A converters use this /// struct. This struct is actually the union of several smaller structs, so /// that it can be used multiple times. // ---------------------------------------------------------------------------- typedef struct seaio_ioctl_s { union { seaio_ioctl_address_s address; ///< IOCTL_SET_ADDRESS seaio_ioctl_comms_s comms; ///< IOCTL_READ_COMM_PARAM seaio_ioctl_get_params_s params; ///< IOCTL_SET_COMM_PARAM SeaMAX_PIO_ioctl_s pio; ///< IOCTL_GET/SET_PIO seaio_ioctl_ext_config config; ///< IOCTL_GET_EXT_CONFIG } u; ///< Keep size down to largest struct inside. } seaio_ioctl_s; // ---------------------------------------------------------------------------- // | ADDA structs and types. | // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief ADDA conversion range configuration type. /// This is the range of voltages that the A/D will convert into values from /// 0x000 to 0xFFF (0-4095). Plus to minus conversions do use a sign bit, so /// 4095 is not necessarily the highest value. // ---------------------------------------------------------------------------- typedef enum { ZERO_TO_FIVE = 0, ///< 0-5V (0x000-0xFFF) PLS_MIN_FIVE = 1, ///< -5-5V (0x800-0x7FF) ZERO_TO_TEN = 2, ///< 0-10V (0x000-0xFFF) PLS_MIN_TEN = 3 ///< -10-10V (0x800-0x7FF) } channel_range_type; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// ADDA mode configuration type. /// This is how the board is physically configured to read Analog signals. The /// way to measure. You can either measure 16 signals with a single common /// ground, 8 isolated signals, or the current pulled through internal resistors /// from 8 separate signals. // ---------------------------------------------------------------------------- typedef enum { SINGLE_ENDED = 0, ///< 16 common ground channels. DIFFERENTIAL = 1, ///< 8 differential channels. CURRENT_LOOP = 2 ///< 8 current loop measurements. } channel_mode_type; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief ADDA reference type configuration. /// This controls the mux that is in charge of input to the single A/D chip on /// an A/D capable device. This provides some small A/D diagnostics if you /// desire to use them. // ---------------------------------------------------------------------------- typedef enum { ANALOG_OFFSET = 0, ///< The A/D inputs available on the device. GND_OFFSET = 1, ///< A ground value. Should always read 0V. AD_REF_OFFSET = 2, ///< A/D reference value. Should always read 0V. DA_CHANNEL_1 = 4, ///< D/A channel one as input. DA_CHANNEL_2 = 8 ///< D/A channel two as input. } ad_reference_type; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief The ADDA data struct used in the ADDA ioctl calls. /// Contains information about device configuration. // ---------------------------------------------------------------------------- typedef struct adda_config { /// Overall device settings. struct { unsigned char reference_offset; ///< A/D Mux address. unsigned char channel_mode; ///< Measurement mode. } device; /// Each channel uses 2 bits for configuration. /// Each of the bytes in this struct uses the lowest /// two bits for each channel configuration. struct { unsigned char ch_1; unsigned char ch_2; unsigned char ch_3; unsigned char ch_4; unsigned char ch_5; unsigned char ch_6; unsigned char ch_7; unsigned char ch_8; unsigned char ch_9; unsigned char ch_10; unsigned char ch_11; unsigned char ch_12; unsigned char ch_13; unsigned char ch_14; unsigned char ch_15; unsigned char ch_16; } channels; } adda_config; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief Data struct returned by get ext adda ioctl. /// Contains information about the physical jumper configuration of the device. // ---------------------------------------------------------------------------- typedef struct adda_ext_config { unsigned char ad_multiplier_enabled; ///< A/D amplifier. channel_range_type da_channel_1_range; ///< D/A1 range. channel_range_type da_channel_2_range; ///< D/A2 range } adda_ext_config; // ---------------------------------------------------------------------------- /// \ingroup group_seamax_all /// \brief SeaDAC Lite range configuration type. /// This is the range of available SeaDAC products // ---------------------------------------------------------------------------- typedef enum { SDL_8111 = 0x8111, ///< 4 inputs and 4 reed outputs SDL_8112, ///< 4 inputs and 4 form-c outputs SDL_8113, ///< 4 inputs SDL_8114, ///< 4 reed outputs SDL_8115, ///< 4 form-c outputs SDL_8126 = 0x8126 ///< 32 TTL I/O } sdl_range_type; typedef enum { SCL = 0x01, SDA = 0x02, TDO = 0x04, CS = 0x08, GPIO_0 = 0x01, GPIO_1 = 0x02, GPIO_2 = 0x04, GPIO_3 = 0x08, GPIO_4 = 0x10, GPIO_5 = 0x20, GPIO_6 = 0x40, GPIO_7 = 0x80 } sdl_i2c_type; // ---------------------------------------------------------------------------- // SeaMaxModule struct. // This structure is used internally to keep track of a module that open() has // been called on. // ---------------------------------------------------------------------------- typedef struct seaMaxModule { int throttle; //Throttling delay for RTU mode. seaio_mode_t commMode; //Communication medium (RTU or TCP). HANDLE hDevice; //Device comm interface. int mutex; //Multithread (force sequential). struct termios *initalConfig; //Original serial configuration. struct ftdi_context ftdic; //For SeaDAC Lite modules int deviceType; } seaMaxModule; // ---------------------------------------------------------------------------- // | private prototypes | // ---------------------------------------------------------------------------- int InitializeI2C(seaMaxModule*); void ExecuteQueue(seaMaxModule*); void InitializeQueue(void); void ExecuteQueue(seaMaxModule*); void ReadRegister(unsigned char, unsigned char, unsigned char*); void WriteRegister(unsigned char, unsigned char, unsigned char); void SetGPIO(unsigned char, unsigned char); // ---------------------------------------------------------------------------- // | API prototypes | // ---------------------------------------------------------------------------- SeaMaxLin *SeaMaxLinCreate(void); int SeaMaxLinDestroy(SeaMaxLin *SeaMaxPointer); int SeaMaxLinOpen(SeaMaxLin *SeaMaxPointer, char *filename); int SeaMaxLinClose(SeaMaxLin *SeaMaxPointer); int SeaMaxLinRead(SeaMaxLin *SeaMaxPointer, slave_address_t slaveId, seaio_type_t type, address_loc_t starting_address, address_range_t range, void *data); int SeaDacLinRead(SeaMaxLin *SeaMaxPointer, unsigned char *data, int numBytes); int SeaMaxLinWrite(SeaMaxLin *SeaMaxPointer, slave_address_t slaveId, seaio_type_t type, address_loc_t starting_address, address_range_t range, unsigned char *data); int SeaDacLinWrite(SeaMaxLin *SeaMaxPointer, unsigned char *data, int numBytes); int SeaMaxLinIoctl(SeaMaxLin *SeaMaxPointer, slave_address_t slaveId, IOCTL_t which, void *data); int SeaMaxLinSetIMDelay(SeaMaxLin *SeaMaxPointer, int delay); int SeaDacGetPIO(SeaMaxLin *SeaMaxPointer, unsigned char* data); int SeaDacSetPIO(SeaMaxLin *SeaMaxPointer, unsigned char* data); int SeaDacSetPIODirection(SeaMaxLin *SeaMaxPointer, unsigned char* data); int SeaDacGetPIODirection(SeaMaxLin *SeaMaxPointer, unsigned char* data); HANDLE SeaMaxLinGetCommHandle(SeaMaxLin *SeaMaxPointer); // ---------------------------------------------------------------------------- // | End of C library function calls. | // ---------------------------------------------------------------------------- #ifdef __cplusplus } class CSeaMaxLin { public: CSeaMaxLin(void); ~CSeaMaxLin(void); int Open(char *filename); int Close(void); int Read(slave_address_t slaveId, seaio_type_t type, address_loc_t starting_address, address_range_t range, void *data); int Read(unsigned char *data, int length); int Write(slave_address_t slaveId, seaio_type_t type, address_loc_t starting_address, address_range_t range, unsigned char *data); int Write(unsigned char *data, int length); int Ioctl(slave_address_t slaveId, IOCTL_t which, void *data); int set_intermessage_delay(int delay); int GetPIO(unsigned char* data); int SetPIO(unsigned char* data); int SetPIODirection(unsigned char* data); int GetPIODirection(unsigned char* data); HANDLE getCommHandle(void); private: SeaMaxLin *SeaMaxPointer; }; #endif //__cplusplus #endif //SEAMAXLIN_H__