/*********************************************************************
 *
 *                  DMA API definitions
 *
 *********************************************************************
 * FileName:        Dma.h
 * Dependencies:    xc.h
 *                  int.h
 *
 * Processor:       PIC32
 *
 * Complier:        MPLAB C32
 *                  MPLAB IDE
 * Company:         Microchip Technology Inc.
 *
 * Software License Agreement
 *
 * The software supplied herewith by Microchip Technology Incorporated
 * (the “Company”) for its PIC32/PIC24F Microcontroller is intended
 * and supplied to you, the Company’s customer, for use solely and
 * exclusively on Microchip PIC32/PIC24F Microcontroller products.
 * The software is owned by the Company and/or its supplier, and is
 * protected under applicable copyright laws. All rights are reserved.
 * Any use in violation of the foregoing restrictions may subject the
 * user to criminal sanctions under applicable laws, as well as to
 * civil liability for the breach of the terms and conditions of this
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 *
 * $Id: Dma.h,v 1.9 2007/01/17 21:35:46 C12878 Exp $
 * $Name:  $
 *
 ********************************************************************/

#ifndef _DMA_5XX_6XX__7XX_H_
#define _DMA_5XX_6XX__7XX_H_

#include <xc.h>

/*
*  WARNING: All the Peripheral Library (PLIB) functions, including those in this file,
*  will be removed from future releases of MPLAB XC32 C/C++ Compiler.
*  Please refer to the MPLAB Harmony Libraries for new projects.  For legacy support,
*  these PLIB Libraries will be available for download from: www.microchip.com/pic32_peripheral_lib
*/
#ifndef _SUPPRESS_PLIB_WARNING
  #warning The PLIB functions and macros in this file will be removed from the MPLAB XC32 C/C++ Compiler in future releases
#endif


// DMA definitions

#ifdef _DMAC0
    #define _DMA_CHANNELS       // DMA channels exist


