//=============================================================================
// (c) Copyright 2017 Diamond Systems Corporation. Use of this source code
// is subject to the terms of Diamond Systems' Software License Agreement.
// Diamond Systems provides no warranty of proper performance if this
// source code is modified.
//
// File: VENUSDIOFUNCTION.c  
//
// Depedency :	VENUSDIO.H - Include file.
//				
//				VenusDIOLib.lib	- Library file for Windows 10
//						
//				
// VENUSDIOFUNCTION.c  
// Desc: Writes and reads from Digital I/O port
//============================================================================

#include "JasperGPIO.h"


// globals var declarations
ERRPARAMS errorParams; // structure for returning error code and error string

unsigned char gpioDir = 0xFF;

int portConfig[3];//used to store the port directions
char input_buffer[20];

void setGPIOConfiguration();
void setBitGPIOConfiguration();
void readAllBitsGPIOPort();
void writeBitGPIOPort();
void writeByteDIOPort();
void readByteDIOPort();
void GPIOPortLoopbackTest();



//=============================================================================
// Name: main()
// Desc: Starting function call.
//
//		 NOTE: By convention, you should capture the BYTE return value for each
//		 driver API call, and check the error code.
//
//	     I. 	I2C  Initialization
//	     II. 	DIO INPUT AND OUTPUT
//	     III. 	Cleanup
//
//=============================================================================
int main(void)
{
    UINT intBuff = 0; 
    char input_mbuffer[20];

    //=========================================================================
    // I. Jasper1185GREGPIOInitBoard
    //
    //    Initializes the Jasper GPIO library.
    //
    //    STEPS TO FOLLOW:
    //
    //    1. Initialize the board.
    //=========================================================================

    if (Jasper1185GREGPIOInitBoard() != DE_NONE)
    {
        GetLastErrorGPIO(&errorParams);
        printf("Init error: %s %s\n", GetErrorString(&errorParams), (errorParams.errstring));
        return 0;


        printf("Init error");
        return 0;
    }

    printf("\nJASPER 1185GRE GPIO FUNCTIONS DEMO\n");

    //=========================================================================
    // II. GPIO INPUT AND OUTPUT
    //
    //      Guide:
    //
    //      1. Set Bit Configuration
    //      2. Read All Bits
    //      3. Write a Bit
    //      4. Loopback Test (0–255)
    //      q. Quit Program
    //
    //      Choose these options in any order from the menu!
    //=========================================================================

    printf("\nGPIO INPUT AND OUTPUT: Main Menu \n");

    do
    {
        intBuff = 0;
        printf("########################################################\n");
        printf("Please Select an option from below!\n");
        printf("1) Set GPIO Configuration\n");
        printf("2) Set GPIO BIT Level Configuration\n");
        printf("3) Read Byte from  port\n");
        printf("4) Read all bits from port\n");
        printf("5) Write Byte to port\n");
        printf("6) Write Bit to a port\n");
        printf("7) Port loopback 0 to 255 read/write repetitive\n");
        printf("q) Quit Program\n");
        printf("########################################################\n");

        fgets(input_mbuffer, sizeof(input_mbuffer), stdin);
        sscanf(input_mbuffer, "%d", &intBuff);

        if (input_mbuffer[0] == 'q')
        {
            intBuff = 'q';
        }

        switch (intBuff)
        {
            case 1:
                setGPIOConfiguration();
                break;
            case 2:
                setBitGPIOConfiguration();
                break;
            case 3:
                readByteDIOPort();
                break;
            case 4:
                readAllBitsGPIOPort();
                break;
            case 5:
                writeByteDIOPort();
                break;

            case 6:
                writeBitGPIOPort();
                break;

           case 7:
                GPIOPortLoopbackTest();
                break;

            case 'q':
                return 0;

            default:
                printf("Please enter a valid option\r\n");
                break;
        }

    } while (input_mbuffer[0] != 'q');

    //=========================================================================
    // III. CLEANUP
    //
    //      Cleanup any remnants left by the program and free resources.
    //
    //      STEPS TO FOLLOW:
    //
    //      1. Free the board and internal resources.
    //=========================================================================

    Jasper1185GREGPIOFreeBoard();

    printf("\nJASPER GPIO FUNCTION completed.\n");

    return;
}

//=============================================================================
// 
// Name: setGPIOConfiguration()
// Desc: Set the GPIO configuration
// Parameter: void
// Return: void
// 
//=============================================================================


void setGPIOConfiguration()
{
    int mGPIODir = 0, intBuff = 0;
    char input_mbuffer[20];
    
    printf("Enter the GPIO Byte Configuration (1=input, 0=output): \n");
    scanf("%d",&intBuff);
    if (intBuff == 0)
    {
        mGPIODir = 0x00;
    }
    else if (intBuff == 1)
    {
        mGPIODir = 0xFF;
    }
    else
    {
        printf("Wrong Entry...\n");
        return;
    }

    if (Jasper1185GREGPIOConfig(mGPIODir) != 0)
    {
        GetLastErrorGPIO(&errorParams);
        fprintf(stderr, "Jasper1185GREGPIOConfig error: %s %s\n", GetErrorString(errorParams.ErrCode), errorParams.errstring);
        printf("Error using standard DIO ports.\n");
        return;
    }
    getchar();
}

