/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */

/*
 * ----------------------------------------------------------------------------------
 * The code in this file is copied (with a slight modifications) from:
 *     esp8266_peri.h - peripheral registers exposed in more AVR style for esp8266
 * ----------------------------------------------------------------------------------
 * Copyright (C) 2015 Hristo Gochkov. All rights reserved.
 *
 * This file is part of the esp8266 core for Arduino environment.
 *
 * This library is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at your option) any later
 * version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this library; if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 * ----------------------------------------------------------------------------------
 */


#ifndef ECXX_PLATFORM_NODEMCU_ESP8266_PERIPHERAL_H
#define ECXX_PLATFORM_NODEMCU_ESP8266_PERIPHERAL_H


// Base
#undef ESP8266_CLOCK
#undef ESP8266_REG
#undef ESP8266_DREG

#define ESP8266_CLOCK      80000000UL
#define ESP8266_REG(addr)  *( reinterpret_cast<volatile uint32_t*>( 0x60000000 + (addr) ) )
#define ESP8266_DREG(addr) *( reinterpret_cast<volatile uint32_t*>( 0x3FF00000 + (addr) ) )

// CPU Register
#define CPU2X     ESP8266_DREG(0x14) // When bit 0 is set, F_CPU = 160MHz

// OTP Registers
#define MAC0      ESP8266_DREG(0x50)
#define MAC1      ESP8266_DREG(0x54)
#define CHIPID    ESP8266_DREG(0x58)

// GPIO (0-15) control registers
#define GPO       ESP8266_REG(0x300) // GPIO_OUT        RW (Output Level)
#define GPOS      ESP8266_REG(0x304) // GPIO_OUT_SET    WO
#define GPOC      ESP8266_REG(0x308) // GPIO_OUT_CLR    WO
#define GPE       ESP8266_REG(0x30C) // GPIO_ENABLE     RW (Enable)
#define GPES      ESP8266_REG(0x310) // GPIO_ENABLE_SET WO
#define GPEC      ESP8266_REG(0x314) // GPIO_ENABLE_CLR WO
#define GPI       ESP8266_REG(0x318) // GPIO_IN         RO (Read Input Level)
#define GPIE      ESP8266_REG(0x31C) // GPIO_STATUS     RW (Interrupt Enable)
#define GPIES     ESP8266_REG(0x320) // GPIO_STATUS_SET WO
#define GPIEC     ESP8266_REG(0x324) // GPIO_STATUS_CLR WO

#undef GPOP
#undef GPEP
#undef GPIP
#undef GPIEP

#define GPOP(P)   ( ( GPO  & (1 << ( (P) & 0xF) ) ) != 0 )
#define GPEP(P)   ( ( GPE  & (1 << ( (P) & 0xF) ) ) != 0 )
#define GPIP(P)   ( ( GPI  & (1 << ( (P) & 0xF) ) ) != 0 )
#define GPIEP(P)  ( ( GPIE & (1 << ( (P) & 0xF) ) ) != 0 )

// GPIO (0-15) pin control registers
#undef GPC

#define GPC(P) ESP8266_REG( 0x328 + ( ( (P) & 0xF) * 4 ) )

#define GPC0   ESP8266_REG(0x328) // GPIO_PIN0
#define GPC1   ESP8266_REG(0x32C) // GPIO_PIN1
#define GPC2   ESP8266_REG(0x330) // GPIO_PIN2
#define GPC3   ESP8266_REG(0x334) // GPIO_PIN3
#define GPC4   ESP8266_REG(0x338) // GPIO_PIN4
#define GPC5   ESP8266_REG(0x33C) // GPIO_PIN5
#define GPC6   ESP8266_REG(0x340) // GPIO_PIN6
#define GPC7   ESP8266_REG(0x344) // GPIO_PIN7
#define GPC8   ESP8266_REG(0x348) // GPIO_PIN8
#define GPC9   ESP8266_REG(0x34C) // GPIO_PIN9
#define GPC10  ESP8266_REG(0x350) // GPIO_PIN10
#define GPC11  ESP8266_REG(0x354) // GPIO_PIN11
#define GPC12  ESP8266_REG(0x358) // GPIO_PIN12
#define GPC13  ESP8266_REG(0x35C) // GPIO_PIN13
#define GPC14  ESP8266_REG(0x360) // GPIO_PIN14
#define GPC15  ESP8266_REG(0x364) // GPIO_PIN15

// GPIO (0-15) pin control nits
#define GPCWE  10 // WAKEUP_ENABLE      => can be 1 only when INT_TYPE is high or low
#define GPCI   7  // INT_TYPE [3- bits] => 0:disable   ; 1:rising     ; 2:falling ; 3:change ; 4:low ; 5:high
#define GPCD   2  // DRIVER             => 0:normal    ; 1:open drain
#define GPCS   0  // SOURCE             => 0:GPIO_DATA ; 1:SigmaDelta

#define GPMUX  ESP8266_REG(0x800)

// GPIO (0-15) pin function registers
#define GPF0   ESP8266_REG(0x834)
#define GPF1   ESP8266_REG(0x818)
#define GPF2   ESP8266_REG(0x838)
#define GPF3   ESP8266_REG(0x814)
#define GPF4   ESP8266_REG(0x83C)
#define GPF5   ESP8266_REG(0x840)
#define GPF6   ESP8266_REG(0x81C)
#define GPF7   ESP8266_REG(0x820)
#define GPF8   ESP8266_REG(0x824)
#define GPF9   ESP8266_REG(0x828)
#define GPF10  ESP8266_REG(0x82C)
#define GPF11  ESP8266_REG(0x830)
#define GPF12  ESP8266_REG(0x804)
#define GPF13  ESP8266_REG(0x808)
#define GPF14  ESP8266_REG(0x80C)
#define GPF15  ESP8266_REG(0x810)

// GPIO (0-15) pin function bits
#define GPFSOE 0 // Sleep OE
#define GPFSS  1 // Sleep select
#define GPFSPD 2 // Sleep pulldown
#define GPFSPU 3 // Sleep pullup
#define GPFFS0 4 // Function select bit 0
#define GPFFS1 5 // Function select bit 1
#define GPFPD  6 // Pulldown
#define GPFPU  7 // Pullup
#define GPFFS2 8 // Function select bit 2

#undef GPFFS
#undef GPFFS_GPIO
#undef GPFFS_BUS

#define GPFFS(F)      ( ( ( ( (F) & 4 ) != 0 ) << GPFFS2 ) | ( ( ( (F) & 2 ) != 0 ) << GPFFS1 ) | ( ( ( (F) & 1 ) != 0 ) << GPFFS0 ) )
#define GPFFS_GPIO(P) ( ( (P) == 0 || (P) == 2 || (P) == 4 || (P) == 5 ) ? 0 : ( (P) == 16 ) ? 1 : 3 )
#define GPFFS_BUS(P)  ( ( (P) == 1 || (P) == 3 ) ? 0 :( (P) == 2 || (P) == 12 || (P) == 13 || (P) == 14 || (P) == 15 ) ? 2 : ( (P) == 0 ) ? 4 : 1 )

// GPIO 16 control Registers
#define GP16O ESP8266_REG(0x768)
#define GP16E ESP8266_REG(0x774)
#define GP16I ESP8266_REG(0x78C)

