#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_check.h"
#include "pca9554.h"

#define PCA9554_I2C_ADDR         (0x38)
#define PCA9554_I2C_PORT         CONFIG_PCA9554_I2C_NUM
#define PCA9554_SDA_GPIO         CONFIG_PCA9554_I2C_SDA  
#define PCA9554_SCL_GPIO         CONFIG_PCA9554_I2C_SCL  

static const char* TAG = "PCA9554";

i2c_master_bus_handle_t i2c_bus_init(uint8_t sda_io, uint8_t scl_io);

void app_main(void)
{                  
    esp_err_t err;
    i2c_master_bus_handle_t bus_handle;
    i2c_master_dev_handle_t pca9554_handle;
    
    bus_handle     = i2c_bus_init(PCA9554_SDA_GPIO, PCA9554_SCL_GPIO);
    pca9554_handle = pca9554_device_create(bus_handle, PCA9554_I2C_ADDR, 100000);
    
    err = i2c_master_probe(bus_handle, PCA9554_I2C_ADDR, 200);  

    if (err == ESP_OK) {
      ESP_LOGI(TAG,"Found PCA9554");
    } else {
      pca9554_device_remove(pca9554_handle);
      ESP_LOGI(TAG,"Not found PCA9554");
    }
  
    pca9554_config_io(pca9554_handle, 0xF0);  /* P0-P3 is output, P4-P7 is input */
  
  while(1) {
      pca9554_pin_set_logic(pca9554_handle, PCA9554_PORT_P0, PCA9554_LOGIC_LOW);
      ESP_LOGI(TAG, "RELAY1 ON");
      vTaskDelay(1000 / portTICK_PERIOD_MS);
      
      pca9554_pin_set_logic(pca9554_handle, PCA9554_PORT_P0, PCA9554_LOGIC_HIGH);
      ESP_LOGI(TAG, "RELAY1 OFF");
      vTaskDelay(1000/portTICK_PERIOD_MS);
      
      pca9554_pin_set_logic(pca9554_handle, PCA9554_PORT_P1, PCA9554_LOGIC_LOW);
      ESP_LOGI(TAG, "RELAY2 ON");
      vTaskDelay(1000 / portTICK_PERIOD_MS);
      
      pca9554_pin_set_logic(pca9554_handle, PCA9554_PORT_P1, PCA9554_LOGIC_HIGH);
      ESP_LOGI(TAG, "RELAY2 OFF");
      vTaskDelay(1000/portTICK_PERIOD_MS);
      
      pca9554_pin_set_logic(pca9554_handle, PCA9554_PORT_P2, PCA9554_LOGIC_LOW);
      ESP_LOGI(TAG, "RELAY3 ON");
      vTaskDelay(1000 / portTICK_PERIOD_MS);
      
      pca9554_pin_set_logic(pca9554_handle, PCA9554_PORT_P2, PCA9554_LOGIC_HIGH);
      ESP_LOGI(TAG, "RELAY3 OFF");
      vTaskDelay(1000/portTICK_PERIOD_MS);
      
      pca9554_pin_set_logic(pca9554_handle, PCA9554_PORT_P3, PCA9554_LOGIC_LOW);
      ESP_LOGI(TAG, "RELAY4 ON");
      vTaskDelay(1000 / portTICK_PERIOD_MS);
      
      pca9554_pin_set_logic(pca9554_handle, PCA9554_PORT_P3, PCA9554_LOGIC_HIGH);
      ESP_LOGI(TAG, "RELAY4 OFF");
      vTaskDelay(1000/portTICK_PERIOD_MS);
  }
}

i2c_master_bus_handle_t i2c_bus_init (uint8_t sda_io, uint8_t scl_io)
{
    i2c_master_bus_handle_t bus_handle;
    
    i2c_master_bus_config_t  bus_cfg = { 
        .i2c_port   = PCA9554_I2C_PORT,
        .scl_io_num = scl_io,
        .sda_io_num = sda_io,
        .clk_source = I2C_CLK_SRC_DEFAULT,
        .glitch_ignore_cnt = 7,
        .flags.enable_internal_pullup = true,                                      
    };

    ESP_ERROR_CHECK(i2c_new_master_bus(&bus_cfg, &bus_handle));
    ESP_LOGI(TAG, "I2C master bus created");

    return (bus_handle);        
}