//=============================================================================
// Set per-pin GPIO configuration (Windows Version for Jasper)
// User inputs 1 = Input, 0 = Output
//=============================================================================
void setBitGPIOConfiguration()
{
    int bit = 0;
    int dir = 0;

    printf("\nInfo Mapping: Configure GPIO (0 = Output, 1 = Input)\n");
    printf("----------------------------------------\n");

    gpioDir = 0;

    // -----------------------------
    // Read direction for each bit
    // -----------------------------
    for (bit = 0; bit < 8; bit++)
    {
        printf("Enter direction for Bit %d (0/1): ", bit);
        fgets(input_buffer, sizeof(input_buffer), stdin);
        sscanf(input_buffer, "%d", &dir);

        if (dir == 1)              // Input
            gpioDir |= (1 << bit);
        else if (dir == 0)         // Output
            gpioDir &= ~(1 << bit);
        else
        {
            printf("Invalid value! Use only 0 or 1.\n");
            bit--;        // retry
        }
    }

    if (Jasper1185GREGPIOConfig(gpioDir) != 0)
    {
        GetLastErrorGPIO(&errorParams);
        fprintf(stderr, "Jasper1185GREGPIOConfig error: %s %s\n", GetErrorString(errorParams.ErrCode), errorParams.errstring);
        printf("Error using standard DIO ports.\n");
    }

}

void readAllBitsGPIOPort()
{
    UINT digital_value = 0;
    int bit = 0;

    printf("The GPIO each bit values are \n");
    printf("--------------------------------------------------------------------\r\n");
    printf("BitNo:\t7\t6\t5\t4\t3\t2\t1\t0\r\n");
    printf("--------------------------------------------------------------------\r\n");
    printf("Value:");

    for (bit = 7;bit >= 0; bit--)
    {

        if ((Jasper1185GREGPIOInputBit(bit, &digital_value) != DE_NONE))
        {
            GetLastErrorGPIO(&errorParams);
            fprintf(stderr, "Jasper1185GREGPIOInputBit error: %s %s\n", GetErrorString(errorParams.ErrCode), errorParams.errstring);
            printf("Error using standard DIO ports.\n");
        }

        printf("\t%x", digital_value);

    }

    printf("\n");

}


//=============================================================================
// Name: writeBitGPIOPort()
// Desc: Program a GPIO bit by sending a digital value to the selected bit.
// Parameters: void
// Return: void
//=============================================================================
void writeBitGPIOPort()
{
    UINT config = 0x00;
    UINT digital_value = 0;
    UINT bit = 0;
    UINT port = 0;
    UINT intBuf = 0;

    do
    {
        printf("Enter Bit (0-7):or q to quit :");
        fgets(input_buffer, 20, stdin);
        sscanf(input_buffer, "%d", &bit);

        if (input_buffer[0] != 'q')
        {
            printf("Enter Bit value (0-1):");
            fgets(input_buffer, 20, stdin);
            sscanf(input_buffer, "%d", &intBuf);
            digital_value = intBuf;


            if ((Jasper1185GREGPIOOutputBit(bit, digital_value) != DE_NONE))
            {
                GetLastErrorGPIO(&errorParams);
                fprintf(stderr, "Jasper1185GREGPIOOutputBit error: %s %s\n", GetErrorString(errorParams.ErrCode), errorParams.errstring);
                return;
            }
        }
    } while (input_buffer[0] != 'q');


    return;
}

//=============================================================================
// Name: readByteDIOPort()
// Desc: Read Byte  from the selected port's  register.
// Parameters:void
// Return: void
//=============================================================================
void readByteDIOPort()
{
    UINT digital_value = 0;
    int bit = 0;

    if (Jasper1185GREGPIOInputByte( &digital_value) != 0)
    {
            GetLastErrorGPIO(&errorParams);
            fprintf(stderr, "Jasper1185GREGPIOInputBit error: %s %s\n", GetErrorString(errorParams.ErrCode), errorParams.errstring);
            return;
    } 

    printf("Byte value received from GPIO = 0x%x\r\n", digital_value);

    return;

}



