gpio.h 2.83 KB
#ifndef REGS_GPIO_H
#define REGS_GPIO_H

#include "register.h"

class GPIO {
public:
  class MODER : public Register32 {
  public:
    enum class Mode {
      Input = 0,
      Output = 1,
      AlternateFunction = 2,
      Analog = 3
    };
    Mode getMode(int index) { return (Mode)getBitRange(2*index+1, 2*index); }
    void setMode(int index, Mode mode) volatile { setBitRange(2*index+1, 2*index, (uint32_t)mode); }
  };

  class OTYPER : Register32 {
  public:
    enum class Type {
      PushPull = 0,
      OpenDrain = 1
    };
    Type getType(int index) { return (Type)getBitRange(index, index); }
    void setType(int index, Type type) volatile { setBitRange(index, index, (uint32_t)type); }
  };

  class PUPDR : public Register32 {
  public:
    enum class Pull {
      None = 0,
      Up = 1,
      Down = 2,
      Reserved = 3
    };
    Pull getPull(int index) { return (Pull)getBitRange(2*index+1, 2*index); }
    void setPull(int index, Pull pull) volatile { setBitRange(2*index+1, 2*index, (uint32_t)pull); }
  };

  class IDR : public Register32 {
  public:
    bool get(int index) volatile { return (bool)getBitRange(index, index); }
  };

  class ODR : public Register32 {
  public:
    bool get(int index) volatile { return (bool)getBitRange(index, index); }
    void set(int index, bool state) volatile { setBitRange(index, index, state); }
  };

  class AFR : Register64 {
    /* The AFR register doesn't exist per-se in the documentation. It is the
     * consolidation of AFRL and AFRH which are two 32 bits registers. */
  public:
    enum class AlternateFunction {
      AF0 = 0,   AF1 = 1,   AF2 = 2,   AF3 = 3,
      AF4 = 4,   AF5 = 5,   AF6 = 6,   AF7 = 7,
      AF8 = 8,   AF9 = 9,   AF10 = 10, AF11 = 11,
      AF12 = 12, AF13 = 13, AF14 = 14, AF15 = 15
    };
    AlternateFunction getAlternateFunction(int index) {
      return (AlternateFunction)getBitRange(4*index+3, 4*index);
    }
    void setAlternateFunction(int index, AlternateFunction af) volatile {
      setBitRange(4*index+3, 4*index, (uint64_t)af);
    }
  };

  constexpr GPIO(int i) : m_index(i) {}
  constexpr operator int() const { return m_index; }
  REGS_REGISTER_AT(MODER, 0x00);
  REGS_REGISTER_AT(OTYPER, 0x04);
  REGS_REGISTER_AT(PUPDR, 0x0C);
  REGS_REGISTER_AT(IDR, 0x10);
  REGS_REGISTER_AT(ODR, 0x14);
  REGS_REGISTER_AT(AFR, 0x20);
private:
  constexpr uint32_t Base() const {
    return 0x40020000 + 0x400*m_index;
  };
  int m_index;
};

constexpr GPIO GPIOA(0);
constexpr GPIO GPIOB(1);
constexpr GPIO GPIOC(2);
constexpr GPIO GPIOD(3);
constexpr GPIO GPIOE(4);
constexpr GPIO GPIOF(5);
constexpr GPIO GPIOG(6);
constexpr GPIO GPIOH(7);

class GPIOPin {
public:
  constexpr GPIOPin(GPIO group, uint8_t pin) : m_data(((group&0xF) << 4) | (pin&0xF)) {}
  GPIO group() const { return GPIO(m_data>>4); }
  uint8_t pin() const { return m_data & 0xF; }
private:
  uint8_t m_data;
};

#endif