#define MICROPY_HW_BOARD_NAME "i.MX RT1170 EVK"
#define MICROPY_HW_MCU_NAME   "MIMXRT1176DVMAA"

#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-1070evk"

// Do not use WFE when waiting for an event.
#define MICROPY_INTERNAL_WFE(TIMEOUT_MS)

// MIMXRT1170_EVK has 2 user LEDs
#define MICROPY_HW_LED1_PIN (pin_GPIO_AD_04)
#define MICROPY_HW_LED2_PIN (pin_GPIO_AD_26)
#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin))
#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin))

#define MICROPY_HW_NUM_PIN_IRQS (6 * 32)

// Define mapping hardware UART # to logical UART #
// LPUART2  on D0/D1    -> 1
// LPUART3  on D12/D11  -> 2
// LPUART5  on D10/D13  -> 3
// LPUART11 on D15/D14  -> 4
// LPUART12 on D25/D26  -> 5
// LPUART8  on D33/D34  -> 6
// LPUART7  on D35/D36  -> 7

#define MICROPY_HW_UART_NUM     (sizeof(uart_index_table) / sizeof(uart_index_table)[0])
#define MICROPY_HW_UART_INDEX   { 1, 2, 3, 5, 11, 12, 8, 7 }

#define IOMUX_TABLE_UART \
    { IOMUXC_GPIO_AD_24_LPUART1_TXD }, { IOMUXC_GPIO_AD_25_LPUART1_RXD }, \
    { IOMUXC_GPIO_DISP_B2_10_LPUART2_TXD }, { IOMUXC_GPIO_DISP_B2_11_LPUART2_RXD }, \
    { IOMUXC_GPIO_AD_30_LPUART3_TXD }, { IOMUXC_GPIO_AD_31_LPUART3_RXD }, \
    { 0 }, { 0 }, \
    { IOMUXC_GPIO_AD_28_LPUART5_TXD }, { IOMUXC_GPIO_AD_29_LPUART5_RXD }, \
    { 0 }, { 0 }, \
    { IOMUXC_GPIO_AD_00_LPUART7_TXD }, { IOMUXC_GPIO_AD_01_LPUART7_RXD }, \
    { IOMUXC_GPIO_AD_02_LPUART8_TXD }, { IOMUXC_GPIO_AD_03_LPUART8_RXD }, \
    { 0 }, { 0 }, \
    { 0 }, { 0 }, \
    { IOMUXC_GPIO_LPSR_04_LPUART11_TXD }, { IOMUXC_GPIO_LPSR_05_LPUART11_RXD }, \
    { IOMUXC_GPIO_LPSR_10_LPUART12_TXD }, { IOMUXC_GPIO_LPSR_11_LPUART12_RXD },

#define IOMUX_TABLE_UART_CTS_RTS \
    { IOMUXC_GPIO_AD_26_LPUART1_CTS_B }, { IOMUXC_GPIO_AD_27_LPUART1_RTS_B }, \
    { IOMUXC_GPIO_DISP_B2_12_LPUART2_CTS_B }, { IOMUXC_GPIO_DISP_B2_13_LPUART2_RTS_B }, \
    { IOMUXC_GPIO_SD_B2_07_LPUART3_CTS_B }, { IOMUXC_GPIO_SD_B2_08_LPUART3_RTS_B }, \
    { 0 }, { 0 }, \
    { IOMUXC_GPIO_SD_B2_09_LPUART5_CTS_B }, { IOMUXC_GPIO_SD_B2_10_LPUART5_RTS_B }, \
    { 0 }, { 0 }, \
    { IOMUXC_GPIO_AD_02_LPUART7_CTS_B }, { IOMUXC_GPIO_AD_03_LPUART7_RTS_B }, \
    { IOMUXC_GPIO_AD_04_LPUART8_CTS_B }, { IOMUXC_GPIO_AD_05_LPUART8_RTS_B }, \
    { 0 }, { 0 }, \
    { 0 }, { 0 }, \
    { IOMUXC_GPIO_LPSR_10_LPUART11_CTS_B }, { IOMUXC_GPIO_LPSR_11_LPUART11_RTS_B }, \
    { IOMUXC_GPIO_LPSR_05_LPUART12_CTS_B }, { IOMUXC_GPIO_LPSR_04_LPUART12_RTS_B },