// GPIO 16 pin control register
#define GP16C ESP8266_REG(0x790)
#define GPC16 GP16C

// GPIO 16 pin gunction Register
#define GP16F ESP8266_REG(0x7A0)
#define GPF16 GP16F

// GPIO 16 pin function bits
#define GP16FFS0 0 // Function select bit 0
#define GP16FFS1 1 // Function select bit 1
#define GP16FPD  3 // pulldown
#define GP16FSPD 5 // Sleep pulldown
#define GP16FFS2 6 // Function select bit 2

#undef  GP16FFS
#define GP16FFS(F) ( ( (F) & 0x03 ) | ( ( (F) & 0x04 ) << 4) )

// Timer 1 registers (23-bit count-down timer)
#define T1L   ESP8266_REG(0x600) // Load value (starting value of counter 23-bit => 0-8388607)
#define T1V   ESP8266_REG(0x604) // Current value (RO)
#define T1C   ESP8266_REG(0x608) // Control register
#define T1I   ESP8266_REG(0x60C) // Interrupt status register (1-bit); write to clear

// Edge interrupt enable register
#define TEIE  ESP8266_DREG(0x04)
#define TEIE1 0x02 // Bit for timer 1

// Timer 2 registers (32-bit count-up timer)
#define T2L   ESP8266_REG(0x620) // Load value (starting value of counter)
#define T2V   ESP8266_REG(0x624) // Current calue (RO)
#define T2C   ESP8266_REG(0x628) // Control register
#define T2I   ESP8266_REG(0x62C) // Interrupt status register (1-bit); write to clear
#define T2A   ESP8266_REG(0x630) // Alarm value

// Timer control bits
#define TCIS  8 // Interrupt status
#define TCTE  7 // Timer enable
#define TCAR  6 // Auto reload (restart timer when condition is reached)
#define TCPD  2 // Prescale divider (2-bit) => 0:1(12.5nS/tick) ; 1:16(0.2us/tick) ; 2/3:256(3.2us/tick)
#define TCIT  0 // Interrupt type (0:edge ; 1:level)

// RTC registers
#define RTCSV ESP8266_REG(0x704) // RTC SLEEP COUNTER target value
#define RTCCV ESP8266_REG(0x71C) // RTC SLEEP COUNTER value
#define RTCIS ESP8266_REG(0x720) // RTC INT status
#define RTCIC ESP8266_REG(0x724) // RTC INT clear
#define RTCIE ESP8266_REG(0x728) // RTC INT enable

#undef  RTC_USER_MEM
#define RTC_USER_MEM ( reinterpret_cast<volatile uint32_t*>(0x60001200) )

// IO swap Register
#define IOSWAP    ESP8266_DREG(0x28)
#define IOSWAPU   0 // Swaps UART
#define IOSWAPS   1 // Swaps SPI
#define IOSWAPU0  2 // Swaps UART 0 pins (u0rxd <-> u0cts), (u0txd <-> u0rts)
#define IOSWAPU1  3 // Swaps UART 1 pins (u1rxd <-> u1cts), (u1txd <-> u1rts)
#define IOSWAPHS  5 // Sets HSPI with higher prio
#define IOSWAP2HS 6 // Sets two SPI masters on HSPI
#define IOSWAP2CS 7 // Sets two SPI masters on CSPI

// UART interrupt status
#define UIS  ESP8266_DREG(0x20020)
#define UIS0 0
#define UIS1 2

// UART 0 registers
#define U0F  ESP8266_REG(0x000) // UART FIFO
#define U0IR ESP8266_REG(0x004) // INT_RAW
#define U0IS ESP8266_REG(0x008) // INT_STATUS
#define U0IE ESP8266_REG(0x00c) // INT_ENABLE
#define U0IC ESP8266_REG(0x010) // INT_CLEAR
#define U0D  ESP8266_REG(0x014) // CLKDIV
#define U0A  ESP8266_REG(0x018) // AUTOBAUD
#define U0S  ESP8266_REG(0x01C) // STATUS
#define U0C0 ESP8266_REG(0x020) // CONF0
#define U0C1 ESP8266_REG(0x024) // CONF1
#define U0LP ESP8266_REG(0x028) // LOW_PULSE
#define U0HP ESP8266_REG(0x02C) // HIGH_PULSE
#define U0PN ESP8266_REG(0x030) // PULSE_NUM
#define U0DT ESP8266_REG(0x078) // DATE
#define U0ID ESP8266_REG(0x07C) // ID

// UART 1 registers
#define U1F  ESP8266_REG(0xF00) // UART FIFO
#define U1IR ESP8266_REG(0xF04) // INT_RAW
#define U1IS ESP8266_REG(0xF08) // INT_STATUS
#define U1IE ESP8266_REG(0xF0c) // INT_ENABLE
#define U1IC ESP8266_REG(0xF10) // INT_CLEAR
#define U1D  ESP8266_REG(0xF14) // CLKDIV
#define U1A  ESP8266_REG(0xF18) // AUTOBAUD
#define U1S  ESP8266_REG(0xF1C) // STATUS
#define U1C0 ESP8266_REG(0xF20) // CONF0
#define U1C1 ESP8266_REG(0xF24) // CONF1
#define U1LP ESP8266_REG(0xF28) // LOW_PULSE
#define U1HP ESP8266_REG(0xF2C) // HIGH_PULSE
#define U1PN ESP8266_REG(0xF30) // PULSE_NUM
#define U1DT ESP8266_REG(0xF78) // DATE
#define U1ID ESP8266_REG(0xF7C) // ID

// UART(N) registers
#undef USF
#undef USIR
#undef USIS
#undef USIE
#undef USIC
#undef USD
#undef USA
#undef USS
#undef USC0
#undef USC1
#undef USLP
#undef USHP
#undef USPN
#undef USDT
#undef USID

#define USF(N)  ESP8266_REG( 0x000 + ( 0xF00 * ( (N) & 1 ) ) ) // UART FIFO
#define USIR(N) ESP8266_REG( 0x004 + ( 0xF00 * ( (N) & 1 ) ) ) // INT_RAW
#define USIS(N) ESP8266_REG( 0x008 + ( 0xF00 * ( (N) & 1 ) ) ) // INT_STATUS
#define USIE(N) ESP8266_REG( 0x00c + ( 0xF00 * ( (N) & 1 ) ) ) // INT_ENABLE
#define USIC(N) ESP8266_REG( 0x010 + ( 0xF00 * ( (N) & 1 ) ) ) // INT_CLEAR
#define USD(N)  ESP8266_REG( 0x014 + ( 0xF00 * ( (N) & 1 ) ) ) // CLKDIV
#define USA(N)  ESP8266_REG( 0x018 + ( 0xF00 * ( (N) & 1 ) ) ) // AUTOBAUD
#define USS(N)  ESP8266_REG( 0x01C + ( 0xF00 * ( (N) & 1 ) ) ) // STATUS
#define USC0(N) ESP8266_REG( 0x020 + ( 0xF00 * ( (N) & 1 ) ) ) // CONF0
#define USC1(N) ESP8266_REG( 0x024 + ( 0xF00 * ( (N) & 1 ) ) ) // CONF1
#define USLP(N) ESP8266_REG( 0x028 + ( 0xF00 * ( (N) & 1 ) ) ) // LOW_PULSE
#define USHP(N) ESP8266_REG( 0x02C + ( 0xF00 * ( (N) & 1 ) ) ) // HIGH_PULSE
#define USPN(N) ESP8266_REG( 0x030 + ( 0xF00 * ( (N) & 1 ) ) ) // PULSE_NUM
#define USDT(N) ESP8266_REG( 0x078 + ( 0xF00 * ( (N) & 1 ) ) ) // DATE
#define USID(N) ESP8266_REG( 0x07C + ( 0xF00 * ( (N) & 1 ) ) ) // ID

