/******************************* JVTestSwitchDebouncer.c *************************************
This program tests the switch_debouncer_0 peripheral that is connected to the position buttons 
on the ML403 EVB. An interrupt is generated when the state of the buttons is changed. The 
LEDs_4Bit peripheral is incremented and a message telling the user which button was pushed is 
printed every time the interrupt is generated.
***********************************************************************/
// System definitions
#include "xparameters.h" 
#include "stdio.h"
#include "xbasic_types.h"

// Low-level driver to access the GPIO peripherals
#include "xgpio_l.h"

// Low-level driver to configure the Interrupt Controller
#include "xintc_l.h"

// Low-level driver to configure interrupt on PowerPC
//#include "xexception_l.h"
#include "xil_exception.h"

// Low-level driver to access the switch_debouncer peripheral
#include "switch_debouncer.h"

volatile Xuint8 interrupt_flag;
volatile Xuint32 button_state;

// ==============================================================================================================
// Interrupt handler for the Switch Debouncer. This handler clears the interrupt flag and increments the 4-bit LEDs
void Switch_Debouncer_Interrupt_Handler (void * baseaddr_p)
   {
   Xuint32 baseaddr = (Xuint32) baseaddr_p;
   Xuint32 Status;
   static Xuint8 led_counter = 0;

// Read status from Interrupt Status Register.
   Status = SWITCH_DEBOUNCER_mReadReg(baseaddr, SWITCH_DEBOUNCER_INTR_IPISR_OFFSET );

// Write back status to Interrupt Status Register to clear interrupt
   SWITCH_DEBOUNCER_mWriteReg(baseaddr, SWITCH_DEBOUNCER_INTR_IPISR_OFFSET , Status);

// Read button state and output it to the LEDs_Positions peripheral
   button_state = SWITCH_DEBOUNCER_mReadSlaveReg0 (baseaddr, 0);

// Increment 4-bit LEDs
   XGpio_WriteReg(XPAR_LEDS_8BIT_BASEADDR, 0x00, ++led_counter);
   interrupt_flag = 1; // Set the interrupt flag
   }


// ==============================================================================================================
// ==============================================================================================================
int main()
   {
   interrupt_flag = 0;
   print("Welcome to the Test_Switch_Debouncer program\r\n\r\n");

// Configure GPIO for 4-bit LEDs as output
//XGpio_mSetDataDirection(XPAR_LEDS_8BIT_BASEADDR, 0x00, 0x00);
//XGpio_WriteReg(XPAR_LEDS_8BIT_BASEADDR, 0x01, 0x00); //Set I/O Direction Register

// Turn off 4-Bit LEDs
   XGpio_WriteReg(XPAR_LEDS_8BIT_BASEADDR, 0x00, 0x00);//////

// Initialize Interrupts on PowerPC
   Xil_ExceptionInit();

// Register the interrupt handler of the XPS Interrupt Controller with the PowerPC's external interrupt.
//XExc_RegisterHandler(XEXC_ID_NON_CRITICAL_INT,
   Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (XExceptionHandler)XIntc_DeviceInterruptHandler, (void *)XPAR_INTC_0_DEVICE_ID);

// Register the Switch Debouncer interrupt handler in the vector table of the XPS Interrupt Controller
   XIntc_RegisterHandler(XPAR_INTC_0_BASEADDR,

   XPAR_XPS_INTC_0_SWITCH_DEBOUNCER_0_IP2INTC_IRPT_INTR, (XInterruptHandler)Switch_Debouncer_Interrupt_Handler,
      (void *)XPAR_SWITCH_DEBOUNCER_0_BASEADDR);

// Start the XPS Interrupt Controller
   XIntc_MasterEnable(XPAR_INTC_0_BASEADDR);

// Enable Switch Debouncer interrupt requests in the XPS Interrupt Controller
   XIntc_EnableIntr(XPAR_INTC_0_BASEADDR,
   XPAR_SWITCH_DEBOUNCER_0_IP2INTC_IRPT_MASK);

// Local Interrupt enable for the Switch Debouncer peripheral
   SWITCH_DEBOUNCER_mWriteReg(XPAR_SWITCH_DEBOUNCER_0_BASEADDR,
   SWITCH_DEBOUNCER_INTR_IPIER_OFFSET, 1);

// Global interrupt enable for the Switch Debouncer peripheral
   SWITCH_DEBOUNCER_mWriteReg(XPAR_SWITCH_DEBOUNCER_0_BASEADDR,
   SWITCH_DEBOUNCER_INTR_DGIER_OFFSET, INTR_GIE_MASK);

// Enable PowerPC non-critical (external) interrupts
//XExc_mEnableExceptions(XEXC_NON_CRITICAL);
//XExc_mEnableExceptions(XIL_EXCEPTION_ID_INT);/////?????????????????????????????????
   Xil_ExceptionEnable();

// Wait for the state of the Buttons to change
   while(1)
      {

// When the state of the buttons changes, print which button is pressed (one button at a time)
      if (interrupt_flag)
         {

//xil_printf("Button State is %d\n",button_state);
         switch(button_state)
            {
            case 0x01:
               print("BTN3 Pressed\r\n");
               break;
            case 0x02:
               print("BTN2 Pressed\r\n");
               break;
            case 0x04:
               print("BTN1 Pressed\r\n");
               break;
            }

// Clear the interrupt flag
         interrupt_flag = 0; 
         }
      }
   }
