#include <iostream>
#include <stdint.h>

#include "utils/BitField.hpp"



union GPIO_MODER
{
    struct MODER{
        enum{
            INPUT_MODE,
            OUTPUT,
            ALT_FUNCTION,
            ANALOG
        };
    };

    struct MODER_0 : public MODER{
        typedef BitField<uint32_t, 0, 2> Bits;
    };
    struct MODER_1 : public MODER{
        typedef BitField<uint32_t, 2, 2> Bits;
    };
    struct MODER_2 : public MODER{
        typedef BitField<uint32_t, 4, 2> Bits;
    };
    struct MODER_3 : public MODER{
        typedef BitField<uint32_t, 6, 2> Bits;
    };
    struct MODER_4 : public MODER{
        typedef BitField<uint32_t, 8, 2> Bits;
    };
    struct MODER_5 : public MODER{
        typedef BitField<uint32_t, 10, 2> Bits;
    };
    struct MODER_6 : public MODER{
        typedef BitField<uint32_t, 12, 2> Bits;
    };
    struct MODER_7 : public MODER{
        typedef BitField<uint32_t, 14, 2> Bits;
    };
    struct MODER_8 : public MODER{
        typedef BitField<uint32_t, 16, 2> Bits;
    };
    struct MODER_9 : public MODER{
        typedef BitField<uint32_t, 18, 2> Bits;
    };
    struct MODER_10 : public MODER{
        typedef BitField<uint32_t, 20, 2> Bits;
    };
    struct MODER_11 : public MODER{
        typedef BitField<uint32_t, 22, 2> Bits;
    };
    struct MODER_12 : public MODER{
        typedef BitField<uint32_t, 24, 2> Bits;
    };
    struct MODER_13 : public MODER{
        typedef BitField<uint32_t, 26, 2> Bits;
    };
    struct MODER_14 : public MODER{
        typedef BitField<uint32_t, 28, 2> Bits;
    };
    struct MODER_15 : public MODER{
        typedef BitField<uint32_t, 30, 2> Bits;
    };
    union{
        GPIO_MODER::MODER_0::Bits MODER_0;
        GPIO_MODER::MODER_1::Bits MODER_1;
        GPIO_MODER::MODER_2::Bits MODER_2;
        GPIO_MODER::MODER_3::Bits MODER_3;
        GPIO_MODER::MODER_4::Bits MODER_4;
        GPIO_MODER::MODER_5::Bits MODER_5;
        GPIO_MODER::MODER_6::Bits MODER_6;
        GPIO_MODER::MODER_7::Bits MODER_7;
        GPIO_MODER::MODER_8::Bits MODER_8;
        GPIO_MODER::MODER_9::Bits MODER_9;
        GPIO_MODER::MODER_10::Bits MODER_10;
        GPIO_MODER::MODER_11::Bits MODER_11;
        GPIO_MODER::MODER_12::Bits MODER_12;
        GPIO_MODER::MODER_13::Bits MODER_13;
        GPIO_MODER::MODER_14::Bits MODER_14;
        GPIO_MODER::MODER_15::Bits MODER_15;
    }bits;

    uint32_t raw;

    GPIO_MODER(uint32_t v = 0x00) : raw(v) {}
    operator uint32_t() {return raw;}
    void operator = (uint32_t v) {raw = v;}  
};

int main(void)
{
    GPIO_MODER MODER_A;

    //  for reference use the STM32F0 reference manualchapter GPIO

    MODER_A.bits.MODER_0 = GPIO_MODER::MODER_0::OUTPUT;
    MODER_A.bits.MODER_5 = GPIO_MODER::MODER_5::ALT_FUNCTION;

    std::cout << +MODER_A << std::endl;

    return 0;
}