// UART interrupt registers bits
#define UITO  8 // RX FIFO timeout
#define UIBD  7 // Break detected
#define UICTS 6 // CTS changed
#define UIDSR 5 // DSR change
#define UIOF  4 // RX FIFO overFlow
#define UIFR  3 // Frame error
#define UIPE  2 // Parity error
#define UIFE  1 // TX FIFO empty
#define UIFF  0 // RX FIFO full

// UART status registers bits
//
// USTX does not seem to work (always reads as 0 for both uarts)
// Possible workaround: enable loopback UxC0 |= (1 << UCLBE) and read USRXD
// see https://github.com/esp8266/Arduino/issues/7256 for discussion
#define USTX    31 // TX  pin  level
#define USRTS   30 // RTS pin  level
#define USDTR   39 // DTR pin  level
#define USTXC   16 // TX  FIFO count (8-bit)
#define USRXD   15 // RX  pin  level
#define USCTS   14 // CTS pin  level
#define USDSR   13 // DSR pin  level
#define USRXC    0 // RX  FIFO count (8-bit)

// UART configuration 0 registers bits
#define UCDTRI  24 // Invert DTR
#define UCRTSI  23 // Invert RTS
#define UCTXI   22 // Invert TX
#define UCDSRI  21 // Invert DSR
#define UCCTSI  20 // Invert CTS
#define UCRXI   19 // Invert RX
#define UCTXRST 18 // Reset TX FIFO
#define UCRXRST 17 // Reset RX FIFO
#define UCTXHFE 15 // TX harware flow enable
#define UCLBE   14 // LoopBack enable
#define UCBRK   8  // Send break on the TX line
#define UCSWDTR 7  // Set this bit to assert DTR
#define UCSWRTS 6  // Set this bit to assert RTS
#define UCSBN   4  // Stop bits count (2-bit) => 0:disable ; 1:1bit ; 2:1.5bit ; 3:2bit
#define UCBN    2  // Data bits count (2-bit) => 0:5bit ; 1:6bit ; 2:7bit ; 3:8bit
#define UCPAE   1  // Parity Enable
#define UCPA    0  // Parity (0:even ; 1:odd)

// UART configuration 1 registers bits
#define UCTOE   31 // RX timeOut enable
#define UCTOT   24 // RX timeOut treshold (7-bit)
#define UCRXHFE 23 // RX harware flow enable
#define UCRXHFT 16 // RX harware flow treshold (7-bit)
#define UCFET   8  // TX FIFO empty treshold (7-bit)
#define UCFFT   0  // RX FIFO full treshold (7-bit)

// WDT feed register
#define WDTFEED    ESP8266_REG(0x914)
#define WDT_FEED() (WDTFEED = 0x73)

// SPI_READY
#define SPIRDY   ESP8266_DREG(0x0C)
#define SPI_BUSY 9 // Wait SPI idle

// SPI0 registers (SPI0 is used for the flash)
#define SPI0CMD  ESP8266_REG(0x200)
#define SPI0A    ESP8266_REG(0x204)
#define SPI0C    ESP8266_REG(0x208)
#define SPI0C1   ESP8266_REG(0x20C)
#define SPI0RS   ESP8266_REG(0x210)
#define SPI0C2   ESP8266_REG(0x214)
#define SPI0CLK  ESP8266_REG(0x218)
#define SPI0U    ESP8266_REG(0x21C)
#define SPI0U1   ESP8266_REG(0x220)
#define SPI0U2   ESP8266_REG(0x224)
#define SPI0WS   ESP8266_REG(0x228)
#define SPI0P    ESP8266_REG(0x22C)
#define SPI0S    ESP8266_REG(0x230)
#define SPI0S1   ESP8266_REG(0x234)
#define SPI0S2   ESP8266_REG(0x238)
#define SPI0S3   ESP8266_REG(0x23C)
#define SPI0W0   ESP8266_REG(0x240)
#define SPI0W1   ESP8266_REG(0x244)
#define SPI0W2   ESP8266_REG(0x248)
#define SPI0W3   ESP8266_REG(0x24C)
#define SPI0W4   ESP8266_REG(0x250)
#define SPI0W5   ESP8266_REG(0x254)
#define SPI0W6   ESP8266_REG(0x258)
#define SPI0W7   ESP8266_REG(0x25C)
#define SPI0W8   ESP8266_REG(0x260)
#define SPI0W9   ESP8266_REG(0x264)
#define SPI0W10  ESP8266_REG(0x268)
#define SPI0W11  ESP8266_REG(0x26C)
#define SPI0W12  ESP8266_REG(0x270)
#define SPI0W13  ESP8266_REG(0x274)
#define SPI0W14  ESP8266_REG(0x278)
#define SPI0W15  ESP8266_REG(0x27C)
#define SPI0E3   ESP8266_REG(0x2FC)

#undef  SPI0W
#define SPI0W(P) ESP8266_REG( 0x240 + ( ( (P) & 0xF ) * 4 ) )

// SPI1 registers
#define SPI1CMD  ESP8266_REG(0x100)
#define SPI1A    ESP8266_REG(0x104)
#define SPI1C    ESP8266_REG(0x108)
#define SPI1C1   ESP8266_REG(0x10C)
#define SPI1RS   ESP8266_REG(0x110)
#define SPI1C2   ESP8266_REG(0x114)
#define SPI1CLK  ESP8266_REG(0x118)
#define SPI1U    ESP8266_REG(0x11C)
#define SPI1U1   ESP8266_REG(0x120)
#define SPI1U2   ESP8266_REG(0x124)
#define SPI1WS   ESP8266_REG(0x128)
#define SPI1P    ESP8266_REG(0x12C)
#define SPI1S    ESP8266_REG(0x130)
#define SPI1S1   ESP8266_REG(0x134)
#define SPI1S2   ESP8266_REG(0x138)
#define SPI1S3   ESP8266_REG(0x13C)
#define SPI1W0   ESP8266_REG(0x140)
#define SPI1W1   ESP8266_REG(0x144)
#define SPI1W2   ESP8266_REG(0x148)
#define SPI1W3   ESP8266_REG(0x14C)
#define SPI1W4   ESP8266_REG(0x150)
#define SPI1W5   ESP8266_REG(0x154)
#define SPI1W6   ESP8266_REG(0x158)
#define SPI1W7   ESP8266_REG(0x15C)
#define SPI1W8   ESP8266_REG(0x160)
#define SPI1W9   ESP8266_REG(0x164)
#define SPI1W10  ESP8266_REG(0x168)
#define SPI1W11  ESP8266_REG(0x16C)
#define SPI1W12  ESP8266_REG(0x170)
#define SPI1W13  ESP8266_REG(0x174)
#define SPI1W14  ESP8266_REG(0x178)
#define SPI1W15  ESP8266_REG(0x17C)
#define SPI1E0   ESP8266_REG(0x1F0)
#define SPI1E1   ESP8266_REG(0x1F4)
#define SPI1E2   ESP8266_REG(0x1F8)
#define SPI1E3   ESP8266_REG(0x1FC)