// Define the mapping hardware SPI # to logical SPI #
// SCK/CS/SDO/SDI  HW-SPI   Logical SPI
// D13/D10/D11/D12 LPSPI1  ->  0
// D26/D28/D25/D24 LPSPI6  ->  1
// D24/ - /D14/D15 LPSPI5  ->  2

#define MICROPY_HW_SPI_INDEX { 1, 6, 5 }

#define IOMUX_TABLE_SPI \
    { IOMUXC_GPIO_AD_28_LPSPI1_SCK }, { IOMUXC_GPIO_AD_29_LPSPI1_PCS0 }, \
    { IOMUXC_GPIO_AD_30_LPSPI1_SOUT }, { IOMUXC_GPIO_AD_31_LPSPI1_SIN }, \
    { 0 }, { 0 }, \
    { 0 }, { 0 }, \
    { 0 }, { 0 }, \
    { 0 }, { 0 }, \
    { 0 }, { 0 }, \
    { 0 }, { 0 }, \
    { IOMUXC_GPIO_LPSR_12_LPSPI5_SCK }, { IOMUXC_GPIO_LPSR_13_LPSPI5_PCS0 }, \
    { IOMUXC_GPIO_LPSR_04_LPSPI5_SOUT }, { IOMUXC_GPIO_LPSR_05_LPSPI5_SIN }, \
    { IOMUXC_GPIO_LPSR_10_LPSPI6_SCK }, { IOMUXC_GPIO_LPSR_09_LPSPI6_PCS0 }, \
    { IOMUXC_GPIO_LPSR_11_LPSPI6_SOUT }, { IOMUXC_GPIO_LPSR_12_LPSPI6_SIN },


#define DMA_REQ_SRC_RX { 0, kDmaRequestMuxLPSPI1Rx, kDmaRequestMuxLPSPI2Rx, \
                         kDmaRequestMuxLPSPI3Rx, kDmaRequestMuxLPSPI4Rx }

#define DMA_REQ_SRC_TX { 0, kDmaRequestMuxLPSPI1Tx, kDmaRequestMuxLPSPI2Tx, \
                         kDmaRequestMuxLPSPI3Tx, kDmaRequestMuxLPSPI4Tx }

// Define the mapping hardware I2C # to logical I2C #
// SDA/SCL  HW-I2C    Logical I2C
// D14/D15  LPI2C5 ->    0
// D1/D0    LPI2C3 ->    1
// A4/A5    LPI2C1 ->    2
// D26/D25  LPI2C6 ->    3
// D19/D18  LPI2C2 ->    4

#define MICROPY_HW_I2C_INDEX   { 5, 3, 1, 6, 2 }

#define IOMUX_TABLE_I2C \
    { IOMUXC_GPIO_AD_08_LPI2C1_SCL }, { IOMUXC_GPIO_AD_09_LPI2C1_SDA }, \
    { IOMUXC_GPIO_AD_18_LPI2C2_SCL }, { IOMUXC_GPIO_AD_19_LPI2C2_SDA }, \
    { IOMUXC_GPIO_DISP_B2_10_LPI2C3_SCL }, { IOMUXC_GPIO_DISP_B2_11_LPI2C3_SDA }, \
    { 0 }, { 0 }, \
    { IOMUXC_GPIO_LPSR_05_LPI2C5_SCL }, { IOMUXC_GPIO_LPSR_04_LPI2C5_SDA }, \
    { IOMUXC_GPIO_LPSR_11_LPI2C6_SCL }, { IOMUXC_GPIO_LPSR_10_LPI2C6_SDA },

