/* 
* classPio.h
*
* Created: 01/02/2020 20:24:27
* Author: Ledo
*/


#ifndef __CLASSPIO_H__
#define __CLASSPIO_H__

#include "sam.h"
#include <sam4e16c.h>

//#define NULL 0
#define PMC_WPKEY 0x504D43

/*  Default pin configuration (no attribute). */
#define PIO_DEFAULT             (0u << 0)
/*  The internal pin pull-up is active. */
#define PIO_PULLUP              (1u << 0)
/*  The internal glitch filter is active. */
#define PIO_DEGLITCH            (1u << 1)
/*  The pin is open-drain. */
#define PIO_OPENDRAIN           (1u << 2)

/*  The internal debouncing filter is active. */
#define PIO_DEBOUNCE            (1u << 3)

/*  Enable additional interrupt modes. */
#define PIO_IT_AIME             (1u << 4)

/*  Interrupt High Level/Rising Edge detection is active. */
#define PIO_IT_RE_OR_HL         (1u << 5)
/*  Interrupt Edge detection is active. */
#define PIO_IT_EDGE             (1u << 6)

/*  Low level interrupt is active */
#define PIO_IT_LOW_LEVEL        (0               | 0 | PIO_IT_AIME)
/*  High level interrupt is active */
#define PIO_IT_HIGH_LEVEL       (PIO_IT_RE_OR_HL | 0 | PIO_IT_AIME)
/*  Falling edge interrupt is active */
#define PIO_IT_FALL_EDGE        (0               | PIO_IT_EDGE | PIO_IT_AIME)
/*  Rising edge interrupt is active */
#define PIO_IT_RISE_EDGE        (PIO_IT_RE_OR_HL | PIO_IT_EDGE | PIO_IT_AIME)

/* Compute PIO register length */
#define PIO_DELTA   ((uint32_t) PIOB - (uint32_t) PIOA)

/* GPIO Support */
#define PIO_TYPE_Pos                  27
/* PIO Type Mask */
#define PIO_TYPE_Msk                  (0xFu << PIO_TYPE_Pos)
/* The pin is not a function pin. */
#define PIO_TYPE_NOT_A_PIN            (0x0u << PIO_TYPE_Pos)
/* The pin is controlled by the peripheral A. */
#define PIO_TYPE_PIO_PERIPH_A         (0x1u << PIO_TYPE_Pos)
/* The pin is controlled by the peripheral B. */
#define PIO_TYPE_PIO_PERIPH_B         (0x2u << PIO_TYPE_Pos)
/* The pin is controlled by the peripheral C. */
#define PIO_TYPE_PIO_PERIPH_C         (0x3u << PIO_TYPE_Pos)
/* The pin is controlled by the peripheral D. */
#define PIO_TYPE_PIO_PERIPH_D         (0x4u << PIO_TYPE_Pos)
/* The pin is an input. */
#define PIO_TYPE_PIO_INPUT            (0x5u << PIO_TYPE_Pos)
/* The pin is an output and has a default level of 0. */
#define PIO_TYPE_PIO_OUTPUT_0         (0x6u << PIO_TYPE_Pos)
/* The pin is an output and has a default level of 1. */
#define PIO_TYPE_PIO_OUTPUT_1         (0x7u << PIO_TYPE_Pos)

#define PIN_0_bp        0
#define PIN_1_bp        1
#define PIN_2_bp        2
#define PIN_3_bp        3
#define PIN_4_bp        4
#define PIN_5_bp        5
#define PIN_6_bp        6
#define PIN_7_bp        7
#define PIN_8_bp        8
#define PIN_9_bp        9
#define PIN_10_bp       10
#define PIN_11_bp       11
#define PIN_12_bp       12
#define PIN_13_bp       13
#define PIN_14_bp       14
#define PIN_15_bp       15
#define PIN_16_bp       16
#define PIN_17_bp       17
#define PIN_18_bp       18
#define PIN_19_bp       19
#define PIN_20_bp       20
#define PIN_21_bp       21
#define PIN_22_bp       22
#define PIN_23_bp       23
#define PIN_24_bp       24
#define PIN_25_bp       25
#define PIN_26_bp       26
#define PIN_27_bp       27
#define PIN_28_bp       28
#define PIN_29_bp       29
#define PIN_30_bp       30
#define PIN_31_bp       31


 typedef enum pio_type {
	PIO_NOT_A_PIN   = PIO_TYPE_NOT_A_PIN,
	PIO_PERIPH_A    = PIO_TYPE_PIO_PERIPH_A,
	PIO_PERIPH_B    = PIO_TYPE_PIO_PERIPH_B,
	PIO_PERIPH_C    = PIO_TYPE_PIO_PERIPH_C,
	PIO_PERIPH_D    = PIO_TYPE_PIO_PERIPH_D,
	PIO_INPUT       = PIO_TYPE_PIO_INPUT,
	PIO_OUTPUT_0    = PIO_TYPE_PIO_OUTPUT_0,
	PIO_OUTPUT_1    = PIO_TYPE_PIO_OUTPUT_1
}pio_type_t;


