/*
 * ESPRESSIF MIT License
 *
 * Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
 *
 * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
 * it is free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#ifndef _EAGLE_SOC_H_
#define _EAGLE_SOC_H_

//Register Bits{{
#define BIT31   0x80000000
#define BIT30   0x40000000
#define BIT29   0x20000000
#define BIT28   0x10000000
#define BIT27   0x08000000
#define BIT26   0x04000000
#define BIT25   0x02000000
#define BIT24   0x01000000
#define BIT23   0x00800000
#define BIT22   0x00400000
#define BIT21   0x00200000
#define BIT20   0x00100000
#define BIT19   0x00080000
#define BIT18   0x00040000
#define BIT17   0x00020000
#define BIT16   0x00010000
#define BIT15   0x00008000
#define BIT14   0x00004000
#define BIT13   0x00002000
#define BIT12   0x00001000
#define BIT11   0x00000800
#define BIT10   0x00000400
#define BIT9     0x00000200
#define BIT8     0x00000100
#define BIT7     0x00000080
#define BIT6     0x00000040
#define BIT5     0x00000020
#define BIT4     0x00000010
#define BIT3     0x00000008
#define BIT2     0x00000004
#define BIT1     0x00000002
#define BIT0     0x00000001
//}}

//Registers Operation {{
#define ETS_UNCACHED_ADDR(addr) (addr)
#define ETS_CACHED_ADDR(addr) (addr)


#define READ_PERI_REG(addr) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr)))
#define WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val)
#define CLEAR_PERI_REG_MASK(reg, mask) WRITE_PERI_REG((reg), (READ_PERI_REG(reg)&(~(mask))))
#define SET_PERI_REG_MASK(reg, mask)   WRITE_PERI_REG((reg), (READ_PERI_REG(reg)|(mask)))
#define GET_PERI_REG_BITS(reg, hipos,lowpos)      ((READ_PERI_REG(reg)>>(lowpos))&((1<<((hipos)-(lowpos)+1))-1))
#define SET_PERI_REG_BITS(reg,bit_map,value,shift) (WRITE_PERI_REG((reg),(READ_PERI_REG(reg)&(~((bit_map)<<(shift))))|((value)<<(shift)) ))
//}}

//Periheral Clock {{
#define  APB_CLK_FREQ                                80*1000000       //unit: Hz
#define  UART_CLK_FREQ                               APB_CLK_FREQ
#define  TIMER_CLK_FREQ                              (APB_CLK_FREQ>>8) //divided by 256
//}}

//Peripheral device base address define{{
#define PERIPHS_DPORT_BASEADDR              0x3ff00000
#define PERIPHS_GPIO_BASEADDR               0x60000300
#define PERIPHS_TIMER_BASEDDR               0x60000600
#define PERIPHS_RTC_BASEADDR                0x60000700
#define PERIPHS_IO_MUX						0x60000800
//}}

//Interrupt remap control registers define{{
#define EDGE_INT_ENABLE_REG                 (PERIPHS_DPORT_BASEADDR+0x04)
#define TM1_EDGE_INT_ENABLE()             SET_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT1)
#define TM1_EDGE_INT_DISABLE()            CLEAR_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT1)
//}}

//GPIO reg {{
#define GPIO_REG_READ(reg)                         READ_PERI_REG(PERIPHS_GPIO_BASEADDR + reg)
#define GPIO_REG_WRITE(reg, val)                 WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + reg, val)
#define GPIO_OUT_ADDRESS                         0x00
#define GPIO_OUT_W1TS_ADDRESS             0x04
#define GPIO_OUT_W1TC_ADDRESS             0x08

#define GPIO_ENABLE_ADDRESS                  0x0c
#define GPIO_ENABLE_W1TS_ADDRESS      0x10
#define GPIO_ENABLE_W1TC_ADDRESS      0x14
#define GPIO_OUT_W1TC_DATA_MASK      0x0000ffff

#define GPIO_IN_ADDRESS                            0x18

#define GPIO_STATUS_ADDRESS                  0x1c
#define GPIO_STATUS_W1TS_ADDRESS       0x20
#define GPIO_STATUS_W1TC_ADDRESS      0x24
#define GPIO_STATUS_INTERRUPT_MASK 0x0000ffff

#define GPIO_RTC_CALIB_SYNC                  PERIPHS_GPIO_BASEADDR+0x6c
#define RTC_CALIB_START                           BIT31  //first write to zero, then to one to start
#define RTC_PERIOD_NUM_MASK              0x3ff   //max 8ms
#define GPIO_RTC_CALIB_VALUE               PERIPHS_GPIO_BASEADDR+0x70
#define RTC_CALIB_RDY_S                           31  //after measure, flag to one, when start from zero to one, turn to zero
#define RTC_CALIB_VALUE_MASK             0xfffff

#define GPIO_PIN0_ADDRESS                        0x28

#define GPIO_ID_PIN0                                     0
#define GPIO_ID_PIN(n)                                   (GPIO_ID_PIN0+(n))
#define GPIO_LAST_REGISTER_ID                GPIO_ID_PIN(15)
#define GPIO_ID_NONE                                  0xffffffff

#define GPIO_PIN_COUNT                              16

#define GPIO_PIN_CONFIG_MSB                    12
#define GPIO_PIN_CONFIG_LSB                     11
#define GPIO_PIN_CONFIG_MASK                 0x00001800
#define GPIO_PIN_CONFIG_GET(x)                 (((x) & GPIO_PIN_CONFIG_MASK) >> GPIO_PIN_CONFIG_LSB)
#define GPIO_PIN_CONFIG_SET(x)                  (((x) << GPIO_PIN_CONFIG_LSB) & GPIO_PIN_CONFIG_MASK)

#define GPIO_WAKEUP_ENABLE                               1
#define GPIO_WAKEUP_DISABLE                              (~GPIO_WAKEUP_ENABLE)
#define GPIO_PIN_WAKEUP_ENABLE_MSB             10
#define GPIO_PIN_WAKEUP_ENABLE_LSB              10
#define GPIO_PIN_WAKEUP_ENABLE_MASK          0x00000400
#define GPIO_PIN_WAKEUP_ENABLE_GET(x)          (((x) & GPIO_PIN_WAKEUP_ENABLE_MASK) >> GPIO_PIN_WAKEUP_ENABLE_LSB)
#define GPIO_PIN_WAKEUP_ENABLE_SET(x)           (((x) << GPIO_PIN_WAKEUP_ENABLE_LSB) & GPIO_PIN_WAKEUP_ENABLE_MASK)

#define GPIO_PIN_INT_TYPE_MASK             0x380
#define GPIO_PIN_INT_TYPE_MSB                9
#define GPIO_PIN_INT_TYPE_LSB                 7
#define GPIO_PIN_INT_TYPE_GET(x)             (((x) & GPIO_PIN_INT_TYPE_MASK) >> GPIO_PIN_INT_TYPE_LSB)
#define GPIO_PIN_INT_TYPE_SET(x)             (((x) << GPIO_PIN_INT_TYPE_LSB) & GPIO_PIN_INT_TYPE_MASK)

#define GPIO_PAD_DRIVER_ENABLE             1
#define GPIO_PAD_DRIVER_DISABLE            (~GPIO_PAD_DRIVER_ENABLE)
#define GPIO_PIN_PAD_DRIVER_MSB            2
#define GPIO_PIN_PAD_DRIVER_LSB             2
#define GPIO_PIN_PAD_DRIVER_MASK         0x00000004
#define GPIO_PIN_PAD_DRIVER_GET(x)         (((x) & GPIO_PIN_PAD_DRIVER_MASK) >> GPIO_PIN_PAD_DRIVER_LSB)
#define GPIO_PIN_PAD_DRIVER_SET(x)          (((x) << GPIO_PIN_PAD_DRIVER_LSB) & GPIO_PIN_PAD_DRIVER_MASK)

#define GPIO_AS_PIN_SOURCE                        0
#define SIGMA_AS_PIN_SOURCE                     (~GPIO_AS_PIN_SOURCE)
#define GPIO_PIN_SOURCE_MSB                     0
#define GPIO_PIN_SOURCE_LSB                      0
#define GPIO_PIN_SOURCE_MASK                  0x00000001
#define GPIO_PIN_SOURCE_GET(x)                 (((x) & GPIO_PIN_SOURCE_MASK) >> GPIO_PIN_SOURCE_LSB)
#define GPIO_PIN_SOURCE_SET(x)                  (((x) << GPIO_PIN_SOURCE_LSB) & GPIO_PIN_SOURCE_MASK)
// }}

// TIMER reg {{
#define RTC_REG_READ(addr)                        READ_PERI_REG(PERIPHS_TIMER_BASEDDR + addr)
#define RTC_REG_WRITE(addr, val)                WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + addr, val)
#define RTC_CLR_REG_MASK(reg, mask)      CLEAR_PERI_REG_MASK(PERIPHS_TIMER_BASEDDR +reg, mask)
/* Returns the current time according to the timer timer. */
#define NOW()                                                 RTC_REG_READ(FRC2_COUNT_ADDRESS)

