/*####################################################
 * FILE: MW_c28xGPIO.c
 * TITLE: GPIO functions to access the GPIO specific registers for C2000 target
 * Copyright 2017-2020 The MathWorks, Inc.
 * ####################################################*/

/* ***************************************************************************/
/* the includes */

#include "MW_c28xGPIO.h"
#ifdef CPU2
#ifdef MW_F2837XD
#include "F2837xD_Ipc_drivers.h"
#define CPU01_TO_CPU02_PASSMSG  0x0003FFF4
#endif //MW_F2837XD
#ifdef MW_F2838X
#include "MW_f2838x_includes.h"
#endif //MW_F2838X
#endif //CPU2

/* ***************************************************************************/
/* the defines */

/* ***************************************************************************/
/* the globals */

Uint16 GPIO_oneTimeInit = 0;

/* ***************************************************************************/
/* the functions*/

/* One time initialization of all GPIOs */
void OneTimeGpioInit()
{    
    if(GPIO_oneTimeInit == 0)
    {
#ifdef CPU1
        InitGpio();
#endif //End of CPU1
        GPIO_oneTimeInit = 1;
    }
}

#ifndef MW_F281X /*GPIO implementation not supported for C281x */
#ifndef F2837X_REG_FORMAT /*GPIO functions are provided by TI*/
#ifndef MW_F2804X /*GPIO initialization is provided by TI for F2804x*/

/*Sets all pins to be muxed to GPIO in input mode with pull-ups enabled.
 * Also sets the qualification to synchronous.*/
void InitGpio()
{
    volatile Uint32 *gpioBaseAddr;
    Uint16 regOffset;
    EALLOW;
    /*Fill all registers with zeros. Writing to each register separately
     * for all GPIO modules would make this function *very* long. Fortunately,
     * we'd be writing them all with zeros anyway, so this saves a lot of space.*/
    gpioBaseAddr = (Uint32 *)&GpioCtrlRegs;
    for (regOffset = 0; regOffset < sizeof(GpioCtrlRegs)/2; regOffset++)
    {
        /*Hack to avoid enabling pull-ups on all pins. GPyPUD is offset
         * 0x0C in each register group of 0x40 words. Since this is a
         * 32-bit pointer, the addresses must be divided by 2.*/
        if (regOffset % (0x10/2) != (0x0C/2))
            gpioBaseAddr[regOffset] = 0x00000000;
    }
    
    gpioBaseAddr = (Uint32 *)&GpioDataRegs;
    for (regOffset = 0; regOffset < sizeof(GpioDataRegs)/2; regOffset++)
    {
        gpioBaseAddr[regOffset] = 0x00000000;
    }
    
    /* For concerto additional registers needs to be initialized*/
    #ifdef MW_PIL_TIC2000_CONCERTO
    /*Fill all registers with zeros. Writing to each register separately
     * for all GPIO modules would make this function *very* long. Fortunately,
     * we'd be writing them all with zeros anyway, so this saves a lot of space.*/
    gpioBaseAddr = (Uint32 *)&GpioG1CtrlRegs;
    for (regOffset = 0; regOffset < sizeof(GpioG1CtrlRegs)/2; regOffset++)
    {
        /*Hack to avoid enabling pull-ups on all pins. GPyPUD is offset
         * 0x0C in each register group of 0x40 words. Since this is a
         * 32-bit pointer, the addresses must be divided by 2.*/
        if (regOffset % (0x10/2) != (0x0C/2))
            gpioBaseAddr[regOffset] = 0x00000000;
    }
    
    gpioBaseAddr = (Uint32 *)&GpioG1DataRegs;
    for (regOffset = 0; regOffset < sizeof(GpioG1DataRegs)/2; regOffset++)
    {
        gpioBaseAddr[regOffset] = 0x00000000;
    }
    #endif //End of MW_PIL_TIC2000_CONCERTO
    EDIS;
}
#endif // End of MW_F2804X

/*Set the peripheral muxing for the specified pin.
 * The appropriate parameters can be found in the GPIO Muxed Pins table.
 * Use the GPIO index row (0 to 4) to select a muxing option for the GPIO.*/
