From 9727df5f6cb88fe81c2754b45f73f4db53d9da51 Mon Sep 17 00:00:00 2001
From: Alex Stewart <Alexander.Stewart@consensuscorp.com>
Date: Tue, 18 Aug 2015 17:38:31 -0700
Subject: [PATCH] Add esp/iomux_regs.h

---
 core/include/common_macros.h  |   9 ++
 core/include/esp/gpio.h       |  10 +--
 core/include/esp/iomux.h      | 150 ++-----------------------------
 core/include/esp/iomux_regs.h | 160 ++++++++++++++++++++++++++++++++++
 core/include/esp/registers.h  |  34 +-------
 core/include/esp/types.h      |   8 ++
 examples/blink/blink.c        |   6 +-
 7 files changed, 197 insertions(+), 180 deletions(-)
 create mode 100644 core/include/esp/iomux_regs.h
 create mode 100644 core/include/esp/types.h

diff --git a/core/include/common_macros.h b/core/include/common_macros.h
index fa13ff9..1ed2e22 100644
--- a/core/include/common_macros.h
+++ b/core/include/common_macros.h
@@ -16,6 +16,15 @@
 #define BIT(X) (1<<(X))
 #endif
 
+/* These macros convert values to/from bitfields specified by *_M and *_S (mask
+ * and shift) constants.  Used primarily with ESP8266 register access.
+ */
+
+#define VAL2FIELD(fieldname, value) (((value) & fieldname##_M) << fieldname##_S)
+#define FIELD2VAL(fieldname, regbits) (((regbits) >> fieldname##_S) & fieldname##_M)
+
+#define SETFIELD(regbits, fieldname, value) (((regbits) & ~(fieldname##_M << fieldname##_S)) | VAL2FIELD(fieldname, value))
+
 /* Use this macro to store constant values in IROM flash instead
    of having them loaded into rodata (which resides in DRAM)
 
diff --git a/core/include/esp/gpio.h b/core/include/esp/gpio.h
index 57d6d9a..c4bca56 100644
--- a/core/include/esp/gpio.h
+++ b/core/include/esp/gpio.h
@@ -35,15 +35,15 @@ INLINED void gpio_enable(const uint8_t gpio_num, const gpio_direction_t directio
         ctrl_val = GPIO_SOURCE_GPIO;
         break;
     case GPIO_OUTPUT:
-        iomux_flags = IOMUX_OE;
+        iomux_flags = IOMUX_PIN_OUTPUT_ENABLE;
         ctrl_val = GPIO_DRIVE_PUSH_PULL|GPIO_SOURCE_GPIO;
         break;
     case GPIO_OUT_OPEN_DRAIN:
-        iomux_flags = IOMUX_OE;
+        iomux_flags = IOMUX_PIN_OUTPUT_ENABLE;
         ctrl_val = GPIO_DRIVE_OPEN_DRAIN|GPIO_SOURCE_GPIO;
         break;
     case GPIO_INPUT_PULLUP:
-        iomux_flags = IOMUX_PU;
+        iomux_flags = IOMUX_PIN_PULLUP;
         ctrl_val = GPIO_SOURCE_GPIO;
     }
     iomux_set_gpio_function(gpio_num, iomux_flags);
@@ -57,12 +57,12 @@ INLINED void gpio_enable(const uint8_t gpio_num, const gpio_direction_t directio
 /* Disable GPIO on the specified pin, and set it Hi-Z.
  *
  * If later muxing this pin to a different function, make sure to set
- * IOMUX_OE if necessary to enable the output buffer.
+ * IOMUX_PIN_OUTPUT_ENABLE if necessary to enable the output buffer.
  */
 INLINED void gpio_disable(const uint8_t gpio_num)
 {
     GPIO_DIR_CLEAR = BIT(gpio_num);
-    *gpio_iomux_reg(gpio_num) &= ~IOMUX_OE;
+    *gpio_iomux_reg(gpio_num) &= ~IOMUX_PIN_OUTPUT_ENABLE;
 }
 
 /* Set output of a pin high or low.
diff --git a/core/include/esp/iomux.h b/core/include/esp/iomux.h
index fd5a51d..f4096ed 100644
--- a/core/include/esp/iomux.h
+++ b/core/include/esp/iomux.h
@@ -8,8 +8,8 @@
  */
 #ifndef _ESP_IOMUX_H
 #define _ESP_IOMUX_H
