/*
io4ledbtn.c
20200705 rwbl
*/
#include "io4ledbtn.h"

#include <stdio.h>

#include "../bindings/bricklet_io4_v2.h"
#include "../bindings/errors.h"

TF_IO4V2 io;
UID_IO4V2 = "G4d";
CH1_CALLBACK_PERIOD = 100;		// in ms

bool io_ret_value[4];			// used in the loop to trigger the callback
bool led_state = false;			// init led off
bool button_pressed = false;	// init with button released

// Callback function for input value callback
// Sets the state of the button_pressed and led
void io4ledbtn_cb_input_value(struct TF_IO4V2 *device, uint8_t channel, bool changed, bool value, void *user_data) {
    (void)user_data; // avoid unused parameter warning
    // tf_hal_log_info("Channel: ch=%u, c=%s, v=%s", channel, changed ? "true" : "false", value ? "true" : "false");

   	// If value = true, the button is pressed or released
	if (value == true) {
		button_pressed = !button_pressed;
		tf_hal_log_info("Channel: ch=%u, c=%s, v=%s", channel, changed ? "true" : "false", value ? "true" : "false");
		if (button_pressed == true){
			led_state = !led_state;
			tf_hal_log_info("Push-button pressed channel 1. Led state %s", led_state ? "true" : "false");
			// <TODO> This function is not triggered - need to explore why
			// tf_io4_v2_set_selected_value(&io, 0, led_state);
			// Workaround handled in the function io4ledbtn_loop()
		}
	}
}

void io4ledbtn_check(int rc, char *msg) {
    if (rc >= 0)
        return;
    tf_hal_log_error("Failed to %s: %d", msg, rc);
}

void io4ledbtn_setup(TF_HalContext *hal) {
	// Create the io4 device object
	io4ledbtn_check(tf_io4_v2_create(&io, UID_IO4V2, hal), "Create io4");

	// Set status led
	tf_io4_v2_set_status_led_config(&io, TF_IO4_V2_STATUS_LED_CONFIG_ON);

	// Configure channel 0 as output low
	tf_io4_v2_set_configuration(&io, 0, 'o', false);
    tf_hal_log_info("Channel 0 set as output");

	// Configure channel 1 as input pull-up
	tf_io4_v2_set_configuration(&io, 1, 'i', true);
    tf_hal_log_info("Channel 1 set as input pull-up");
	// Configure edge count = leave default = just to test the functions
	tf_io4_v2_set_edge_count_configuration(&io, 1, 0, 0);
	uint8_t et;
	uint8_t deb;
	tf_io4_v2_get_edge_count_configuration(&io,1,&et,&deb);
    tf_hal_log_info("Channel 1 edge count: %u, %u", et,deb);

	// Register input value callback to function io4ledbtn_cb_input_value
    tf_io4_v2_register_input_value_callback(&io,
                             io4ledbtn_cb_input_value,
                             NULL);
    tf_hal_log_info("Channel 1 callback registered");

    // Set period for input value (channel 1) callback
    tf_io4_v2_set_input_value_callback_configuration(&io, 1, CH1_CALLBACK_PERIOD, true);	// false
    tf_hal_log_info("Channel 1 callback input value set");
}

void io4ledbtn_loop(TF_HalContext *hal) {
	// Get the logic levels currently measured on the channels.
	// The ret_value is not used as handled by the callback.
	// If this function (or any other could be used as well) is not executed, the button callback is not triggered.
	tf_io4_v2_callback_tick(&io, 1000);

	// Handle button pressed to set the led state on or off.
	// The values button_pressed and led_state are set in the button callback io4ledbtn_cb_input_value()
	if (button_pressed == true){
		int rc = tf_io4_v2_set_selected_value(&io, 0, led_state);
		if(rc != TF_E_OK)
			tf_hal_log_error("rc %d", rc);
	}
}