void GPIO_SetupPinMux(Uint16 pin, Uint16 cpu, Uint16 peripheral)
{
    volatile Uint32 *gpioBaseAddr;
    volatile Uint32 *mux;
    Uint16 pin32, pin16;
    
    pin32 = pin % 32;
    pin16 = pin % 16;
    #ifdef MW_PIL_TIC2000_CONCERTO
    if (pin >= 128)
    {
        #ifdef F28M36x_DEVICE_H
        if (pin <= 135)
        {
            gpioBaseAddr = (Uint32 *)&GpioCtrlRegs;
        }
        else if (pin >=192 && pin <= 199)
        {
            gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (0x1080/2);
        }
        #endif //End of F28M36x_DEVICE_H
        #ifdef F28M35x_DEVICE_H
        if (pin <= 135)
        {
            gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (0x1000/2);
        }
        #endif //End of F28M35x_DEVICE_H
    }
    else
    {
        #ifdef F28M36x_DEVICE_H
        gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (0x80/2) + (pin/32)*GPY_CTRL_OFFSET;
        #endif //End of F28M36x_DEVICE_H
        #ifdef F28M35x_DEVICE_H
        gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (pin/32)*GPY_CTRL_OFFSET;
        #endif //End of F28M35x_DEVICE_H
    }
    #else
    gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (pin/32)*GPY_CTRL_OFFSET;
    #endif // End of MW_PIL_TIC2000_CONCERTO
    
    /*Sanity check for valid peripheral values*/
    if (peripheral > 0x4)
        return;
    
    /*Create pointers to the appropriate registers. This is a workaround
     * for the way GPIO registers are defined. The standard definition
     * in the header file makes it very easy to do named accesses of one
     * register or bit, but hard to do arbitrary numerical accesses. It's
     * easier to have an array of GPIO modules with identical registers,
     * including arrays for multi-register groups like GPyCSEL1-4. But
     * the header file doesn't define anything we can turn into an array,
     * so manual pointer arithmetic is used instead.*/
    mux = gpioBaseAddr + GPYMUX + pin32/16;
    
    //Now for the actual function
    EALLOW;
    
    /* Unfortunately, since we don't know the pin in
     * advance we can't hardcode a bitfield reference, so there's some tricky
     * bit twiddling here.*/
    *mux &= ~(0x3UL << (2*pin16));
    *mux |= (Uint32)(peripheral & 0x3UL) << (2*pin16);
    
    //WARNING: This code does not touch the analog mode select registers,
    //which are needed to give the USB module control of its IOs.
    EDIS;
}

/*Setup up the GPIO input/output options for the specified pin.
 * The flags are a 16-bit mask produced by ORing together options.
 * For input pins, the valid flags are:
 * GPIO_PULLUP    Enable pull-up
 * GPIO_SYNC        Synchronize the input latch to PLLSYSCLK (default -- you don't need to specify this)
 * GPIO_QUAL3    Use 3-sample qualification
 * GPIO_QUAL6    Use 6-sample qualification
 * GPIO_ASYNC    Do not use synchronization or qualification
 * (Note: only one of SYNC, QUAL3, QUAL6, or ASYNC is allowed)
 * For output pins, the valid flags are:
 * GPIO_PULLUP        If open drain enabled, also enable the pull-up
 * and the input qualification flags (SYNC/QUAL3/QUAL6/SYNC) listed above.
 * With no flags, the default input state is synchronous with no pull-up or polarity inversion.
 * The default output state is the standard digital output.*/