#undef  SPI1W
#define SPI1W(P) ESP8266_REG( 0x140 + ( ( (P) & 0xF ) * 4 ) )

// SPI0, SPI1 & I2S interupt register
#define SPIIR ESP8266_DREG(0x20)
#define SPII0 4 // SPI0 interrupt
#define SPII1 7 // SPI1 interrupt
#define SPII2 9 // I2S  interrupt

// SPI command
#define SPICMDREAD (1 << 31) // SPI_FLASH_READ
#define SPICMDWREN (1 << 30) // SPI_FLASH_WREN
#define SPICMDWRDI (1 << 29) // SPI_FLASH_WRDI
#define SPICMDRDID (1 << 28) // SPI_FLASH_RDID
#define SPICMDRDSR (1 << 27) // SPI_FLASH_RDSR
#define SPICMDWRSR (1 << 26) // SPI_FLASH_WRSR
#define SPICMDPP   (1 << 25) // SPI_FLASH_PP
#define SPICMDSE   (1 << 24) // SPI_FLASH_SE
#define SPICMDBE   (1 << 23) // SPI_FLASH_BE
#define SPICMDCE   (1 << 22) // SPI_FLASH_CE
#define SPICMDDP   (1 << 21) // SPI_FLASH_DP
#define SPICMDRES  (1 << 20) // SPI_FLASH_RES
#define SPICMDHPM  (1 << 19) // SPI_FLASH_HPM
#define SPICMDUSR  (1 << 18) // SPI_FLASH_USR
#define SPIBUSY    (1 << 18) // SPI_USR

// SPI control (SPIxC)
#define SPICWBO       (1 << 26) // SPI_WR_BIT_ODER
#define SPICRBO       (1 << 25) // SPI_RD_BIT_ODER
#define SPICQIO       (1 << 24) // SPI_QIO_MODE
#define SPICDIO       (1 << 23) // SPI_DIO_MODE
#define SPIC2BSE      (1 << 22) // SPI_TWO_BYTE_STATUS_EN
#define SPICWPR       (1 << 21) // SPI_WP_REG
#define SPICQOUT      (1 << 20) // SPI_QOUT_MODE
#define SPICSHARE     (1 << 19) // SPI_SHARE_BUS
#define SPICHOLD      (1 << 18) // SPI_HOLD_MODE
#define SPICAHB       (1 << 17) // SPI_ENABLE_AHB
#define SPICSSTAAI    (1 << 16) // SPI_SST_AAI
#define SPICRESANDRES (1 << 15) // SPI_RESANDRES
#define SPICDOUT      (1 << 14) // SPI_DOUT_MODE
#define SPICFASTRD    (1 << 13) // SPI_FASTRD_MODE

// SPI CTRL1 (SPIxC1)
#define SPIC1TCSH   0xF    // SPI_T_CSH
#define SPIC1TCSH_S 28     // SPI_T_CSH_S
#define SPIC1TRES   0xFFF  // SPI_T_RES
#define SPIC1TRES_S 16     // SPI_T_RES_S
#define SPIC1BTL    0xFFFF // SPI_BUS_TIMER_LIMIT
#define SPIC1BTL_S  0      // SPI_BUS_TIMER_LIMIT_S

// SPI status (SPIxRS)
#define SPIRSEXT    0xFF     // SPI_STATUS_EXT
#define SPIRSEXT_S  24       // SPI_STATUS_EXT_S
#define SPIRSWB     0xFF     // SPI_WB_MODE
#define SPIRSWB_S   16       // SPI_WB_MODE_S
#define SPIRSSP     (1 << 7) // SPI_FLASH_STATUS_PRO_FLAG
#define SPIRSTBP    (1 << 5) // SPI_FLASH_TOP_BOT_PRO_FLAG
#define SPIRSBP2    (1 << 4) // SPI_FLASH_BP2
#define SPIRSBP1    (1 << 3) // SPI_FLASH_BP1
#define SPIRSBP0    (1 << 2) // SPI_FLASH_BP0
#define SPIRSWRE    (1 << 1) // SPI_FLASH_WRENABLE_FLAG
#define SPIRSBUSY   (1 << 0) // SPI_FLASH_BUSY_FLAG

// SPI CTRL2 (SPIxC2)
#define SPIC2CSDN     0xF // SPI_CS_DELAY_NUM
#define SPIC2CSDN_S   28  // SPI_CS_DELAY_NUM_S
#define SPIC2CSDM     0x3 // SPI_CS_DELAY_MODE
#define SPIC2CSDM_S   26  // SPI_CS_DELAY_MODE_S
#define SPIC2MOSIDN   0x7 // SPI_MOSI_DELAY_NUM
#define SPIC2MOSIDN_S 23  // SPI_MOSI_DELAY_NUM_S
#define SPIC2MOSIDM   0x3 // SPI_MOSI_DELAY_MODE
#define SPIC2MOSIDM_S 21  // SPI_MOSI_DELAY_MODE_S
#define SPIC2MISODN   0x7 // SPI_MISO_DELAY_NUM
#define SPIC2MISODN_S 18  // SPI_MISO_DELAY_NUM_S
#define SPIC2MISODM   0x3 // SPI_MISO_DELAY_MODE
#define SPIC2MISODM_S 16  // SPI_MISO_DELAY_MODE_S
#define SPIC2CKOHM    0xF // SPI_CK_OUT_HIGH_MODE
#define SPIC2CKOHM_S  12  // SPI_CK_OUT_HIGH_MODE_S
#define SPIC2CKOLM    0xF // SPI_CK_OUT_LOW_MODE
#define SPIC2CKOLM_S  8   // SPI_CK_OUT_LOW_MODE_S
#define SPIC2HT       0xF // SPI_HOLD_TIME
#define SPIC2HT_S     4   // SPI_HOLD_TIME_S
#define SPIC2ST       0xF // SPI_SETUP_TIME
#define SPIC2ST_S     0   // SPI_SETUP_TIME_S

// SPI clock (SPIxCLK)
#define SPICLK_EQU_SYSCLK (1 << 31) // SPI_CLK_EQU_SYSCLK
#define SPICLKDIVPRE      0x1FFF    // SPI_CLKDIV_PRE
#define SPICLKDIVPRE_S    18        // SPI_CLKDIV_PRE_S
#define SPICLKCN          0x3F      // SPI_CLKCNT_N
#define SPICLKCN_S        12        // SPI_CLKCNT_N_S
#define SPICLKCH          0x3F      // SPI_CLKCNT_H
#define SPICLKCH_S        6         // SPI_CLKCNT_H_S
#define SPICLKCL          0x3F      // SPI_CLKCNT_L
#define SPICLKCL_S        0         // SPI_CLKCNT_L_S

