/*
 * MDR32F9Qx gpio.h
 * cp1251 ru
 *  Created on: 21 ���. 2016 �.
 *      Author: alexrayne
  ------------------------------------------------------------------------
    Copyright (c) alexrayne

   All rights reserved.
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
   - Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
   - Neither the name of ARM nor the names of its contributors may be used
     to endorse or promote products derived from this software without
     specific prior written permission.
   *
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE. *
  ------------------------------------------------------------------------
 *      heplers fo port pins manipulation of MDR32F9Qx
 */

#ifndef _GPIO_HAL_H
#define _GPIO_HAL_H

#include <compiler-port.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

#include "mcu_gpio.h"
#include "mcu_rcc.h"


// конфигурация пинов gpio
void gpio_conf_pin(GPIO_TypeDef* port, unsigned pin);
void gpio_conf_pout(GPIO_TypeDef* port, unsigned pin);
void gpio_conf_pout_oc(GPIO_TypeDef* port, unsigned pin);
void gpio_conf_out(const PIN_INIT* x);
void gpio_conf_func(const GPIOFUNC_INIT* x);
void gpio_conf_in(const PIN_INIT* x);



// функции GPIO_XXX -  инлайнятся, и предназначены для использования с константами
//          которые могут оптимизироваться во время компиляции

// функции gpio_xxx -  предназначены для использования с переменными непредсказуемыми
//          которые оптимизироваться во время компиляции не могут

// назначает пинам функцию
void gpio_set_func(GPIO_TypeDef* port, unsigned pin, PORT_FUNC_TypeDef f);
// \return - функция первого пина в pins
//         - 0= PORT_FUNC_PORT если pins пусто
PORT_FUNC_TypeDef gpio_func(GPIO_TypeDef* port, unsigned pins);

INLINE
uint32_t gpio_pins(GPIO_TypeDef* port, unsigned pin){
  return port->RXTX & pin;
}

INLINE
uint32_t gpio_pouts(GPIO_TypeDef* port, unsigned pin){
  return port->RXTX & pin;
}

#define GPIO_PINS(port, pin)    gpio_pins(port, pin)
#define GPIO_POUTS(port, pin)   gpio_pouts(port, pin)


uint32_t gpio_on(GPIO_TypeDef* port, unsigned pin);
uint32_t gpio_set(GPIO_TypeDef* port, unsigned pin, unsigned mask);
uint32_t gpio_off(GPIO_TypeDef* port, unsigned pin);
uint32_t gpio_twist(GPIO_TypeDef* port, unsigned pin);

INLINE
uint32_t GPIO_ON(GPIO_TypeDef* port, unsigned pin){
  uint32_t res = port->RXTX | pin;
  port->RXTX = FIX_JTAG_PINS(port, res);
  return res;
}

INLINE
uint32_t GPIO_SET(GPIO_TypeDef* port, unsigned pin, unsigned mask){
  uint32_t res = (port->RXTX & ~mask) | (pin & mask);
  port->RXTX = FIX_JTAG_PINS(port, res);
  return res;
}


INLINE
uint32_t GPIO_OFF(GPIO_TypeDef* port, unsigned pin){
  uint32_t res = port->RXTX & ~pin;
  port->RXTX = FIX_JTAG_PINS(port, res);
  return res;
}

INLINE
uint32_t GPIO_TWIST(GPIO_TypeDef* port, unsigned pin){
  uint32_t res = port->RXTX ^ pin;
  port->RXTX = FIX_JTAG_PINS(port, res);
  return res;
}



uint32_t gpio_styled_pins(GPIO_TypeDef* port, unsigned pin, unsigned style);
uint32_t gpio_styled_pouts(GPIO_TypeDef* port, unsigned pin, unsigned style);

INLINE
uint32_t GPIO_STYLED_PINS(GPIO_TypeDef* port, unsigned pin, unsigned style){
    uint32_t res = port->RXTX;
    if ((style & psINV) != 0)
        res = ~res;
    return res & pin;
}
#define GPIO_STYLED_POUTS(port, pin, style)   GPIO_STYLED_PINS(port, pin, style)

INLINE
uint32_t GPIO_STYLED_SET(GPIO_TypeDef* port, unsigned pin, unsigned mask, unsigned style){
  if ((style & psINV)!= 0){
      pin = (~pin);
  }
  uint32_t res = (port->RXTX & ~mask) | (pin & mask);
  port->RXTX = FIX_JTAG_PINS(port, res);
  return res;
}



#ifdef __cplusplus
}
#endif

#ifdef __cplusplus
// назначает функцию GPIO IN для x
void gpio_conf_pin(const GPIOFUNC_INIT* x);

// назначает пинам функцию
void gpio_set_func(const GPIOFUNC_INIT* x);

// \return - функция первого пина в pins
//         - 0= PORT_FUNC_PORT если pins пусто
PORT_FUNC_TypeDef gpio_func(const GPIOFUNC_INIT* x);

uint32_t gpio_on(const PIN_INIT* x);
uint32_t gpio_off(const PIN_INIT* x);
uint32_t gpio_pins(const PIN_INIT* x);
void gpio_conf_in(const PIN_INIT* x, unsigned pins);
#endif

#endif