-#include <stdint.h>
-#include "esp/registers.h"
+#include "esp/types.h"
+#include "esp/iomux_regs.h"
 
 /**
  * Convert a GPIO pin number to an iomux register index.
@@ -32,11 +32,11 @@ inline static uint8_t iomux_to_gpio(const uint8_t iomux_num);
 /**
  * Directly get the IOMUX register for a particular gpio number
  *
- * ie *gpio_iomux_reg(3) is equivalent to IOMUX_GP03
+ * ie *gpio_iomux_reg(3) is equivalent to IOMUX_GPIO3
  */
 inline static esp_reg_t gpio_iomux_reg(const uint8_t gpio_number)
 {
-    return &IOMUX_REG(gpio_to_iomux(gpio_number));
+    return &(IOMUX.PIN[gpio_to_iomux(gpio_number)]);
 }
 
 /**
@@ -45,153 +45,21 @@ inline static esp_reg_t gpio_iomux_reg(const uint8_t gpio_number)
  * This allows you to set pins to GPIO without knowing in advance the
  * exact register masks to use.
  *
- * flags can be any of IOMUX_OE, IOMUX_PU, IOMUX_PD, etc. Any other flags will be cleared.
+ * flags can be any of IOMUX_PIN_OUTPUT_ENABLE, IOMUX_PIN_PULLUP, IOMUX_PIN_PULLDOWN, etc. Any other flags will be cleared.
  *
  * Equivalent to a direct register operation if gpio_number is known at compile time.
  * ie the following are equivalent:
  *
- * iomux_set_gpio_function(12, IOMUX_OE);
- * IOMUX_GP12 = (IOMUX_GP12 & ~IOMUX_FUNC_MASK) | IOMUX_GP12_GPIO | IOMUX_OE;
+ * iomux_set_gpio_function(12, IOMUX_PIN_OUTPUT_ENABLE);
+ * IOMUX_GPIO12 = IOMUX_GPIO12_FUNC_GPIO | IOMUX_PIN_OUTPUT_ENABLE;
  */
-inline static void iomux_set_gpio_function(const uint8_t gpio_number, const uint8_t flags)
+inline static void iomux_set_gpio_function(const uint8_t gpio_number, const uint32_t flags)
 {
     const uint8_t reg_idx = gpio_to_iomux(gpio_number);
-    const esp_reg_t reg = &IOMUX_REG(reg_idx);
     const uint32_t func = (reg_idx > 11 ? IOMUX_FUNC_A : IOMUX_FUNC_D) | flags;
-    const uint32_t val = *reg & ~(IOMUX_FUNC_MASK | IOMUX_FLAG_MASK);
-    *reg = val | func;
+    IOMUX.PIN[reg_idx] = func | flags;
 }
 