// SPI phases (SPIxU)
#define SPIUCOMMAND   (1 << 31) // COMMAND pahse, SPI_USR_COMMAND
#define SPIUADDR      (1 << 30) // ADDRESS phase, SPI_FLASH_USR_ADDR
#define SPIUDUMMY     (1 << 29) // DUMMY phase, SPI_FLASH_USR_DUMMY
#define SPIUMISO      (1 << 28) // MISO phase, SPI_FLASH_USR_DIN
#define SPIUMOSI      (1 << 27) // MOSI phase, SPI_FLASH_DOUT
#define SPIUDUMMYIDLE (1 << 26) // SPI_USR_DUMMY_IDLE
#define SPIUMOSIH     (1 << 25) // MOSI phase uses W8-W15, SPI_USR_DOUT_HIGHPART
#define SPIUMISOH     (1 << 24) // MISO pahse uses W8-W15, SPI_USR_DIN_HIGHPART
#define SPIUPREPHOLD  (1 << 23) // SPI_USR_PREP_HOLD
#define SPIUCMDHOLD   (1 << 22) // SPI_USR_CMD_HOLD
#define SPIUADDRHOLD  (1 << 21) // SPI_USR_ADDR_HOLD
#define SPIUDUMMYHOLD (1 << 20) // SPI_USR_DUMMY_HOLD
#define SPIUMISOHOLD  (1 << 19) // SPI_USR_DIN_HOLD
#define SPIUMOSIHOLD  (1 << 18) // SPI_USR_DOUT_HOLD
#define SPIUHOLDPOL   (1 << 17) // SPI_USR_HOLD_POL
#define SPIUSIO       (1 << 16) // SPI_SIO
#define SPIUFWQIO     (1 << 15) // SPI_FWRITE_QIO
#define SPIUFWDIO     (1 << 14) // SPI_FWRITE_DIO
#define SPIUFWQUAD    (1 << 13) // SPI_FWRITE_QUAD
#define SPIUFWDUAL    (1 << 12) // SPI_FWRITE_DUAL
#define SPIUWRBYO     (1 << 11) // SPI_WR_BYTE_ORDER
#define SPIURDBYO     (1 << 10) // SPI_RD_BYTE_ORDER
#define SPIUAHBEM     0x3       // SPI_AHB_ENDIAN_MODE
#define SPIUAHBEM_S   8         // SPI_AHB_ENDIAN_MODE_S
#define SPIUSME       (1 << 7)  // SPI master edge (0:falling, 1:rising), SPI_CK_OUT_EDGE
#define SPIUSSE       (1 << 6)  // SPI mlave edge (0:falling, 1:rising), SPI_CK_I_EDGE
#define SPIUCSSETUP   (1 << 5)  // SPI_CS_SETUP
#define SPIUCSHOLD    (1 << 4)  // SPI_CS_HOLD
#define SPIUAHBUCMD   (1 << 3)  // SPI_AHB_USR_COMMAND
#define SPIUAHBUCMD4B (1 << 1)  // SPI_AHB_USR_COMMAND_4BYTE
#define SPIUDUPLEX    (1 << 0)  // SPI_DOUTDIN

// SPI phase length locations
#define SPILCOMMAND 28 // 4 bits in SPIxU2 default 7  (8-bit)
#define SPILADDR    26 // 6 bits in SPIxU1 default:23 (24-bit)
#define SPILDUMMY   0  // 8 bits in SPIxU1 default:0  (0 cycle)
#define SPILMISO    8  // 9 bits in SPIxU1 default:0  (1-bit)
#define SPILMOSI    17 // 9 bits in SPIxU1 default:0  (1-bit)

// SPI phase length masks
#define SPIMCOMMAND 0xF
#define SPIMADDR    0x3F
#define SPIMDUMMY   0xFF
#define SPIMMISO    0x1FF
#define SPIMMOSI    0x1FF

// SPI slave (SPIxS)
#define SPISSRES    (1 << 31) // SYNC RESET, SPI_SYNC_RESET
#define SPISE       (1 << 30) // Slave Enable, SPI_SLAVE_MODE
#define SPISBE      (1 << 29) // WR/RD BUF enable, SPI_SLV_WR_RD_BUF_EN
#define SPISSE      (1 << 28) // STA enable, SPI_SLV_WR_RD_STA_EN
#define SPISCD      (1 << 27) // CMD define, SPI_SLV_CMD_DEFINE
#define SPISTRCNT   0xF       // SPI_TRANS_CNT
#define SPISTRCNT_S 23        // SPI_TRANS_CNT_S
#define SPISSLS     0x7       // SPI_SLV_LAST_STATE
#define SPISSLS_S   20        // SPI_SLV_LAST_STATE_S
#define SPISSLC     0x7       // SPI_SLV_LAST_COMMAND
#define SPISSLC_S   17        // SPI_SLV_LAST_COMMAND_S
#define SPISCSIM    0x3       // SPI_CS_I_MODE
#define SPIDCSIM_S  10        // SPI_CS_I_MODE_S
#define SPISTRIE    (1 << 9)  // TRANS interrupt enable
#define SPISWSIE    (1 << 8)  // WR_STA interrupt enable
#define SPISRSIE    (1 << 7)  // RD_STA interrupt enable
#define SPISWBIE    (1 << 6)  // WR_BUF interrupt enable
#define SPISRBIE    (1 << 5)  // RD_BUF interrupt enable
#define SPISTRIS    (1 << 4)  // TRANS interrupt status
#define SPISWSIS    (1 << 3)  // WR_STA interrupt status
#define SPISRSIS    (1 << 2)  // RD_STA interrupt status
#define SPISWBIS    (1 << 1)  // WR_BUF interrupt status
#define SPISRBIS    (1 << 0)  // RD_BUF interrupt status

// SPI slave 1 (SPIxS1)
#define SPIS1LSTA   27        // 5-bit in SPIxS1 default:0 (1-bit), SPI_SLV_STATUS_BITLEN
#define SPIS1FE     (1 << 26) // SPI_SLV_STATUS_FAST_EN
#define SPIS1RSTA   (1 << 25) // default:0 enable STA read from master, SPI_SLV_STATUS_READBACK
#define SPIS1LBUF   16        // 9-bit in SPIxS1 default:0 (1-bit), SPI_SLV_BUF_BITLEN
#define SPIS1LRBA   10        // 6-bit in SPIxS1 default:0 (1-bit), SPI_SLV_RD_ADDR_BITLEN
#define SPIS1LWBA   4         // 6-bit in SPIxS1 default:0 (1-bit), SPI_SLV_WR_ADDR_BITLEN
#define SPIS1WSDE   (1 << 3)  // SPI_SLV_WRSTA_DUMMY_EN
#define SPIS1RSDE   (1 << 2)  // SPI_SLV_RDSTA_DUMMY_EN
#define SPIS1WBDE   (1 << 1)  // SPI_SLV_WRBUF_DUMMY_EN
#define SPIS1RBDE   (1 << 0)  // SPI_SLV_RDBUF_DUMMY_EN

// SPI slave 2 (SPIxS2)
#define SPIS2WBDL   0xFF // SPI_SLV_WRBUF_DUMMY_CYCLELEN
#define SPIS2WBDL_S 24   // SPI_SLV_WRBUF_DUMMY_CYCLELEN_S
#define SPIS2RBDL   0xFF // SPI_SLV_RDBUF_DUMMY_CYCLELEN
#define SPIS2RBDL_S 16   // SPI_SLV_RDBUF_DUMMY_CYCLELEN_S
#define SPIS2WSDL   0xFF // SPI_SLV_WRSTA_DUMMY_CYCLELEN
#define SPIS2WSDL_S 8    // SPI_SLV_WRSTA_DUMMY_CYCLELEN_S
#define SPIS2RSDL   0xFF // SPI_SLV_RDSTA_DUMMY_CYCLELEN
#define SPIS2RSDL_S 0    // SPI_SLV_RDSTA_DUMMY_CYCLELEN_S

