#ifndef COPROCESSORH #define COPROCESSORH /*coprocessor.h wrapper functions for interpreting the protocol used by the 37e12. */ /*! @addtogroup COP This module contains wrapper functions for interpreting the protocol of the 37e12, it essentially defines the high level API for communicating with the device. Because all communication with the 37e12 comes through one IO channel, all data, incoming and outcoming, is wrapped in a proprietary packet structure. This data can be commands sent to the 37e12, requests for data from the 37e12, responses to requests, and in some cases unsolicited asychronous data. When a user application is expecting data from a 37e12 device it calls read to read back a chunk of raw data. Typically this is done by setting number of bytes in the read function to some high value. The driver will cut it off and return the data when it has nothing left to send(or when the number is reached). This raw data is then interpreted by passing it into the E12_Packet_Route function, which breaks it down and puts received data into the fields of a Cop_Data structure. User programs know what data has been returned by reading the return value from the packet routing function(E12_Packet_Route).This returned value is a bitmask, because more than one packet may be contained in any given chunk of raw data. Different types of data will set different bits, as detailed in the function descriptions below. Cop_Data structures are created and initialized with the CopDeviceCreate function, and destroyed with the CopDeviceDestroy function. */ /*@{*/ //#include "counter.h" #include "CAN.h" #include "serial.h" #define NEW 1 #define OLD 0 #define TRUE 1 #define FALSE 0 #define RS232BUFSIZE 1000 #define RS422BUFSIZE 1000 #define LCD_QSZ 10 #define COPCODE /*specifies that this code is on the coproc side*/ #define BITMASK(data) (1<External_AD[0] and Cop->External_AD[1]. */ typedef struct RG_ParseMask { /*!bitmask of internal AtoD channels, 1 indicates new data received*/ __u16 Internal_AD; /*!bitmask of External AtoD channels, 1 indicates new data received*/ __u8 External_AD; /*!bitmask of counter channels, 1 indicates the counter data structure or counter config structure has been modified*/ __u8 counter; /*!bitmask of counter channels notification, 1 indicates a zero crossing*/ __u8 zero; /*!bitmask of PWM channels notification, 1 indicates returned configuration data*/ __u16 pwm; }RG_ParseMask; /*!This PWMconfig structure is used to configure an internal digital port to be a PWM. E12_PWMControl fills out this structure based on parameters passed to it and passes it the e12packetout @see E12_PWMControl */ typedef struct PWMconfig{ /*! pwm number 0-15*/ __u16 pwm; /*!frequency of the PWM*/ __u16 frequency; /*!duty cycle*/ __u16 duty; /*legacy protocol parameter, no longer used*/ __u16 delay; }PWMconfig; /*!This countconfig structure is used to configure an port 0 digital line to be a counter. E12_CountConfig fills out this structure based on parameters passed to it and passes it the e12packetout @see E12_CountConfig */ typedef struct countconfig{ /*! counter number 0 - COUNTNUM*/ __u16 counter; /*! int value from 0-3 determining what edge the counter counts on*/ __u16 trigger; /*!The reload value for the counter when AUTOLOAD is on*/ __u16 threshold; /*!Bitmask of counter options */ __u16 flags; }countconfig; /*!Counter data structure. This type of structure contains data collected from a running counter */ typedef struct countdata{ /*the current counter reading, as of the last request*/ __u16 counter; /*!The value the counter started at, this is updated by loading the counter, or when an autoreload occurs if zero crossing notification is enabled. Coprocessor.c keeps track of this*/ __u16 countstart; /*!The last value the counter started at, prior to countstart, this is updated by loading the counter, or when an autoreload occurs if zero crossing notification is enabled. Coprocessor.c keeps track of this*/ __u16 laststart; /*!the timestamp from the 37e12 when the counter started or when the last zero crossing occurred, 32 bits, measured in ms*/ unsigned long timestamp; /*!the previous timestamp*/ unsigned long laststamp; /*!number of zerocrossing that have occurred since initialization*/ int zerocross; }countdata; /*!The Cop_Data typedef This is a type of structure created and initialized by CopDeviceCreate. It is used for the stored of packet data currently being parsed, as well as to store data that has already been parsed and is being passed back to the user. @see CopDeviceCreate @see CopDeviceDestroy @see E12_Packet_Route */ typedef struct Cop_Data { /*!Data received flag*/ __u8 Datarxd; /*!data bytes remaining in current packet*/ int ptogo; /*!number of chars currently in the packet*/ int psize; /*! the current packet being worked on */ char packet[MAXPACKETSIZE]; /*!internal A to D channels 0-15 */ __u16 Internal_AD[INTERNAL_ATOD_NUM]; /*!optional external A to D channels 16-23 */ __u16 External_AD[EXTERNAL_ATOD_NUM]; /*!config settings for the PWMs this is currently a shadow variable*/ PWMconfig PWM_config[PWMNUM]; /*!8 16 bit counters */ countdata counter_data[COUNTNUM]; /*!config settings for the counters this is currently a shadow variable*/ countconfig counter_config[COUNTNUM]; /*!Digital IO ports (port1 output state only)*/ __u8 Digital[2]; /*!RS232 serial port string*/ char RS232_string[RS232BUFSIZE]; /*!RS422 serial port string*/ char RS422_string[RS422BUFSIZE]; /*!Keypad character*/ char Key; /*!Can message*/ E12Can_Message *CAN_message; /*!Firmware Version information*/ VersionInfo version; /*!parsemask for multiple channel RGs*/ RG_ParseMask parsemask; /*!Parsed packet information, see packet.h*/ PcpkPacket packetdata; /*!general purpose user data pointer*/ void *userdata; }Cop_Data; /*!Create a Coprocessor structure This function creates a Cop_Data structure which can be passed to E12_Packet_Route to be filled with with incoming data from the coprocessor device @param flags unused @return a pointer to a new Cop_Data structure */ Cop_Data *CopDeviceCreate(int flags); /*!Destroys a Coprocessor structure This function destroys a previously allocated Cop_Data structure @param Cop the structure to destroy @return 0 */ int CopDeviceDestroy(Cop_Data *Cop); /*!Interpret raw data read from the 37e12 This is the main packet parsing function, it takes a chunk of raw data "data" of size "datasize" interprets it and updates the fields in "Cop" appropriately. Typically this would be called right after a read as in: rxnum = read(fd,buffer,sizeof(buffer)); typemask = E12_Packet_Route(CopRouter,buffer, rxnum); where fd would be a pointer to a /dev/37e12 device, buffer would be a user allocated buffer and CopRouter would be a previously allocated Cop_Data structure. @param Cop The previously allocated Cop_Data structure to fill @param data pointer to the raw data obtained through a read to a 37e12 @param datasize the size of the raw data packet @return bitmask of the packets that have been received */ __u32 E12_Packet_Route(Cop_Data *Cop, unsigned char *data, int datasize); /*!Read and Interpret raw data read from the 37e12 until the desired packet is returned This is a secondary packet parsing function, it reads data from fd and parses it until it receives a typemask containing one of the bits in bitmask. This function calls read so whether or not it blocks is dependent on the driver and the flags that were passed to it when the fd was opened. If the function is used in non-blocking mode it does 1000 iterations before timing out and returning if no data is available. @param fd the 37e12 device being addressed @param Cop The previously allocated Cop_Data structure to fill @param bitmask type of packet to parse until. If any bit in the bitmask is reached the function will return. @return bitmask of the packets that have been received */ __u32 E12_Parse_Until(int fd, Cop_Data *Cop, __u32 bitmask ); /*!Create and send a packet to the device described by fd This function is a low level function used by the other transmit functions to send packets to the 37e12 It's direct use is not recommended as it requires some knowledge of the internal packet structure. Use the wrapper functions instead. @param fd the 37e12 device being addressed @param device a packet header nibble @param maskcnt a mask/count of the bytes being transmitted @param data generic data pointer to data to transmit @return 0 */ int e12packetout(int fd,__u8 device,__u8 maskcnt,void *data); /*!Write a byte of data to a digital port. This is used to set the lines of a digital port to 1(logic on) or 0(logic off) This function applies to the internal ports 0 and 1 of the 37e12. The isolated ports are controlled externally from the processor and are accessed directly by the driver. see e12digitalGP.c for an example of how to write to the internal ports, and ISO_out.c/ISO_in.c for examples of how to write to the external isolated ports. the byte is a bitmask of the lines. ex: 0x03 is binary for 00000011 which would activate lines 0 and 1 of the port being addressed, and deactivate the other lines. @param fd the 37e12 device being addressed @param data the bitmask to write to the port @param port the portnumber to write to, on the 37e12 this is 0-1 @return 0 */ int E12_Digitalout(int fd, __u8 data,int port); /*!Request Internal Digital port reading. This requests a packet from the 37e12 containing the readings from both the digital ports. When E12_Packet_Route parses raw data containing a return packet from this function it sets BITMASK(PRTIN0) to 1 in it's return value . See e12digitalGP.c for an example of this. @param fd the 37e12 device being addressed @return 0 @see E12_Packet_Route */ int E12_Digital_Req(int fd); /*!Write a byte of configuration data to a digital port. This is used to configure the lines of a digital port to be 1(outputs) or 0(inputs) This function applies to the internal ports 0 and 1 of the 37e12. The isolated external ports are not configurable. the byte is a bitmask of the lines. ex: 0x03 is binary for 00000011 which would activate lines 0 and 1 of the port being addressed, and deactivate the other lines. @param fd the 37e12 device being addressed @param mask the bitmask to write to the port @param port the portnumber to write to, on the 37e12 this is 0-1 @return 0 */ int E12_Digital_Cfg(int fd, __u8 mask, int port); /*!Configure an internal Digital port to be a pwm. This function sets up a one of the digital port lines to be a PWM. The 2 ports, 0 and 1 behave differently with respect to this function. It requires a the Cop data structure to be passed to it so that it can shadow the configuration. This also updates the other configuration parameters to reflect the effect of the PWM configuration, ie, if a the port was previously configured as a counter it changes the counters shadow status to show that it is no longer on. Configuring a Port 0 line to be a PWM uses the DG128's IOC counter functionality to emulate PWM's . This does not allow as high a frequency as the hardware PWM's, but has the advantage of having independent channels(the frequency of one has no bearing on the frequency of the others). Since the PWM cycle is software based, maximum frequency and duty cycle are a function of the system load. The software PWM's can reliably handle pulse widths between 60us and 2.7ms, which would limit the frequency's to 186-8334Hz at 50% duty cycle. Port 1 PWMS use the hardware PWM's of the DG128 processor. This allows for much higher PWM rates, but suffers in that it doesn't allow for many different frequencies. This is because the hardware PWM's share internal clocks so if one gets bumped up too high, the others will change frequency as well. There are 2 clocks(ClockA and ClockB) shared among the eight lines as follows: - 0 A - 1 A - 2 B - 3 B - 4 A - 5 A - 6 B - 7 B These clocks will automatically pre-scale to accommodate a requested frequency when a new packet is received. Therefore changing the frequency of one hardware PWM can potentially effect the frequency of other hardware PWM's on the same clock. The frequency/prescale ratio is as follows - Hz - prescale - 65535 to 47059 - 0 - 47058 to 23530 - 1 - 23529 to 11765 - 2 - 11764 to 5883 - 3 - 5882 to 2942 - 4 - 2941 to 1471 - 5 - 1470 to 738 - 6 - 735 to 367 - 7 Duty cycles are unaffected by the prescale and can be set to any value between 0 and 100. ex: setting pin 7 of port 1 to 1Khz would cause clock B to be set at a prescale of 6. If pin 6 (which shares the same clock) was then set to 2Khz clock B's prescale would change to 5 and which would double the frequency of pin 7 to 200)KHz as well. Setting pin 6 to 1KHz would have had no effect because it would be within the same prescale range, also setting pin 5 to any value would have no effect on pin 7 because it uses a different clock. @param fd the 37e12 device being addressed @param pwm the line number to address 0-7 are port0 0-7, 8-15 are port1 0-7 @param frequency the frequency of the PWM @param duty the duty cycle of the PWM. @param Cop Cop data structure to shadow the variables into. @return 0 */ int E12_PWMControl(int fd,int pwm, int frequency, int duty,Cop_Data *Cop); /*!Request Internal AtoD reading Raw data containing a packet returned from this function will set BITMASK(ADBLK0) in E12_Packet_Route's return value. It will also set a bit in the Cop_Data structure's parsemask.Internal_AD element, indicating the number of the channel returned. @param fd the 37e12 device being addressed @param channel the channel to address @return 0 */ int E12_Internal_AtoD_Req(int fd, int channel); /*!Request External AtoD reading Raw data containing a packet returned from this function will set BITMASK(ADBLK1) in E12_Packet_Route's return value. It will also set a bit in the Cop_Data structure's parsemask.External_AD element, indicating the number of the channel returned. @param fd the 37e12 device being addressed @param channel the channel to address @return 0 */ int E12_External_AtoD_Req(int fd, int channel); /*!Request AtoD reading calls Internal or External AtoD req based on the number if the number is greater than the number of internal AtoD channels it call external at channel-internal Atod channels. Return packets will set the appropriate bits in E12_Packet_Route's return value and in the Cop_Data structure's parsemask. @param fd the 37e12 device being addressed @param channel the channel to address @see E12_Internal_AtoD_Req @see E12_External_AtoD_Req @return 0 */ int E12_AtoD_Req(int fd, int channel); /*!Write to DtoA Writes the value data to external DtoA channel channel This is a 12 bit DtoA, bits above that in the data field are ignored. @param fd the 37e12 device being addressed @param channel the channel to address 0-3 @param data the data to write to the channel. @return 0 */ int E12_DtoA_Write(int fd, int channel,int data); /*!Request version info Sends a request to the 37e12 for firmware version information, the version number and the __DATE__ it was compiled. @param fd the 37e12 device being addressed @param channel the channel to address 0-3 @param data the data to write to the channel. @return 0 */ int E12_VersionReq(int fd); /*!Update the Cop structures PWM_config structures with data from the hardware. @param fd the 37e12 device being addressed @param Cop Cop data structure to shadow the variables into. @return 0 */ int UpdatetHardwarePWMInfo(int fd, Cop_Data *Cop); int E12_PWMCfg_Req(int fd, int pwm); /*@}*/ #endif