void GPIO_SetupPinOptions(Uint16 pin, Uint16 output, Uint16 flags)
{
    {
    volatile Uint32 *gpioBaseAddr;
    volatile Uint32 *dir, *pud, *qsel;
    Uint32 pin32, pin16, pinMask, qual;
    
    pin32 = pin % 32;
    pin16 = pin % 16;
    pinMask = 1UL << pin32;
    #ifdef MW_PIL_TIC2000_CONCERTO
    if (pin >= 128)
    {
        #ifdef F28M36x_DEVICE_H
        if (pin <= 135)
        {
            gpioBaseAddr = (Uint32 *)&GpioCtrlRegs;
        }
        else if (pin >=192 && pin <= 199)
        {
            gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (0x1080/2);
        }
        #endif //End of F28M36x_DEVICE_H
        #ifdef F28M35x_DEVICE_H
        if (pin <= 135)
        {
            gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (0x1000/2);
        }
        #endif //End of F28M35x_DEVICE_H
    }
    else
    {
        #ifdef F28M36x_DEVICE_H
        gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (0x80/2) + (pin/32)*GPY_CTRL_OFFSET;
        #endif //End of F28M36x_DEVICE_H
        #ifdef F28M35x_DEVICE_H
        gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (pin/32)*GPY_CTRL_OFFSET;
        #endif //End of F28M35x_DEVICE_H
    }
    #else
    gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (pin/32)*GPY_CTRL_OFFSET;
    #endif // End of MW_PIL_TIC2000_CONCERTO
    
    /*Create pointers to the appropriate registers. This is a workaround
     * for the way GPIO registers are defined. The standard definition
     * in the header file makes it very easy to do named accesses of one
     * register or bit, but hard to do arbitrary numerical accesses. It's
     * easier to have an array of GPIO modules with identical registers,
     * including arrays for multi-register groups like GPyQSEL1-2. But
     * the header file doesn't define anything we can turn into an array,
     * so manual pointer arithmetic is used instead.*/
    dir = gpioBaseAddr + GPYDIR;
    pud = gpioBaseAddr + GPYPUD;
    qsel = gpioBaseAddr + GPYQSEL + pin32/16;
    
    EALLOW;
    
    /*Set the data direction*/
    *dir &= ~pinMask;
    if (output == 1)
    {
        /*Output, with optional open drain mode and pull-up*/
        *dir |= pinMask;
        
        /*Enable pull-up if necessary. Open drain mode must be active.*/
        if (flags & GPIO_PULLUP)
            *pud &= ~pinMask;
        else
            *pud |= pinMask;
    } else
    {
        /*Input, with optional pull-up, qualification, and polarity inversion*/
        *dir &= ~pinMask;
        
        /*Enable pull-up if necessary*/
        if (flags & GPIO_PULLUP)
            *pud &= ~pinMask;
        else
            *pud |= pinMask;
    }
    
    /*Extract the qualification parameter and load it into the register. This is
     * also needed for open drain outputs, so we might as well do it all the time.*/
    qual = (flags & GPIO_ASYNC) / GPIO_QUAL3;
    *qsel &= ~(0x3L << (2 * pin16));
    if (qual != 0x0)
        *qsel |= qual << (2 * pin16);
    
    EDIS;
    }
}

/*Read the GPyDAT register bit for the specified pin.
 * Note that this returns the actual state of the pin, not the state of the output latch.*/
Uint16 GPIO_ReadPin(Uint16 pin)
{
    volatile Uint32 *gpioDataReg;
    Uint16 pinVal;

    #ifdef MW_PIL_TIC2000_CONCERTO
    if (pin >= 128)
    {
        #ifdef F28M36x_DEVICE_H
        if (pin <= 135)
        {
            gpioDataReg = (Uint32 *)&GpioDataRegs + (0x40/2);
        }
        else if (pin >=192 && pin <= 199)
        {
            gpioDataReg = (Uint32 *)&GpioDataRegs + (0x10C0/2);
        }
        #endif //End of F28M36x_DEVICE_H
        #ifdef F28M35x_DEVICE_H
        if (pin <= 135)
        {
            gpioDataReg = (Uint32 *)&GpioDataRegs + (0x1000/2);
        }
        #endif //End of F28M35x_DEVICE_H
    }
    else
    {
        #ifdef F28M36x_DEVICE_H
        gpioDataReg = (Uint32 *)&GpioDataRegs + (0xC0/2) + (pin/32)*GPY_DATA_OFFSET;
        #endif //End of F28M36x_DEVICE_H
        #ifdef F28M35x_DEVICE_H
        gpioDataReg = (Uint32 *)&GpioDataRegs + (pin/32)*GPY_DATA_OFFSET;
        #endif //End of F28M35x_DEVICE_H
    }
    #else
    gpioDataReg = (volatile Uint32 *)&GpioDataRegs + (pin/32)*GPY_DATA_OFFSET;
    #endif // End of MW_PIL_TIC2000_CONCERTO
    pinVal = (gpioDataReg[GPYDAT] >> (pin % 32)) & 0x1;
    
    return pinVal;
}