// SPI slave3 (SPIxS3)
#define SPIS3WSCV   0xFF // SPI_SLV_WRSTA_CMD_VALUE
#define SPIS3WSCV_S 24   // SPI_SLV_WRSTA_CMD_VALUE_S
#define SPIS3RSCV   0xFF // SPI_SLV_RDSTA_CMD_VALUE
#define SPIS3RSCV_S 16   // SPI_SLV_RDSTA_CMD_VALUE_S
#define SPIS3WBCV   0xFF // SPI_SLV_WRBUF_CMD_VALUE
#define SPIS3WBCV_S 8    // SPI_SLV_WRBUF_CMD_VALUE_S
#define SPIS3RBCV   0xFF // SPI_SLV_RDBUF_CMD_VALUE
#define SPIS3RBCV_S 0    // SPI_SLV_RDBUF_CMD_VALUE_S

// SPI EXT0 (SPIxE0)
#define SPIE0TPPEN  (1 << 31) // SPI_T_PP_ENA
#define SPIE0TPPS   0xF       // SPI_T_PP_SHIFT
#define SPIE0TPPS_S 16        // SPI_T_PP_SHIFT_S
#define SPIE0TPPT   0xFFF     // SPI_T_PP_TIME
#define SPIE0TPPT_S 0         // SPI_T_PP_TIME_S

// SPI EXT1 (SPIxE1)
#define SPIE1TEREN  (1 << 31) // SPI_T_ERASE_ENA
#define SPIE1TERS   0xF       // SPI_T_ERASE_SHIFT
#define SPIE1TERS_S 16        // SPI_T_ERASE_SHIFT_S
#define SPIE1TERT   0xFFF     // SPI_T_ERASE_TIME
#define SPIE1TERT_S 0         // SPI_T_ERASE_TIME_S

// SPI EXT2 (SPIxE2)
#define SPIE2ST   0x7 // SPI_ST
#define SPIE2ST_S 0   // SPI_ST_S

// SPI EXT3 (SPIxE3)
#define SPIE2IHEN   0x3 // SPI_INT_HOLD_ENA
#define SPIE2IHEN_S 0   // SPI_INT_HOLD_ENA_S

// SPI pin (SPIxP)
#define SPIPCS2DIS (1 << 2)
#define SPIPCS1DIS (1 << 1)
#define SPIPCS0DIS (1 << 0)

// SLC (DMA) registers
#define SLCC0     ESP8266_REG(0xB00) // SLC_CONF0
#define SLCIR     ESP8266_REG(0xB04) // SLC_INT_RAW
#define SLCIS     ESP8266_REG(0xB08) // SLC_INT_STATUS
#define SLCIE     ESP8266_REG(0xB0C) // SLC_INT_ENA
#define SLCIC     ESP8266_REG(0xB10) // SLC_INT_CLR
#define SLCRXS    ESP8266_REG(0xB14) // SLC_RX_STATUS
#define SLCRXP    ESP8266_REG(0xB18) // SLC_RX_FIFO_PUSH
#define SLCTXS    ESP8266_REG(0xB1C) // SLC_TX_STATUS
#define SLCTXP    ESP8266_REG(0xB20) // SLC_TX_FIFO_POP
#define SLCRXL    ESP8266_REG(0xB24) // SLC_RX_LINK
#define SLCTXL    ESP8266_REG(0xB28) // SLC_TX_LINK
#define SLCIVTH   ESP8266_REG(0xB2C) // SLC_INTVEC_TOHOST
#define SLCT0     ESP8266_REG(0xB30) // SLC_TOKEN0
#define SLCT1     ESP8266_REG(0xB34) // SLC_TOKEN1
#define SLCC1     ESP8266_REG(0xB38) // SLC_CONF1
#define SLCS0     ESP8266_REG(0xB3C) // SLC_STATE0
#define SLCS1     ESP8266_REG(0xB40) // SLC_STATE1
#define SLCBC     ESP8266_REG(0xB44) // SLC_BRIDGE_CONF
#define SLCRXEDA  ESP8266_REG(0xB48) // SLC_RX_EOF_DES_ADDR
#define SLCTXEDA  ESP8266_REG(0xB4C) // SLC_TX_EOF_DES_ADDR
#define SLCRXEBDA ESP8266_REG(0xB50) // SLC_RX_EOF_BFR_DES_ADDR
#define SLCAT     ESP8266_REG(0xB54) // SLC_AHB_TEST
#define SLCSS     ESP8266_REG(0xB58) // SLC_SDIO_ST
#define SLCRXDC   ESP8266_REG(0xB5C) // SLC_RX_DSCR_CONF
#define SLCTXD    ESP8266_REG(0xB60) // SLC_TXLINK_DSCR
#define SLCTXDB0  ESP8266_REG(0xB64) // SLC_TXLINK_DSCR_BF0
#define SLCTXDB1  ESP8266_REG(0xB68) // SLC_TXLINK_DSCR_BF1
#define SLCRXD    ESP8266_REG(0xB6C) // SLC_RXLINK_DSCR
#define SLCRXDB0  ESP8266_REG(0xB70) // SLC_RXLINK_DSCR_BF0
#define SLCRXDB1  ESP8266_REG(0xB74) // SLC_RXLINK_DSCR_BF1
#define SLCDT     ESP8266_REG(0xB78) // SLC_DATE
#define SLCID     ESP8266_REG(0xB7C) // SLC_ID
#define SLCHIR    ESP8266_REG(0xB88) // SLC_HOST_INTR_RAW
#define SLCHC0    ESP8266_REG(0xB94) // SLC_HOST_CONF_W0
#define SLCHC1    ESP8266_REG(0xB98) // SLC_HOST_CONF_W1
#define SLCHIS    ESP8266_REG(0xB9C) // SLC_HOST_INTR_ST
#define SLCHC2    ESP8266_REG(0xBA0) // SLC_HOST_CONF_W2
#define SLCHC3    ESP8266_REG(0xBA4) // SLC_HOST_CONF_W3
#define SLCHC4    ESP8266_REG(0xBA8) // SLC_HOST_CONF_W4
#define SLCHIC    ESP8266_REG(0xBB0) // SLC_HOST_INTR_CLR
#define SLCHIE    ESP8266_REG(0xBB4) // SLC_HOST_INTR_ENA
#define SLCHC5    ESP8266_REG(0xBBC) // SLC_HOST_CONF_W5

// SLC (DMA) configuration 0
#define SLCMM     (0x3)    // SLC_MODE
#define SLCM      (12)     // SLC_MODE_S
#define SLCDTBE   (1 << 9) // SLC_DATA_BURST_EN
#define SLCDBE    (1 << 8) // SLC_DSCR_BURST_EN
#define SLCRXNRC  (1 << 7) // SLC_RX_NO_RESTART_CLR
#define SLCRXAW   (1 << 6) // SLC_RX_AUTO_WRBACK
#define SLCRXLT   (1 << 5) // SLC_RX_LOOP_TEST
#define SLCTXLT   (1 << 4) // SLC_TX_LOOP_TEST
#define SLCAR     (1 << 3) // SLC_AHBM_RST
#define SLCAFR    (1 << 2) // SLC_AHBM_FIFO_RST
#define SLCRXLR   (1 << 1) // SLC_RXLINK_RST
#define SLCTXLR   (1 << 0) // SLC_TXLINK_RST