//=============================================================================
// Name: writeByteDIOPort()
// Desc: Program a GPIO by sending a byte to the register.
// Parameters: void
// Return: void
//=============================================================================
void writeByteDIOPort()
{
    UINT config = 0x00;
    UINT port = 0;
    BYTE output_byte = 0;
    UINT intBuff = 0;
    do
    {
        printf("Enter value 0-255 or q to quit:");
        fgets(input_buffer, 20, stdin);
        sscanf(input_buffer, "%d", &intBuff);

        if (input_buffer[0] == 'q')
        {
            intBuff = 'q';
        }
        else
        {
            output_byte = (BYTE)intBuff;

            if ((Jasper1185GREGPIOOutputByte(output_byte) != DE_NONE))
            {
                GetLastErrorGPIO(&errorParams);
                fprintf(stderr, "Jasper1185GREGPIOOutputByte error: %s %s\n", GetErrorString(errorParams.ErrCode), errorParams.errstring);
                return;
            }
            printf("The Byte value  %d is sent to GPIO \n", output_byte);
        }
    } while (input_buffer[0] != 'q');

    return;

}



//=============================================================================
// Name: GPIOPortLoopbackTest()
// Desc: Loopback test on Jasper 1185GRE GPIO (Windows version, Venus-style)
// Parameters: void
// Return: void
//=============================================================================


void GPIOPortLoopbackTest()
{
    int* config;
    BYTE output_port = 0, input_port = 0, input_p = 0, output_p = 0;
    BYTE output_byte = 0, input_byte = 0;
    BYTE errorcount = 0;
    int pin_config = 0;
    int intBuff = 0;
    int common = 0;
    int verbose_mode = 0, i, iterations = 0;
    printf("Do you want to enable the Verbose Mode 0-Enable 1-Disable\n");
    fgets(input_buffer, 20, stdin);
    sscanf(input_buffer, "%d", &verbose_mode);
    do
    {
        gpioDir = 0xFF;output_byte = 0;
        if (Jasper1185GREGPIOConfig(gpioDir) != 0)
        {
            GetLastErrorGPIO(&errorParams);
            fprintf(stderr, "Jasper1185GREGPIOConfig error: %s %s\n", GetErrorString(errorParams.ErrCode), errorParams.errstring);
            printf("Error using standard DIO ports.\n");
            return;
        }
        if ((Jasper1185GREGPIOOutputByte(output_byte) != DE_NONE))
        {
            GetLastErrorGPIO(&errorParams);
            fprintf(stderr, "Jasper1185GREGPIOOutputByte error: %s %s\n", GetErrorString(errorParams.ErrCode), errorParams.errstring);
            return;
        }
        iterations = 15;
        intBuff = 0;
        printf("Enter GPIO Bits to Write \n0 - BIT 0 to BIT 3 [Output] BIT 4 to BIT 7 [Input];\n1 - BIT 0 to BIT 3 [Input] & BIT 4 to BIT 7 [Output]\n-1 go to Main menu: ");
        fgets(input_buffer, 20, stdin);
        sscanf(input_buffer, "%d", &pin_config);
        if (pin_config == -1) break;
        if (pin_config < 0)
        {
            printf("ERROR: Valid options are: (0-1)\n ");
            return;
        }

        if (pin_config == 0)
        {
            gpioDir = 0xF0;
        }
        else
        {
            gpioDir = 0x0F;
        }
        if (Jasper1185GREGPIOConfig(gpioDir) != 0)
        {
            GetLastErrorGPIO(&errorParams);
            fprintf(stderr, "Jasper1185GREGPIOConfig error: %s %s\n", GetErrorString(errorParams.ErrCode), errorParams.errstring);
            printf("Error using standard DIO ports.\n");
            return;
        }

        errorcount = 0;
        
        for (; intBuff <= iterations;intBuff++)
        {
            output_byte = 0;
            if (pin_config == 0)
            {
                output_byte = intBuff;
            }
            else
            {
                output_byte = intBuff << 4;
            }

            if ((Jasper1185GREGPIOOutputByte(output_byte) != DE_NONE))
            {
                GetLastErrorGPIO(&errorParams);
                fprintf(stderr, "Jasper1185GREGPIOOutputByte error: %s %s\n", GetErrorString(errorParams.ErrCode), errorParams.errstring);
                return;
            }

            if ((Jasper1185GREGPIOInputByte( &input_byte) != DE_NONE))
            {
                GetLastErrorGPIO(&errorParams);
                fprintf(stderr, "Jasper1185GREGPIOInputByte error: %s %s\n", GetErrorString(errorParams.ErrCode), errorParams.errstring);
                return;
            }
            
            if (pin_config == 0)
            {
                input_byte = input_byte & 0xF0;
                input_byte = input_byte >> 4;
            }
            else
            {
                input_byte = input_byte & 0x0F;
                input_byte = input_byte << 4;
            }

            if (output_byte != input_byte)
            {
                errorcount += 1;
            }

            if (verbose_mode == 0)
            {
                if (output_byte != input_byte)
                {
                    printf("FAILED: Output: 0x%x  Input: 0x%x \n", output_byte, input_byte);
                }
                else
                {
                    printf("PASSED: Output: 0x%x  Input: 0x%x \n", output_byte, input_byte);
                }
            }
            if (_kbhit())
                break;

           // dscSleep(1);
        }
        printf("\nValues written : %d and Errors: %d \n\n", intBuff, errorcount);

    } while (!(_kbhit()));

}