#define MICROPY_HW_CAN1_NAME "CAN1"
#define MICROPY_HW_CAN2_NAME "CAN2"
#define MICROPY_HW_NUM_CAN (2)
#define MICROPY_HW_CAN_INDEX { 3, 1 }
#define MICROPY_HW_NUM_CAN_IRQS (2)

#define IOMUX_TABLE_CAN \
    { IOMUXC_GPIO_AD_06_FLEXCAN1_TX }, { IOMUXC_GPIO_AD_07_FLEXCAN1_RX }, \
    { 0 }, { 0 }, \
    { IOMUXC_GPIO_LPSR_00_FLEXCAN3_TX }, { IOMUXC_GPIO_LPSR_01_FLEXCAN3_RX },

#define MICROPY_PY_MACHINE_I2S (1)
#define MICROPY_HW_I2S_NUM (1)
#define I2S_CLOCK_MUX { 0, kCLOCK_Root_Sai1, kCLOCK_Root_Sai2, kCLOCK_Root_Sai3, kCLOCK_Root_Sai4 }
#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx, kDmaRequestMuxSai2Rx, kDmaRequestMuxSai3Rx, kDmaRequestMuxSai4Rx }
#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx, kDmaRequestMuxSai2Tx, kDmaRequestMuxSai3Tx, kDmaRequestMuxSai4Tx }
#define I2S_WM8960_RX_MODE  (1)
#define I2S_AUDIO_PLL_CLOCK (4U)
#define DMAMUX DMAMUX0

#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
    { \
        .hw_id = _hwid, \
        .fn = _fn, \
        .mode = _mode, \
        .name = MP_QSTR_##_pin, \
        .iomux = {_iomux}, \
    }

#define I2S_GPIO_MAP \
    { \
        I2S_GPIO(1, MCK, TX, GPIO_AD_17, IOMUXC_GPIO_AD_17_SAI1_MCLK), \
        I2S_GPIO(1, SCK, RX, GPIO_AD_19, IOMUXC_GPIO_AD_19_SAI1_RX_BCLK), \
        I2S_GPIO(1, WS, RX, GPIO_AD_18, IOMUXC_GPIO_AD_18_SAI1_RX_SYNC), \
        I2S_GPIO(1, SD, RX, GPIO_AD_20, IOMUXC_GPIO_AD_20_SAI1_RX_DATA00),  \
        I2S_GPIO(1, SCK, TX, GPIO_AD_22, IOMUXC_GPIO_AD_22_SAI1_TX_BCLK), \
        I2S_GPIO(1, WS, TX, GPIO_AD_23, IOMUXC_GPIO_AD_23_SAI1_TX_SYNC),  \
        I2S_GPIO(1, SD, TX, GPIO_AD_21, IOMUXC_GPIO_AD_21_SAI1_TX_DATA00), \
    }

// USDHC1

#define USDHC_DUMMY_PIN NULL, 0
#define MICROPY_USDHC1 \
    { \
        .cmd = {GPIO_SD_B1_00_USDHC1_CMD}, \
        .clk = { GPIO_SD_B1_01_USDHC1_CLK }, \
        .cd_b = { USDHC_DUMMY_PIN }, \
        .data0 = { GPIO_SD_B1_02_USDHC1_DATA0 }, \
        .data1 = { GPIO_SD_B1_03_USDHC1_DATA1 }, \
        .data2 = { GPIO_SD_B1_04_USDHC1_DATA2 }, \
        .data3 = { GPIO_SD_B1_05_USDHC1_DATA3 }, \
    }
#define USDHC_DATA3_PULL_DOWN_ON_BOARD    (1)

// Network definitions

// Transceiver Phy Parameters
#define ENET_PHY_ADDRESS    (2)
#define ENET_PHY            KSZ8081
#define ENET_PHY_OPS        phyksz8081_ops