/*Set the GPyDAT register bit for the specified pin.*/
void GPIO_WritePin(Uint16 pin, Uint16 outVal)
{
    volatile Uint32 *gpioDataReg;
    Uint32 pinMask;
    
    #ifdef MW_PIL_TIC2000_CONCERTO
    if (pin >= 128)
    {
        #ifdef F28M36x_DEVICE_H
        if (pin <= 135)
        {
            gpioDataReg = (Uint32 *)&GpioDataRegs + (0x40/2);
        }
        else if (pin >=192 && pin <= 199)
        {
            gpioDataReg = (Uint32 *)&GpioDataRegs + (0x10C0/2);
        }
        #endif //End of F28M36x_DEVICE_H
        #ifdef F28M35x_DEVICE_H
        if (pin <= 135)
        {
            gpioDataReg = (Uint32 *)&GpioDataRegs + (0x1000/2);
        }
        #endif //End of F28M35x_DEVICE_H
    }
    else
    {
        #ifdef F28M36x_DEVICE_H
        gpioDataReg = (Uint32 *)&GpioDataRegs + (0xC0/2) + (pin/32)*GPY_DATA_OFFSET;
        #endif //End of F28M36x_DEVICE_H
        #ifdef F28M35x_DEVICE_H
        gpioDataReg = (Uint32 *)&GpioDataRegs + (pin/32)*GPY_DATA_OFFSET;
        #endif //End of F28M35x_DEVICE_H
    }
    #else
    gpioDataReg = (volatile Uint32 *)&GpioDataRegs + (pin/32)*GPY_DATA_OFFSET;
    #endif // End of MW_PIL_TIC2000_CONCERTO
    pinMask = 1UL << (pin % 32);
    
    if (outVal == 0)
        gpioDataReg[GPYCLEAR] = pinMask;
    else
        gpioDataReg[GPYSET] = pinMask;
}

/*Toggle the GPyDAT register bit for the specified pin.*/
void GPIO_TogglePin(Uint16 pin)
{
    volatile Uint32 *gpioDataReg;
    Uint32 pinMask;
    
    #ifdef MW_PIL_TIC2000_CONCERTO
    if (pin >= 128)
    {
        #ifdef F28M36x_DEVICE_H
        if (pin <= 135)
        {
            gpioDataReg = (Uint32 *)&GpioDataRegs + (0x40/2);
        }
        else if (pin >=192 && pin <= 199)
        {
            gpioDataReg = (Uint32 *)&GpioDataRegs + (0x10C0/2);
        }
        #endif //End of F28M36x_DEVICE_H
        #ifdef F28M35x_DEVICE_H
        if (pin <= 135)
        {
            gpioDataReg = (Uint32 *)&GpioDataRegs + (0x1000/2);
        }
        #endif //End of F28M35x_DEVICE_H
    }
    else
    {
        #ifdef F28M36x_DEVICE_H
        gpioDataReg = (Uint32 *)&GpioDataRegs + (0xC0/2) + (pin/32)*GPY_DATA_OFFSET;
        #endif //End of F28M36x_DEVICE_H
        #ifdef F28M35x_DEVICE_H
        gpioDataReg = (Uint32 *)&GpioDataRegs + (pin/32)*GPY_DATA_OFFSET;
        #endif //End of F28M35x_DEVICE_H
    }
    #else
    gpioDataReg = (volatile Uint32 *)&GpioDataRegs + (pin/32)*GPY_DATA_OFFSET;
    #endif // End of MW_PIL_TIC2000_CONCERTO
    pinMask = 1UL << (pin % 32);
    
    
    gpioDataReg[GPYTOGGLE] = pinMask;

}

#else // for F2837X_REG_FORMAT
#if defined(MW_F2838X) 
#if defined(CPU1)

