CANPort provides a higher level interface to a CAN communication channel, and provides timestamping, servicing additional hardware interfaces (optional activity LED, CAN transceiver slope control)

CANPort.h

Committer:
WiredHome
Date:
2012-07-15
Revision:
0:7b81b19d9b10
Child:
1:f0b4e47d948d

File content as of revision 0:7b81b19d9b10:

/// @file CANPort.h is where all the port level functionality is defined
///
/// This module creates the physical interface, services the hardware, and provides
/// additional functionality on top of that (e.g. timestamp messages).
///
/// @todo Instead of providing a callback directly to the user code, all 
///       callbacks should be handled in this class, and then the user 
///       callback could be activated. In this way, the rxCounter, timestamps,
///       and other features are preserved.
///
/// @note Copyright &copr; 2011 by Smartware Computing, all rights reserved.
///     Individuals may use this application for evaluation or non-commercial
///     purposes. Within this restriction, changes may be made to this application
///     as long as this copyright notice is retained. The user shall make
///     clear that their work is a derived work, and not the original.
///     Users of this application and sources accept this application "as is" and
///     shall hold harmless Smartware Computing, for any undesired results while
///     using this application - whether real or imagined.
///
/// @author David Smart, Smartware Computing
///
/// History
/// v1.01 20110608
/// \li initial version numbered to match other CAN components
///
#ifndef CANPORT_H
#define CANPORT_H
#include "mbed.h"
#include "CANMessage.h"
#include "Utilities.h"      // mbed <-> Visual Studio


typedef enum {
    HIGHSPEED,
    NORMALSPEED,
    STANDBY
} CANSlopeControl_T;

typedef enum {
    MONITOR,
    ACTIVE
} CANBusMode_T;

/// This is the CANPort, which is the physical interface to CAN
///
/// This derived class has a number of additional capabilities:
/// \li activity indicator to show receive and transmit activity per port
/// \li slope control pin to permit controlling performance and power modes
/// \li counters, to keep track of received and transmitted messages
/// \li and more...
///
class CANPort {
public:

    /// The advanced form of the constructure to create a CANPort, name 
    /// an activity indicator, and name a slope control pin
    ///
    /// This version lets you specify the receive and transmit pins
    /// for a CANPort, indicate a pin which is used to indicate
    /// CAN activity, both receive and transmit, and identify a slope
    /// control pin.
    ///
    /// @param chNum is the user assigned channel number given to this port
    /// @param rd is the receive pin
    /// @param td is the transmit pin
    /// @param activityPin is the PWM pin used to indicate CAN traffic
    /// @param slopePin is the DigitalInOut pin used to control slope
    /// @param slope is the initial slope setting
    ///
    CANPort(CANCHANNEL_T chNum, PinName rd, PinName td, PinName activityPin = NC, PinName slopePin = NC, CANSlopeControl_T slope = NORMALSPEED);
    
    /// Destroys the CANPort
    virtual ~CANPort();

    /// Transmit a message to the bus
    ///
    /// This method transmits a message to the bus.
    ///
    /// @param msg is a CANmsg
    /// @returns true if the message was successfully written to CAN
    ///
    bool TransmitMsg(CANmsg msg);
    
    /// Read a message from the bus into a buffer
    ///
    /// This method will extract a message from the bus and put it 
    /// in the message space provided
    ///
    /// @param msg is a reference to a CANmsg into which the msg is placed
    /// @returns true if a message was received and processed
    ///
    bool ReceiveMsg(CANmsg &msg);
    
    /// This flashes the activity indicator associated with this CANPort
    ///
    /// If the activity indicator is configured.
    ///
    /// @param tx indiciates if the flash is to be a sign of xmt or rcv
    ///        it will flash dimly for a transmit and bright for a receive
    ///
    void Flash(CANDIR_T tx);
    
    /// This extinguishes the activity indicator associated with this CANPort
    ///
    /// If the activity indicator is configured.
    ///
    void Extinguish(void);
    
    /// Attach a callback whenever a CAN receive interrupt is generated
    ///
    /// This attaches a simple callback to the CAN ISR
    ///
    /// @param fptr pointer to the function to be called 
    ///
    void Attach( void  (*fptr)(void) );
    
    /// Attach a callback whenever a CAN receive interrupt is generated
    ///
    /// This attaches a callback to the CAN ISR
    ///
    /// @param tptr pointer to the object to call the member function on 
    /// @param mptr pointer to the member function to be called 
    ///
    template <typename T> void Attach(T * tptr, void (T::*mptr)(void)) {
        can->attach(tptr, mptr);
    }
    
    /// This provides control of the AutoReset feature
    ///
    /// AutoReset is a feature that permits automatically resetting the 
    /// CAN chip when it is trapped in an error state (e.g. bus off).
    /// The default is disabled.
    ///
    /// @param enable is used to enable or disable the auto reset feature
    /// @returns true if the command was accepted
    ///
    bool SetAutoReset(bool enable);
    
