/** 
**************************************************************************
* @file bit_access.h
* @brief Заголочный файл для дефайнов битового доступа.
**************************************************************************
* @defgroup BIT_ACCESS_DEFINES    Bit access defines
* @ingroup  MYLIBS_TOOLS 
* @brief     Макросы и typedef'ы для работы с битами в unsigned типах.
* @details
В этом файле определены макросы для получения значения конкретного бита^
- @ref uint8_bit
- @ref uint16_bit
- @ref uint32_bit
- @ref uint64_bit

Особенности использования:
- Индекс бита должен быть **константой на этапе компиляции**.
  Пример верного использования:
    @code
      uint8_t val = 0x05;
      uint8_t b2 = uint8_bit(val, 2); // Получить бит 2
      uint8_bit(val, 6) = 1; // Записать бит 6
    @endcode
- Нельзя использовать переменные в качестве индекса:
    @code
      uint8_t i = 2;
      uint8_bit(val, i); // Не сработает!
    @endcode
- Макросы возвращают 0 или 1.
- Доступ реализован через приведение к `union` с битовыми полями, поэтому это
  безопасный способ работы с отдельными битами без ручного сдвига и маскирования.
* @{
*************************************************************************/
#ifndef __BIT_ACCESS_H_
#define __BIT_ACCESS_H_
#include "mylibs_defs.h"

  
typedef union
{
  uint8_t all;
  struct
  {
    unsigned bit0:1;
    unsigned bit1:1;
    unsigned bit2:1;
    unsigned bit3:1;
    unsigned bit4:1;
    unsigned bit5:1;
    unsigned bit6:1;
    unsigned bit7:1;
  }bit;
}uint8_BitTypeDef;

typedef union
{
  uint16_t all;
  struct
  {
    unsigned bit0:1;
    unsigned bit1:1;
    unsigned bit2:1;
    unsigned bit3:1;
    unsigned bit4:1;
    unsigned bit5:1;
    unsigned bit6:1;
    unsigned bit7:1;
    unsigned bit8:1;
    unsigned bit9:1;
    unsigned bit10:1;
    unsigned bit11:1;
    unsigned bit12:1;
    unsigned bit13:1;
    unsigned bit14:1;
    unsigned bit15:1;
  }bit;
}uint16_BitTypeDef;


typedef union
{
  uint32_t all;
  struct
  {
    unsigned bit0:1;     unsigned bit1:1;     unsigned bit2:1;     unsigned bit3:1;
    unsigned bit4:1;     unsigned bit5:1;     unsigned bit6:1;     unsigned bit7:1;
    unsigned bit8:1;     unsigned bit9:1;     unsigned bit10:1;    unsigned bit11:1;
    unsigned bit12:1;    unsigned bit13:1;    unsigned bit14:1;    unsigned bit15:1;
    unsigned bit16:1;    unsigned bit17:1;    unsigned bit18:1;    unsigned bit19:1;
    unsigned bit20:1;    unsigned bit21:1;    unsigned bit22:1;    unsigned bit23:1;
    unsigned bit24:1;    unsigned bit25:1;    unsigned bit26:1;    unsigned bit27:1;
    unsigned bit28:1;    unsigned bit29:1;    unsigned bit30:1;    unsigned bit31:1;
  }bit;
}uint32_BitTypeDef;


typedef union
{
  uint64_t all;
  struct
  {
    unsigned bit0:1;     unsigned bit1:1;     unsigned bit2:1;     unsigned bit3:1;
    unsigned bit4:1;     unsigned bit5:1;     unsigned bit6:1;     unsigned bit7:1;
    unsigned bit8:1;     unsigned bit9:1;     unsigned bit10:1;    unsigned bit11:1;
    unsigned bit12:1;    unsigned bit13:1;    unsigned bit14:1;    unsigned bit15:1;
    unsigned bit16:1;    unsigned bit17:1;    unsigned bit18:1;    unsigned bit19:1;
    unsigned bit20:1;    unsigned bit21:1;    unsigned bit22:1;    unsigned bit23:1;
    unsigned bit24:1;    unsigned bit25:1;    unsigned bit26:1;    unsigned bit27:1;
    unsigned bit28:1;    unsigned bit29:1;    unsigned bit30:1;    unsigned bit31:1;
    unsigned bit32:1;    unsigned bit33:1;    unsigned bit34:1;    unsigned bit35:1;
    unsigned bit36:1;    unsigned bit37:1;    unsigned bit38:1;    unsigned bit39:1;
    unsigned bit40:1;    unsigned bit41:1;    unsigned bit42:1;    unsigned bit43:1;
    unsigned bit44:1;    unsigned bit45:1;    unsigned bit46:1;    unsigned bit47:1;
    unsigned bit48:1;    unsigned bit49:1;    unsigned bit50:1;    unsigned bit51:1;
    unsigned bit52:1;    unsigned bit53:1;    unsigned bit54:1;    unsigned bit55:1;
    unsigned bit56:1;    unsigned bit57:1;    unsigned bit58:1;    unsigned bit59:1;
    unsigned bit60:1;    unsigned bit61:1;    unsigned bit62:1;    unsigned bit63:1;
  }bit;
}uint64_BitTypeDef;


/**
  * @brief Получить n-й бит из любого числа
  * @param _uint8_ Переменная типа uint8_t
  * @param _bit_   Константный номер бита (0..7)
  * @return Значение выбранного бита (0 или 1)
  * @note    Индекс бита вычисляется программно, а не на этапе компиляции
  */
#define read_bit(_val_, _bit_)       ((_val_) & ((uint64_t)1 << _bit_))

/**
  * @brief Получить n-й бит из uint8_t
  * @param _uint8_ Переменная типа uint8_t
  * @param _bit_   Константный номер бита (0..7)
  * @return Значение выбранного бита (0 или 1)
  * @note    Индекс бита должен быть известен на этапе компиляции!
  */
#define uint8_bit(_uint8_, _bit_)       (*(uint8_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_
/**
  * @brief Получить n-й бит из uint16_t
  * @param _uint16_ Переменная типа uint16_t
  * @param _bit_    Константный номер бита (0..15)
  * @return Значение выбранного бита (0 или 1)
  * @note    Индекс бита должен быть известен на этапе компиляции!
  */
#define uint16_bit(_uint8_, _bit_)      (*(uint16_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_
/**
  * @brief Получить n-й бит из uint32_t
  * @param _uint32_ Переменная типа uint32_t
  * @param _bit_    Константный номер бита (0..31)
  * @return Значение выбранного бита (0 или 1)
  * @note    Индекс бита должен быть известен на этапе компиляции!
  */
#define uint32_bit(_uint8_, _bit_)      (*(uint32_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_
/**
  * @brief Получить n-й бит из uint64_t
  * @param _uint64_ Переменная типа uint64_t
  * @param _bit_    Константный номер бита (0..63)
  * @return Значение выбранного бита (0 или 1)
  * @note    Индекс бита должен быть известен на этапе компиляции!
  */
#define uint64_bit(_uint8_, _bit_)      (*(uint64_BitTypeDef *)(&(_uint8_))).bit.bit##_bit_

#endif //__BIT_ACCESS_H_ 

/** BIT_ACCESS_DEFINES
  * @}
  */
