#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"

//PROTÓTIPO DE FUNÇÕES===================================================
void app_main(void);
void Task_bitwise(void *pvParameter);


//DEFINIÇÕES E CONSTATNTES
#define delay(value) vTaskDelay(value/portTICK_PERIOD_MS)
#define LED_0 GPIO_NUM_27
#define LED_1 GPIO_NUM_26
#define LED_2 GPIO_NUM_25
#define LED_3 GPIO_NUM_33
#define LED_4 GPIO_NUM_22
#define LED_5 GPIO_NUM_4
#define LED_6 GPIO_NUM_2
#define LED_7 GPIO_NUM_15
#define BOTAOVERDE_DIREITA GPIO_NUM_13
#define BOTAOVERMELHO_ESQUERDA GPIO_NUM_12

//Máscara para Saídas
#define GPIO_OUTPUT_PIN_SEL ((1ULL<<LED_0) | (1ULL<<LED_1) | (1ULL<<LED_2) | (1ULL<<LED_3) | (1ULL<<LED_4) | (1ULL<<LED_5) | (1ULL<<LED_6) | (1ULL<<LED_7))

//Máscara para entradas
#define GPIO_INPUT_PIN_SEL ((1ULL<<BOTAOVERDE_DIREITA) | (1ULL<<BOTAOVERMELHO_ESQUERDA))

//VARIÁVEIS
char ledsDirection=0;
uint16_t ledsOn=1;

//INTERRUPÇÃO_BOTAOVERDE
static void IRAM_ATTR gpio13_isr_handler(void* arg){
  uint8_t *v = (uint8_t*) arg;  		
	*v=1;			
}

//INTERRUPÇÃO_BOTAOVERMELHO
static void IRAM_ATTR gpio12_isr_handler(void* arg){
  uint8_t *v = (uint8_t*) arg;  		
	*v=0;			
}