#define IOMUX_TABLE_ENET \
    { IOMUXC_GPIO_DISP_B2_06_ENET_RX_DATA00, 0, 0x06u }, \
    { IOMUXC_GPIO_DISP_B2_07_ENET_RX_DATA01, 0, 0x06u }, \
    { IOMUXC_GPIO_DISP_B2_08_ENET_RX_EN, 0, 0x06u }, \
    { IOMUXC_GPIO_DISP_B2_02_ENET_TX_DATA00, 0, 0x02u }, \
    { IOMUXC_GPIO_DISP_B2_03_ENET_TX_DATA01, 0, 0x02u }, \
    { IOMUXC_GPIO_DISP_B2_04_ENET_TX_EN, 0, 0x06u }, \
    { IOMUXC_GPIO_DISP_B2_05_ENET_REF_CLK, 1, 0x03u }, \
    { IOMUXC_GPIO_DISP_B2_09_ENET_RX_ER, 0, 0x06u }, \
    { IOMUXC_GPIO_AD_33_ENET_MDIO, 0, 0x06u }, \
    { IOMUXC_GPIO_AD_32_ENET_MDC, 0, 0x06u },

// 1G Transceiver Phy Parameters (second ETH port)
#define ENET_1_PHY_ADDRESS     (1)
#define ENET_1_PHY             RTL8211F
#define ENET_1_PHY_OPS         phyrtl8211f_ops

// 1G Ethernet PIN definitions
#define IOMUX_TABLE_ENET_1 \
    { IOMUXC_GPIO_DISP_B1_00_ENET_1G_RX_EN, 0, 0x08U }, \
    { IOMUXC_GPIO_DISP_B1_01_ENET_1G_RX_CLK, 0, 0x08U }, \
    { IOMUXC_GPIO_DISP_B1_02_ENET_1G_RX_DATA00, 0, 0x08U }, \
    { IOMUXC_GPIO_DISP_B1_03_ENET_1G_RX_DATA01, 0, 0x08U }, \
    { IOMUXC_GPIO_DISP_B1_04_ENET_1G_RX_DATA02, 0, 0x08U }, \
    { IOMUXC_GPIO_DISP_B1_05_ENET_1G_RX_DATA03, 0, 0x08U }, \
    { IOMUXC_GPIO_DISP_B1_06_ENET_1G_TX_DATA03, 0, 0x0CU }, \
    { IOMUXC_GPIO_DISP_B1_07_ENET_1G_TX_DATA02, 0, 0x0CU }, \
    { IOMUXC_GPIO_DISP_B1_08_ENET_1G_TX_DATA01, 0, 0x0CU }, \
    { IOMUXC_GPIO_DISP_B1_09_ENET_1G_TX_DATA00, 0, 0x0CU }, \
    { IOMUXC_GPIO_DISP_B1_10_ENET_1G_TX_EN, 0, 0x0CU }, \
    { IOMUXC_GPIO_DISP_B1_11_ENET_1G_TX_CLK_IO, 0, 0x0CU }, \
    { IOMUXC_GPIO_EMC_B2_20_ENET_1G_MDIO, 0, 0x06u }, \
    { IOMUXC_GPIO_EMC_B2_19_ENET_1G_MDC, 0, 0x06u },