void InitGpio()
{
    volatile Uint32 *gpioBaseAddr;
    Uint16 regOffset;

    /*Disable pin locks*/
    EALLOW;
    GpioCtrlRegs.GPALOCK.all = 0x00000000;
    GpioCtrlRegs.GPBLOCK.all = 0x00000000;
    GpioCtrlRegs.GPCLOCK.all = 0x00000000;
    GpioCtrlRegs.GPDLOCK.all = 0x00000000;
    GpioCtrlRegs.GPELOCK.all = 0x00000000;
    GpioCtrlRegs.GPFLOCK.all = 0x00000000;

    /* Fill all registers with zeros. Writing to each register separately
     * for six GPIO modules would make this function *very* long.
     * Fortunately, we'd be writing them all with zeros anyway, so this
     * saves a lot of space.*/
    gpioBaseAddr = (Uint32 *)&GpioCtrlRegs;
    for (regOffset = 0; regOffset < sizeof(GpioCtrlRegs)/2; regOffset++)
    {
        /* Hack to avoid enabling pull-ups on all pins. GPyPUD is offset
         * 0x0C in each register group of 0x40 words. Since this is a
         * 32-bit pointer, the addresses must be divided by 2.*/
        if (regOffset % (0x40/2) != (0x0C/2))
        {
            gpioBaseAddr[regOffset] = 0x00000000;
        }
    }

    gpioBaseAddr = (Uint32 *)&GpioDataRegs;
    for (regOffset = 0; regOffset < sizeof(GpioDataRegs)/2; regOffset++)
    {
        gpioBaseAddr[regOffset] = 0x00000000;
    }

    EDIS;
}

void GPIO_SetupPinMux(Uint16 gpioNumber, Uint16 cpu, Uint16 muxPosition)
{
    volatile Uint32 *gpioBaseAddr;
    volatile Uint32 *mux, *gmux, *csel;
    Uint16 pin32, pin16, pin8;

    pin32 = gpioNumber % 32;
    pin16 = gpioNumber % 16;
    pin8 = gpioNumber % 8;
    gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (gpioNumber/32)*GPY_CTRL_OFFSET;

    /*Sanity check for valid cpu and peripheral values*/
    if (cpu > GPIO_MUX_CM || muxPosition > 0xF)
        return;

    /* Create pointers to the appropriate registers. This is a workaround
     * for the way GPIO registers are defined. The standard definition
     * in the header file makes it very easy to do named accesses of one
     * register or bit, but hard to do arbitrary numerical accesses. It's
     * easier to have an array of GPIO modules with identical registers,
     * including arrays for multi-register groups like GPyCSEL1-4. But
     * the header file doesn't define anything we can turn into an array,
     * so manual pointer arithmetic is used instead.*/
    mux = gpioBaseAddr + GPYMUX + pin32/16;
    gmux = gpioBaseAddr + GPYGMUX + pin32/16;
    csel = gpioBaseAddr + GPYCSEL + pin32/8;

    /* Now for the actual function */
    EALLOW;

    /* To change the muxing, set the peripheral mux to 0/GPIO first to avoid
     * glitches, then change the group mux, then set the peripheral mux to
     * its target value. Finally, set the CPU select. This procedure is
     * described in the TRM. Unfortunately, since we don't know the pin in
     * advance we can't hardcode a bitfield reference, so there's some
     * tricky bit twiddling here.*/
    *mux &= ~(0x3UL << (2*pin16));
    *gmux &= ~(0x3UL << (2*pin16));
    *gmux |= (Uint32)((muxPosition >> 2) & 0x3UL) << (2*pin16);
    *mux |= (Uint32)(muxPosition & 0x3UL) << (2*pin16);

    *csel &= ~(0x7L << (4*pin8));
    *csel |= (Uint32)(cpu & 0x7L) << (4*pin8);

    /* WARNING: This code does not touch the analog mode select registers,
     * which are needed to give the USB module control of its IOs.*/
    EDIS;
}