// SLC (DMA) interrupt
#define SLCITXDE  (1 << 21) // SLC_TX_DSCR_EMPTY_INT
#define SLCIRXDER (1 << 20) // SLC_RX_DSCR_ERR_INT
#define SLCITXDER (1 << 19) // SLC_TX_DSCR_ERR_INT
#define SLCITH    (1 << 18) // SLC_TOHOST_INT
#define SLCIRXEOF (1 << 17) // SLC_RX_EOF_INT
#define SLCIRXD   (1 << 16) // SLC_RX_DONE_INT
#define SLCITXEOF (1 << 15) // SLC_TX_EOF_INT
#define SLCITXD   (1 << 14) // SLC_TX_DONE_INT
#define SLCIT0    (1 << 13) // SLC_TOKEN1_1TO0_INT
#define SLCIT1    (1 << 12) // SLC_TOKEN0_1TO0_INT
#define SLCITXO   (1 << 11) // SLC_TX_OVF_INT
#define SLCIRXU   (1 << 10) // SLC_RX_UDF_INT
#define SLCITXS   (1 << 9)  // SLC_TX_START_INT
#define SLCIRXS   (1 << 8)  // SLC_RX_START_INT
#define SLCIFH7   (1 << 7)  // SLC_FRHOST_BIT7_INT
#define SLCIFH6   (1 << 6)  // SLC_FRHOST_BIT6_INT
#define SLCIFH5   (1 << 5)  // SLC_FRHOST_BIT5_INT
#define SLCIFH4   (1 << 4)  // SLC_FRHOST_BIT4_INT
#define SLCIFH3   (1 << 3)  // SLC_FRHOST_BIT3_INT
#define SLCIFH2   (1 << 2)  // SLC_FRHOST_BIT2_INT
#define SLCIFH1   (1 << 1)  // SLC_FRHOST_BIT1_INT
#define SLCIFH0   (1 << 0)  // SLC_FRHOST_BIT0_INT

// SLC (DMA) RX_STATUS
#define SLCRXE    (1 << 1) // SLC_RX_EMPTY
#define SLCRXF    (1 << 0) // SLC_RX_FULL

// SLC (DMA) TX_STATUS
#define SLCTXE    (1 << 1) // SLC_TX_EMPTY
#define SLCTXF    (1 << 0) // SLC_TX_FULL

// SLC (DMA) RX_FIFO_PUSH
#define SLCRXFP   (1 << 16) // SLC_RXFIFO_PUSH
#define SLCRXWDM  (0x1FF)   // SLC_RXFIFO_WDATA
#define SLCRXWD   (0)       // SLC_RXFIFO_WDATA_S

// SLC (DMA) TX_FIFO_POP
#define SLCTXFP   (1 << 16) // SLC_TXFIFO_POP
#define SLCTXRDM  (0x7FF)   // SLC_TXFIFO_RDATA
#define SLCTXRD   (0)       // SLC_TXFIFO_RDATA_S

// SLC (DMA) RX_LINK
#define SLCRXLP   (1 << 31) // SLC_RXLINK_PARK
#define SLCRXLRS  (1 << 30) // SLC_RXLINK_RESTART
#define SLCRXLS   (1 << 29) // SLC_RXLINK_START
#define SLCRXLE   (1 << 28) // SLC_RXLINK_STOP
#define SLCRXLAM  (0xFFFF)  // SLC_RXLINK_DESCADDR_MASK
#define SLCRXLA   (0)       // SLC_RXLINK_ADDR_S

// SLC (DMA) TX_LINK
#define SLCTXLP   (1 << 31) // SLC_TXLINK_PARK
#define SLCTXLRS  (1 << 30) // SLC_TXLINK_RESTART
#define SLCTXLS   (1 << 29) // SLC_TXLINK_START
#define SLCTXLE   (1 << 28) // SLC_TXLINK_STOP
#define SLCTXLAM  (0xFFFF)  // SLC_TXLINK_DESCADDR_MASK
#define SLCTXLA   (0)       // SLC_TXLINK_ADDR_S

// SLC (DMA) TOKENx
#define SLCTM     (0xFFF)   // SLC_TOKENx_MASK
#define SLCTT     (16)      // SLC_TOKENx_S
#define SLCTIM    (1 << 14) // SLC_TOKENx_LOCAL_INC_MORE
#define SLCTI     (1 << 13) // SLC_TOKENx_LOCAL_INC
#define SLCTW     (1 << 12) // SLC_TOKENx_LOCAL_WR
#define SLCTDM    (0xFFF)   // SLC_TOKENx_LOCAL_WDATA
#define SLCTD     (0)       // SLC_TOKENx_LOCAL_WDATA_S

// SLC (DMA) BRIDGE_CONF
#define SLCBFMEM  (0xF)     // SLC_FIFO_MAP_ENA
#define SLCBFME   (8)       // SLC_FIFO_MAP_ENA_S
#define SLCBTEEM  (0x3F)    // SLC_TXEOF_ENA
#define SLCBTEE   (0)       // SLC_TXEOF_ENA_S

// SLC (DMA) AHB_TEST
#define SLCATAM   (0x3)     // SLC_AHB_TESTADDR
#define SLCATA    (4)       // SLC_AHB_TESTADDR_S
#define SLCATMM   (0x7)     // SLC_AHB_TESTMODE
#define SLCATM    (0)       // SLC_AHB_TESTMODE_S

// SLC (DMA) SDIO_ST
#define SLCSBM    (0x7)     // SLC_BUS_ST
#define SLCSB     (12)      // SLC_BUS_ST_S
#define SLCSW     (1 << 8)  // SLC_SDIO_WAKEUP
#define SLCSFM    (0xF)     // SLC_FUNC_ST
#define SLCSF     (4)       // SLC_FUNC_ST_S
#define SLCSCM    (0x7)     // SLC_CMD_ST
#define SLCSC     (0)       // SLC_CMD_ST_S

// SLC (DMA) RX_DSCR_CONF
#define SLCBRXFE  (1 << 20) // SLC_RX_FILL_EN
#define SLCBRXEM  (1 << 19) // SLC_RX_EOF_MODE
#define SLCBRXFM  (1 << 18) // SLC_RX_FILL_MODE
#define SLCBINR   (1 << 17) // SLC_INFOR_NO_REPLACE
#define SLCBTNR   (1 << 16) // SLC_TOKEN_NO_REPLACE
#define SLCBPICM  (0xFFFF)  // SLC_POP_IDLE_CNT
#define SLCBPIC   (0)       // SLC_POP_IDLE_CNT_S

// I2S registers
#define i2c_writeReg_Mask(BLOCK, HOST_ID, REG_ADD, MSB, LSB, INDATA) rom_i2c_writeReg_Mask(BLOCK, HOST_ID, REG_ADD, MSB, LSB, INDATA)
#define i2c_writeReg_Mask_def(BLOCK, REG_ADD, INDATA)                i2c_writeReg_Mask(BLOCK, BLOCK##_hostid, REG_ADD, REG_ADD##_msb, REG_ADD##_lsb, INDATA)