//load initial_value to timer1
#define FRC1_LOAD_ADDRESS                    0x00

//timer1's counter value(count from initial_value to 0)
#define FRC1_COUNT_ADDRESS                 0x04

#define FRC1_CTRL_ADDRESS                    0x08

//clear timer1's interrupt when write this address
#define FRC1_INT_ADDRESS                      0x0c
#define FRC1_INT_CLR_MASK                   0x00000001

//timer2's counter value(count from initial_value to 0)
#define FRC2_COUNT_ADDRESS                0x24
// }}

//RTC reg {{
#define REG_RTC_BASE  PERIPHS_RTC_BASEADDR

#define RTC_STORE0                              (REG_RTC_BASE + 0x030)
#define RTC_STORE1                              (REG_RTC_BASE + 0x034)
#define RTC_STORE2                              (REG_RTC_BASE + 0x038)
#define RTC_STORE3                              (REG_RTC_BASE + 0x03C)

#define RTC_GPIO_OUT                            (REG_RTC_BASE + 0x068)
#define RTC_GPIO_ENABLE                         (REG_RTC_BASE + 0x074)
#define RTC_GPIO_IN_DATA                        (REG_RTC_BASE + 0x08C)
#define RTC_GPIO_CONF                           (REG_RTC_BASE + 0x090)
#define PAD_XPD_DCDC_CONF                       (REG_RTC_BASE + 0x0A0)
//}}