// --- SEMC --- //
#define MIMXRT_IOMUXC_SEMC_DATA00 IOMUXC_GPIO_EMC_B1_00_SEMC_DATA00
#define MIMXRT_IOMUXC_SEMC_DATA01 IOMUXC_GPIO_EMC_B1_01_SEMC_DATA01
#define MIMXRT_IOMUXC_SEMC_DATA02 IOMUXC_GPIO_EMC_B1_02_SEMC_DATA02
#define MIMXRT_IOMUXC_SEMC_DATA03 IOMUXC_GPIO_EMC_B1_03_SEMC_DATA03
#define MIMXRT_IOMUXC_SEMC_DATA04 IOMUXC_GPIO_EMC_B1_04_SEMC_DATA04
#define MIMXRT_IOMUXC_SEMC_DATA05 IOMUXC_GPIO_EMC_B1_05_SEMC_DATA05
#define MIMXRT_IOMUXC_SEMC_DATA06 IOMUXC_GPIO_EMC_B1_06_SEMC_DATA06
#define MIMXRT_IOMUXC_SEMC_DATA07 IOMUXC_GPIO_EMC_B1_07_SEMC_DATA07
#define MIMXRT_IOMUXC_SEMC_DATA08 IOMUXC_GPIO_EMC_B1_30_SEMC_DATA08
#define MIMXRT_IOMUXC_SEMC_DATA09 IOMUXC_GPIO_EMC_B1_31_SEMC_DATA09
#define MIMXRT_IOMUXC_SEMC_DATA10 IOMUXC_GPIO_EMC_B1_32_SEMC_DATA10
#define MIMXRT_IOMUXC_SEMC_DATA11 IOMUXC_GPIO_EMC_B1_33_SEMC_DATA11
#define MIMXRT_IOMUXC_SEMC_DATA12 IOMUXC_GPIO_EMC_B1_34_SEMC_DATA12
#define MIMXRT_IOMUXC_SEMC_DATA13 IOMUXC_GPIO_EMC_B1_35_SEMC_DATA13
#define MIMXRT_IOMUXC_SEMC_DATA14 IOMUXC_GPIO_EMC_B1_36_SEMC_DATA14
#define MIMXRT_IOMUXC_SEMC_DATA15 IOMUXC_GPIO_EMC_B1_37_SEMC_DATA15

#define MIMXRT_IOMUXC_SEMC_ADDR00 IOMUXC_GPIO_EMC_B1_09_SEMC_ADDR00
#define MIMXRT_IOMUXC_SEMC_ADDR01 IOMUXC_GPIO_EMC_B1_10_SEMC_ADDR01
#define MIMXRT_IOMUXC_SEMC_ADDR02 IOMUXC_GPIO_EMC_B1_11_SEMC_ADDR02
#define MIMXRT_IOMUXC_SEMC_ADDR03 IOMUXC_GPIO_EMC_B1_12_SEMC_ADDR03
#define MIMXRT_IOMUXC_SEMC_ADDR04 IOMUXC_GPIO_EMC_B1_13_SEMC_ADDR04
#define MIMXRT_IOMUXC_SEMC_ADDR05 IOMUXC_GPIO_EMC_B1_14_SEMC_ADDR05
#define MIMXRT_IOMUXC_SEMC_ADDR06 IOMUXC_GPIO_EMC_B1_15_SEMC_ADDR06
#define MIMXRT_IOMUXC_SEMC_ADDR07 IOMUXC_GPIO_EMC_B1_16_SEMC_ADDR07
#define MIMXRT_IOMUXC_SEMC_ADDR08 IOMUXC_GPIO_EMC_B1_17_SEMC_ADDR08
#define MIMXRT_IOMUXC_SEMC_ADDR09 IOMUXC_GPIO_EMC_B1_18_SEMC_ADDR09
#define MIMXRT_IOMUXC_SEMC_ADDR10 IOMUXC_GPIO_EMC_B1_23_SEMC_ADDR10
#define MIMXRT_IOMUXC_SEMC_ADDR11 IOMUXC_GPIO_EMC_B1_19_SEMC_ADDR11
#define MIMXRT_IOMUXC_SEMC_ADDR12 IOMUXC_GPIO_EMC_B1_20_SEMC_ADDR12