void GPIO_SetupPinOptions(Uint16 gpioNumber, Uint16 output, Uint16 flags)
{
    volatile Uint32 *gpioBaseAddr;
    volatile Uint32 *dir, *pud, *inv, *odr, *qsel;
    Uint32 pin32, pin16, pinMask, qual;

    pin32 = gpioNumber % 32;
    pin16 = gpioNumber % 16;
    pinMask = 1UL << pin32;
    gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (gpioNumber/32)*GPY_CTRL_OFFSET;

    /* Create pointers to the appropriate registers. This is a workaround
     * for the way GPIO registers are defined. The standard definition
     * in the header file makes it very easy to do named accesses of one
     * register or bit, but hard to do arbitrary numerical accesses. It's
     * easier to have an array of GPIO modules with identical registers,
     * including arrays for multi-register groups like GPyQSEL1-4. But
     * the header file doesn't define anything we can turn into an array,
     * so manual pointer arithmetic is used instead.*/
    dir = gpioBaseAddr + GPYDIR;
    pud = gpioBaseAddr + GPYPUD;
    inv = gpioBaseAddr + GPYINV;
    odr = gpioBaseAddr + GPYODR;
    qsel = gpioBaseAddr + GPYQSEL + pin32/16;

    EALLOW;

    /*Set the data direction*/
    *dir &= ~pinMask;
    if (output == 1)
    {        
        /* Output, with optional open drain mode and pull-up */        
        *dir |= pinMask;

        /* Enable open drain if necessary */
        if (flags & GPIO_OPENDRAIN)
        {
            *odr |= pinMask;
        }
        else
        {
            *odr &= ~pinMask;
        }

        /* Enable pull-up if necessary. Open drain mode must be active. */
        if (flags & (GPIO_OPENDRAIN | GPIO_PULLUP))
        {
            *pud &= ~pinMask;
        }
        else
        {
            *pud |= pinMask;
        }
    }
    else
    {
        /* Input, with optional pull-up, qualification, and polarity
         * inversion */
        *dir &= ~pinMask;

        /* Enable pull-up if necessary */
        if (flags & GPIO_PULLUP)
        {
            *pud &= ~pinMask;
        }
        else
        {
            *pud |= pinMask;
        }

        /* Invert polarity if necessary */
        if (flags & GPIO_INVERT)
        {
            *inv |= pinMask;
        }
        else
        {
            *inv &= ~pinMask;
        }
    }

    /* Extract the qualification parameter and load it into the register.
     * This is also needed for open drain outputs, so we might as well do it
     * all the time. */
    qual = (flags & GPIO_ASYNC) / GPIO_QUAL3;
    *qsel &= ~(0x3L << (2 * pin16));
    if (qual != 0x0)
    {
        *qsel |= qual << (2 * pin16);
    }

    EDIS;
}

void GPIO_EnableUnbondedIOPullupsFor176Pin()
{
	EALLOW;
	GpioCtrlRegs.GPCPUD.all = ~0x80000000;  /* GPIO 95 */
	GpioCtrlRegs.GPDPUD.all = ~0xFFFFFFF7;  /* GPIOs 96-127 */
	GpioCtrlRegs.GPEPUD.all = ~0xFFFFFFDF;  /* GPIOs 128-159 except for 133 */
	GpioCtrlRegs.GPFPUD.all = ~0x000001FF;  /* GPIOs 160-168 */
	EDIS;
}

void GPIO_EnableUnbondedIOPullupsFor100Pin()
{
    EALLOW;
    GpioCtrlRegs.GPAPUD.all = ~0xFFC003E3;  //GPIOs 0-1, 5-9, 22-31
    GpioCtrlRegs.GPBPUD.all = ~0x03FFF1FF;  //GPIOs 32-40, 44-57
    GpioCtrlRegs.GPCPUD.all = ~0xE10FBC18;  //GPIOs 67-68, 74-77, 79-83, 93-95
    GpioCtrlRegs.GPDPUD.all = ~0xFFFFFFF7;  //GPIOs 96-127
    GpioCtrlRegs.GPEPUD.all = ~0xFFFFFFFF;  //GPIOs 128-159
    GpioCtrlRegs.GPFPUD.all = ~0x000001FF;  //GPIOs 160-168
    EDIS;
}