//PIN Mux reg {{
#define PERIPHS_IO_MUX_FUNC             0x13
#define PERIPHS_IO_MUX_FUNC_S           4
#define PERIPHS_IO_MUX_PULLUP           BIT7
#define PERIPHS_IO_MUX_PULLUP2          BIT6
#define PERIPHS_IO_MUX_SLEEP_PULLUP     BIT3
#define PERIPHS_IO_MUX_SLEEP_PULLUP2    BIT2
#define PERIPHS_IO_MUX_SLEEP_OE         BIT1
#define PERIPHS_IO_MUX_OE               BIT0

#define PERIPHS_IO_MUX_CONF_U           (PERIPHS_IO_MUX + 0x00)
#define SPI0_CLK_EQU_SYS_CLK            BIT8
#define SPI1_CLK_EQU_SYS_CLK            BIT9
#define PERIPHS_IO_MUX_MTDI_U           (PERIPHS_IO_MUX + 0x04)
#define FUNC_GPIO12                     3
#define PERIPHS_IO_MUX_MTCK_U           (PERIPHS_IO_MUX + 0x08)
#define FUNC_GPIO13                     3
#define PERIPHS_IO_MUX_MTMS_U           (PERIPHS_IO_MUX + 0x0C)
#define FUNC_GPIO14                     3
#define PERIPHS_IO_MUX_MTDO_U           (PERIPHS_IO_MUX + 0x10)
#define FUNC_GPIO15                     3
#define FUNC_U0RTS                      4
#define PERIPHS_IO_MUX_U0RXD_U          (PERIPHS_IO_MUX + 0x14)
#define FUNC_GPIO3                      3
#define PERIPHS_IO_MUX_U0TXD_U          (PERIPHS_IO_MUX + 0x18)
#define FUNC_U0TXD                      0
#define FUNC_GPIO1                      3
#define PERIPHS_IO_MUX_SD_CLK_U         (PERIPHS_IO_MUX + 0x1c)
#define FUNC_SDCLK                      0
#define FUNC_SPICLK                     1
#define PERIPHS_IO_MUX_SD_DATA0_U       (PERIPHS_IO_MUX + 0x20)
#define FUNC_SDDATA0                    0
#define FUNC_SPIQ                       1
#define FUNC_U1TXD                      4
#define PERIPHS_IO_MUX_SD_DATA1_U       (PERIPHS_IO_MUX + 0x24)
#define FUNC_SDDATA1                    0
#define FUNC_SPID                       1
#define FUNC_U1RXD                      4
#define FUNC_SDDATA1_U1RXD              7
#define PERIPHS_IO_MUX_SD_DATA2_U       (PERIPHS_IO_MUX + 0x28)
#define FUNC_SDDATA2                    0
#define FUNC_SPIHD                      1
#define FUNC_GPIO9                      3
#define PERIPHS_IO_MUX_SD_DATA3_U       (PERIPHS_IO_MUX + 0x2c)
#define FUNC_SDDATA3                    0
#define FUNC_SPIWP                      1
#define FUNC_GPIO10                     3
#define PERIPHS_IO_MUX_SD_CMD_U         (PERIPHS_IO_MUX + 0x30)
#define FUNC_SDCMD                      0
#define FUNC_SPICS0                     1
#define PERIPHS_IO_MUX_GPIO0_U          (PERIPHS_IO_MUX + 0x34)
#define FUNC_GPIO0                      0
#define PERIPHS_IO_MUX_GPIO2_U          (PERIPHS_IO_MUX + 0x38)
#define FUNC_GPIO2                      0
#define FUNC_U1TXD_BK                   2
#define FUNC_U0TXD_BK                   4
#define PERIPHS_IO_MUX_GPIO4_U          (PERIPHS_IO_MUX + 0x3C)
#define FUNC_GPIO4                      0
#define PERIPHS_IO_MUX_GPIO5_U          (PERIPHS_IO_MUX + 0x40)
#define FUNC_GPIO5                      0

#define PIN_PULLUP_DIS(PIN_NAME)                 CLEAR_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP)
#define PIN_PULLUP_EN(PIN_NAME)                  SET_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP)

#define PIN_FUNC_SELECT(PIN_NAME, FUNC)  do { \
    WRITE_PERI_REG(PIN_NAME,   \
                                (READ_PERI_REG(PIN_NAME) \
                                     &  (~(PERIPHS_IO_MUX_FUNC<<PERIPHS_IO_MUX_FUNC_S)))  \
                                     |( (((FUNC&BIT2)<<2)|(FUNC&0x3))<<PERIPHS_IO_MUX_FUNC_S) );  \
    } while (0)

//}}

#endif //_EAGLE_SOC_H_