//TASK
void Task_bitwise(void *pvParameter){

	//CONFIGURANDO SAÍDAS
	gpio_config_t output_config = {};//variável descritora
	output_config.intr_type = GPIO_INTR_DISABLE;//desabilita interrupção externa
	output_config.mode = GPIO_MODE_OUTPUT;//configura GPIO como saídas
	output_config.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;//carrega GPIOs configuradas
	output_config.pull_up_en = 0;//desativa pull_up
	output_config.pull_down_en = 0;//desativa pull_down 
	gpio_config(&output_config);//configura GPIO conforme descritor

	//CONFIGURANDO ENTRADAS
	gpio_config_t input_config = {};//variável descritora
	input_config.intr_type = GPIO_INTR_LOW_LEVEL;//habilita interrupção externa
	input_config.mode = GPIO_MODE_INPUT;//configura GPIO como entradas
	input_config.pin_bit_mask = GPIO_INPUT_PIN_SEL;
	input_config.pull_up_en = 1;//ativa pull_up
	input_config.pull_down_en = 0;//desativa pull_down
	gpio_config(&input_config);//configura GPIO conforme descritor


	gpio_set_level(LED_0, 0);
	gpio_set_level(LED_1, 0);
	gpio_set_level(LED_2, 0);
	gpio_set_level(LED_3, 0);
	gpio_set_level(LED_4, 0);
	gpio_set_level(LED_5, 0);
	gpio_set_level(LED_6, 0);
	gpio_set_level(LED_7, 0);
	delay(50);

	while(1){
		printf("============================================================\n");
		printf("VALOR: %d\n", ledsOn);

		switch(ledsOn){
			case 128:
				gpio_set_level(LED_0, 0);
				gpio_set_level(LED_1, 0);
				gpio_set_level(LED_2, 0);
				gpio_set_level(LED_3, 0);
				gpio_set_level(LED_4, 0);
				gpio_set_level(LED_5, 0);
				gpio_set_level(LED_6, 0);
				gpio_set_level(LED_7, 1);
				break;
			case 64:
				gpio_set_level(LED_0, 0);
				gpio_set_level(LED_1, 0);
				gpio_set_level(LED_2, 0);
				gpio_set_level(LED_3, 0);
				gpio_set_level(LED_4, 0);
				gpio_set_level(LED_5, 0);
				gpio_set_level(LED_6, 1);
				gpio_set_level(LED_7, 0);
				break;
			case 32:
				gpio_set_level(LED_0, 0);
				gpio_set_level(LED_1, 0);
				gpio_set_level(LED_2, 0);
				gpio_set_level(LED_3, 0);
				gpio_set_level(LED_4, 0);
				gpio_set_level(LED_5, 1);
				gpio_set_level(LED_6, 0);
				gpio_set_level(LED_7, 0);
				break;
			case 16:
				gpio_set_level(LED_0, 0);
				gpio_set_level(LED_1, 0);
				gpio_set_level(LED_2, 0);
				gpio_set_level(LED_3, 0);
				gpio_set_level(LED_4, 1);
				gpio_set_level(LED_5, 0);
				gpio_set_level(LED_6, 0);
				gpio_set_level(LED_7, 0);
				break;
			case 8:
				gpio_set_level(LED_0, 0);
				gpio_set_level(LED_1, 0);
				gpio_set_level(LED_2, 0);
				gpio_set_level(LED_3, 1);
				gpio_set_level(LED_4, 0);
				gpio_set_level(LED_5, 0);
				gpio_set_level(LED_6, 0);
				gpio_set_level(LED_7, 0);
				break;
			case 4:
				gpio_set_level(LED_0, 0);
				gpio_set_level(LED_1, 0);
				gpio_set_level(LED_2, 1);
				gpio_set_level(LED_3, 0);
				gpio_set_level(LED_4, 0);
				gpio_set_level(LED_5, 0);
				gpio_set_level(LED_6, 0);
				gpio_set_level(LED_7, 0);
				break;
			case 2:
				gpio_set_level(LED_0, 0);
				gpio_set_level(LED_1, 1);
				gpio_set_level(LED_2, 0);
				gpio_set_level(LED_3, 0);
				gpio_set_level(LED_4, 0);
				gpio_set_level(LED_5, 0);
				gpio_set_level(LED_6, 0);
				gpio_set_level(LED_7, 0);
				break;
			case 1:
				gpio_set_level(LED_0, 1);
				gpio_set_level(LED_1, 0);
				gpio_set_level(LED_2, 0);
				gpio_set_level(LED_3, 0);
				gpio_set_level(LED_4, 0);
				gpio_set_level(LED_5, 0);
				gpio_set_level(LED_6, 0);
				gpio_set_level(LED_7, 0);
				break;
			case 0:
				gpio_set_level(LED_0, 0);
				gpio_set_level(LED_1, 0);
				gpio_set_level(LED_2, 0);
				gpio_set_level(LED_3, 0);
				gpio_set_level(LED_4, 0);
				gpio_set_level(LED_5, 0);
				gpio_set_level(LED_6, 0);
				gpio_set_level(LED_7, 0);
				break;				
			default:
				gpio_set_level(LED_0, 0);
				gpio_set_level(LED_1, 0);
				gpio_set_level(LED_2, 0);
				gpio_set_level(LED_3, 0);
				gpio_set_level(LED_4, 0);
				gpio_set_level(LED_5, 0);
				gpio_set_level(LED_6, 0);
				gpio_set_level(LED_7, 0);
				break;
		}
		delay(1000);
		if(ledsDirection & 1<<0){
			ledsOn = ledsOn>>1;//multiplica por 2			
		}
		else{
			ledsOn = ledsOn<<1;//divide por 2
		}
		if(ledsOn>128){
			ledsOn=1;
		}
		if(ledsOn<1){
			ledsOn=128;
		}						
		delay(20);		
	}
}

void app_main(void){
		//install gpio isr service
		gpio_install_isr_service(ESP_INTR_FLAG_LOWMED);
    //hook isr handler for specific gpio pin
  	gpio_isr_handler_add(BOTAOVERDE_DIREITA, gpio13_isr_handler, (void*) &ledsDirection);
		//hook isr handler for specific gpio pin
  	gpio_isr_handler_add(BOTAOVERMELHO_ESQUERDA, gpio12_isr_handler, (void*) &ledsDirection);

    xTaskCreate(Task_bitwise, " BITWISE ", 2048, NULL, 2, NULL);		
		}