#include <msp430.h>
#include <stdint.h>

/*class SPI {

public:
    virtual void enable() = 0;
    virtual void disable() = 0;
    virtual uint8_t transfer(uint8_t data) = 0;

};

volatile uint8_t derp, durp;

template <int useless>
class SoftSPI : public SPI {

public:
    virtual void enable() {
        derp = 1;
    }

    virtual void disable() {
        derp = 0;
    }

    virtual uint8_t transfer(uint8_t data) {
        durp += data;
        return durp;
    }

};

class RF {
public:

    SPI &spi;

    RF(SPI &spi) : spi(spi) {
        
    }
    
    void do_something() {
        spi.transfer(0x69);
        spi.transfer(0x70);
        spi.transfer(0x71);
    }
};

SoftSPI<1> spi;

RF rf(spi);

int main() {
    rf.do_something();
}*/

const char gpio_shift_table[] = {
    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
};


#ifndef T_MHZ
#define T_MHZ 16
#endif

#define T_PIN_REG(type, pin) (*(port8_t)(((pin) >= 8 ) ? P2##type : P1##type))
#define T_PIN_BIT(pin) (gpio_shift_table[(pin) & 0x07])
#define T_PIN_CLEAR(type, pin) T_PIN_REG(type, pin) &= (uint8_t)~T_PIN_BIT(pin)
#define T_PIN_SET(type, pin) T_PIN_REG(type, pin) |= T_PIN_BIT(pin)

typedef volatile uint8_t * const port8_t;
typedef volatile uint16_t * const port16_t;


template<int pin_n>
class Tristate {

private:
    void set_dynamic(bool value) const {
        if (value)
            T_PIN_SET(OUT_, pin_n);
        else
            T_PIN_CLEAR(OUT_, pin_n);
    }

public:

    void output() {
        T_PIN_SET(DIR_, pin_n);
    }

    void input() {
        T_PIN_CLEAR(DIR_, pin_n);
    }

    void pull_up() {
        T_PIN_SET(REN_, pin_n);
        T_PIN_SET(OUT_, pin_n);
    }

    void pull_down() {
        T_PIN_SET(REN_, pin_n);
        T_PIN_CLEAR(OUT_, pin_n);
    }

    void pull_none() {
        T_PIN_CLEAR(REN_, pin_n);
    }

    void operator=(bool value) const __attribute__((always_inline)) {
        if (__builtin_constant_p(value)) {
            if (value)
                T_PIN_SET(OUT_, pin_n);
            else
                T_PIN_CLEAR(OUT_, pin_n);
        } else {
            set_dynamic(value);
        }
    }

    operator bool() const {
        return (T_PIN_REG(IN_, pin_n) & T_PIN_BIT(pin_n)) != 0;
    }
};

template<int pin_n>
class Output : protected Tristate<pin_n> {

public:

    Output() {
        Tristate<pin_n>::output();
    }

    Tristate<pin_n>::operator=;

};

template<int pin_n>
class Input : protected Tristate<pin_n> {

public:

    Tristate<pin_n>::operator bool;
    Tristate<pin_n>::pull_up;
    Tristate<pin_n>::pull_down;
    Tristate<pin_n>::pull_none;

};

Output<2> out;

int main() {
    out = true;
    out = false;
}