#define MIMXRT_IOMUXC_SEMC_BA0 IOMUXC_GPIO_EMC_B1_21_SEMC_BA0
#define MIMXRT_IOMUXC_SEMC_BA1 IOMUXC_GPIO_EMC_B1_22_SEMC_BA1
#define MIMXRT_IOMUXC_SEMC_CAS IOMUXC_GPIO_EMC_B1_24_SEMC_CAS
#define MIMXRT_IOMUXC_SEMC_RAS IOMUXC_GPIO_EMC_B1_25_SEMC_RAS
#define MIMXRT_IOMUXC_SEMC_CLK IOMUXC_GPIO_EMC_B1_26_SEMC_CLK
#define MIMXRT_IOMUXC_SEMC_CKE IOMUXC_GPIO_EMC_B1_27_SEMC_CKE
#define MIMXRT_IOMUXC_SEMC_WE IOMUXC_GPIO_EMC_B1_28_SEMC_WE
#define MIMXRT_IOMUXC_SEMC_DM00 IOMUXC_GPIO_EMC_B1_08_SEMC_DM00
#define MIMXRT_IOMUXC_SEMC_DM01 IOMUXC_GPIO_EMC_B1_38_SEMC_DM01
#define MIMXRT_IOMUXC_SEMC_DQS IOMUXC_GPIO_EMC_B1_39_SEMC_DQS

#define MIMXRT_IOMUXC_SEMC_CS0 IOMUXC_GPIO_EMC_B1_29_SEMC_CS0

#define MIMXRT_IOMUXC_SEMC_DATA16 IOMUXC_GPIO_EMC_B2_00_SEMC_DATA16
#define MIMXRT_IOMUXC_SEMC_DATA17 IOMUXC_GPIO_EMC_B2_01_SEMC_DATA17
#define MIMXRT_IOMUXC_SEMC_DATA18 IOMUXC_GPIO_EMC_B2_02_SEMC_DATA18
#define MIMXRT_IOMUXC_SEMC_DATA19 IOMUXC_GPIO_EMC_B2_03_SEMC_DATA19
#define MIMXRT_IOMUXC_SEMC_DATA20 IOMUXC_GPIO_EMC_B2_04_SEMC_DATA20
#define MIMXRT_IOMUXC_SEMC_DATA21 IOMUXC_GPIO_EMC_B2_05_SEMC_DATA21
#define MIMXRT_IOMUXC_SEMC_DATA22 IOMUXC_GPIO_EMC_B2_06_SEMC_DATA22
#define MIMXRT_IOMUXC_SEMC_DATA23 IOMUXC_GPIO_EMC_B2_07_SEMC_DATA23
#define MIMXRT_IOMUXC_SEMC_DM02   IOMUXC_GPIO_EMC_B2_08_SEMC_DM02

#define MIMXRT_IOMUXC_SEMC_DATA24 IOMUXC_GPIO_EMC_B2_09_SEMC_DATA24
#define MIMXRT_IOMUXC_SEMC_DATA25 IOMUXC_GPIO_EMC_B2_10_SEMC_DATA25
#define MIMXRT_IOMUXC_SEMC_DATA26 IOMUXC_GPIO_EMC_B2_11_SEMC_DATA26
#define MIMXRT_IOMUXC_SEMC_DATA27 IOMUXC_GPIO_EMC_B2_12_SEMC_DATA27
#define MIMXRT_IOMUXC_SEMC_DATA28 IOMUXC_GPIO_EMC_B2_13_SEMC_DATA28
#define MIMXRT_IOMUXC_SEMC_DATA29 IOMUXC_GPIO_EMC_B2_14_SEMC_DATA29
#define MIMXRT_IOMUXC_SEMC_DATA30 IOMUXC_GPIO_EMC_B2_15_SEMC_DATA30
#define MIMXRT_IOMUXC_SEMC_DATA31 IOMUXC_GPIO_EMC_B2_16_SEMC_DATA31
#define MIMXRT_IOMUXC_SEMC_DM03   IOMUXC_GPIO_EMC_B2_17_SEMC_DM03
#define MIMXRT_IOMUXC_SEMC_DQS4   IOMUXC_GPIO_EMC_B2_18_SEMC_DQS4

#if MICROPY_PY_MACHINE_I2S
#define MICROPY_BOARD_ROOT_POINTERS \
    struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
#endif