#define i2c_bbpll                        0x67
#define i2c_bbpll_hostid                 4
#define i2c_bbpll_en_audio_clock_out     4
#define i2c_bbpll_en_audio_clock_out_msb 7
#define i2c_bbpll_en_audio_clock_out_lsb 7
#define I2S_CLK_ENABLE()                 i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1)
#define I2SBASEFREQ                      (160000000L)

#define I2STXF  ESP8266_REG(0xe00) // I2STXFIFO (32-bit)
#define I2SRXF  ESP8266_REG(0xe04) // I2SRXFIFO (32-bit)
#define I2SC    ESP8266_REG(0xe08) // I2SCONF
#define I2SIR   ESP8266_REG(0xe0C) // I2SINT_RAW
#define I2SIS   ESP8266_REG(0xe10) // I2SINT_ST
#define I2SIE   ESP8266_REG(0xe14) // I2SINT_ENA
#define I2SIC   ESP8266_REG(0xe18) // I2SINT_CLR
#define I2ST    ESP8266_REG(0xe1C) // I2STIMING
#define I2SFC   ESP8266_REG(0xe20) // I2S_FIFO_CONF
#define I2SRXEN ESP8266_REG(0xe24) // I2SRXEOF_NUM (32-bit)
#define I2SCSD  ESP8266_REG(0xe28) // I2SCONF_SIGLE_DATA (32-bit)
#define I2SCC   ESP8266_REG(0xe2C) // I2SCONF_CHAN

// I2S configuration
#define I2SBDM  (0x3F)    // I2S_BCK_DIV_NUM
#define I2SBD   (22)      // I2S_BCK_DIV_NUM_S
#define I2SCDM  (0x3F)    // I2S_CLKM_DIV_NUM
#define I2SCD   (16)      // I2S_CLKM_DIV_NUM_S
#define I2SBMM  (0xF)     // I2S_BITS_MOD
#define I2SBM   (12)      // I2S_BITS_MOD_S
#define I2SRMS  (1 << 11) // I2S_RECE_MSB_SHIFT
#define I2STMS  (1 << 10) // I2S_TRANS_MSB_SHIFT
#define I2SRXS  (1 << 9)  // I2S_I2S_RX_START
#define I2STXS  (1 << 8)  // I2S_I2S_TX_START
#define I2SMR   (1 << 7)  // I2S_MSB_RIGHT
#define I2SRF   (1 << 6)  // I2S_RIGHT_FIRST
#define I2SRSM  (1 << 5)  // I2S_RECE_SLAVE_MOD
#define I2STSM  (1 << 4)  // I2S_TRANS_SLAVE_MOD
#define I2SRXFR (1 << 3)  // I2S_I2S_RX_FIFO_RESET
#define I2STXFR (1 << 2)  // I2S_I2S_TX_FIFO_RESET
#define I2SRXR  (1 << 1)  // I2S_I2S_RX_RESET
#define I2STXR  (1 << 0)  // I2S_I2S_TX_RESET
#define I2SRST  (0xF)     // I2S_I2S_RESET_MASK

// I2S interrupt
#define I2SITXRE (1 << 5) // I2S_I2S_TX_REMPTY_INT
#define I2SITXWF (1 << 4) // I2S_I2S_TX_WFULL_INT
#define I2SIRXRE (1 << 3) // I2S_I2S_RX_REMPTY_INT
#define I2SIRXWF (1 << 2) // I2S_I2S_RX_WFULL_INT
#define I2SITXPD (1 << 1) // I2S_I2S_TX_PUT_DATA_INT
#define I2SIRXTD (1 << 0) // I2S_I2S_RX_TAKE_DATA_INT

// I2S timing
#define I2STBII  (1 << 22)  // I2S_TRANS_BCK_IN_INV
#define I2SRDS   (1 << 21)  // I2S_RECE_DSYNC_SW
#define I2STDS   (1 << 20)  // I2S_TRANS_DSYNC_SW
#define I2SRBODM (0x3)      // I2S_RECE_BCK_OUT_DELAY
#define I2SRBOD  (18)       // I2S_RECE_BCK_OUT_DELAY_S
#define I2SRWODM (0x3)      // I2S_RECE_WS_OUT_DELAY
#define I2SRWOD  (16)       // I2S_RECE_WS_OUT_DELAY_S
#define I2STSODM (0x3)      // I2S_TRANS_SD_OUT_DELAY
#define I2STSOD  (14)       // I2S_TRANS_SD_OUT_DELAY_S
#define I2STWODM (0x3)      // I2S_TRANS_WS_OUT_DELAY
#define I2STWOD  (12)       // I2S_TRANS_WS_OUT_DELAY_S
#define I2STBODM (0x3)      // I2S_TRANS_BCK_OUT_DELAY
#define I2STBOD  (10)       // I2S_TRANS_BCK_OUT_DELAY_S
#define I2SRSIDM (0x3)      // I2S_RECE_SD_IN_DELAY
#define I2SRSID  (8)        // I2S_RECE_SD_IN_DELAY_S
#define I2SRWIDM (0x3)      // I2S_RECE_WS_IN_DELAY
#define I2SRWID  (6)        // I2S_RECE_WS_IN_DELAY_S
#define I2SRBIDM (0x3)      // I2S_RECE_BCK_IN_DELAY
#define I2SRBID  (4)        // I2S_RECE_BCK_IN_DELAY_S
#define I2STWIDM (0x3)      // I2S_TRANS_WS_IN_DELAY
#define I2STWID  (2)        // I2S_TRANS_WS_IN_DELAY_S
#define I2STBIDM (0x3)      // I2S_TRANS_BCK_IN_DELAY
#define I2STBID  (0)        // I2S_TRANS_BCK_IN_DELAY_S

// I2S FIFO configuration
#define I2SRXFMM (0x7)      // I2S_I2S_RX_FIFO_MOD
#define I2SRXFM  (16)       // I2S_I2S_RX_FIFO_MOD_S
#define I2STXFMM (0x7)      // I2S_I2S_TX_FIFO_MOD
#define I2STXFM  (13)       // I2S_I2S_TX_FIFO_MOD_S
#define I2SDE    (1 << 12)  // I2S_I2S_DSCR_EN
#define I2STXDNM (0x3F)     // I2S_I2S_TX_DATA_NUM
#define I2STXDN  (6)        // I2S_I2S_TX_DATA_NUM_S
#define I2SRXDNM (0x3F)     // I2S_I2S_RX_DATA_NUM
#define I2SRXDN  (0)        // I2S_I2S_RX_DATA_NUM_S

// I2S configuration channel
#define I2SRXCMM (0x3)      // I2S_RX_CHAN_MOD
#define I2SRXCM  (3)        // I2S_RX_CHAN_MOD_S
#define I2STXCMM (0x7)      // I2S_TX_CHAN_MOD
#define I2STXCM  (0)        // I2S_TX_CHAN_MOD_S

// Random Number Generator 32bit
// http://esp8266-re.foogod.com/wiki/Random_Number_Generator
#define RANDOM_REG32  ESP8266_DREG(0x20E44)


#endif