void GPIO_EnableUnbondedIOPullups()
{
	/* bits 8-10 have pin count */
    unsigned char pin_count = ((DevCfgRegs.PARTIDL.all & 0x00000700) >> 8) ;

	/* 5 = 100 pin
	 * 6 = 176 pin
	 * 7 = 337 pin */
    if(pin_count == 5)
    {
        GPIO_EnableUnbondedIOPullupsFor100Pin();
    }
    else if (pin_count == 6)
	{
		GPIO_EnableUnbondedIOPullupsFor176Pin();
	}
	else
	{
		/* do nothing - this is 337 pin package */
	}
}
#endif // defined(CPU1)
/*Read the GPyDAT register bit for the specified pin.
 * Note that this returns the actual state of the pin, not the state of the output latch.*/
Uint16 GPIO_ReadPin(Uint16 pin)
{
    volatile Uint32 *gpioDataReg;
    Uint16 pinVal;

    gpioDataReg = (volatile Uint32 *)&GpioDataRegs + (pin/32)*GPY_DATA_OFFSET;
    pinVal = (gpioDataReg[GPYDAT] >> (pin % 32)) & 0x1;
    
    return pinVal;
}

/*Set the GPyDAT register bit for the specified pin.*/
void GPIO_WritePin(Uint16 pin, Uint16 outVal)
{
    volatile Uint32 *gpioDataReg;
    Uint32 pinMask;
    
    gpioDataReg = (volatile Uint32 *)&GpioDataRegs + (pin/32)*GPY_DATA_OFFSET;
    pinMask = 1UL << (pin % 32);
    
    if (outVal == 0)
    {
        gpioDataReg[GPYCLEAR] = pinMask;
    }
    else
    {
        gpioDataReg[GPYSET] = pinMask;
    }
}

#endif // end of defined(MW_F2838X)

/*Toggle the GPyDAT register bit for the specified pin.*/
void GPIO_TogglePin(Uint16 pin)
{
    volatile Uint32 *gpioDataReg;
    Uint32 pinMask;
    
    gpioDataReg = (volatile Uint32 *)&GpioDataRegs + (pin/32)*GPY_DATA_OFFSET;
    pinMask = 1UL << (pin % 32);
    gpioDataReg[GPYTOGGLE] = pinMask;
}
#endif // end of F2837X_REG_FORMAT

/*Set the GPIO pin. Set the mux values and pin options for the specified pin.
  This function can be used for all processors except C281x. The implementation is dependant on CPU1 and CPU2*/ 
void Set_GPIOPin(Uint16 pin, Uint16 cpu, Uint16 peripheral, Uint16 output, Uint16 flags)
{
#if defined(F2837X_REG_FORMAT) && defined(CPU2)
    Uint32 *pulMsgRam = (void *)CPU01_TO_CPU02_PASSMSG;
    Uint32 gpioData = 0x00000000;
    //Sanity check for valid cpu and peripheral values
    if (cpu > GPIO_MUX_CPU2CLA || peripheral > 0xF)
        return;
    gpioData = gpioData | pin;
    gpioData = gpioData | ((Uint32)peripheral << 8);
    gpioData = gpioData | ((Uint32)output << 16);
    gpioData = gpioData | ((Uint32)flags << 24);
    #ifdef MW_F2837XD
    Uint32 ulRWord32 = 0;
    IPCLiteLtoRFunctionCall(IPC_FLAG0, pulMsgRam[0], gpioData, IPC_FLAG31);
    while (IPCLiteLtoRGetResult(&ulRWord32,IPC_LENGTH_32_BITS,
            IPC_FLAG31) != STATUS_PASS)
    {
    }
    #else
     MW_IPC_sendCommand(IPC_CPU2_L_CPU1_R, (IPC_FLAG0 | IPC_FLAG31), IPC_ADDR_CORRECTION_DISABLE, IPC_FUNC_CALL, pulMsgRam[0], gpioData);
    IPC_waitForAck(IPC_CPU2_L_CPU1_R, IPC_FLAG31);
    IPC_getResponse(IPC_CPU2_L_CPU1_R);
    #endif //MW_F2837XD
#else
    GPIO_SetupPinMux(pin, cpu, peripheral);
    GPIO_SetupPinOptions(pin, output, flags);
#endif // end of defined(F2837X_REG_FORMAT) && defined(CPU2)
}
#endif //end of MW_F281X
    
