Small project to display some OBD values from the Toyota GT86/ Subaru BRZ/ Scion FRS on an OLED display.

Dependencies:   Adafruit_GFX MODSERIAL mbed-rtos mbed

IsoTpHandler.h

Committer:
chrta
Date:
2014-04-22
Revision:
1:ca506b88b1d6
Parent:
0:6b1f6139fb25
Child:
3:eb807d330292

File content as of revision 1:ca506b88b1d6:

#ifndef ISO_TP_HANDLER
#define ISO_TP_HANDLER

#include "mbed.h"

/**
 * http://en.wikipedia.org/wiki/ISO_15765-2
 */
class IsoTpHandler
{
private:

    /**
     * Represents a state.
     */
    class State
    {
    public:
    
        /**
         * Empty destructor.
         */
        virtual ~State() {}
        
        /**
         * Processes the received can message.
         *
         * \param[in] message This can message it processed.
         * \param context This state machine (context) is used.
         */
        virtual void processInput(const CANMessage* message, IsoTpHandler* context) const = 0;
        
        /**
         * This method is called when this state is entered.
         * \param context This state machine (context) is used.
         */
        virtual void onEnter(IsoTpHandler* context) const = 0;
        
        /**
         * This method is called when leaving this state.
         * \param context This state machine (context) is used.
         */
        virtual void onLeave(IsoTpHandler* context) const = 0;
    };
    
    /**
     * No special packet expected 
     */
    class IdleState : public State
    {
    public:
        IdleState();
        
        virtual void processInput(const CANMessage* message, IsoTpHandler* context) const;
        virtual void onEnter(IsoTpHandler* context) const;
        virtual void onLeave(IsoTpHandler* context) const;
    };
    
    /**
     * Expect packets of type "consecutive frame"
     */
    class ConsequtiveTransferState : public State
    {
    public:
        ConsequtiveTransferState();
        
        virtual void processInput(const CANMessage* message, IsoTpHandler* context) const;
        virtual void onEnter(IsoTpHandler* context) const;
        virtual void onLeave(IsoTpHandler* context) const;
    };
public:

    /**
     * Constructor
     *
     * \param[in] canInterface The can interface the packets should be sent to. It must not be NULL.
     */
    IsoTpHandler(CAN* canInterface);
    
    /**
     * Processes the given can message.
     *
     * This is the main method. It must be called for every received IsoTp can packet.
     * It updates the internal state and sends the can response.
     *
     * \param[in] message The received can message. It must not be NULL.
     */  
    void processCanMessage(const CANMessage* message);
    
    /**
     * This method is called when a complete Iso Tp message was received.
     *
     * Currently the packet is only printed out.
     * Later a user callbeck must be executed from here.
     *
     * \param[in] data The content of the Iso Tp message.
     * \param[in] length The amount of bytes in data.
     */
    void handle_decoded_packet(const uint8_t* data, uint16_t length);
        
    /**
     *
     * \param[in] messageSize Total bytes included in the consequtive transfer. 
     * \param[in] data Always 6 bytes.
     */
    void init_consequtive_reading(uint16_t messageSize, const uint8_t* data);
    
    /**
     * Returns the next expected index value of the can packet.
     *
     * \return The next expected index value.
     */
    uint8_t getExpectedIndex() const;
    
    /**
     * Increments the expected index.
     *
     * This method ensures an automatic wrap around from 15 to 0.
     */
    void incrementExpectedIndex();
    
    /**
     * Appends the given data to the internal consequtive transfer buffer.
     *
     * \retval \c True if the state should be switched.
     * \retval \c False if the state not change.
     */
    bool appendReceivedData(const uint8_t* data, uint8_t length);

    /**
     * Modifies the internal state.
     *
     * Should not be used externally.
     *
     * \param[in] The new state.
     */
    void setState(const State* state);

    static const IdleState idleState;
    static const ConsequtiveTransferState consequtiveTransferState;
    
    static bool isValidIsoTpPacket(const CANMessage* message);

private:

    /** The current state. */
    const State* m_state;
    
    /** The used can interface. */
    CAN* m_canInterface;
    
    /** This buffer must be able to store the maximum message size. */
    uint8_t m_messageBuffer[256];
    
    /** The expected size of the current message. */
    uint16_t m_expectedMessageSize;
    
    /** The current size of the message that is currently received. */
    uint16_t m_currentMessageSize;
    
    /** Stores the index that is expected in the next can packet. */
    uint8_t m_expectedIndex;
};
    

#endif //ISO_TP_HANDLER