/**
 * Maximum number of interrupt sources that can be defined. This
 * constant can be increased, but the current value is the smallest possible one
 * that will be compatible with all existing projects.
 */
#define MAX_INTERRUPT_SOURCES       7

/**
 * Describes a PIO interrupt source, including the PIO instance triggering the
 * interrupt and the associated interrupt handler.
 */
typedef struct s_interrupt_source {
	uint32_t id;
	uint32_t mask;
	uint32_t attr;

	/* Interrupt handler. */
	void (*handler) (const uint32_t, const uint32_t);
}s_interrupt_source;


class classPio
{
//variables
public:
    /* List of interrupt sources. */
    s_interrupt_source gs_interrupt_sources[MAX_INTERRUPT_SOURCES];

    /* Number of currently defined interrupt sources. */
    uint32_t gs_ul_nb_sources = 0;
    /* PIO Capture handler */
    void (*pio_capture_handler)(Pio *) = 0;
    uint32_t pio_capture_enable_flag;

protected:
private:

//functions
public:
	classPio();
	~classPio();
	void PeripheralClock_enable(Pio *p_pio);
	void pin_set_input(Pio *p_pio, const uint32_t ul_mask,
	const uint32_t ul_attribute);
	void pin_set_output(Pio *p_pio, const uint32_t ul_mask,
	const uint32_t ul_default_level,
	const uint32_t ul_multidrive_enable,
	const uint32_t ul_pull_up_enable);
	void pin_set_debounce_filter(Pio *p_pio, const uint32_t ul_mask,
	const uint32_t ul_cut_off);
	void pin_set_peripheral(Pio *p_pio, const pio_type_t ul_type,
	const uint32_t ul_mask);
	void set_pin_high(Pio *p_pio, uint32_t ul_pin);
    void set_pin_low(Pio *p_pio, uint32_t ul_pin);
	void toggle_pin(Pio *p_pio, uint32_t ul_pin);
	bool get_pin_level(Pio *p_pio, uint32_t ul_pin);
	void configure_interrupt(Pio *p_pio, const uint32_t ul_mask,
	const uint32_t ul_attr);
	void enable_pin_interrupt(Pio *p_pio, uint32_t ul_pin);
	void disable_pin_interrupt(Pio *p_pio, uint32_t ul_pin);
	void handler_process(Pio *p_pio, uint32_t ul_id);
	uint32_t handler_set_pin(Pio *p_pio, uint32_t ul_pin, uint32_t ul_flag,
	void (*p_handler) (uint32_t, uint32_t));
    void NVIC_handler_register(Pio *p_pio, IRQn_Type ul_irqn, uint32_t ul_priority);	
uint32_t handler_set(Pio *p_pio, uint32_t ul_id, uint32_t ul_mask,
	uint32_t ul_attr, void (*p_handler) (uint32_t, uint32_t));
	uint32_t handler_set_pin(uint32_t ul_pin, uint32_t ul_flag,
	void (*p_handler) (uint32_t, uint32_t));
	void capture_handler_set(void (*p_handler)(Pio *));
	void PIOA_Handler(void);
	void PIOB_Handler(void);
	void PIOD_Handler(void);


protected:
private:
	classPio( const classPio &c );
	classPio& operator=( const classPio &c );

}; //classPio

#endif //__CLASSPIO_H__