-/**
- * Set an IOMUX register directly
- *
- * Shortcut for
- * IOMUX_GPxx = (IOMUX_GPxx & ~IOMUX_FUNC_MASK) | IOMUX_GPxx_func
- *
- * instead call
- * IOMUX_SET_FN(GPxx, func);
- * can also do
- * IOMUX_SET_FN(GP12, GPIO)|IOMUX_OE;
- * ... to set the OE flag if it was previously cleared.
- *
- * but a better option is:
- * IOMUX_SET(GP12, GPIO, IOMUX_OE);
- * ...which clears any other flags at the same time.
- */
-#define IOMUX_SET_FN(GP,FN) IOMUX_##GP = ((IOMUX_##GP & ~IOMUX_FUNC_MASK) | IOMUX_##GP##_##FN)
-#define IOMUX_SET(GP,FN,FLAGS) IOMUX_##GP = ((IOMUX_##GP & ~(IOMUX_FUNC_MASK|IOMUX_FLAG_MASK)) | IOMUX_##GP##_##FN|FLAGS)
-
-/* IOMUX register index 0, GPIO 12 */
-#define IOMUX_GP12           IOMUX_REG(0)
-#define IOMUX_GP12_MTDI      IOMUX_FUNC_A
-#define IOMUX_GP12_I2S_DIN   IOMUX_FUNC_B
-#define IOMUX_GP12_HSPI_MISO IOMUX_FUNC_C
-#define IOMUX_GP12_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP12_UART0_DTR IOMUX_FUNC_E
-
-/* IOMUX register index 1, GPIO 13 */
-#define IOMUX_GP13           IOMUX_REG(1)
-#define IOMUX_GP13_MTCK      IOMUX_FUNC_A
-#define IOMUX_GP13_I2SI_BCK  IOMUX_FUNC_B
-#define IOMUX_GP13_HSPI_MOSI IOMUX_FUNC_C
-#define IOMUX_GP13_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP13_UART0_CTS IOMUX_FUNC_E
-
-/* IOMUX register index 2, GPIO 14 */
-#define IOMUX_GP14           IOMUX_REG(2)
-#define IOMUX_GP14_MTMS      IOMUX_FUNC_A
-#define IOMUX_GP14_I2SI_WS   IOMUX_FUNC_B
-#define IOMUX_GP14_HSPI_CLK  IOMUX_FUNC_C
-#define IOMUX_GP14_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP14_UART0_DSR IOMUX_FUNC_E
-
-/* IOMUX register index 3, GPIO 15 */
-#define IOMUX_GP15           IOMUX_REG(3)
-#define IOMUX_GP15_MTDO      IOMUX_FUNC_A
-#define IOMUX_GP15_I2SO_BCK  IOMUX_FUNC_B
-#define IOMUX_GP15_HSPI_CS0  IOMUX_FUNC_C
-#define IOMUX_GP15_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP15_UART0_RTS IOMUX_FUNC_E
-
-/* IOMUX register index 4, GPIO 3 */
-#define IOMUX_GP03           IOMUX_REG(4)
-#define IOMUX_GP03_UART0_RX  IOMUX_FUNC_A
-#define IOMUX_GP03_I2SO_DATA IOMUX_FUNC_B
-#define IOMUX_GP03_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP03_CLK_XTAL_BK IOMUX_FUNC_E
-
-/* IOMUX register index 5, GPIO 1 */
-#define IOMUX_GP01           IOMUX_REG(5)
-#define IOMUX_GP01_UART0_TX  IOMUX_FUNC_A
-#define IOMUX_GP01_SPICS1    IOMUX_FUNC_B
-#define IOMUX_GP01_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP01_CLK_RTC_BK IOMUX_FUNC_E
-
-/* IOMUX register index 6, GPIO 6 */
-#define IOMUX_GP06           IOMUX_REG(6)
-#define IOMUX_GP06_SD_CLK    IOMUX_FUNC_A
-#define IOMUX_GP06_SP_ICLK   IOMUX_FUNC_B
-#define IOMUX_GP06_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP06_UART1_CTS IOMUX_FUNC_E
-
-/* IOMUX register index 7, GPIO 7 */
-#define IOMUX_GP07           IOMUX_REG(7)
-#define IOMUX_GP07_SD_DATA0  IOMUX_FUNC_A
-#define IOMUX_GP07_SPIQ_MISO IOMUX_FUNC_B
-#define IOMUX_GP07_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP07_UART1_TX  IOMUX_FUNC_E
-
-/* IOMUX register index 8, GPIO 8 */
-#define IOMUX_GP08           IOMUX_REG(8)
-#define IOMUX_GP08_SD_DATA1  IOMUX_FUNC_A
-#define IOMUX_GP08_SPID_MOSI IOMUX_FUNC_B
-#define IOMUX_GP08_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP08_UART1_RX  IOMUX_FUNC_E
-
-/* IOMUX register index 9, GPIO 9 */
-#define IOMUX_GP09           IOMUX_REG(9)
-#define IOMUX_GP09_SD_DATA2  IOMUX_FUNC_A
-#define IOMUX_GP09_SPI_HD    IOMUX_FUNC_B
-#define IOMUX_GP09_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP09_UFNC_HSPIHD IOMUX_FUNC_E
-
-/* IOMUX register index 10, GPIO 10 */
-#define IOMUX_GP10           IOMUX_REG(10)
-#define IOMUX_GP10_SD_DATA3  IOMUX_FUNC_A
-#define IOMUX_GP10_SPI_WP    IOMUX_FUNC_B
-#define IOMUX_GP10_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP10_HSPIWP    IOMUX_FUNC_E
-
-/* IOMUX register index 11, GPIO 11 */
-#define IOMUX_GP11           IOMUX_REG(11)
-#define IOMUX_GP11_SD_CMD    IOMUX_FUNC_A
-#define IOMUX_GP11_SPI_CS0   IOMUX_FUNC_B
-#define IOMUX_GP11_GPIO      IOMUX_FUNC_D
-#define IOMUX_GP11_UART1_RTS IOMUX_FUNC_E
-
-/* IOMUX register index 12, GPIO 0 */
-#define IOMUX_GP00           IOMUX_REG(12)
-#define IOMUX_GP00_GPIO      IOMUX_FUNC_A
-#define IOMUX_GP00_SPI_CS2   IOMUX_FUNC_B
-#define IOMUX_GP00_CLK_OUT   IOMUX_FUNC_E
-
-/* IOMUX register index 13, GPIO 2 */
-#define IOMUX_GP02           IOMUX_REG(13)
-#define IOMUX_GP02_GPIO      IOMUX_FUNC_A
-#define IOMUX_GP02_I2SO_WS   IOMUX_FUNC_B
-#define IOMUX_GP02_UART1_TX  IOMUX_FUNC_C
-#define IOMUX_GP02_UART0_TX  IOMUX_FUNC_E
-
-/* IOMUX register index 14, GPIO 4 */
-#define IOMUX_GP04           IOMUX_REG(14)
-#define IOMUX_GP04_GPIO4     IOMUX_FUNC_A
-#define IOMUX_GP04_CLK_XTAL  IOMUX_FUNC_B
-
-/* IOMUX register index 15, GPIO 5 */
-#define IOMUX_GP05           IOMUX_REG(15)
-#define IOMUX_GP05_GPIO5     IOMUX_FUNC_A
-#define IOMUX_GP05_CLK_RTC   IOMUX_FUNC_B
-
 /* esp_iomux_private contains implementation parts of the inline functions
    declared above */
 #include "esp/iomux_private.h"
