/*$$$LICENCE_NORDIC_STANDARD<2016>$$$*/

#include <stdlib.h>
#include <string.h>

#include "nrf.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "app_debug_pin.h"

#if CONFIG_DEBUG_PIN_ENABLED

#define PIO_INIT(pin)               \
do {                                \
    if (IS_IO_VALID((pin)))         \
    {                               \
        nrf_gpio_cfg_output((pin)); \
        nrf_gpio_pin_clear((pin));  \
    }                               \
} while (0)

void debug_pin_init(void)
{
    PIO_INIT(CONFIG_IO_DBG_MARK);
    PIO_INIT(CONFIG_IO_DBG_CLOCK);
    PIO_INIT(CONFIG_IO_DBG_DATA);

    PIO_INIT(CONFIG_IO_DBG_AUDIO_CAPTURE);
    PIO_INIT(CONFIG_IO_DBG_AUDIO_PROCESS);

    PIO_INIT(CONFIG_IO_DBG_SLEEP);

    PIO_INIT(CONFIG_IO_DBG_IR_TX_PWM_INT);
    PIO_INIT(CONFIG_IO_DBG_IR_TX_SACK);
    PIO_INIT(CONFIG_IO_DBG_IR_TX_EACK);
}

void debug_pin_set(const unsigned int pio)
{
    if (IS_IO_VALID(pio))
    {
        nrf_gpio_pin_set(pio);
    }
}

void debug_pin_clear(const unsigned int pio)
{
    if (IS_IO_VALID(pio))
    {
        nrf_gpio_pin_clear(pio);
    }
}

void debug_pin_pulse(const unsigned int pio)
{
    if (IS_IO_VALID(pio))
    {
        nrf_gpio_pin_set(pio);
        nrf_delay_us(1);
        nrf_gpio_pin_clear(pio);
    }
}

void debug_pin_flag(const unsigned int pio, bool flag)
{
    if (IS_IO_VALID(pio))
    {
        if (flag)
        {
            nrf_gpio_pin_set(pio);
        }
        else
        {
            nrf_gpio_pin_clear(pio);
        }
    }
}

void debug_pin_toggle(const unsigned int pio)
{
    if (IS_IO_VALID(pio))
    {
        nrf_gpio_pin_toggle(pio);
    }
}

void debug_pin_send(const uint32_t word, const uint8_t bits)
{
#if IS_IO_VALID(CONFIG_IO_DBG_MARK) && \
    IS_IO_VALID(CONFIG_IO_DBG_CLOCK) && \
    IS_IO_VALID(CONFIG_IO_DBG_DATA)

    nrf_gpio_pin_set(CONFIG_IO_DBG_MARK);
    for (unsigned int bit = bits; bit > 0; )
    {
        if ((word & (1<<(--bit))) != 0)
        {
            nrf_gpio_pin_set(CONFIG_IO_DBG_DATA);
        }

        nrf_gpio_pin_set(CONFIG_IO_DBG_CLOCK);
        nrf_gpio_pin_clear(CONFIG_IO_DBG_CLOCK);
        nrf_gpio_pin_clear(CONFIG_IO_DBG_DATA);
    }
    nrf_gpio_pin_clear(CONFIG_IO_DBG_MARK);
#endif
}

void debug_pin_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name)
{
    debug_pin_pulse(CONFIG_IO_DBG_MARK);
    debug_pin_send(error_code, 32);
    debug_pin_send(line_num, 32);

    if (p_file_name)
    {
        while (*p_file_name)
        {
            debug_pin_send(*(p_file_name++), 8);
        }
    }
}
#endif /* CONFIG_DEBUG_PIO_ENABLED */