// existent DMA channels
    typedef enum
    {
        DMA_CHANNEL0,
    #ifdef _DMAC1
        DMA_CHANNEL1,
    #ifdef _DMAC2
        DMA_CHANNEL2,
    #ifdef _DMAC3
        DMA_CHANNEL3,
    #ifdef _DMAC4
        DMA_CHANNEL4,
    #ifdef _DMAC5
        DMA_CHANNEL5,
    #ifdef _DMAC6
        DMA_CHANNEL6,
    #ifdef _DMAC7
        DMA_CHANNEL7,
    #endif  // _DMAC7
    #endif  // _DMAC6
    #endif  // _DMAC5
    #endif  // _DMAC4
    #endif  // _DMAC3
    #endif  // _DMAC2
    #endif  // _DMAC1
        //  add/remove DMA channel as needed here

        DMA_CHANNELS    // number of current available channels
    }DmaChannel;


    // Relative Dma channels priority, between each other
    typedef enum
    {
        DMA_CHN_PRI0,
        DMA_CHN_PRI1,
        DMA_CHN_PRI2,
        DMA_CHN_PRI3
    }DmaChannelPri;



    // high level definitions for the API functions

    typedef enum
    {
        DMA_OPEN_DEFAULT = 0,                                   // DMA default operation
        DMA_OPEN_AUTO   = _DCH0CON_CHAEN_MASK,                  // DMA channel is auto enabled
        DMA_OPEN_CHAIN_LOW  = (_DCH0CON_CHCHN_MASK|_DCH0CON_CHCHNS_MASK),   // DMA channel is chained to lower channel
        DMA_OPEN_CHAIN_HI  = (_DCH0CON_CHCHN_MASK),             // DMA channel is chained to higher channel
        DMA_OPEN_DET_EN = _DCH0CON_CHAED_MASK,                  // events detection enabled while channel off
        DMA_OPEN_ENABLE = _DCH0CON_CHEN_MASK,                   // DMA channel is enabled after open
        DMA_OPEN_MATCH  = 0x80000000,                           // DMA channel stops on match
    }DmaOpenFlags;  // flags for the channel open


    typedef enum
    {
        DMA_EV_ERR =            0x1,        // address error event
        DMA_EV_ABORT =          0x2,        // transfer abort event
        DMA_EV_CELL_DONE =      0x4,        // cell transfer complete event
        DMA_EV_BLOCK_DONE =     0x8,        // block transfer complete event
        DMA_EV_DST_HALF =       0x10,       // destination half event
        DMA_EV_DST_FULL =       0x20,       // destination full event
        DMA_EV_SRC_HALF =       0x40,       // source half event
        DMA_EV_SRC_FULL =       0x80,       // source full event

        DMA_EV_ALL_EVNTS=       (DMA_EV_ERR|DMA_EV_ABORT|DMA_EV_CELL_DONE|DMA_EV_BLOCK_DONE|DMA_EV_DST_HALF|
                                    DMA_EV_DST_FULL|DMA_EV_SRC_HALF|DMA_EV_SRC_FULL)                // all available events
    }DmaEvFlags;    // flags for controlling the DMA channel events; Bit fields from the processor header file.


    typedef enum
    {
        DMA_TXFER_OK,           // the transfer was performed successfully
        DMA_TXFER_ADD_ERR,      // address error while performing the transfer
        DMA_TXFER_ABORT,        // the DMA transfer was aborted
        DMA_TXFER_BC_ERR,       // block complete not set after the DMA transfer performed
        DMA_TXFER_CC_ERR,       // cell complete not set after the DMA transfer performed
        DMA_TXFER_TMO           // DMA transfer timeout
    }DmaTxferRes;       // DMA transfer result

    typedef enum
    {
        DMA_WAIT_NOT,       // don't wait for the transfer to complete, return immediately
        DMA_WAIT_CELL,      // wait for the cell transfer to complete, than return
        DMA_WAIT_BLOCK      // wait for the block transfer to complete, than return
    }DmaWaitMode;       // DMA transfer wait mode

    typedef enum
    {
        DMA_CHKSUM_CRC,     // LFSR CRC
        DMA_CHKSUM_IP,      // IP Checksum
    }DmaChksumType;     // DMA SFM supported checksum types

    typedef enum
    {
        DMA_BITO_MSb,       // MSb first (not reflected)
        DMA_BITO_LSb,       // LSb first (reflected)
    }DmaBitOrder;       // DMA SFM supported bit ordering

    typedef enum
    {
        DMA_REORDER_NOT,    // no reordering, destination matches the source
        DMA_REORDER_ENDIAN, // change endianess on word (32 bit) boundaries: LE<->BE
        DMA_REORDER_SWAP_HALF,  // swap half words (16 bit) within word (32 bit)
        DMA_REORDER_SWAP_BYTE,  // swap bytes within half word (16 bit)
    }DmaReorderMode;    // DMA SFM supported re-ordering modes


    /*********************************************************************
     * Function:        void DmaChnOpen(DmaChannel chn, DmaChannelPri chPri, DmaOpenFlags oFlags)
     *
     * PreCondition:    chPri  - valid channel priority, 0-3
     *
     * Input:           chn    - channel to be configured in the DMA controller
     *                  chPri  - the priority given to the channel, 0-3
     *                  oFlags - orred flags specifying the open mode:
     *                           DMA_OPEN_DEFAULT: DMA default operation mode
     *                           DMA_OPEN_AUTO: DMA channel is auto enabled
     *                           DMA_OPEN_CHAIN_LOW: DMA channel is chained to lower channel
     *                           DMA_OPEN_CHAIN_HI: DMA channel is chained to higher channel
     *                           DMA_OPEN_DET_EN: events detection enabled while channel off
     *                           DMA_OPEN_ENABLE: DMA channel is enabled when opened
     *                           DMA_OPEN_MATCH:    DMA channel stops on match
     *
     *
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function opens and configures the selected DMA channel using the supplied user flags and priority.
     *
     * Note:            - This is a high level access function that doesn't give access to all the settings possible for a DMA channel.
     *                  Use the low level functions to address special settings.
     *                  - The channel is turned off, the pending interrupts are cleared, interrupts are disabled.
     *                  After that the channel is configured.
     *                  - After calling this function, the channel should be enabled using DmaChnEnable(chn) call
     *                  if DMA_OPEN_ENABLE flag was not specified.
     *                  - If the CRC is attached to the submitted channel, the CRC append mode will be turned off.
     *                  This way, the transfer will occur correctly together with CRC calculation.
     *                  - The start and abort Irqs will be disabled and the channel event enable flags are disabled.
     *                  User has to call event channel functions to enable the event flags if needed.
     *
     * Example:         DmaChnOpen(DMA_CHANNEL2, DMA_CHN_PRI2, DMA_OPEN_AUTO|DMA_OPEN_MATCH|DMA_OPEN_ENABLE);
     ********************************************************************/
     void           DmaChnOpen(DmaChannel chn, DmaChannelPri chPri, DmaOpenFlags oFlags);

    /*********************************************************************
     * Function:        void DmaChnEnable(DmaChannel chn)
     *
     * PreCondition:    None
     *
     * Input:           chn     - channel to be enabled
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function enables a previously configured DMA channel.
     *
     * Note:            DmaChnOpen()/DmaChnConfigure() should have been called before.
     *
     * Example:         DmaChnEnable(DMA_CHANNEL3);
     ********************************************************************/
     void           DmaChnEnable(DmaChannel chn);

    /*********************************************************************
     * Function:        void DmaChnDisable(DmaChannel chn)
     *
     * PreCondition:    None
     *
     * Input:           chn     - selected channel in the DMA controller
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function disables a DMA channel. The channel operation stops.
     *
     * Note:            None.
     *
     * Example:         DmaChnDisable(DMA_CHANNEL3);
     ********************************************************************/
     void           DmaChnDisable(DmaChannel chn);

    /*********************************************************************
     * Function:        void DmaChnSetTxfer(DmaChannel chn, const void* vSrcAdd, void* vDstAdd, int srcSize, int dstSize, int cellSize)
     *
     * PreCondition:    chn     - valid DMA channel
     *              - vSrcAdd, vDstAdd  - valid pointers
     *                              - 0 < srcSize <= DmaGetMaxTxferSize()
     *                              - 0 < dstSize <= DmaGetMaxTxferSize()
     *                              - 0 < cellSize <= DmaGetMaxTxferSize()
     *
     * Input:           chn         - DMA channel number
     *                              - vSrcAdd: source of the DMA transfer
     *                              - vDstAdd: destination of the DMA transfer
     *                              - srcSize: source buffer size, 1 to DmaGetMaxTxferSize() bytes, wrapped arround
     *                              - dstSize: destination buffer size, 1 to DmaGetMaxTxferSize() bytes, wrapped around
     *                              - cellSize: cell transfer size, 1 to DmaGetMaxTxferSize() bytes.
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function sets the transfer characteristics for a DMA channel transfer:
     *                  the source and the destination addresses.
     *                  the source and destination lengths
     *                  and the number of bytes transferred per event.
     *
     * Note:            The function clears the existing DMA channel event flags.
     *                  The source to destination byte re-ordering is affected by DmaSfmConfigure(), DmaSfmTxferReorder().
     *
     * Example:         DmaChnSetTxfer(DMA_CHANNEL3, &U2RXREG, dstBuff, 1, 200, 1);
     ********************************************************************/
     void           DmaChnSetTxfer(DmaChannel chn, const void* vSrcAdd, void* vDstAdd, int srcSize, int dstSize, int cellSize);


    /*********************************************************************
     * Function:        void DmaChnSetSrcAdd(DmaChannel chn, const void* vSrcAdd)
     *
     * PreCondition:    chn     - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *              - vSrcAdd: source (virtual) of the DMA transfer
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function is a helper to set directly the transfer source address.
     *
     * Note:            None.
     *
     * Example:         DmaChnSetSrcAdd(DMA_CHANNEL2, srcBuff+sizeof(srcBuff));
     ********************************************************************/
     void           DmaChnSetSrcAdd(DmaChannel chn, const void* vSrcAdd);

    /*********************************************************************
     * Function:        void DmaChnSetDstAdd(DmaChannel chn, void* vDstAdd)
     *
     * PreCondition:    chn     - valid DMA channel
     *
     * Input:           chn         - DMA channel number
     *                              - vDstAdd: destination (virtual) of the DMA transfer
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function is a helper to set directly the transfer destination address.
     *
     * Note:            None
     *
     * Example:         DmaChnSetDstAdd(DMA_CHANNEL2, dstBuff+sizeof(dstBuff));
     ********************************************************************/
     void           DmaChnSetDstAdd(DmaChannel chn, void* vDstAdd);

    /*********************************************************************
     * Function:        void DmaChnSetMatchPattern(DmaChannel chn, int pattern)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *                  pattern -  the match pattern
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function sets the curent match pattern for the selected DMA channel.
     *
     * Note:            None.
     *
     * Example:         DmaChnSetMatchPattern(DMA_CHANNEL3, '\r');
     ********************************************************************/
     void           DmaChnSetMatchPattern(DmaChannel chn, int pattern);

    /*********************************************************************
     * Function:        int DmaChnGetMatchPattern(DmaChannel chn)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *
     * Output:          The channel match pattern.
     *
     * Side Effects:    None
     *
     * Overview:        The function retrieves the curent match pattern for the selected DMA channel.
     *
     * Note:            None.
     *
     * Example:         int pattern=DmaChnGetMatchPattern(DMA_CHANNEL3);
     ********************************************************************/
     int            DmaChnGetMatchPattern(DmaChannel chn);

    /*********************************************************************
     * Function:        DmaTxferRes DmaChnStartTxfer(DmaChannel chn, DmaWaitMode wMode, unsigned long retries)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *                  wMode   - if DMA_WAIT_NOT, return immediately
     *                          - if DMA_WAIT_CELL, return after the cell transfer complete
     *                          - if DMA_WAIT_BLOCK, return after the whole transfer is done
     *                  retries - retry counter: if transfer not complete after so many retries, return with tmo.
     *                              If 0, wait forever.
     *
     * Output:          DMA_TXFER_OK if not waiting for the transfer completion or if the transfer ended normally,
     *                  an DmaTxferRes error code  otherwise
     *
     * Side Effects:    None
     *
     * Overview:        The function initiates (forces) a DMA transfer for the selected DMA channel.
     *                  The DMA channel is enabled.
     *                  If waiting for the transfer completion needed (user doesn't use an ISR to catch
     *                  this event) the function will periodically query the DMA controller for the
     *                  transfer completion status.
     *                  If DMA_WAIT_BLOCK is specified and multiple cell transfers are needed to complete
     *                  the block transfer than the function will re-force the transfer for each cell.
     *
     * Note:            This function can not ne used when the DMA channel is triggerred
     *                  by hardware interrupt requests.
     *                  This is because the transfers are software forced, theere is no
     *                  wait for the occurrence of the hardware trigger.
     *
     * Example:         DmaChnStartTxfer(DMA_CHANNEL2, DMA_WAIT_BLOCK, 0);
     ********************************************************************/
     DmaTxferRes DmaChnStartTxfer(DmaChannel chn, DmaWaitMode wMode, unsigned long retries);

    /*********************************************************************
     * Function:        void DmaChnForceTxfer(DmaChannel chn)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function forces a DMA transfer to occur for the selected DMA channel.
     *
     * Note:            None.
     *
     * Example:         DmaChnForceTxfer(DMA_CHANNEL3);
     ********************************************************************/
     void           DmaChnForceTxfer(DmaChannel chn);

    /*********************************************************************
     * Function:        void DmaChnAbortTxfer(DmaChannel chn)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function aborts a current undergoing DMA transfer for the selected DMA channel.
     *
     * Note:            None.
     *
     * Example:         DmaChnAbortTxfer(DMA_CHANNEL3);
     ********************************************************************/
     void           DmaChnAbortTxfer(DmaChannel chn);

    // High level channel event and interrupt control functions

    /*********************************************************************
     * Function:        void DmaChnSetEvEnableFlags(DmaChannel chn, DmaEvFlags eFlags)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *                  eFlags  - event flags with the following significance:
     *                              - DMA_EV_ERR: address error event
     *                              - DMA_EV_ABORT: transfer abort event
     *                              - DMA_EV_CELL_DONE: cell transfer complete event
     *                              - DMA_EV_BLOCK_DONE: block transfer complete event
     *                              - DMA_EV_DST_HALF: destination half event
     *                              - DMA_EV_DST_FULL: destination full event
     *                              - DMA_EV_SRC_HALF: source half event
     *                              - DMA_EV_SRC_FULL: source full event
     *                              - DMA_EV_ALL_EVNTS: all of the above flags
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function sets the event enable flags for the selected DMA channel.
     *                  Multiple flags can be orr-ed together. Any flag that is set in the eFlags will be
     *                  enabled for the selected channel, the other channel event flags won't be touched.
     *
     * Note:            None.
     *
     * Example:         DmaChnSetEvEnableFlags(DMA_CHANNEL3, DMA_EV_ERR|DMA_EV_ABORT|DMA_EV_BLOCK_DONE|DMA_EV_SRC_FULL);
     ********************************************************************/
     void           DmaChnSetEvEnableFlags(DmaChannel chn, DmaEvFlags eFlags);

    /*********************************************************************
     * Function:        void DmaChnClrEvEnableFlags(DmaChannel chn, DmaEvFlags eFlags)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *                  eFlags  - event flags with the following significance:
     *                              - DMA_EV_ERR: address error event
     *                              - DMA_EV_ABORT: transfer abort event
     *                              - DMA_EV_CELL_DONE: cell transfer complete event
     *                              - DMA_EV_BLOCK_DONE: block transfer complete event
     *                              - DMA_EV_DST_HALF: destination half event
     *                              - DMA_EV_DST_FULL: destination full event
     *                              - DMA_EV_SRC_HALF: source half event
     *                              - DMA_EV_SRC_FULL: source full event
     *                              - DMA_EV_ALL_EVNTS: all of the above flags
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function clears the event enable flags for the selected DMA channel.
     *                  Multiple flags can be orr-ed together. Any flag that is set in the eFlags will be
     *                  disabled for the selected channel, the other channel event flags won't be touched.
     *
     * Note:            None.
     *
     * Example:         DmaChnClrEvEnableFlags(DMA_CHANNEL3, DMA_EV_ERR|DMA_EV_ABORT|DMA_EV_BLOCK_DONE|DMA_EV_SRC_FULL);
     ********************************************************************/
     void           DmaChnClrEvEnableFlags(DmaChannel chn, DmaEvFlags eFlags);

    /*********************************************************************
     * Function:        void DmaChnWriteEvEnableFlags(DmaChannel chn, DmaEvFlags eFlags)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *                  eFlags  - event flags with the following significance:
     *                              - DMA_EV_ERR: address error event
     *                              - DMA_EV_ABORT: transfer abort event
     *                              - DMA_EV_CELL_DONE: cell transfer complete event
     *                              - DMA_EV_BLOCK_DONE: block transfer complete event
     *                              - DMA_EV_DST_HALF: destination half event
     *                              - DMA_EV_DST_FULL: destination full event
     *                              - DMA_EV_SRC_HALF: source half event
     *                              - DMA_EV_SRC_FULL: source full event
     *                              - DMA_EV_ALL_EVNTS: all of the above flags
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function sets the event enable flags for the selected DMA channel.
     *                  The channel event flags are forced to the eFlags value.
     *
     * Note:            None.
     *
     * Example:         DmaChnWriteEvEnableFlags(DMA_CHANNEL3, DMA_EV_ALL_EVNTS);
     ********************************************************************/
     void           DmaChnWriteEvEnableFlags(DmaChannel chn, DmaEvFlags eFlags);

    /*********************************************************************
     * Function:        DmaEvFlags DmaChnGetEvEnableFlags(DmaChannel chn)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *
     * Output:          - event flags with the following significance:
     *                      - DMA_EV_ERR: address error event
     *                      - DMA_EV_ABORT: transfer abort event
     *                      - DMA_EV_CELL_DONE: cell transfer complete event
     *                      - DMA_EV_BLOCK_DONE: block transfer complete event
     *                      - DMA_EV_DST_HALF: destination half event
     *                      - DMA_EV_DST_FULL: destination full event
     *                      - DMA_EV_SRC_HALF: source half event
     *                      - DMA_EV_SRC_FULL: source full event
     *                      - DMA_EV_ALL_EVNTS: all of the above flags
     *
     * Side Effects:    None
     *
     * Overview:        The function returns the event enabled flags for the selected DMA channel.
     *
     * Note:            None.
     *
     * Example:         DmaEvFlags enabledFlags=DmaChnGetEvEnableFlags(DMA_CHANNEL3);
     ********************************************************************/
     DmaEvFlags DmaChnGetEvEnableFlags(DmaChannel chn);

    /*********************************************************************
     * Function:        void DmaChnClrEvFlags(DmaChannel chn, DmaEvFlags eFlags)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *                  eFlags  - event flags with the following significance:
     *                              - DMA_EV_ERR: address error event
     *                              - DMA_EV_ABORT: transfer abort event
     *                              - DMA_EV_CELL_DONE: cell transfer complete event
     *                              - DMA_EV_BLOCK_DONE: block transfer complete event
     *                              - DMA_EV_DST_HALF: destination half event
     *                              - DMA_EV_DST_FULL: destination full event
     *                              - DMA_EV_SRC_HALF: source half event
     *                              - DMA_EV_SRC_FULL: source full event
     *                              - DMA_EV_ALL_EVNTS: all of the above flags
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function clears the event flags for the selected DMA channel.
     *                  Multiple flags can be orr-ed together. Any flag that is set in the eFlags will be
     *                  cleared for the selected channel, the other channel event flags won't be touched.
     *
     * Note:            None.
     *
     * Example:         DmaChnClrEvFlags(DMA_CHANNEL3, DMA_EV_ALL_EVNTS);
     ********************************************************************/
     void           DmaChnClrEvFlags(DmaChannel chn, DmaEvFlags eFlags);

    /*********************************************************************
     * Function:        DmaEvFlags DmaChnGetEvFlags(DmaChannel chn)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *
     * Output:          event flags with the following significance:
     *                      - DMA_EV_ERR: address error event
     *                      - DMA_EV_ABORT: transfer abort event
     *                      - DMA_EV_CELL_DONE: cell transfer complete event
     *                      - DMA_EV_BLOCK_DONE: block transfer complete event
     *                      - DMA_EV_DST_HALF: destination half event
     *                      - DMA_EV_DST_FULL: destination full event
     *                      - DMA_EV_SRC_HALF: source half event
     *                      - DMA_EV_SRC_FULL: source full event
     *                      - DMA_EV_ALL_EVNTS: all of the above flags
     *
     * Side Effects:    None
     *
     * Overview:        The function returns the event flags for the selected DMA channel.
     *
     * Note:            None.
     *
     * Example:         DmaEvFlags intSetFlags=DmaChnGetEvFlags(DMA_CHANNEL3);
     ********************************************************************/
     DmaEvFlags DmaChnGetEvFlags(DmaChannel chn);


    // high level helpers for fast strcpy/memcpy transfers

    /*********************************************************************
     * Function:        DmaTxferRes DmaChnMemcpy(void* s1, const void* s2, int n, DmaChannel chn, DmaChannelPri chPri)
     *
     * PreCondition:    chn     - a valid DMA channel
     *                  s1, s2  - valid memory pointers
     *                  n>0, n<=DmaGetMaxTxferSize()
     *
     * Input:           s1      - destination pointer
     *                  s2      - source pointer
     *                  n       - number of bytes to transfer
     *                  chn     - the DMA channel to perform the transfer
     *                  chPri   - the desired channel priority
     *
     * Output:          DMA_TXFER_OK if the transfer ended normally,
     *                  an DmaTxferRes error code  otherwise
     *
     * Side Effects:    None
     *
     * Overview:        The function configures a DMA channel for a fast memory transfer.
     *          Then it copies one block of memory from source to destination.
     *
     *
     * Note:            - If the SFM is attached to the submitted channel, the SFM append mode will be turned off.
     *                    This way, the transfer will occur correctly together with checksum calculation.
     *                  - The start and abort Irqs will be disabled and the channel event enable flags are disabled.
     *                  - Multiple channels could be opened to perform fast memory transfers, if necessary.
     *                  - The function clears the suspend state and resumes the operation of the DMA controller.
     *                  - The source to destination byte re-ordering is affected by DmaSfmConfigure(), DmaSfmTxferReorder().
     *
     * Example:     res=DmaChnMemcpy(pDst, pSrc, buffSz, DMA_CHANNEL0, DMA_CHN_PRI3);
     ********************************************************************/
     DmaTxferRes    DmaChnMemcpy(void* s1, const void* s2, int n, DmaChannel chn, DmaChannelPri chPri);

    /*********************************************************************
     * Function:        DmaTxferRes DmaChnStrcpy(char* s1, const char* s2, DmaChannel chn, DmaChannelPri chPri)
     *
     * PreCondition:    chn     - a valid DMA channel
     *                  s1, s2  - valid memory pointers
     *
     * Input:           s1      - destination pointer
     *                  s2      - source pointer
     *                  chn     - the DMA channel to perform the transfer
     *                  chPri   - the desired channel priority
     *
     * Output:          DMA_TXFER_OK if the transfer ended normally,
     *                  an DmaTxferRes error code  otherwise
     *
     * Side Effects:    None
     *
     * Overview:        The function configures a DMA channel for a fast memory transfer.
     *          Then it copies one zero terminated string from source to destination.
     *
     *
     * Note:            - If the SFM is attached to the submitted channel, the SFM append mode will be turned off.
     *                    This way, the transfer will occur correctly together with checksum calculation.
     *                  - The start and abort Irqs will be disabled and the channel event enable flags are disabled.
     *                  - Multiple channels could be opened to perform fast memory transfers, if necessary.
     *                  - The function clears the suspend state and resumes the operation of the DMA controller.
     *                  - The source to destination byte re-ordering is affected by DmaSfmConfigure(), DmaSfmTxferReorder().
     *
     *
     * Example:     res=DmaChnStrcpy(str1, str2, DMA_CHANNEL1, DMA_CHN_PRI3);
     *********************************************************************/
     DmaTxferRes    DmaChnStrcpy(char* s1, const char* s2, DmaChannel chn, DmaChannelPri chPri);

    /*********************************************************************
     * Function:        DmaTxferRes DmaChnStrncpy(char* s1, const char* s2, int n, DmaChannel chn, DmaChannelPri chPri)
     *
     * PreCondition:    chn     - a valid DMA channel
     *              - s1, s2    - valid memory pointers
     *                              - 0 < n <= DmaGetMaxTxferSize()
     *
     * Input:           s1      - destination pointer
     *                  s2      - source pointer
     *                  n   - max number of bytes to transfer
     *                  chn     - the DMA channel to perform the transfer
     *                  chPri   - the desired channel priority
     *
     * Output:          DMA_TXFER_OK if the transfer ended normally,
     *                  an DmaTxferRes error code  otherwise
     *
     * Side Effects:    None
     *
     * Overview:        The function configures a DMA channel for a fast memory transfer.
     *          Then it copies one zero terminated string from source to destination.
     *          It copies no more than n characters from s2.
     *
     *
     * Note:            - If the SFM is attached to the submitted channel, the SFM append mode will be turned off.
     *                    This way, the transfer will occur correctly together with checksum calculation.
     *                  - The start and abort Irqs will be disabled and the channel event enable flags are disabled.
     *                  - Multiple channels could be opened to perform fast memory transfers, if necessary.
     *                  - The function clears the suspend state and resumes the operation of the DMA controller.
     *                  - The source to destination byte re-ordering is affected by DmaSfmConfigure(), DmaSfmTxferReorder().
     *
     *
     * Example:     res=DmaChnStrncpy(str1, str2, MAX_STR_LEN, DMA_CHANNEL1, DMA_CHN_PRI3);
     ********************************************************************/
     DmaTxferRes DmaChnStrncpy(char* s1, const char* s2, int n, DmaChannel chn, DmaChannelPri chPri);

    /*********************************************************************
     * Function:        DmaTxferRes DmaChnMemCrc(void* d, const void* s, int n, DmaChannel chn, DmaChannelPri chPri)
     *
     * PreCondition:    chn    - a valid DMA channel
     *                  d, s   - valid memory pointer
     *                  n>0, n<=DmaGetMaxTxferSize()
     *
     * Input:           d     - address where to deposit the result
     *                  s     - source buffer pointer
     *                  n     - number of bytes in the pointer
     *                  chn   - the DMA channel to use
     *                  chPri - the desired channel priority
     *
     * Output:          DMA_TXFER_OK if the transfer ended normally,
     *                  an DmaTxferRes error code  otherwise
     *
     * Side Effects:    None
     *
     * Overview:        The function is a helper that calculates the CRC of a memory block.
     *                  The function configures the DMA channel for a fast memory transfer and calculates the CRC.
     *
     *
     * Note:            - The CRC generator must have been previously configured using DmaSfmCrcConfigure()
     *                  - No transfer is done, just the CRC is calculated.
     *                  - The start and abort Irqs will be disabled and the channel event enable flags are disabled.
     *                  - Append mode is enabled and the data transfer re-ordering is disabled (illegal combination, see DmaSfmTxferReorder()).
     *                  - The checksum type is switched to CRC.
     *                  - The way the data is fed into the checksum calculation block is affected by DmaSfmConfigure().
     *
     * Example:          int myCrc; DmaChnMemCrc(&myCrc, srcBuff, sizeof(srcBuff), DMA_CHANNEL2, DMA_CHN_PRI3);
     ********************************************************************/
     DmaTxferRes    DmaChnMemCrc(void* d, const void* s, int n, DmaChannel chn, DmaChannelPri chPri);

    /*********************************************************************
     * Function:        DmaTxferRes DmaChnMemChecksum(void* d, const void* s, int n, DmaChannel chn, DmaChannelPri chPri)
     *
     * PreCondition:    chn    - a valid DMA channel
     *                  d, s   - valid memory pointer
     *                  n>0, n<=DmaGetMaxTxferSize()
     *
     * Input:           d     - address where to deposit the result
     *                  s     - source buffer pointer
     *                  n     - number of bytes in the pointer
     *                  chn   - the DMA channel to use
     *                  chPri - the desired channel priority
     *
     * Output:          DMA_TXFER_OK if the transfer ended normally,
     *                  an DmaTxferRes error code  otherwise
     *
     * Side Effects:    None
     *
     * Overview:        The function is a helper that calculates the IP checksum of a memory block.
     *                  The function configures the DMA channel for a fast memory transfer and calculates the IP checksum.
     *
     *
     * Note:            - The checksum generator must have been previously seeded using DmaSfmSetSeed()
     *                  - No transfer is done, just the checksum is calculated.
     *                  - The start and abort Irqs will be disabled and the channel event enable flags are disabled.
     *                  - Append mode is enabled and the data transfer re-ordering is disabled (illegal combination, see DmaSfmTxferReorder()).
     *                  - The checksum type is switched to IP checksum.
     *                  - The way the data is fed into the checksum calculation block is affected by DmaSfmConfigure().
     *
     * Example:          int myChecksum; DmaChnMemChecksum(&myChecksum, srcBuff, sizeof(srcBuff), DMA_CHANNEL1, DMA_CHN_PRI3);
     ********************************************************************/
     DmaTxferRes    DmaChnMemChecksum(void* d, const void* s, int n, DmaChannel chn, DmaChannelPri chPri);

    // High level Special Function Module (SFM) functions

    /*********************************************************************
     * Function:        void DmaSfmConfigure(DmaChksumType cType, DmaBitOrder bitO, DmaReorderMode rMode)
     *
     * PreCondition:    cType, bitO, rMode - valid values
     *
     * Input:           cType - checksum type to be calculated: CRC or IP Checksum
     *                  bitO  - the bit order to be used MSb or LSb first
     *                  rMode - the reordering mode of the bytes when calculating the checksum
     *
     * Output:          None
     *
     * Side Effects:    Whenever the Transfer re-ordering is enabled the rMode setting will influence the destination data layout
     *
     * Overview:        The function configures the SFM module by setting the parameters that define the behavior:
     *                      - the type of the checksum to be calculated (either CRC or IP checksum are supported)
     *                      - the bit ordering (how a specific byte is used in the checksum calculation: MSb or LSb first)
     *                      - the data re-ordering (how bytes are re-ordered before calculating the checksum).
     *                      All these values affect the way the checksum is calculated.
     *
     * Note:            None
     *
     * Example:         DmaSfmConfigure(DMA_CHKSUM_CRC, DMA_BITO_LSb, DMA_REORDER_ENDIAN);
     ********************************************************************/
    extern __inline__ void __attribute__((always_inline)) DmaSfmConfigure(DmaChksumType cType, DmaBitOrder bitO, DmaReorderMode rMode)
    {
        DCRCCONCLR=_DCRCCON_CRCTYP_MASK|_DCRCCON_BITO_MASK|_DCRCCON_BYTO_MASK;
        DCRCCONSET=(cType<<_DCRCCON_CRCTYP_POSITION)|(bitO<<_DCRCCON_BITO_POSITION)|(rMode<<_DCRCCON_BYTO_POSITION);
    }

    /*********************************************************************
     * Function:        void DmaSfmTxferReorder(int enable)
     *
     * PreCondition:    None
     *
     * Input:           enable - boolean to enable/disable the re-ordering of the data transfer
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function configures the data transfer re-ordering of the SFM module.
     *                  If the re-ordering is enabled, the data is read from the source, re-ordered accordingly and then written to the destination.
     *                  Otherwise the data is written to the destination un-modified.
     *                  The re-ordering is the one specified by the DmaReorderMode parameter in the DmaSfmConfigure() call.
     *
     *
     * Note:            - The data transfer re-ordering should be used only for normal (background mode) data transfers.
     *                  - In append mode the data transfer re-ordering should not be enabled (undefined behavior)!
     *                  - Whenever the data re-ordering is enabled, the transfer should be aligned at both ends (source and destination).
     *                    Un-aligned transfers are not supported (undefined behavior)!
     *
     * Example:         DmaSfmTxferReorder();
     ********************************************************************/
    extern __inline__ void __attribute__((always_inline)) DmaSfmTxferReorder(int enable)
    {
        DCRCCONCLR=_DCRCCON_WBO_MASK;
        DCRCCONSET=(enable<<_DCRCCON_WBO_POSITION);
    }


     /*********************************************************************
     * Function:        void DmaSfmCrcConfigure(unsigned int polynomial, int pLen, unsigned int seed)
     *
     * PreCondition:    pLen   - valid polynomial length within 1-32
     *
     * Input:           polynomial  - the layout of the CRC generator
     *                  pLen        - the length of the CRC generator polynomial
     *                  seed        - the initial seed of the CRC generator
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function configures the SFM CRC module by setting the parameters that define the generator polynomial:
     *                  - the length of the CRC generator polynomial, pLen;
     *                  - the function sets the layout of the shift stages that take place in the CRC generation.
     *                    Setting a bit to 1 enables the XOR input from the MSb (pLen bit) to the selected stage in the shift register.
     *                    If bit is cleared, the selected shift stage gets data directly from the previous stage in the shift register.
     *                    Note that in a proper CRC polynomial, both the most significant bit (MSb) and least significant bit(LSb)
     *                    are always a '1'. Considering the generator polynomial: X^16+X^15+X^2+1, the value to be written as
     *                    feedback should be 0x8005, or 0x8004, but not 0x018005;
     *                  - the function sets the seed of the CRC generator. This is the initial data present in the
     *                   CRC shift register before the CRC calculation begins. A good initial value is usually 0xffffffff.
     *
     * Note:            - Bit 0 of the generator polynomial is always XOR'ed.
     *                  - When the append mode is set, the attached DMA channel has to have destination size <=4.
     *                    Upon the transfer completion the calculated CRC is stored at the destination address.
     *                  - When append mode is cleared, the DMA transfer occurs normally, and the CRC value is available using
     *                    the CrcResult() function.
     *                  - The CRC module should be configured before enabled.
     *                  - These settings are relevant only when the SFM is configured for the CRC type of checksum.
     *                  - The checksum register is the same for CRC or IP checksum mode. Therefore, this function changes also the seed for the IP checksum.
     *                  - The way the data is fed into the checksum calculation block and the type of the checksum performed is affected by DmaSfmConfigure().
     *
     * Example:         DmaSfmCrcConfigure(0x04c11db7, 32, 0xffffffff);
     ********************************************************************/
    extern __inline__ void __attribute__((always_inline)) DmaSfmCrcConfigure(unsigned int polynomial, int pLen, unsigned int seed)
    {
        DCRCCONCLR=_DCRCCON_PLEN_MASK;
        DCRCCONSET=(pLen-1)<<_DCRCCON_PLEN_POSITION;
        DCRCDATA=seed;
        DCRCXOR=polynomial;
    }

    #define DmaCrcConfigure DmaSfmCrcConfigure  // PIC32_3xx backward compatibility name


    /*********************************************************************
     * Function:        void DmaSfmAttachChannel(DmaChannel chn, int appendMode)
     *
     * PreCondition:    chn    - valid DMA channel
     *
     * Input:           chn         - the DMA channel to be attached to the checksum module.
     *                  appendMode  - if TRUE the data passed to the checksum generator is not transferred to destination
     *                                but it's written to the destination address when the block transfer is complete.
     *                              - if FALSE the data is transferred normally while the checksum is calculated.
     *                                The checksum will be available using the DmaSfmChecksum function.
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function attaches the SFM checksum module to a DMA channel and enables the checksum generator.
     *                  From now on, all the DMA traffic is directed to the SFM checksum generator. Once the DMA block transfer
     *                  is complete, the checksum result is available in the checksum data register.
     *                  If append mode is enabled, no data transfer takes place but the checksum result will be deposited at the DMA destination address.

     *
     * Note:            If append mode is enabled the data transfer re-ordering is disabled (illegal combination, see DmaSfmTxferReorder()).
     *
     * Example:         DmaSfmAttachChannel(DMA_CHANNEL0, TRUE);
     ********************************************************************/
    void            DmaSfmAttachChannel(DmaChannel chn, int appendMode);
    #define         CrcAttachChannel    DmaSfmAttachChannel     // PIC32_3xx backward compatibility name

    /*********************************************************************
     * Function:        unsigned int DmaSfmChecksum(void)
     *
     * PreCondition:    None
     *
     * Input:           None
     *
     * Output:          the current value of the checksum generator.
     *
     * Side Effects:    None
     *
     * Overview:        The function returns the calculated checksum value.
     *
     * Note:            - The function returns the valid checksum result. The masking out the unused MSbits in the checksum register is done by the hardware.
     *                  - The way the data is fed into the checksum calculation block and the type of the checksum performed is affected by DmaSfmConfigure().
     *
     * Example:         unsigned int myChk=DmaSfmChecksum();
     ********************************************************************/
    extern __inline__ int __attribute__((always_inline)) DmaSfmChecksum(void)
    {
        return DCRCDATA;
    }
    #define     CrcResult   DmaSfmChecksum      // PIC32_3xx backward compatibility name
    #define     DmaCrcGetValue  DmaSfmChecksum      // PIC32_3xx backward compatibility name


    /*********************************************************************
     * Function:        void DmaSfmSetSeed(unsigned int seed)
     *
     * PreCondition:    None
     *
     * Input:           seed    - the initial seed of the checksum generator
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function sets the seed of the checksum generator. This is the initial data present in the
     *                  CRC shift register or the IP checksum calculator before the actual transfer/calculation begins.
     *
     * Note:            When the SFM is configured for IP checksum mode, only the least significant 16 bits are relevant.
     *
     * Example:         DmaSfmSetSeed(0xffffffff);
     ********************************************************************/
    extern __inline__ void __attribute__((always_inline)) DmaSfmSetSeed(unsigned int seed)
    {
        DCRCDATA=seed;
    }
    #define     DmaCrcSetSeed   DmaSfmSetSeed       // PIC32_3xx backward compatibility name