diff --git a/core/include/esp/iomux_regs.h b/core/include/esp/iomux_regs.h
new file mode 100644
index 0000000..0e67a9c
--- /dev/null
+++ b/core/include/esp/iomux_regs.h
@@ -0,0 +1,160 @@
+/* esp/iomux_regs.h
+ *
+ * ESP8266 IOMUX register definitions
+ *
+ * Not compatible with ESP SDK register access code.
+ *
+ * Note that IOMUX register order is _not_ the same as GPIO order. See
+ * esp/iomux.h for programmer-friendly IOMUX configuration options.
+ */
+
+#ifndef _ESP_IOMUX_REGS_H
+#define _ESP_IOMUX_REGS_H
+
+#include "esp/types.h"
+#include "common_macros.h"
+
+#define IOMUX_BASE 0x60000800
+#define IOMUX (*(struct IOMUX_REGS *)(IOMUX_BASE))
+
+struct IOMUX_REGS {
+    uint32_t volatile CONF;    // 0x00
+    uint32_t volatile PIN[16]; // 0x04 - 0x40
+} __attribute__ (( packed ));
+
+/* Double-check the structure size to make sure the compiler hasn't done
+ * something strange (or somebody typoed in the struct definition, etc)
+ */
+_Static_assert(sizeof(struct IOMUX_REGS) == 0x44, "IOMUX_REGS is the wrong size");
+
+/* Bit mapping for CONF register */
+
+#define IOMUX_CONF_SPI0_CLOCK_EQU_SYS_CLOCK  BIT(8)
+#define IOMUX_CONF_SPI1_CLOCK_EQU_SYS_CLOCK  BIT(9)
+
+/* Bit mapping for PIN registers */
+
+#define IOMUX_PIN_OUTPUT_ENABLE        BIT(0)
+#define IOMUX_PIN_OUTPUT_ENABLE_SLEEP  BIT(1)
+#define IOMUX_PIN_PULLDOWN_SLEEP       BIT(2)
+#define IOMUX_PIN_PULLUP_SLEEP         BIT(3)
+#define IOMUX_PIN_FUNC_LOW_M           0x00000003
+#define IOMUX_PIN_FUNC_LOW_S           4
+#define IOMUX_PIN_PULLDOWN             BIT(6)
+#define IOMUX_PIN_PULLUP               BIT(7)
+#define IOMUX_PIN_FUNC_HIGH_M          0x00000004
+#define IOMUX_PIN_FUNC_HIGH_S          8
+
+#define IOMUX_PIN_FUNC_MASK            0x00001030
+
+/* WARNING: Macro evaluates argument twice */
+#define IOMUX_FUNC(val) (VAL2FIELD(IOMUX_PIN_FUNC_LOW, val) | VAL2FIELD(IOMUX_PIN_FUNC_HIGH, val))
+
+/* WARNING: Macro evaluates argument twice */
+#define IOMUX_FUNC_VALUE(regbits) (FIELD2VAL(IOMUX_PIN_FUNC_LOW, regbits) | FIELD2VAL(IOMUX_PIN_FUNC_HIGH, regbits))
+
+#define IOMUX_SET_FUNC(regbits, funcval) (((regbits) & ~IOMUX_PIN_FUNC_MASK) | (funcval))
+
+#define IOMUX_FUNC_A  IOMUX_FUNC(0)
+#define IOMUX_FUNC_B  IOMUX_FUNC(1)
+#define IOMUX_FUNC_C  IOMUX_FUNC(2)
+#define IOMUX_FUNC_D  IOMUX_FUNC(3)
+#define IOMUX_FUNC_E  IOMUX_FUNC(4)
+
+#define IOMUX_GPIO0   IOMUX.PIN[12]
+#define IOMUX_GPIO1   IOMUX.PIN[5]
+#define IOMUX_GPIO2   IOMUX.PIN[13]
+#define IOMUX_GPIO3   IOMUX.PIN[4]
+#define IOMUX_GPIO4   IOMUX.PIN[14]
+#define IOMUX_GPIO5   IOMUX.PIN[15]
+#define IOMUX_GPIO6   IOMUX.PIN[6]
+#define IOMUX_GPIO7   IOMUX.PIN[7]
+#define IOMUX_GPIO8   IOMUX.PIN[8]
+#define IOMUX_GPIO9   IOMUX.PIN[9]
+#define IOMUX_GPIO10  IOMUX.PIN[10]
+#define IOMUX_GPIO11  IOMUX.PIN[11]
+#define IOMUX_GPIO12  IOMUX.PIN[0]
+#define IOMUX_GPIO13  IOMUX.PIN[1]
+#define IOMUX_GPIO14  IOMUX.PIN[2]
+#define IOMUX_GPIO15  IOMUX.PIN[3]
+
+#define IOMUX_GPIO0_FUNC_GPIO              IOMUX_FUNC(0)
+#define IOMUX_GPIO0_FUNC_SPI0_CS2          IOMUX_FUNC(1)
+#define IOMUX_GPIO0_FUNC_CLOCK_OUT         IOMUX_FUNC(4)
+
+#define IOMUX_GPIO1_FUNC_UART0_TXD         IOMUX_FUNC(0)
+#define IOMUX_GPIO1_FUNC_SPI0_CS1          IOMUX_FUNC(1)
+#define IOMUX_GPIO1_FUNC_GPIO              IOMUX_FUNC(3)
+#define IOMUX_GPIO1_FUNC_CLOCK_RTC_BLINK   IOMUX_FUNC(4)
+
+#define IOMUX_GPIO2_FUNC_GPIO              IOMUX_FUNC(0)
+#define IOMUX_GPIO2_FUNC_I2SO_WS           IOMUX_FUNC(1)
+#define IOMUX_GPIO2_FUNC_UART1_TXD_BLINK   IOMUX_FUNC(2)
+#define IOMUX_GPIO2_FUNC_UART0_TXD_BLINK   IOMUX_FUNC(4)
+
+#define IOMUX_GPIO3_FUNC_UART0_RXD         IOMUX_FUNC(0)
+#define IOMUX_GPIO3_FUNC_I2SO_DATA         IOMUX_FUNC(1)
+#define IOMUX_GPIO3_FUNC_GPIO              IOMUX_FUNC(3)
+#define IOMUX_GPIO3_FUNC_CLOCK_XTAL_BLINK  IOMUX_FUNC(4)
+
+#define IOMUX_GPIO4_FUNC_GPIO              IOMUX_FUNC(0)
+#define IOMUX_GPIO4_FUNC_CLOCK_XTAL        IOMUX_FUNC(1)
+
+#define IOMUX_GPIO5_FUNC_GPIO              IOMUX_FUNC(0)
+#define IOMUX_GPIO5_FUNC_CLOCK_RTC         IOMUX_FUNC(1)
+
+#define IOMUX_GPIO6_FUNC_SD_CLK            IOMUX_FUNC(0)
+#define IOMUX_GPIO6_FUNC_SPI0_CLK          IOMUX_FUNC(1)
+#define IOMUX_GPIO6_FUNC_GPIO              IOMUX_FUNC(3)
+#define IOMUX_GPIO6_FUNC_UART1_CTS         IOMUX_FUNC(4)
+
+#define IOMUX_GPIO7_FUNC_SD_DATA0          IOMUX_FUNC(0)
+#define IOMUX_GPIO7_FUNC_SPI0_Q_MISO       IOMUX_FUNC(1)
+#define IOMUX_GPIO7_FUNC_GPIO              IOMUX_FUNC(3)
+#define IOMUX_GPIO7_FUNC_UART1_TXD         IOMUX_FUNC(4)
+
+#define IOMUX_GPIO8_FUNC_SD_DATA1          IOMUX_FUNC(0)
+#define IOMUX_GPIO8_FUNC_SPI0_D_MOSI       IOMUX_FUNC(1)
+#define IOMUX_GPIO8_FUNC_GPIO              IOMUX_FUNC(3)
+#define IOMUX_GPIO8_FUNC_UART1_RXD         IOMUX_FUNC(4)
+
+#define IOMUX_GPIO9_FUNC_SD_DATA2          IOMUX_FUNC(0)
+#define IOMUX_GPIO9_FUNC_SPI0_HD           IOMUX_FUNC(1)
+#define IOMUX_GPIO9_FUNC_GPIO              IOMUX_FUNC(3)
+#define IOMUX_GPIO9_FUNC_SPI1_HD           IOMUX_FUNC(4)
+
+#define IOMUX_GPIO10_FUNC_SD_DATA3         IOMUX_FUNC(0)
+#define IOMUX_GPIO10_FUNC_SPI0_WP          IOMUX_FUNC(1)
+#define IOMUX_GPIO10_FUNC_GPIO             IOMUX_FUNC(3)
+#define IOMUX_GPIO10_FUNC_SPI1_WP          IOMUX_FUNC(4)
+
+#define IOMUX_GPIO11_FUNC_SD_CMD           IOMUX_FUNC(0)
+#define IOMUX_GPIO11_FUNC_SPI0_CS0         IOMUX_FUNC(1)
+#define IOMUX_GPIO11_FUNC_GPIO             IOMUX_FUNC(3)
+#define IOMUX_GPIO11_FUNC_UART1_RTS        IOMUX_FUNC(4)
+
+#define IOMUX_GPIO12_FUNC_MTDI             IOMUX_FUNC(0)
+#define IOMUX_GPIO12_FUNC_I2SI_DATA        IOMUX_FUNC(1)
+#define IOMUX_GPIO12_FUNC_SPI1_Q_MISO      IOMUX_FUNC(2)
+#define IOMUX_GPIO12_FUNC_GPIO             IOMUX_FUNC(3)
+#define IOMUX_GPIO12_FUNC_UART0_DTR        IOMUX_FUNC(4)
+
+#define IOMUX_GPIO13_FUNC_MTCK             IOMUX_FUNC(0)
+#define IOMUX_GPIO13_FUNC_I2SI_BCK         IOMUX_FUNC(1)
+#define IOMUX_GPIO13_FUNC_SPI1_D_MOSI      IOMUX_FUNC(2)
+#define IOMUX_GPIO13_FUNC_GPIO             IOMUX_FUNC(3)
+#define IOMUX_GPIO13_FUNC_UART0_CTS        IOMUX_FUNC(4)
+
+#define IOMUX_GPIO14_FUNC_MTMS             IOMUX_FUNC(0)
+#define IOMUX_GPIO14_FUNC_I2SI_WS          IOMUX_FUNC(1)
+#define IOMUX_GPIO14_FUNC_SPI1_CLK         IOMUX_FUNC(2)
+#define IOMUX_GPIO14_FUNC_GPIO             IOMUX_FUNC(3)
+#define IOMUX_GPIO14_FUNC_UART0_DSR        IOMUX_FUNC(4)
+
+#define IOMUX_GPIO15_FUNC_MTDO             IOMUX_FUNC(0)
+#define IOMUX_GPIO15_FUNC_I2SO_BCK         IOMUX_FUNC(1)
+#define IOMUX_GPIO15_FUNC_SPI1_CS0         IOMUX_FUNC(2)
+#define IOMUX_GPIO15_FUNC_GPIO             IOMUX_FUNC(3)
+#define IOMUX_GPIO15_FUNC_UART0_RTS        IOMUX_FUNC(4)
+
+#endif /* _ESP_IOMUX_REGS_H */
diff --git a/core/include/esp/registers.h b/core/include/esp/registers.h
index 7468dfb..ae8f169 100644
--- a/core/include/esp/registers.h
+++ b/core/include/esp/registers.h
@@ -14,8 +14,9 @@
 #ifndef _ESP_REGISTERS
 #define _ESP_REGISTERS
 #include "common_macros.h"
