/*================================================================================================*
 * Управление коммутацией выводов GD32F4xx и GPIO
 *================================================================================================*/

#ifndef CHIP_PIN_H_
#define CHIP_PIN_H_

#define CHIP_PIN_TOGGLE(pin_id) do { GPIO_TG(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id))) = BIT(CHIP_PIN_ID_q(pin_id)); } while(0)

#define CHIP_PIN_OUT(pin_id, on) do { \
    if(on) { \
        GPIO_BOP(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id))) = BIT(CHIP_PIN_ID_q(pin_id)); \
    } else { \
        GPIO_BC(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id))) = BIT(CHIP_PIN_ID_q(pin_id)); \
    } \
} while(0)

#define CHIP_PIN_IN(pin_id) ((GPIO_ISTAT(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id))) & (BIT(CHIP_PIN_ID_q(pin_id)))) != 0)

#define CHIP_PIN_CONFIG_OUT(pin_id, on) do {\
    rcu_periph_clock_enable(RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, CHIP_PIN_ID_p(pin_id))); \
    gpio_mode_set(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id)), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, BIT(CHIP_PIN_ID_q(pin_id))); \
    gpio_output_options_set(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id)), GPIO_OTYPE_PP, (CHIP_PIN_ID_f(pin_id)), (BIT(CHIP_PIN_ID_q(pin_id)))); \
    CHIP_PIN_OUT(pin_id, on); \
} while(0)

#define CHIP_PIN_CONFIG_AF(pin_id) do {\
    rcu_periph_clock_enable(RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, CHIP_PIN_ID_p(pin_id))); \
    gpio_af_set(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id)), CHIP_PIN_ID_n(pin_id), (BIT(CHIP_PIN_ID_q(pin_id)))); \
    gpio_mode_set(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id)), GPIO_MODE_AF, GPIO_PUPD_NONE, BIT(CHIP_PIN_ID_q(pin_id))); \
    gpio_output_options_set(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id)), GPIO_OTYPE_PP, (CHIP_PIN_ID_f(pin_id)), (BIT(CHIP_PIN_ID_q(pin_id)))); \
} while(0)

#define CHIP_PIN_CONFIG_AF_PU(pin_id) do {\
    rcu_periph_clock_enable(RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, CHIP_PIN_ID_p(pin_id))); \
    gpio_af_set(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id)), CHIP_PIN_ID_n(pin_id), (BIT(CHIP_PIN_ID_q(pin_id)))); \
    gpio_mode_set(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id)), GPIO_MODE_AF, GPIO_PUPD_PULLUP, BIT(CHIP_PIN_ID_q(pin_id))); \
} while(0)

#define CHIP_PIN_CONFIG_IN(pin_id) do { \
    rcu_periph_clock_enable(RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, CHIP_PIN_ID_p(pin_id))); \
    gpio_mode_set(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id)), GPIO_MODE_INPUT, GPIO_PUPD_NONE, BIT(CHIP_PIN_ID_q(pin_id))); \
} while(0)

#define CHIP_PIN_CONFIG_IN_PU(pin_id) do { \
    rcu_periph_clock_enable(RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, CHIP_PIN_ID_p(pin_id))); \
    gpio_mode_set(GPIO_BASE + (0x00000400U * CHIP_PIN_ID_p(pin_id)), GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, BIT(CHIP_PIN_ID_q(pin_id))); \
} while(0)
/*================================================================================================*
 * Адрес ножки контроллера и ее функция задается одной константой
 * CHIP_PIN_ID(p, q, n, m, f), где:
 * p - GPIO_A, GPIO_B, ..., GPIO_I
 * q - номер ножки, например, для PE2 будет - CHIP_PIN_ID(GPIO_E, 2, 0, 0, 0)
 * f - GPIO_AF_...
 * f - GPIO_OSPEED_..
 * остальные параметры пока не используются
 *
 *================================================================================================*/

/* PIN ID: 0x0pqqnmmf */
#define CHIP_PIN_ID(p, q, n, m, f)   ((((p) & 0xF) << 24) | (((q) & 0x1F) << 16) | \
                                    (((n) & 0xF) << 12) | (((m) & 0x1F) << 4) | ((f) & 7))

/* Извлечение полей ID (internal use) */
#define CHIP_PIN_ID_p(id)            (((id) >> 24) & 0xF)
#define CHIP_PIN_ID_q(id)            (((id) >> 16) & 0x1F)
#define CHIP_PIN_ID_n(id)            (((id) >> 12) & 0xF)
#define CHIP_PIN_ID_m(id)            (((id) >> 4) & 0x1F)
#define CHIP_PIN_ID_f(id)            ((id) & 7)

/*================================================================================================*/


#endif /* CHIP_PIN_H_ */