/*********************  end of high level functions ****************************************/

    // low level definitions for the API functions


    typedef struct
    {
        union
        {
            struct
            {
                unsigned int chn:   3;      // last active DMA channel
                unsigned int rdOp:  1;      // last DMA operation, read if 1, write if 0
            };
            unsigned int    w;                      // word access
        }lastAccess;
        void*   lastAddress;        // most recent DMA address
    }DmaStatus;         // DMA controller status

    typedef enum
    {
        DMA_GFLG_SUSPEND =  _DMACON_SUSPEND_MASK,   // suspend DMA controller operation
        DMA_GFLG_ON =       _DMACON_ON_MASK,        // DMA module enabled/desabled
        //
        DMA_GFLG_ALL_FLAGS= DMA_GFLG_SUSPEND|DMA_GFLG_ON        // all flags
    }DmaGlblFlags;  // flags for controlling global DMA controller behavior. From processor header file.




    typedef enum
    {
        DMA_EV_ABORT_IRQ_EN =       _DCH0ECON_AIRQEN_MASK,
        DMA_EV_START_IRQ_EN =       _DCH0ECON_SIRQEN_MASK,
        // use DMA_EV_START_IRQ() and DMA_EV_ABORT_IRQ() below for selecting
        // the start and abort IRQ signals
        DMA_EV_MATCH_EN =           _DCH0ECON_PATEN_MASK,


        // compiler use only field
        _DMA_EV_MAX_MASK =     _DCH0ECON_CHAIRQ_MASK,
    }DmaEvCtrlFlags;    /*DMA channel event control fields accessible as flags also
                          part of DmaEvCtrlFlags:
                        */
    #define DMA_EV_START_IRQ(irq)   (DMA_EV_START_IRQ_EN | ((irq)<<_DCH0ECON_CHSIRQ_POSITION))  // NOTE: irq has to be a symbol from the processor header file
    #define DMA_EV_ABORT_IRQ(irq)   (DMA_EV_ABORT_IRQ_EN | ((irq)<<_DCH0ECON_CHAIRQ_POSITION))  // NOTE: irq has to be a symbol from the processor header file

    // DMA channel event control as a structure:
    #define DmaEvCtrl   __DCH0ECONbits_t




    typedef enum
    {
        DMA_CTL_AUTO_EN =       _DCH0CON_CHAEN_MASK,
        DMA_CTL_CHAIN_EN =      _DCH0CON_CHCHN_MASK,
        DMA_CTL_DET_EN =        _DCH0CON_CHAED_MASK,
        DMA_CTL_CHN_EN =        _DCH0CON_CHEN_MASK,
        DMA_CTL_CHAIN_DIR =     _DCH0CON_CHCHNS_MASK,
        // use the DMA_CTL_PRI() below for selecting the DMA
        // channel priority
    }DmaChnCtrlFlags;   // controlling the DMA channel with flags
    // also part of DmaChnCtrlFlags:
    #define DMA_CTL_PRI(pri)    ((pri)&_DCH0CON_CHPRI_MASK) // DMA Control channel priority

    // DMA channel control as a structure:
    #define DmaChnCtrl      __DCH0CONbits_t

    typedef struct
    {
        void*   vSrcAdd;        // source of the DMA transfer, virtual
        void*   vDstAdd;        // destination of the DMA transfer, virtual
        int srcSize;        // source buffer size, 1 to DmaGetMaxTxferSize() bytes. Wrapped around.
        int dstSize;        // destination buffer size, 1 to DmaGetMaxTxferSize() bytes. Wrapped around.
        int cellSize;       // no of bytes txferred per event, 1 to DmaGetMaxTxferSize().
    }DmaTxferCtrl;      // transfer setting: the transfer source, destination addresses and size, cell size


    /********************** low level DMA channel functions *******************************/



    // Global DMA controller functions

    /*********************************************************************
     * Function:        void DmaEnable(int enable)
     *
     * PreCondition:    None
     *
     * Input:           enable - boolean to enable/disable the DMA controller
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:       The function enables/disables the DMA controller.
     *
     * Note:           None.
     *
     * Example:        DmaEnable(1);
     ********************************************************************/
    extern __inline__ void __attribute__((always_inline)) DmaEnable(int enable)
    {
        if(enable)
        {
            DMACONSET=_DMACON_ON_MASK;
        }
        else
        {
            DMACONCLR=_DMACON_ON_MASK;
            while(DMACONbits.ON);       // wait to take effect
        }
    }

    /*********************************************************************
     * Function:        void DmaReset(void)
     *
     * PreCondition:    None
     *
     * Input:       None
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function resets the DMA controller.
     *
     * Note:            None.
     *
     * Example:        DmaReset();
     ********************************************************************/
    #define            DmaReset()   DmaEnable(0)


    /*********************************************************************
     * Function:        int DmaSuspend(void)
     *
     * PreCondition:    None
     *
     * Input:       None
     *
     * Output:          true if the DMA was previously suspended, false otherwise
     *
     *
     * Side Effects:    None
     *
     * Overview:        The function suspends the DMA controller.
     *
     * Note:            After the execution of this function the DMA operation is supposed to be suspended.
     *                  I.e. the function has to wait for the suspension to take place!
     *
     * Example:         int susp=DmaSuspend();
     ********************************************************************/
        extern __inline__ int __attribute__((always_inline)) DmaSuspend(void)
    {
        int suspSt;
        if(!(suspSt=DMACONbits.SUSPEND))
        {
            DMACONSET=_DMACON_SUSPEND_MASK;     // suspend
            while((DMACONbits.DMABUSY));    // wait to be actually suspended
        }
        return suspSt;
    }



    /*********************************************************************
     * Function:        void DmaResume(int susp)
     *
     * PreCondition:    None
     *
     * Input:       the desired DMA suspended state.
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function restores the DMA controller activity to the old suspended mode.
     *
     * Note:            None.
     *
     * Example:         int isSusp=DmaSuspend(); {....}; DmaResume(isSusp);
     ********************************************************************/
        extern __inline__ void __attribute__((always_inline)) DmaResume(int susp)
    {
        if(susp)
        {
            DmaSuspend();
        }
        else
        {
            DMACONCLR=_DMACON_SUSPEND_MASK;     // resume DMA activity
        }
    }

    /*********************************************************************
     * Function:        void DmaGetStatus(DmaStatus* pStat)
     *
     * PreCondition:    pStat   - valid pointer
     *
     * Input:           pStat   - pointer to a DmaStatus structure to store the current DMA controller
     *                          status, carrying the following info:
     *                              - chn:  the last active DMA channel
     *                              - rdOp: the last DMA operation, read/write
     *                              - lastAddress: the most recent DMA address
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function updates the info for the current DMA controller status.
     *                  It updates the last DMA: operation, channel used and address.
     *
     * Note:            None.
     *
     * Example:         DmaStatus stat; DmaGetStatus(&stat);
     ********************************************************************/
     void           DmaGetStatus(DmaStatus* pStat);

    /*********************************************************************
     * Function:        void DmaSetGlobalFlags(DmaGlblFlags gFlags)
     *
     * PreCondition:    None
     *
     * Input:           gFlags - flags to be set, having the following fields:
     *          - DMA_GFLG_SUSPEND: DMA controller operation suspend
     *          - DMA_GFLG_ON: DMA controller enabled/desabled
     *          - DMA_GFLG_ALL_FLAGS: all flags
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function affects the global behavior of the DMA controller.
     *                  It sets the specified flags. Any flag that is set in the gFlags will be
     *                  enabled, the other flags won't be touched.
     *
     * Note:            None.
     *
     * Example:         DmaSetGlobalFlags(DMA_GFLG_ON);
     ********************************************************************/
        extern __inline__ void __attribute__((always_inline)) DmaSetGlobalFlags(DmaGlblFlags gFlags)
    {
        DMACONSET=gFlags;
    }

    /*********************************************************************
     * Function:        void DmaClrGlobalFlags(DmaGlblFlags gFlags)
     *
     * PreCondition:    None
     *
     * Input:           gFlags - flags to be cleared, having the following fields:
     *                               - DMA_GFLG_SUSPEND: DMA controller operation suspend
     *                               - DMA_GFLG_ON: DMA controller enabled/desabled
     *                               - DMA_GFLG_ALL_FLAGS: all flags
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function affects the global behavior of the DMA controller.
     *                  It clears the specified flags. Any flag that is set in the gFlags will be
     *                  cleared, the other flags won't be touched.
     *
     * Note:            None.
     *
     * Example:         DmaClrGlobalFlags(DMA_GFLG_SUSPEND);
     ********************************************************************/
        extern __inline__ void __attribute__((always_inline)) DmaClrGlobalFlags(DmaGlblFlags gFlags)
    {
        DMACONCLR=gFlags;
    }


    /*********************************************************************
     * Function:        void DmaWriteGlobalFlags(DmaGlblFlags gFlags)
     *
     * PreCondition:    None
     *
     * Input:           gFlags - flags to be set, having the following fields:
     *                                 - DMA_GFLG_SUSPEND: DMA controller operation suspend
     *                                 - DMA_GFLG_ON: DMA controller enabled/desabled
     *                                 - DMA_GFLG_ALL_FLAGS: all flags
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function affects the global behavior of the DMA controller.
     *                  It forces the flags to have the specified gFlags value.
     *
     * Note:            None.
     *
     * Example:         DmaWriteGlobalFlags(DMA_GFLG_ALL_FLAGS);
     ********************************************************************/
        extern __inline__ void __attribute__((always_inline)) DmaWriteGlobalFlags(DmaGlblFlags gFlags)
    {
        DMACON=gFlags;
    }

    /*********************************************************************
     * Function:        DmaGlblFlags DmaGetGlobalFlags(void)
     *
     * PreCondition:    None
     *
     * Input:           None
     *
     * Output:          The current DMA controller flags settings.
     *                              - DMA_GFLG_SUSPEND: DMA controller operation suspend
     *                              - DMA_GFLG_ON: DMA controller enabled/desabled
     *
     * Side Effects:    None
     *
     * Overview:        The function returns the global flags of the DMA controller.
     *
     * Note:            None.
     *
     * Example:         DmaGlblFlags dmaFlags=DmaGetGlobalFlags();
     ********************************************************************/
        extern __inline__ DmaGlblFlags __attribute__((always_inline)) DmaGetGlobalFlags(void)
    {
        return (DmaGlblFlags)DMACON;
    }


    /*********************************************************************
     * Function:        int DmaGetMaxTxferSize(void)
     *
     * PreCondition:    None
     *
     * Input:           None
     *
     * Output:          The maximum transfer capacity for a DMA channel, in bytes.
     *
     * Side Effects:    None
     *
     * Overview:        The function returns the maximum number of bytes that can be transferred by a DMA channel.
     *
     * Note:            Revision dependant.
     *
     * Example:         int dmaMaxSz=DmaGetMaxTxferSize();
     ********************************************************************/
    extern __inline__ int __attribute__((always_inline)) DmaGetMaxTxferSize(void)
    {
        return 65536;
    }

    // Direct Channel control functions

    typedef enum
    {
        DMA_CONFIG_DEFAULT = 0,                             // DMA default operation
        DMA_CONFIG_AUTO = _DCH0CON_CHAEN_MASK,              // DMA channel is auto enabled
        DMA_CONFIG_CHAIN_LOW  = (_DCH0CON_CHCHN_MASK|_DCH0CON_CHCHNS_MASK), // DMA channel is chained to lower channel
        DMA_CONFIG_CHAIN_HI  = (_DCH0CON_CHCHN_MASK),       // DMA channel is chained to higher channel
        DMA_CONFIG_DET_EN = _DCH0CON_CHAED_MASK,            // events detection enabled while channel off
        DMA_CONFIG_ENABLE = _DCH0CON_CHEN_MASK,             // DMA channel is enabled after open
        DMA_CONFIG_MATCH    = 0x80000000,                   // DMA channel stops on match
    }DmaConfigFlags;    // flags for the channel configuration



    /*********************************************************************
     * Function:        void DmaChnConfigure(DmaChannel chn, DmaChannelPri chPri, DmaConfigFlags cFlags)
     *
     * PreCondition:    chPri  - valid channel priority, 0-3
     *
     * Input:           chn    - channel to be configured in the DMA controller
     *                  chPri  - the priority given to the channel, 0-3
     *                  cFlags - orred flags specifying the configuration:
     *                           DMA_CONFIG_DEFAULT: DMA default operation mode
     *                           DMA_CONFIG_AUTO:   DMA channel is auto enabled
     *                           DMA_CONFIG_CHAIN_LOW: DMA channel is chained to lower channel
     *                           DMA_CONFIG_CHAIN_HI: DMA channel is chained to higher channel
     *                           DMA_CONFIG_DET_EN: events detection enabled while channel off
     *                           DMA_CONFIG_ENABLE: DMA channel is enabled when opened
     *                           DMA_CONFIG_MATCH:  DMA channel stops on match
     *
     *
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function configures the selected DMA channel using the supplied user flags and priority.
     *
     * Note:            - The channel is NOT turned off. It should be turned off before calling this function.
     *                  The channel is just configured.
     *                  - After calling this function, the channel should be enabled using DmaChnEnable(chn) call
     *                  if DMA_CONFIG_ENABLE flag was not specified.
     *                  - The function does not touch the interrupt flags, interrupt enables, etc.
     *                  The interrupt flags should have been previously cleared and interrupts disabled before calling this function.
     *                  - The start and abort Irqs, the channel event enable flags are not touched/cleared by this function.
     *                  User has to call event channel functions to clear/enable the event flags if needed.
     *
     * Example:         DmaChnDisable(DMA_CHANNEL2); DmaChnConfigure(DMA_CHANNEL2, DMA_CHN_PRI2, DMA_CONFIG_AUTO|DMA_CONFIG_MATCH|DMA_CONFIG_ENABLE);
     ********************************************************************/
    void            DmaChnConfigure(DmaChannel chn, DmaChannelPri chPri, DmaConfigFlags cFlags);


    /*********************************************************************
     * Function:        int DmaChnGetSrcPnt(DmaChannel chn)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *
     * Output:          Current channel source pointer.
     *
     * Side Effects:    None
     *
     * Overview:        The function retrieves the current source pointer for the selected DMA channel.
     *                  It is the current offset, 0 to DmaGetMaxTxferSize()-1, in the source transfer buffer.
     *
     * Note:            None
     *
     * Example:         int srcPnt=DmaChnGetSrcPnt(DMA_CHANNEL3);
     ********************************************************************/
     int            DmaChnGetSrcPnt(DmaChannel chn);

    /*********************************************************************
     * Function:        int DmaChnGetDstPnt(DmaChannel chn)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *
     * Output:          Current channel destination pointer.
     *
     * Side Effects:    None
     *
     * Overview:        The function retrieves the current destination pointer for the selected DMA channel.
     *                  It is the current offset, 0 to DmaGetMaxTxferSize()-1, in the destination transfer buffer.
     *
     * Note:            None
     *
     * Example:         int dstPnt=DmaChnGetDstPnt(DMA_CHANNEL3);
     ********************************************************************/
     int            DmaChnGetDstPnt(DmaChannel chn);

    /*********************************************************************
     * Function:        int DmaChnGetCellPnt(DmaChannel chn)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *
     * Output:          Current channel transfer pointer.
     *
     * Side Effects:    None
     *
     * Overview:        The function retrieves the current transfer progress pointer for the selected DMA channel.
     *                  It ranges 0 to DmaGetMaxTxferSize()-1.
     *
     * Note:            None
     *
     * Example:         int cellPnt=DmaChnGetCellPnt(DMA_CHANNEL3);
     ********************************************************************/
     int            DmaChnGetCellPnt(DmaChannel chn);



    /*********************************************************************
     * Function:        void DmaChnSetEventControlFlags(DmaChannel chn, DmaEvCtrlFlags dmaEvCtrl)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn         - DMA channel number
     *                  dmaEvCtrl   -   either a DmaEvCtrl structure field, carrying the following info:
     *                                      - AIRQEN: enable/disable the abort IRQ action
     *                                      - SIRQEN: enable/disable the start IRQ action
     *                                      - PATEN: enable/disable the pattern match and abort
     *                                  or any of the DmaEvCtrlFlags:
     *                                      DMA_EV_ABORT_IRQ_EN|DMA_EV_START_IRQ_EN|DMA_EV_MATCH_EN
     *
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function sets the events that start and abort the transfer
     *                  for the selected DMA channel.
     *                  Multiple flags can be orr-ed together. Any flag that is set in the eFlags will be
     *                  enabled for the selected channel, the other channel event flags won't be touched.
     *
     * Note:            None.
     *
     * Example:         either:
     *                      DmaChnSetEventControlFlags(DMA_CHANNEL3, DMA_EV_MATCH_EN|DMA_EV_START_IRQ_EN;
     *                  or:
     *                      DmaEvCtrl evCtrl; evCtrl.w=0; evCtrl.PATEN=1; evCtrl.SIRQEN=1;
     *                      DmaChnSetEventControlFlags(DMA_CHANNEL3, evCtrl.w);
     *
     ********************************************************************/
     void           DmaChnSetEventControlFlags(DmaChannel chn, DmaEvCtrlFlags dmaEvCtrl);


    /*********************************************************************
     * Function:        void DmaChnClrEventControlFlags(DmaChannel chn, DmaEvCtrlFlags dmaEvCtrl)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn         - DMA channel number
     *                  dmaEvCtrl   -   either a DmaEvCtrl structure field, carrying the following info:
     *                                      - AIRQEN: enable/disable the abort IRQ action
     *                                      - SIRQEN: enable/disable the start IRQ action
     *                                      - PATEN: enable/disable the pattern match and abort
     *                                  or any of the DmaEvCtrlFlags:
     *                                      DMA_EV_ABORT_IRQ_EN|DMA_EV_START_IRQ_EN|DMA_EV_MATCH_EN
     *
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function clears the events that start and abort the transfer
     *                  for the selected DMA channel.
     *                  Multiple flags can be orr-ed together. Any flag that is set in the eFlags will be
     *                  disabled for the selected channel, the other channel event flags won't be touched.
     *
     * Note:            None.
     *
     * Example:         either:
     *                      DmaChnClrEventControlFlags(DMA_CHANNEL3, DMA_EV_MATCH_EN|DMA_EV_START_IRQ_EN);
     *                  or:
     *                      DmaEvCtrl evCtrl; evCtrl.w=0; evCtrl.PATEN=1; evCtrl.AIRQEN=1;
     *                      DmaChnClrEventControlFlags(DMA_CHANNEL3, evCtrl.w);
     *
     ********************************************************************/
     void           DmaChnClrEventControlFlags(DmaChannel chn, DmaEvCtrlFlags dmaEvCtrl);



    /*********************************************************************
     * Function:        void DmaChnWriteEventControlFlags(DmaChannel chn, DmaEvCtrlFlags dmaEvCtrl)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn         - DMA channel number
     *                  dmaEvCtrl   -   either a DmaEvCtrl structure field, carrying the following info:
     *                                      - AIRQEN: enable/disable the abort IRQ action
     *                                      - SIRQEN: enable/disable the start IRQ action
     *                                      - PATEN: enable/disable the pattern match and abort
     *                                      - CHSIRQ: IRQ number to start the DMA channel transfer
     *                                      - CHAIRQ: IRQ number to abort the DMA channel transfer
     *                                  or any of the DmaEvCtrlFlags:
     *                                      DMA_EV_ABORT_IRQ_EN|DMA_EV_START_IRQ_EN|DMA_EV_MATCH_EN|DMA_EV_START_IRQ(irq)|DMA_EV_ABORT_IRQ(irq)
     *
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function writes the events that start and abort the transfer
     *                  for the selected DMA channel.
     *
     * Note:            None.
     *
     * Example:         either:
     *                      DmaChnWriteEventControlFlags(DMA_CHANNEL3, DMA_EV_MATCH_EN|DMA_EV_START_IRQ(_UART2_RX_IRQ));
     *                  or:
     *                      DmaEvCtrl evCtrl; evCtrl.w=0; evCtrl.AIRQEN=1; evCtrl.PATEN=1; evCtrl.CHSIRQ=_UART2_RX_IRQ;
     *                      DmaChnWriteEventControlFlags(DMA_CHANNEL3, evCtrl.w);
     *
     ********************************************************************/
     void           DmaChnWriteEventControlFlags(DmaChannel chn, DmaEvCtrlFlags dmaEvCtrl);



    /*********************************************************************
     * Function:        void DmaChnSetEventControl(DmaChannel chn, DmaEvCtrlFlags dmaEvCtrl)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn         - DMA channel number
     *                  dmaEvCtrl   -   either a DmaEvCtrl structure field, carrying the following info:
     *                                      - AIRQEN: enable/disable the abort IRQ action
     *                                      - SIRQEN: enable/disable the start IRQ action
     *                                      - PATEN: enable/disable the pattern match and abort
     *                                      - CHSIRQ: IRQ number to start the DMA channel transfer
     *                                      - CHAIRQ: IRQ number to abort the DMA channel transfer
     *                                  or any of the DmaEvCtrlFlags:
     *                                      DMA_EV_ABORT_IRQ_EN|DMA_EV_START_IRQ_EN|DMA_EV_MATCH_EN|DMA_EV_START_IRQ(irq)|DMA_EV_ABORT_IRQ(irq)
     *
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function sets the events that start and abort the transfer
     *                  for the selected DMA channel.
     *                  Multiple flags can be orr-ed together. Any flag that is set in the eFlags will be
     *                  enabled for the selected channel, the other channel event flags won't be touched.
     *
     * Note:           A shorter name for DmaChnWriteEventControlFlags();
     *
     * Example:         either:
     *                      DmaChnSetEventControl(DMA_CHANNEL3, DMA_EV_MATCH_EN|DMA_EV_START_IRQ(_UART2_RX_IRQ));
     *                  or:
     *                      DmaEvCtrl evCtrl; evCtrl.w=0; evCtrl.AIRQEN=1; evCtrl.PATEN=1; evCtrl.CHSIRQ=_UART2_RX_IRQ;
     *                      DmaChnSetEventControl(DMA_CHANNEL3, evCtrl.w);
     *
     ********************************************************************/
    #define         DmaChnSetEventControl(chn, dmaEvCtrl)   DmaChnWriteEventControlFlags(chn, dmaEvCtrl)


    /*********************************************************************
     * Function:        DmaEvCtrlFlags DmaChnGetEventControl(DmaChannel chn)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *
     * Output:          -   either a DmaEvCtrl structure field, carrying the following info:
     *                          - AIRQEN: enable/disable the abort IRQ action
     *                          - SIRQEN: enable/disable the start IRQ action
     *                          - PATEN: enable/disable the pattern match and abort
     *                          - CHSIRQ: IRQ number to start the DMA channel transfer
     *                          - CHAIRQ: IRQ number to abort the DMA channel transfer
     *                      or any of the DmaEvCtrlFlags:
     *                          DMA_EV_ABORT_IRQ_EN|DMA_EV_START_IRQ_EN|DMA_EV_MATCH_EN|DMA_EV_START_IRQ(irq)|DMA_EV_ABORT_IRQ(irq)
     *
     *
     * Side Effects:    None
     *
     * Overview:        The function retrieves the events that start and abort the transfer
     *                  for the selected DMA channel.
     *
     * Note:            None.
     *
     * Example:         either:
     *                      DmaEvCtrlFlags evCtrlW=DmaChnGetEventControl(DMA_CHANNEL3); if(evCtrlW&DMA_EV_MATCH_EN) {...}
     *                  or:
     *                      DmaEvCtrl evCtrl; evCtrl.w=DmaChnGetEventControl(DMA_CHANNEL3); if(evCtrl.PATEN){...}
     *
     ********************************************************************/
     DmaEvCtrlFlags DmaChnGetEventControl(DmaChannel chn);


    /*********************************************************************
     * Function:        void DmaChnSetControlFlags(DmaChannel chn, DmaChnCtrlFlags dmaChnCtrl)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn         - DMA channel number
     *                  dmaChnCtrl  -   either a DmaChnCtrl structure field, carrying the following info:
     *                                      - autoEn: enable/disable the automatic mode
     *                                      - chainEn: enable/disable channel chaining
     *                                      - detectEn: enable/disable events detection when channel disabled
     *                                      - chEn: enable/disable channel functionality
     *                                      - chainDir: chain direction: chain to lower(1)/higher(0),pri channel
     *                                  or any of the DmaChnCtrlFlags flags:
     *                                      DMA_CTL_AUTO_EN|DMA_CTL_CHAIN_EN|DMA_CTL_DET_EN|DMA_CTL_CHN_EN|DMA_CTL_CHAIN_DIR
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function sets the selected DMA channel control flags:
     *                  the chaining or auto mode, and events detection.
     *                  Multiple flags can be orr-ed together. Any flag that is set in the dmaChnCtrl will be
     *                  set for the selected channel, the other channel control flags won't be touched.
     *
     * Note:            None.
     *
     * Example:         either:
     *                      DmaChnSetControlFlags(DMA_CHANNEL3, DMA_CTL_AUTO_EN|DMA_CTL_CHAIN_EN);
     *                  or:
     *                      DmaChnCtrl chCtrl; chCtrl.w=0; chCtrl.autoEn=1; chCtrl.chainEn=1;
     *                      DmaChnSetControlFlags(DMA_CHANNEL3, chCtrl.w);
     *
     ********************************************************************/
     void           DmaChnSetControlFlags(DmaChannel chn, DmaChnCtrlFlags dmaChnCtrl);

    /*********************************************************************
     * Function:        void DmaChnClrControlFlags(DmaChannel chn, DmaChnCtrlFlags dmaChnCtrl)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn         - DMA channel number
     *                  dmaChnCtrl  -   either a DmaChnCtrl structure field, carrying the following info:
     *                                      - autoEn: enable/disable the automatic mode
     *                                      - chainEn: enable/disable channel chaining
     *                                      - detectEn: enable/disable events detection when channel disabled
     *                                      - chEn: enable/disable channel functionality
     *                                      - chainDir: chain direction: chain to lower(1)/higher(0),pri channel
     *                                  or any of the DmaChnCtrlFlags flags:
     *                                      DMA_CTL_AUTO_EN|DMA_CTL_CHAIN_EN|DMA_CTL_DET_EN|DMA_CTL_CHN_EN|DMA_CTL_CHAIN_DIR
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function clears the selected DMA channel control flags:
     *                  the chaining or auto mode and events detection.
     *                  Multiple flags can be orr-ed together. Any flag that is set in the dmaChnCtrl will be
     *                  cleared for the selected channel, the other channel control flags won't be touched.
     *
     * Note:            None.
     *
     * Example:         either:
     *                      DmaChnClrControlFlags(DMA_CHANNEL3, DMA_CTL_AUTO_EN|DMA_CTL_CHAIN_EN);
     *                  or:
     *                      DmaChnCtrl chCtrl; chCtrl.w=0; chCtrl.autoEn=1; chCtrl.chainEn=1;
     *                      DmaChnClrControlFlags(DMA_CHANNEL3, chCtrl.w);
     *
     ********************************************************************/
     void           DmaChnClrControlFlags(DmaChannel chn, DmaChnCtrlFlags dmaChnCtrl);

    /*********************************************************************
     * Function:        void DmaChnWriteControlFlags(DmaChannel chn, DmaChnCtrlFlags dmaChnCtrl)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn         - DMA channel number
     *                  dmaChnCtrl  -   either a DmaChnCtrl structure field, carrying the following info:
     *                                      - chPri: channel priority 0-3
     *                                      - autoEn: enable/disable the automatic mode
     *                                      - chainEn: enable/disable channel chaining
     *                                      - detectEn: enable/disable events detection when channel disabled
     *                                      - chEn: enable/disable channel functionality
     *                                      - chainDir: chain direction: chain to lower(1)/higher(0),pri channel
     *                                  or any of the DmaChnCtrlFlags flags:
     *                                      DMA_CTL_PRI(pri)|DMA_CTL_AUTO_EN|DMA_CTL_CHAIN_EN|DMA_CTL_DET_EN|DMA_CTL_CHN_EN|DMA_CTL_CHAIN_DIR
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function enables/disables the selected DMA channel and also sets
     *                  the channel priority, chaining mode or auto and events detection.
     *
     * Note:            None.
     *
     * Example:         either:
     *                      DmaChnWriteControlFlags(DMA_CHANNEL3, DMA_CTL_PRI(DMA_CHN_PRI2)|DMA_CTL_AUTO_EN|DMA_CTL_CHAIN_EN);
     *                  or:
     *                      DmaChnCtrl chCtrl; chCtrl.w=0; chCtrl.chPri=DMA_CHN_PRI2; chCtrl.autoEn=1; chCtrl.chainEn=1;
     *                      DmaChnWriteControlFlags(DMA_CHANNEL3, chCtrl.w);
     *
     ********************************************************************/
     void           DmaChnWriteControlFlags(DmaChannel chn, DmaChnCtrlFlags dmaChnCtrl);

    /*********************************************************************
     * Function:        void DmaChnSetControl(DmaChannel chn, DmaChnCtrlFlags dmaChnCtrl)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:       chn     - DMA channel number
     *                  dmaChnCtrl  -   either a DmaChnCtrl structure field, carrying the following info:
     *                      - chPri: channel priority 0-3
     *                      - autoEn: enable/disable the automatic mode
     *                      - chainEn: enable/disable channel chaining
     *                      - detectEn: enable/disable events detection when channel disabled
     *                      - chEn: enable/disable channel functionality
     *                      - chainDir: chain direction: chain to lower(1)/higher(0),pri channel
     *                  or any of the DmaChnCtrlFlags flags:
     *                      DMA_CTL_PRI(pri)|DMA_CTL_AUTO_EN|DMA_CTL_CHAIN_EN|DMA_CTL_DET_EN|DMA_CTL_CHN_EN|DMA_CTL_CHAIN_DIR
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function enables/disables the selected DMA channel and also sets
     *                  the channel priority, chaining mode or auto and events detection.
     *
     * Note:            Another name ( backward compatible) for DmaChnWriteControlFlags().
     *
     * Example:         either:
     *                      DmaChnSetControl(DMA_CHANNEL3, DMA_CTL_PRI(DMA_CHN_PRI2)|DMA_CTL_AUTO_EN|DMA_CTL_CHAIN_EN);
     *                  or:
     *                      DmaChnCtrl chCtrl; chCtrl.w=0; chCtrl.chPri=DMA_CHN_PRI2; chCtrl.autoEn=1; chCtrl.chainEn=1;
     *          DmaChnSetControl(DMA_CHANNEL3, chCtrl.w);
     *
     ********************************************************************/
    #define     DmaChnSetControl(chn, dmaChnCtrl)   DmaChnWriteControlFlags(chn, dmaChnCtrl)

    /*********************************************************************
     * Function:        DmaChnCtrlFlags DmaChnGetControlFlags(DmaChannel chn)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn         - DMA channel number
     *
     * Output:          - either a DmaChnCtrl structure field, carrying the following info:
     *                          - chPri: channel priority 0-3
     *                          - autoEn: enable/disable the automatic mode
     *                          - chainEn: enable/disable channel chaining
     *                          - detectEn: enable/disable events detection when channel disabled
     *                          - chEn: enable/disable channel functionality
     *                          - chainDir: chain direction: chain to lower(1)/higher(0),pri channel
     *                      or any of the DmaChnCtrlFlags flags:
     *                          DMA_CTL_PRI(pri)|DMA_CTL_AUTO_EN|DMA_CTL_CHAIN_EN|DMA_CTL_DET_EN|DMA_CTL_CHN_EN|DMA_CTL_CHAIN_DIR
     *
     * Side Effects:    None
     *
     * Overview:        The function retrieves the current control settings for the selected DMA channel,
     *                  including the channel enable/disable status, the channel priority,
     *                  chaining mode, auto mode and events detection.
     *
     * Note:            None.
     *
     * Example:         either:
     *                      DmaChnCtrlFlags ctrl=DmaChnGetControlFlags(DMA_CHANNEL3); if(ctrl&DMA_CTL_AUTO_EN) {...}
     *                  or:
     *                      DmaChnCtrl chnCtrl; chnCtrl.w=DmaChnGetControlFlags(DMA_CHANNEL3); if(chnCtrl.autoEn) {...}
     *
     ********************************************************************/
     DmaChnCtrlFlags    DmaChnGetControlFlags(DmaChannel chn);


    /*********************************************************************
     * Function:        int DmaChnGetEvDetect(DmaChannel chn)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *
     * Output:          TRUE if an DMA event was detected, FALSE otherwise.
     *
     * Side Effects:    None
     *
     * Overview:        The function returns the current event detection for the selected DMA channel.
     *
     * Note:            None.
     *
     * Example:         int evDetect=DmaChnGetEvDetect(DMA_CHANNEL3);
     *
     ********************************************************************/
     int            DmaChnGetEvDetect(DmaChannel chn);

    /*********************************************************************
     * Function:        void DmaChnGetTxfer(DmaChannel chn, DmaTxferCtrl* pTxCtrl, int mapToK0)
     *
     * PreCondition:    chn     - valid DMA channel
     *                  pTxCtrl - valid pointer
     *
     * Input:           chn         - DMA channel number
     *                  pTxCtrl     - pointer to a DmaTxferCtrl that will carry the following info:
     *                              - vSrcAdd: source of the DMA transfer
     *                              - vDstAdd: destination of the DMA transfer
     *                              - srcSize: source buffer size, 1 to DmaGetMaxTxferSize() bytes, wrapped arround
     *                              - dstSize: destination buffer size, 1 to DmaGetMaxTxferSize() bytes, wrapped around
     *                              - cellSize: cell transfer size, 1 to DmaGetMaxTxferSize() bytes.
     *                  mapToK0     - if TRUE, a Kernel address is mapped to KSeg0, else KSeg1.
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function retrieves the transfer characteristics for a DMA channel transfer:
     *                  the source and the destination addresses.
     *                  It also retrieves the source and destination lengths
     *                  and the number of bytes transferred per event.
     *
     * Note:            None
     *
     * Example:         DmaTxferCtrl txCtl; DmaChnGetTxfer(DMA_CHANNEL3, &txCtl, FALSE);
     ********************************************************************/
     void           DmaChnGetTxfer(DmaChannel chn, DmaTxferCtrl* pTxCtrl, int mapToK0);

    // Low level checksum functions

    /*********************************************************************
     * Function:        void DmaSfmEnable(int enable)
     *
     * PreCondition:    None
     *
     * Input:           enable _ boolean to enable/disable the SFM functionality
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function enables/diables the checksum module functionality.
     *                  When enabled the attached DMA channel transfers are routed to the SFM module.
     *
     * Note:            The SFM module should be properly configured before enabled.
     *
     * Example:         DmaSfmEnable(1);
     ********************************************************************/
    extern __inline__ void __attribute__((always_inline)) DmaSfmEnable(int enable)
    {
        if(enable)
        {
            DCRCCONSET=_DCRCCON_CRCEN_MASK;
        }
        else
        {
            DCRCCONCLR=_DCRCCON_CRCEN_MASK;
        }
    }
    #define DmaCrcEnable    DmaSfmEnable        // PIC32_3xx backward compatibility


    /*********************************************************************
     * Function:        int DmaSfmGetEnable(void)
     *
     * PreCondition:    None
     *
     * Input:           None
     *
     * Output:          TRUE, if the SFM module is enabled
     *          FALSE otherwise
     *
     * Side Effects:    None
     *
     * Overview:        The function returns the SFM module enabling status.
     *
     * Note:            None
     *
     * Example:     int isSfmEnabled=DmaSfmGetEnable();
     ********************************************************************/
    extern __inline__ int __attribute__((always_inline)) DmaSfmGetEnable(void)
    {
        return DCRCCONbits.CRCEN!=0;
    }
    #define     DmaCrcGetEnable     DmaSfmGetEnable     // PIC32_3xx backward compatibility


    /*********************************************************************
     * Function:        void DmaSfmAppendEnable(int enable)
     *
     * PreCondition:    None
     *
     * Input:           enable _ boolean to enable/disable the SFM append mode
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function enables the SFM append mode. In this mode, the attached DMA channel reads
     *                  the source data but does not write it to the destination address. The data it's just passed
     *                  to the checksum generator for CRC/IP checksum calculation.
     *                  When the block transfer is completed, the checksum result is written to the
     *                  DMA channel destination address.
     *
     * Note:            The SFM module should be properly configured before enabled.
     *
     * Example:         DmaSfmAppendModeEnable(TRUE);
     ********************************************************************/
    extern __inline__ void __attribute__((always_inline)) DmaSfmAppendEnable(int enable)
    {
        if(enable)
        {
            DCRCCONSET=_DCRCCON_CRCAPP_MASK;
        }
        else
        {
            DCRCCONCLR=_DCRCCON_CRCAPP_MASK;
        }
    }
    #define     DmaCrcAppendModeEnable  DmaSfmAppendEnable  // PIC32_3xx backward compatibility


    /*********************************************************************
     * Function:        int DmaSfmGetAppendMode(void)
     *
     * PreCondition:    None
     *
     * Input:           None
     *
     * Output:          TRUE, if the SFM append mode is enabled
     *                  FALSE otherwise
     *
     * Side Effects:    None
     *
     * Overview:        The function returns the SFM module enabling status.
     *
     * Note:            None
     *
     * Example:         int isAppendEnabled=DmaSfmGetAppendMode();
     ********************************************************************/
    extern __inline__ int __attribute__((always_inline)) DmaSfmGetAppendMode(void)
    {
        return DCRCCONbits.CRCAPP!=0;
    }
    #define DmaCrcGetAppendMode DmaSfmGetAppendMode     // PIC32_3xx backward compatibility


    /*********************************************************************
     * Function:        void DmaSfmSetAttach(DmaChannel chn)
     *
     * PreCondition:    chn     - valid DMA channel
     *
     * Input:           chn - the DMA channel to be attached to the SFM module (the DMA channel transfers will be routed to the SFM module)
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function directly attaches a DMA channel to the SFM module.
     *
     * Note:            None
     *
     * Example:         DmaSfmSetAttach(DMA_CHANNEL3);
     ********************************************************************/
    extern __inline__ void __attribute__((always_inline)) DmaSfmSetAttach(DmaChannel chn)
    {
        DCRCCONCLR=_DCRCCON_CRCCH_MASK;
        DCRCCONSET=chn;
    }
    #define     DmaCrcSetAttach     DmaSfmSetAttach     // PIC32_3xx backward compatibility


    /*********************************************************************
     * Function:        DmaChannel DmaSfmGetAttach(void)
     *
     * PreCondition:    None
     *
     * Input:           None
     *
     * Output:          the DMA channel that is currently attached to the CRC module
     *
     * Side Effects:    None
     *
     * Overview:        The function returns the DMA channel number that is currently attached to the SFM module.
     *
     * Note:            None
     *
     * Example:         DmaChannel chn=DmaSfmGetAttach();
     ********************************************************************/
    extern __inline__ DmaChannel __attribute__((always_inline)) DmaSfmGetAttach(void)
    {
        return (DmaChannel)DCRCCONbits.CRCCH;
    }
    #define     DmaCrcGetAttach     DmaSfmGetAttach     // PIC32_3xx backward compatibility

    /*********************************************************************
     * Function:        void DmaCrcSetPLen(int pLen)
     *
     * PreCondition:    pLen - valid polynomial length within 1-32
     *
     * Input:           pLen    - the length of the CRC generator polynomial
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The length of the CRC generator polynomial is set as being pLen;
     *
     * Note:            None
     *
     * Example:         DmaCrcSetPLen(32);
     ********************************************************************/
    extern __inline__ void __attribute__((always_inline)) DmaCrcSetPLen(int pLen)
    {
        DCRCCONCLR=_DCRCCON_PLEN_MASK;
        DCRCCONSET=(pLen)-1;
    }

    /*********************************************************************
     * Function:        int DmaCrcGetPLen(void)
     *
     * PreCondition:    None
     *
     * Input:           None
     *
     * Output:          the length of the CRC generator polynomial
     *
     * Side Effects:    None
     *
     * Overview:        The function returns the current length of the CRC generator polynomial.
     *                  It's always a number between 1 and 32.
     *
     * Note:            None
     *
     * Example:         int polyLen=DmaCrcGetPLen();
     ********************************************************************/
    extern __inline__ int __attribute__((always_inline)) DmaCrcGetPLen(void)
    {
        return  DCRCCONbits.PLEN+1;
    }

    /*********************************************************************
     * Function:        void DmaCrcSetShiftFeedback(unsigned int feedback)
     *
     * PreCondition:    None
     *
     * Input:           feedback - the layout of the CRC generator
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function sets the layout of the shift stages that take place in the CRC generation.
     *                  Setting a bit to 1 enables the XOR input from the MSb (pLen bit) to the selected stage in the shift register.
     *                  If bit is cleared, the selected shift stage gets data directly from the previous stage in the shift register.
     *
     * Note:            Bit 0 of the generator polynomial is always XOR'ed.
     *
     * Example:         DmaCrcSetShiftFeedback(0x04c11db7);
     ********************************************************************/
    extern __inline__ void __attribute__((always_inline)) DmaCrcSetShiftFeedback(unsigned int feedback)
    {
        DCRCXOR=feedback;
    }


    /*********************************************************************
     * Function:        unsigned int DmaCrcGetShiftFeedback(void)
     *
     * PreCondition:    None
     *
     * Input:           None
     *
     * Output:          the current layout of the CRC generator
     *
     * Side Effects:    None
     *
     * Overview:        The function returns the layout of the shift stages that take place in the CRC generation.
     *                  A bit set to 1 enables the XOR input from the MSb (pLen bit) to the selected stage in the shift register.
     *                  If a bit is cleared, the selected shift stage gets data directly from the previous stage in the shift register.
     *
     * Note:            Bit 0 of the generator polynomial is always XOR'ed.
     *
     * Example:         int feedback=DmaCrcGetShiftFeedback();
     ********************************************************************/
    extern __inline__ unsigned int __attribute__((always_inline)) DmaCrcGetShiftFeedback(void)
    {
        return DCRCXOR;
    }



    // Channel test/debug and special functions

    /*********************************************************************
     * Function:        void DmaChnSetEvFlags(DmaChannel chn, DmaEvFlags eFlags)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *                  eFlags  - event flags with the following significance:
     *                              - DMA_EV_ERR: address error event
     *                              - DMA_EV_ABORT: transfer abort event
     *                              - DMA_EV_CELL_DONE: cell transfer complete event
     *                              - DMA_EV_BLOCK_DONE: block transfer complete event
     *                              - DMA_EV_DST_HALF: destination half event
     *                              - DMA_EV_DST_FULL: destination full event
     *                              - DMA_EV_SRC_HALF: source half event
     *                              - DMA_EV_SRC_FULL: source full event
     *                              - DMA_EV_ALL_EVNTS: all of the above flags
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function sets the event flags for the selected DMA channel.
     *                  Multiple flags can be orr-ed together. Any flag that is set in the eFlags will be
     *                  set for the selected channel, the other channel event flags won't be touched.
     *
     * Note:            This is intended as a channel test function.
     *
     * Example:         DmaChnSetEvFlags(DMA_CHANNEL0, DMA_EV_ERR|DMA_EV_ABORT|DMA_EV_BLOCK_DONE|DMA_EV_SRC_FULL);
     ********************************************************************/
     void           DmaChnSetEvFlags(DmaChannel chn, DmaEvFlags eFlags);

    /*********************************************************************
     * Function:        void DmaChnWriteEvFlags(DmaChannel chn, DmaEvFlags eFlags)
     *
     * PreCondition:    chn - valid DMA channel
     *
     * Input:           chn     - DMA channel number
     *                  eFlags  - event flags with the following significance:
     *                              - DMA_EV_ERR: address error event
     *                              - DMA_EV_ABORT: transfer abort event
     *                              - DMA_EV_CELL_DONE: cell transfer complete event
     *                              - DMA_EV_BLOCK_DONE: block transfer complete event
     *                              - DMA_EV_DST_HALF: destination half event
     *                              - DMA_EV_DST_FULL: destination full event
     *                              - DMA_EV_SRC_HALF: source half event
     *                              - DMA_EV_SRC_FULL: source full event
     *                              - DMA_EV_ALL_EVNTS: all of the above flags
     *
     * Output:          None
     *
     * Side Effects:    None
     *
     * Overview:        The function writes the event flags for the selected DMA channel.
     *                  The channel event flags are forced to the eFlags value.
     *
     * Note:            This is intended as a channel test function.
     *
     * Example:         DmaChnWriteEvFlags(DMA_CHANNEL0, DMA_EV_ERR|DMA_EV_ABORT|DMA_EV_BLOCK_DONE|DMA_EV_SRC_FULL);
     ********************************************************************/
     void           DmaChnWriteEvFlags(DmaChannel chn, DmaEvFlags eFlags);


    /********************************************************************
     * Include legacy DMA functions
     * New projects should not use them!
     * Note that interrupt functions are no longer provided.
     * The functions in the int.h should be used instead.
     ********************************************************************/
    #ifndef _PLIB_DISABLE_LEGACY
        #include <peripheral/legacy/dma_legacy.h>
    #endif


#else
    #undef _DMA_CHANNELS        // no DMA channels
#endif  // _DMAC0

#endif /*_DMA_5XX_6XX__7XX_H_*/