+#include "esp/types.h"
 
-typedef volatile uint32_t *esp_reg_t;
+#include "esp/iomux_regs.h"
 
 /* Internal macro, only defined in header body */
 #define _REG(BASE, OFFSET) (*(esp_reg_t)((BASE)+(OFFSET)))
@@ -33,7 +34,7 @@ typedef volatile uint32_t *esp_reg_t;
 #define GPIO0_BASE (MMIO_BASE + 0x0300)
 #define TIMER_BASE (MMIO_BASE + 0x0600)
 #define RTC_BASE   (MMIO_BASE + 0x0700)
-#define IOMUX_BASE (MMIO_BASE + 0x0800)
+//#define IOMUX_BASE (MMIO_BASE + 0x0800)
 #define WDT_BASE   (MMIO_BASE + 0x0900)
 #define I2C_BASE   (MMIO_BASE + 0x0d00)
 #define UART1_BASE (MMIO_BASE + 0x0F00)
@@ -41,35 +42,6 @@ typedef volatile uint32_t *esp_reg_t;
 #define RTCS_BASE  (MMIO_BASE + 0x1100)
 #define RTCU_BASE  (MMIO_BASE + 0x1200)
 
-/*
- * iomux registers, apply to pin functions.
- *
- * Note that IOMUX register order is _not_ the same as GPIO order. See
- * esp_iomux.h for programmer-friendly IOMUX configuration options
- */
-#define IOMUX_REG(X) _REG(IOMUX_BASE,0x04+4*X)
-
-#define IOMUX_OE       BIT(0) /* iomux Output enable bit */
-#define IOMUX_OE_SLEEP BIT(1) /* iomux Output during sleep bit */
-
-#define IOMUX_PD       BIT(6) /* iomux soft pulldown bit */
-#define IOMUX_PD_SLEEP BIT(2) /* iomux soft pulldown during sleep bit */
-#define IOMUX_PU       BIT(7) /* iomux soft pullup bit */
-#define IOMUX_PU_SLEEP BIT(3) /* iomux soft pullup during sleep bit */
-
-#define IOMUX_FLAG_WAKE_MASK (IOMUX_OE|IOMUX_PD|IOMUX_PU)
-#define IOMUX_FLAG_SLEEP_MASK (IOMUX_OE_SLEEP|IOMUX_PD_SLEEP|IOMUX_PU_SLEEP)
-#define IOMUX_FLAG_MASK (IOMUX_FLAG_WAKE_MASK|IOMUX_FLAG_SLEEP_MASK)
-
-#define IOMUX_FUNC_MASK (BIT(4)|BIT(5)|BIT(12))
-
-/* All pins have FUNC_A on reset (unconfirmed) */
-#define IOMUX_FUNC_A (0)
-#define IOMUX_FUNC_B BIT(4)
-#define IOMUX_FUNC_C BIT(5)
-#define IOMUX_FUNC_D BIT(4)|BIT(5)
-#define IOMUX_FUNC_E BIT(12)
-
 
 /*
  * Based on descriptions by mamalala at https://github.com/esp8266/esp8266-wiki/wiki/gpio-registers
diff --git a/core/include/esp/types.h b/core/include/esp/types.h
new file mode 100644
index 0000000..3f0560a
--- /dev/null
+++ b/core/include/esp/types.h
@@ -0,0 +1,8 @@
+#ifndef _ESP_TYPES_H
+#define _ESP_TYPES_H
+
+#include <stdint.h>
+
+typedef volatile uint32_t *esp_reg_t;
+
+#endif /* _ESP_TYPES_H */
diff --git a/examples/blink/blink.c b/examples/blink/blink.c
index be1c473..8f1b4bf 100644
--- a/examples/blink/blink.c
+++ b/examples/blink/blink.c
@@ -30,8 +30,8 @@ void blinkenTask(void *pvParameters)
 
 /* This task uses all raw register operations to set the pins.
 
-   It's not fully parameterised, as the IOMUX_SET macro requires the pin number
-   as part of the GPxx value.
+   It's not fully parameterised, as the IOMUX_GPIO# macros involve a non-linear
+   mapping from GPIO to IOMUX ports.
 
    There is no significant performance benefit to this way over the
    blinkenTask version, so it's probably better to use the blinkenTask
@@ -42,7 +42,7 @@ void blinkenTask(void *pvParameters)
 void blinkenRegisterTask(void *pvParameters)
 {
     GPIO_DIR_SET = BIT(gpio);
-    IOMUX_SET(GP14,GPIO,IOMUX_OE); /* change this line if you change 'gpio' */
+    IOMUX_GPIO14 = IOMUX_GPIO14_FUNC_GPIO | IOMUX_PIN_OUTPUT_ENABLE; /* change this line if you change 'gpio' */
     while(1) {
         GPIO_OUT_SET = BIT(gpio);
         vTaskDelay(1000 / portTICK_RATE_MS);