    /// This returns the current state of the AutoReset feature
    ///
    /// Returns a value indicating the current state
    ///
    /// @returns true if AutoReset is enabled
    /// @returns false if AutoReset is disabled
    ///
    bool GetAutoReset() { return autoReset; }
    
    /// This provides control to set the bus mode as active or listener only
    ///
    /// The CAN adapter can be placed into a monitor(LISTENER) mode (sometimes
    /// called promiscuous mode) or into an active mode, in which case it
    /// will send hardware acknowledge.
    ///
    /// @param mode is either MONITOR or ACTIVE
    /// @returns true if the command was accepted
    ///
    bool SetBusMode(CANBusMode_T mode);
    
    /// This returns the current state of the bus mode
    ///
    /// @returns MONITOR if the chip is in the monitor (listen / promiscuous) mode
    /// @returns ACTIVE if the chip is in the active mode
    ///
    CANBusMode_T GetBusMode();

    /// This provides control to set the transceiver slope control mode
    ///
    /// Many CAN transceivers can be operated in one of several modes - 
    /// \li HIGHSPEED - which supports the highest frequency of communication, but
    ///     does tend to generate more EMI unless the cable is properly shielded
    /// \li NORMALSPEED - which wave-shapes the rising and falling edge, and
    ///     significantly reduces the EMI concerns, but may trade off the
    ///     highest performance.
    /// \li STANDBY - which puts the chip into the lowest power state, and prevents
    ///     transmission of a message. It can typically still receive messages,
    ///     but this mode may also be useful for other purposes (wake on CAN,
    ///     autobaud w/o disrupting bus traffic, etc.)
    ///
    /// @param slope sets the slope control to one of the states HIGHSPEED, 
    ///     NORMALSPEED, or STANDBY
    /// @returns true if the command succeeded
    /// @returns false if the command failed, which may be due to not having
    ///     defined a slope control pin.
    ///
    bool SetSlopeControl(CANSlopeControl_T slope);
    
    /// This returns the current state of the slope control
    /// 
    /// The state is controlled by the SetSlopeControl command.
    ///
    /// @returns the current state; one of HIGHSPEED, NORMALSPEED, or STANDBY
    ///
    CANSlopeControl_T GetSlopeControl();

    /// This sets the bitrate for the CAN channel
    ///
    /// This sets the bitrate for the CAN channel. The rate is in bits per
    /// second. The actual bitrate and the sample point is automagically 
    /// determined from the internal algorithms provided by the mbed library.
    ///
    /// This API appears redundant to the frequency api, however this one
    /// will retain the rate setting and then permits the query of the bitrate.
    /// 
    /// @param rate is the desired bitrate in bits per second.
    /// @returns true if teh command succeeded
    ///
    bool SetBitRate(int rate);
    
    /// This returns the current desired bitrate for the CAN channel
    ///
    /// This returns the previously set bitrate. Note that the actual bitrate
    /// may be different, due to the internal calculations of the mbed library.
    ///
    /// @returns the bitrate in bits per second
    ///
    int GetBitRate();

    /// This returns the number of messages that were sent by this CAN channel
    ///
    /// The counter is never reset.
    ///
    /// @returns the number of messages sent by this CAN channel
    ///
    int GetTxCounter();

    /// This returns the number of messages that were received by this CAN channel
    ///
    /// The counter is never reset.
    ///
    /// @returns the number of messages received by this CAN channel
    ///
    int GetRxCounter();
    
    /// This returns the number of transmit errors
    ///
    /// As counted by the hardware
    ///
    /// @returns the number of transmit errors
    int GetTxErrorCounter();
    
    /// This returns the number of receive errors
    ///
    /// As counted by the hardware
    ///
    /// @returns the number of receive errors
    int GetRxErrorCounter();
    
    /// This resets the CAN interface
    ///
    /// Unconditionally.
    ///
    /// @returns true if success
    ///
    bool ResetChip();
    
    /// This writes various CAN info to the selected serial channel
    ///
    /// When supplied with a Serial port channel, this will output
    /// some possibly interesting information about the CAN configuration.
    /// It does not output details for only the active objects channel,
    /// rather it outputs information about the CAN subsystem.
    ///
    /// @param stream is the handle of a serial channel
    /// @returns nothing
    ///
    void PrintInfo(Serial * stream);

private:
    CANCHANNEL_T channel;       // user assigned port number of this port
    CAN * can;                  // bind to a specific CAN
    CANBusMode_T busMode;       // monitor or active mode
    int bitRate;                // bit rate for this bus
    PwmOut * activityPin;       // LED to indicate activity
    Timeout activityTimeout;    // used to extinguish the LED

    DigitalInOut * slopePin;    // pin used to control the transceiver slope modes
    PinName slopePinName;
    CANSlopeControl_T slopeMode;// current mode

    bool autoReset;             // true when auto reset on error is enabled
    uint32_t txCounter;
    uint32_t rxCounter;
};

#endif // CANPORT_H