diff --git a/include/arm11/hardware/gpio.h b/include/arm11/hardware/gpio.h index e372161..ac82eae 100644 --- a/include/arm11/hardware/gpio.h +++ b/include/arm11/hardware/gpio.h @@ -30,34 +30,36 @@ typedef enum { - GPIO_1_0 = 0u<<4 | 0u, - GPIO_1_1 = 1u<<4 | 0u, - GPIO_1_2 = 2u<<4 | 0u, + GPIO_1_0 = 0u<<3 | 0u, + GPIO_1_1 = 1u<<3 | 0u, + GPIO_1_2 = 2u<<3 | 0u, - GPIO_2_0 = 0u<<4 | 1u, - GPIO_2_1 = 1u<<4 | 1u, + GPIO_2_0 = 0u<<3 | 1u, + GPIO_2_1 = 1u<<3 | 1u, - GPIO_3_0 = 0u<<4 | 2u, - GPIO_3_1 = 1u<<4 | 2u, - GPIO_3_2 = 2u<<4 | 2u, - GPIO_3_3 = 3u<<4 | 2u, - GPIO_3_4 = 4u<<4 | 2u, - GPIO_3_5 = 5u<<4 | 2u, - GPIO_3_6 = 6u<<4 | 2u, - GPIO_3_7 = 7u<<4 | 2u, - GPIO_3_8 = 8u<<4 | 2u, - GPIO_3_9 = 9u<<4 | 2u, - GPIO_3_10 = 10u<<4 | 2u, - GPIO_3_11 = 11u<<4 | 2u, + GPIO_3_0 = 0u<<3 | 2u, - GPIO_4_0 = 0u<<4 | 3u, + GPIO_4_0 = 0u<<3 | 3u, + GPIO_4_1 = 1u<<3 | 3u, + GPIO_4_2 = 2u<<3 | 3u, + GPIO_4_3 = 3u<<3 | 3u, + GPIO_4_4 = 4u<<3 | 3u, + GPIO_4_5 = 5u<<3 | 3u, + GPIO_4_6 = 6u<<3 | 3u, + GPIO_4_7 = 7u<<3 | 3u, + GPIO_4_8 = 8u<<3 | 3u, + GPIO_4_9 = 9u<<3 | 3u, + GPIO_4_10 = 10u<<3 | 3u, + GPIO_4_11 = 11u<<3 | 3u, + + GPIO_5_0 = 0u<<3 | 4u, // Aliases - GPIO_1_TOUCHSCREEN = GPIO_1_1, // Unset while the touchscreen is used + GPIO_1_TOUCHSCREEN = GPIO_1_1, // Unset while touchscreen pen down GPIO_1_SHELL = GPIO_1_2, // 1 when closed - GPIO_3_HEADPH_JACK = GPIO_3_8, // Unset while headphones are plugged in - GPIO_3_MCU = GPIO_3_9 + GPIO_4_HEADPH_JACK = GPIO_4_8, // Unset while headphones are plugged in + GPIO_4_MCU = GPIO_4_9 } Gpio; @@ -69,3 +71,20 @@ * @param[in] cfg The configuration. */ void GPIO_config(Gpio gpio, u8 cfg); + +/** + * @brief Reads a GPIO pin. + * + * @param[in] gpio The gpio. + * + * @return The state. Either 0 or 1. + */ +u8 GPIO_read(Gpio gpio); + +/** + * @brief Writes a GPIO pin. + * + * @param[in] gpio The gpio. + * @param[in] val The value. + */ +void GPIO_write(Gpio gpio, u8 val); diff --git a/include/arm11/hardware/i2c.h b/include/arm11/hardware/i2c.h index 7fbc5e9..5ad4294 100644 --- a/include/arm11/hardware/i2c.h +++ b/include/arm11/hardware/i2c.h @@ -21,29 +21,45 @@ #include "types.h" +// REG_I2C_CNT #define I2C_STOP (1u) #define I2C_START (1u<<1) #define I2C_ERROR (1u<<2) #define I2C_ACK (1u<<4) -#define I2C_DIRE_WRITE (0u) -#define I2C_DIRE_READ (1u<<5) +#define I2C_DIR_WRITE (0u) +#define I2C_DIR_READ (1u<<5) #define I2C_IRQ_ENABLE (1u<<6) #define I2C_ENABLE (1u<<7) +// REG_I2C_CNTEX +#define I2C_SCL_STATE (1u) // Read-only SCL line state? +#define I2C_CLK_STRETCH (1u<<1) // Enables clock stretching +#define I2C_UNK_CNTEX15 (1u<<15) // Unknown + +// REG_I2C_SCL +#define I2C_DELAYS(high, low) ((high)<<8 | (low)) // TODO: How long and when does it delay? + typedef enum { - I2C_DEV_POWER = 0u, // Unconfirmed - I2C_DEV_CAMERA = 1u, // Unconfirmed - I2C_DEV_CAMERA2 = 2u, // Unconfirmed - I2C_DEV_MCU = 3u, - I2C_DEV_GYRO = 10u, - I2C_DEV_DEBUG_PAD = 12u, - I2C_DEV_IR = 13u, - I2C_DEV_EEPROM = 14u, // Unconfirmed + I2C_DEV_TWL_MCU = 0u, // DSi mode MCU + I2C_DEV_CAMERA1 = 1u, // Internal self-facing camera + I2C_DEV_CAMERA2 = 2u, // External right camera + I2C_DEV_CTR_MCU = 3u, + I2C_DEV_CAMERA3 = 4u, // External left camera + I2C_DEV_LCD0 = 5u, // Upper LCD + I2C_DEV_LCD1 = 6u, // Lower LCD + I2C_DEV_UNK7 = 7u, // Debug? + I2C_DEV_UNK8 = 8u, // Debug? + I2C_DEV_UNK9 = 9u, // HID debug? + I2C_DEV_GYRO_OLD = 10u, // Old 3DS only? + I2C_DEV_GYRO_NEW = 11u, // New 3DS only? + I2C_DEV_UNK12 = 12u, // HID "DebugPad"? + I2C_DEV_IR = 13u, // Infrared (IrDA) + I2C_DEV_EEPROM = 14u, // Dev unit only? I2C_DEV_NFC = 15u, - I2C_DEV_QTM = 16u, - I2C_DEV_N3DS_HID = 17u + I2C_DEV_QTM = 16u, // IO expander chip (New 3DS only) + I2C_DEV_N3DS_HID = 17u // C-Stick and ZL/ZR buttons } I2cDevice; diff --git a/include/arm11/hardware/interrupt.h b/include/arm11/hardware/interrupt.h index ebf203a..3cbe35a 100644 --- a/include/arm11/hardware/interrupt.h +++ b/include/arm11/hardware/interrupt.h @@ -92,16 +92,34 @@ IRQ_SPI1 = 87u, // SPI bus 1 interrupt status update IRQ_PDN = 88u, IRQ_I2C3 = 92u, - IRQ_SHELL_OPENED = 96u, - IRQ_SHELL_CLOSED = 98u, - IRQ_TOUCHSCREEN = 99u, // Triggers on hitting the touchscreen. - IRQ_HEADPH_JACK = 100u, // Headphone jack. Triggers on both plugging in and out? GPIO reg 9, bit 8. - IRQ_MCU_HID = 113u, // HOME/POWER pressed/released, shell opened/closed and WiFi switch pressed. GPIO reg 19, bit 9. + IRQ_GPIO_1_2 = 96u, + IRQ_SHELL_CLOSED = 98u, // GPIO_1_0? + IRQ_GPIO_1_1 = 99u, + IRQ_GPIO_2_0 = 100u, + IRQ_GPIO_2_1 = 102u, + IRQ_GPIO_4_0 = 104u, + IRQ_GPIO_4_1 = 105u, + IRQ_GPIO_4_2 = 106u, + IRQ_GPIO_4_3 = 107u, + IRQ_GPIO_4_4 = 108u, + IRQ_GPIO_4_5 = 109u, + IRQ_GPIO_4_6 = 110u, + IRQ_GPIO_4_7 = 111u, + IRQ_GPIO_4_8 = 112u, + IRQ_GPIO_4_9 = 113u, + IRQ_GPIO_4_10 = 114u, + IRQ_GPIO_4_11 = 115u, IRQ_GAMECARD = 117u, // Gamecard inserted IRQ_PERF_MONITOR0 = 120u, // Core 0 performance monitor. Triggers on any counter overflow IRQ_PERF_MONITOR1 = 121u, // Core 1 performance monitor. Triggers on any counter overflow IRQ_PERF_MONITOR2 = 122u, // Unconfirmed. Core 2 performance monitor. Triggers on any counter overflow - IRQ_PERF_MONITOR3 = 123u // Unconfirmed. Core 3 performance monitor. Triggers on any counter overflow + IRQ_PERF_MONITOR3 = 123u, // Unconfirmed. Core 3 performance monitor. Triggers on any counter overflow + + // Aliases + IRQ_SHELL_OPENED = IRQ_GPIO_1_2, + IRQ_TOUCHSCREEN = IRQ_GPIO_1_1, // Triggers on touchscreen pen down. + IRQ_HEADPH_JACK = IRQ_GPIO_2_0, // Headphone jack. Triggers on both plugging in and out? + IRQ_CTR_MCU = IRQ_GPIO_4_9 // Various MCU events trigger this. See MCU interrupt mask. } Interrupt; diff --git a/include/arm11/hardware/spi.h b/include/arm11/hardware/spi.h index 20f6919..53a1f11 100644 --- a/include/arm11/hardware/spi.h +++ b/include/arm11/hardware/spi.h @@ -22,17 +22,17 @@ // REG_NSPI_CNT -#define NSPI_CNT_BUS_1BIT (0u) -#define NSPI_CNT_BUS_4BIT (1u<<12) -#define NSPI_CNT_DIRE_READ (0u) -#define NSPI_CNT_DIRE_WRITE (1u<<13) -#define NSPI_CNT_ENABLE (1u<<15) +#define NSPI_BUS_1BIT (0u) +#define NSPI_BUS_4BIT (1u<<12) +#define NSPI_DIR_READ (0u) +#define NSPI_DIR_WRITE (1u<<13) +#define NSPI_ENABLE (1u<<15) -// REG_NSPI_DONE -#define NSPI_DONE_DONE (0u) +// REG_NSPI_CS +#define NSPI_DESELECT (0u) -// REG_NSPI_STATUS -#define NSPI_STATUS_BUSY (1u) +// NSPI_FIFO_STAT +#define NSPI_FIFO_BUSY (1u) // REG_NSPI_AUTOPOLL #define NSPI_AUTOPOLL_START (1u<<31) @@ -58,13 +58,13 @@ // TODO: Proper device table typedef enum { - NSPI_DEV_UNK1 = 0u, - NSPI_DEV_NVRAM = 1u, - NSPI_DEV_UNK3 = 2u, - NSPI_DEV_CODEC = 3u, - NSPI_DEV_UNK5 = 4u, - NSPI_DEV_UNK6 = 5u, - NSPI_DEV_UNK7 = 6u + NSPI_DEV_POWERMAN = 0u, // Unused DS(i) mode power management + NSPI_DEV_NVRAM = 1u, // WiFi SPI flash + NSPI_DEV_TWL_CODEC = 2u, + NSPI_DEV_CTR_CODEC = 3u, + NSPI_DEV_UNK5 = 4u, // Unused? + NSPI_DEV_UNK6 = 5u, // Unused? + NSPI_DEV_UNK7 = 6u // Unused? } SpiDevice; diff --git a/include/arm9/hardware/spicard.h b/include/arm9/hardware/spicard.h index 4ecaaa9..f86c58d 100644 --- a/include/arm9/hardware/spicard.h +++ b/include/arm9/hardware/spicard.h @@ -22,17 +22,17 @@ // REG_NSPI_CNT -#define NSPI_CNT_BUS_1BIT (0u) -#define NSPI_CNT_BUS_4BIT (1u<<12) -#define NSPI_CNT_DIRE_READ (0u) -#define NSPI_CNT_DIRE_WRITE (1u<<13) -#define NSPI_CNT_ENABLE (1u<<15) +#define NSPI_BUS_1BIT (0u) +#define NSPI_BUS_4BIT (1u<<12) +#define NSPI_DIR_READ (0u) +#define NSPI_DIR_WRITE (1u<<13) +#define NSPI_ENABLE (1u<<15) -// REG_NSPI_DONE -#define NSPI_DONE (0u) +// REG_NSPI_CS +#define NSPI_DESELECT (0u) -// REG_NSPI_STATUS -#define NSPI_STATUS_BUSY (1u) +// NSPI_FIFO_STAT +#define NSPI_FIFO_BUSY (1u) // REG_NSPI_AUTOPOLL #define NSPI_AUTOPOLL_START (1u<<31) diff --git a/source/arm11/hardware/codec.c b/source/arm11/hardware/codec.c index 70f22e1..27547b1 100644 --- a/source/arm11/hardware/codec.c +++ b/source/arm11/hardware/codec.c @@ -20,52 +20,69 @@ #include "types.h" #include "arm11/hardware/spi.h" +#include "arm11/hardware/timer.h" +#include "arm11/hardware/gpio.h" -static void codecReadRegBuf(u8 reg, u32 *buf, u32 size) +static void codecSwitchBank(u8 bank) { - alignas(4) u8 inBuf[4]; + static u8 curBank = 0x63; + if(bank != curBank) + { + alignas(4) u8 inBuf[4]; + inBuf[0] = 0; // Write + inBuf[1] = bank; + NSPI_writeRead(NSPI_DEV_CTR_CODEC, (u32*)inBuf, NULL, 2, 0, true); - inBuf[0] = reg<<1 | 1u; - NSPI_writeRead(NSPI_DEV_CODEC, (u32*)inBuf, buf, 1, size, true); + curBank = bank; + } } -static u8 codecReadReg(u8 reg) +static void codecReadRegBuf(u8 bank, u8 reg, u32 *buf, u32 size) +{ + codecSwitchBank(bank); + + alignas(4) u8 inBuf[4]; + inBuf[0] = reg<<1 | 1u; + NSPI_writeRead(NSPI_DEV_CTR_CODEC, (u32*)inBuf, buf, 1, size, true); +} + +static u8 codecReadReg(u8 bank, u8 reg) { alignas(4) u8 outBuf[4]; - - codecReadRegBuf(reg, (u32*)outBuf, 1); + codecReadRegBuf(bank, reg, (u32*)outBuf, 1); return outBuf[0]; } -static void codecWriteReg(u8 reg, u8 val) +static void codecWriteRegBuf(u8 bank, u8 reg, u32 *buf, u32 size) { - alignas(4) u8 inBuf[4]; + codecSwitchBank(bank); + alignas(4) u8 inBuf[4]; + inBuf[0] = reg<<1; // Write + NSPI_writeRead(NSPI_DEV_CTR_CODEC, (u32*)inBuf, NULL, 1, 0, false); + NSPI_writeRead(NSPI_DEV_CTR_CODEC, buf, NULL, size, 0, true); +} + +static void codecWriteReg(u8 bank, u8 reg, u8 val) +{ + codecSwitchBank(bank); + + alignas(4) u8 inBuf[4]; inBuf[0] = reg<<1; // Write inBuf[1] = val; - - NSPI_writeRead(NSPI_DEV_CODEC, (u32*)inBuf, NULL, 2, 0, true); + NSPI_writeRead(NSPI_DEV_CTR_CODEC, (u32*)inBuf, NULL, 2, 0, true); } -static void codecMaskReg(u8 reg, u8 mask, u8 val) +static void codecMaskReg(u8 bank, u8 reg, u8 val, u8 mask) { - u8 data = codecReadReg(reg); + u8 data = codecReadReg(bank, reg); data = (data & ~mask) | (val & mask); - codecWriteReg(reg, data); + codecWriteReg(bank, reg, data); } -static void codecSwitchBank(u8 bank) -{ - static u8 curBank = 0; - if(bank != curBank) - { - codecWriteReg(0, bank); - curBank = bank; - } -} void CODEC_init(void) { @@ -73,24 +90,26 @@ if(inited) return; inited = true; + NSPI_init(); - codecSwitchBank(0x67); - codecWriteReg(0x24, 0x98); - codecWriteReg(0x26, 0x00); - codecWriteReg(0x25, 0x43); - codecWriteReg(0x24, 0x18); - codecWriteReg(0x17, 0x43); - codecWriteReg(0x19, 0x69); - codecWriteReg(0x1B, 0x80); - codecWriteReg(0x27, 0x11); - codecWriteReg(0x26, 0xEC); - codecWriteReg(0x24, 0x18); - codecWriteReg(0x25, 0x53); + // Circle pad + codecWriteReg(0x67, 0x24, 0x98); + codecWriteReg(0x67, 0x26, 0x00); + codecWriteReg(0x67, 0x25, 0x43); + codecWriteReg(0x67, 0x24, 0x18); + codecWriteReg(0x67, 0x17, 0x43); + codecWriteReg(0x67, 0x19, 0x69); + codecWriteReg(0x67, 0x1B, 0x80); + codecWriteReg(0x67, 0x27, 0x11); + codecWriteReg(0x67, 0x26, 0xEC); + codecWriteReg(0x67, 0x24, 0x18); + codecWriteReg(0x67, 0x25, 0x53); - codecMaskReg(0x26, 0x80, 0x80); - codecMaskReg(0x24, 0x80, 0x00); - codecMaskReg(0x25, 0x3C, 0x10); + // Touchscreen + codecMaskReg(0x67, 0x26, 0x80, 0x80); + codecMaskReg(0x67, 0x24, 0, 0x80); + codecMaskReg(0x67, 0x25, 0x10, 0x3C); } void CODEC_getRawData(u32 buf[13]) @@ -99,6 +118,5 @@ // This reg read seems useless and doesn't affect funtionality. //codecReadReg(0x26); - codecSwitchBank(0xFB); - codecReadRegBuf(1, buf, 52); + codecReadRegBuf(0xFB, 1, buf, 52); } diff --git a/source/arm11/hardware/gpio.c b/source/arm11/hardware/gpio.c index 6b78827..dae8e6c 100644 --- a/source/arm11/hardware/gpio.c +++ b/source/arm11/hardware/gpio.c @@ -22,7 +22,8 @@ #define GPIO_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x47000) -#define REG_GPIO1_UNK0 *((vu16*)(GPIO_REGS_BASE + 0x00)) // ? 3 GPIOs (bits 0-2) +// 3 GPIOs (bits 0-2) +#define REG_GPIO1_DAT *((vu16*)(GPIO_REGS_BASE + 0x00)) // Read-only? #define REG_GPIO1_UNK2 *((vu16*)(GPIO_REGS_BASE + 0x02)) // ? #define REG_GPIO1_UNK4 *((vu32*)(GPIO_REGS_BASE + 0x04)) // ? @@ -32,28 +33,34 @@ #define REG_GPIO2_DIR *((vu8* )(GPIO_REGS_BASE + 0x11)) // 0 = input, 1 = output #define REG_GPIO2_EDGE *((vu8* )(GPIO_REGS_BASE + 0x12)) // IRQ edge 0 = falling, 1 = rising #define REG_GPIO2_IRQ *((vu8* )(GPIO_REGS_BASE + 0x13)) // 1 = IRQ enable -#define REG_GPIO2_UNK4 *((vu8* )(GPIO_REGS_BASE + 0x14)) // Only bit 0 writable -#define REG_GPIO2_UNK5 *((vu8* )(GPIO_REGS_BASE + 0x15)) // Only 1 bit? - -// 12 GPIOs (bits 0-11) -#define REG_GPIO3_H1 *((vu32*)(GPIO_REGS_BASE + 0x20)) // First half -#define REG_GPIO3_DAT *((vu16*)(GPIO_REGS_BASE + 0x20)) -#define REG_GPIO3_DIR *((vu16*)(GPIO_REGS_BASE + 0x22)) -#define REG_GPIO3_H2 *((vu32*)(GPIO_REGS_BASE + 0x24)) // Second half -#define REG_GPIO3_EDGE *((vu16*)(GPIO_REGS_BASE + 0x24)) -#define REG_GPIO3_IRQ *((vu16*)(GPIO_REGS_BASE + 0x26)) // 1 GPIO (bit 0) -#define REG_GPIO4_DAT *((vu16*)(GPIO_REGS_BASE + 0x28)) // ? +#define REG_GPIO3 *((vu8* )(GPIO_REGS_BASE + 0x14)) +#define REG_GPIO3_DAT *((vu8* )(GPIO_REGS_BASE + 0x14)) // Only bit 0 writable +#define REG_GPIO3_UNK5 *((vu8* )(GPIO_REGS_BASE + 0x15)) // Only 1 bit? + +// 12 GPIOs (bits 0-11) +#define REG_GPIO4_H1 *((vu32*)(GPIO_REGS_BASE + 0x20)) // First half +#define REG_GPIO4_DAT *((vu16*)(GPIO_REGS_BASE + 0x20)) +#define REG_GPIO4_DIR *((vu16*)(GPIO_REGS_BASE + 0x22)) +#define REG_GPIO4_H2 *((vu32*)(GPIO_REGS_BASE + 0x24)) // Second half +#define REG_GPIO4_EDGE *((vu16*)(GPIO_REGS_BASE + 0x24)) +#define REG_GPIO4_IRQ *((vu16*)(GPIO_REGS_BASE + 0x26)) + +// 1 GPIO (bit 0) +#define REG_GPIO5_DAT *((vu16*)(GPIO_REGS_BASE + 0x28)) // WiFi + + +static vu16 *const datRegs[5] = {®_GPIO1_DAT, (vu16*)®_GPIO2_DAT, (vu16*)®_GPIO3_DAT, ®_GPIO4_DAT, ®_GPIO5_DAT}; void GPIO_config(Gpio gpio, u8 cfg) { - const u8 bank = gpio & 0xFu; - const u8 pin = gpio>>4; + const u8 bank = gpio & 7u; + const u8 pin = gpio>>3; - // GPIO1 and GPIO4 are not configurable. + // GPIO1 and GPIO5 are not configurable. if(bank == 1) { u32 reg = REG_GPIO2 & ~((1u<<24 | 1u<<16 | 1u<<8)<>3; + + if(bank > 4) return 0; + + return *datRegs[bank]>>pin & 1u; +} + +void GPIO_write(Gpio gpio, u8 val) +{ + const u8 bank = gpio & 7u; + const u8 pin = gpio>>3; + + if(bank == 0 || bank > 4) return; + + u16 tmp = *datRegs[bank]; + tmp &= ~(1u<I2C_CNT & I2C_ENABLE); } -static bool i2cCheckAck(vu8 *const I2C_CNT) +static bool i2cCheckAck(I2cRegs *const regs) { - if(!(*I2C_CNT & I2C_ACK)) // If ack flag is 0 it failed. + if(!(regs->I2C_CNT & I2C_ACK)) // If ack flag is 0 it failed. { - *I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP; + regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP; return false; } @@ -122,18 +122,18 @@ I2cRegs *regs = i2cGetBusRegsBase(I2C_BUS1); while(regs->I2C_CNT & I2C_ENABLE); - regs->I2C_CNTEX = 2; // TODO: Find out what this does. If bit 1 is not set I2C hangs. - regs->I2C_SCL = 1280; // TODO: How to calculate the frequency. + regs->I2C_CNTEX = I2C_CLK_STRETCH; + regs->I2C_SCL = I2C_DELAYS(5u, 0u); regs = i2cGetBusRegsBase(I2C_BUS2); while(regs->I2C_CNT & I2C_ENABLE); - regs->I2C_CNTEX = 2; - regs->I2C_SCL = 1280; + regs->I2C_CNTEX = I2C_CLK_STRETCH; + regs->I2C_SCL = I2C_DELAYS(5u, 0u); regs = i2cGetBusRegsBase(I2C_BUS3); while(regs->I2C_CNT & I2C_ENABLE); - regs->I2C_CNTEX = 2; - regs->I2C_SCL = 1280; + regs->I2C_CNTEX = I2C_CLK_STRETCH; + regs->I2C_SCL = I2C_DELAYS(5u, 0u); } static bool i2cStartTransfer(u8 devAddr, u8 regAddr, bool read, I2cRegs *const regs) @@ -148,23 +148,23 @@ // Select device and start. regs->I2C_DATA = devAddr; - regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE | I2C_START; - i2cWaitBusyIrq(®s->I2C_CNT); - if(!i2cCheckAck(®s->I2C_CNT)) continue; + regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIR_WRITE | I2C_START; + i2cWaitBusyIrq(regs); + if(!i2cCheckAck(regs)) continue; // Select register. regs->I2C_DATA = regAddr; - regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE; - i2cWaitBusyIrq(®s->I2C_CNT); - if(!i2cCheckAck(®s->I2C_CNT)) continue; + regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIR_WRITE; + i2cWaitBusyIrq(regs); + if(!i2cCheckAck(regs)) continue; // Select device in read mode for read transfer. if(read) { regs->I2C_DATA = devAddr | 1u; // Set bit 0 for read. - regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE | I2C_START; - i2cWaitBusyIrq(®s->I2C_CNT); - if(!i2cCheckAck(®s->I2C_CNT)) continue; + regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIR_WRITE | I2C_START; + i2cWaitBusyIrq(regs); + if(!i2cCheckAck(regs)) continue; } break; @@ -183,14 +183,14 @@ while(--size) { - regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_ACK; - i2cWaitBusyIrq(®s->I2C_CNT); + regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIR_READ | I2C_ACK; + i2cWaitBusyIrq(regs); *out++ = regs->I2C_DATA; } // Last byte transfer. - regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_STOP; - i2cWaitBusyIrq(®s->I2C_CNT); + regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIR_READ | I2C_STOP; + i2cWaitBusyIrq(regs); *out = regs->I2C_DATA; return true; @@ -207,16 +207,16 @@ while(--size) { regs->I2C_DATA = *in++; - regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE; - i2cWaitBusyIrq(®s->I2C_CNT); - if(!i2cCheckAck(®s->I2C_CNT)) return false; + regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIR_WRITE; + i2cWaitBusyIrq(regs); + if(!i2cCheckAck(regs)) return false; } // Last byte transfer. regs->I2C_DATA = *in; - regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE | I2C_STOP; - i2cWaitBusyIrq(®s->I2C_CNT); - if(!i2cCheckAck(®s->I2C_CNT)) return false; + regs->I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIR_WRITE | I2C_STOP; + i2cWaitBusyIrq(regs); + if(!i2cCheckAck(regs)) return false; return true; } @@ -246,15 +246,15 @@ // Select device and start. regs->I2C_DATA = devAddr; - regs->I2C_CNT = I2C_ENABLE | I2C_DIRE_WRITE | I2C_START; + regs->I2C_CNT = I2C_ENABLE | I2C_DIR_WRITE | I2C_START; while(regs->I2C_CNT & I2C_ENABLE); - if(!i2cCheckAck(®s->I2C_CNT)) continue; + if(!i2cCheckAck(regs)) continue; // Select register. regs->I2C_DATA = regAddr; - regs->I2C_CNT = I2C_ENABLE | I2C_DIRE_WRITE; + regs->I2C_CNT = I2C_ENABLE | I2C_DIR_WRITE; while(regs->I2C_CNT & I2C_ENABLE); - if(!i2cCheckAck(®s->I2C_CNT)) continue; + if(!i2cCheckAck(regs)) continue; break; } while(--tries > 0); @@ -262,9 +262,9 @@ if(tries == 0) return false; regs->I2C_DATA = data; - regs->I2C_CNT = I2C_ENABLE | I2C_DIRE_WRITE | I2C_STOP; + regs->I2C_CNT = I2C_ENABLE | I2C_DIR_WRITE | I2C_STOP; while(regs->I2C_CNT & I2C_ENABLE); - if(!i2cCheckAck(®s->I2C_CNT)) return false; + if(!i2cCheckAck(regs)) return false; return true; } diff --git a/source/arm11/hardware/mcu.c b/source/arm11/hardware/mcu.c index b3d42df..e655fa3 100644 --- a/source/arm11/hardware/mcu.c +++ b/source/arm11/hardware/mcu.c @@ -47,42 +47,42 @@ void MCU_disableLEDs(void) { // disable wifi LED - I2C_writeReg(I2C_DEV_MCU, RegWifiLED, 0); + I2C_writeReg(I2C_DEV_CTR_MCU, RegWifiLED, 0); // disable 3D LED - I2C_writeReg(I2C_DEV_MCU, Reg3DLED, 0); + I2C_writeReg(I2C_DEV_CTR_MCU, Reg3DLED, 0); // disable camera LED - I2C_writeReg(I2C_DEV_MCU, RegCamLED, 0); + I2C_writeReg(I2C_DEV_CTR_MCU, RegCamLED, 0); } void MCU_powerOnLCDs(void) { // bit1 = lcd power enable for both screens - I2C_writeReg(I2C_DEV_MCU, RegLCDs, 1<<5 | 1<<3 | 1<<1); + I2C_writeReg(I2C_DEV_CTR_MCU, RegLCDs, 1<<5 | 1<<3 | 1<<1); } void MCU_powerOffLCDs(void) { // bit0 = lcd power disable for both screens (also disables backlight) - I2C_writeReg(I2C_DEV_MCU, RegLCDs, 1); + I2C_writeReg(I2C_DEV_CTR_MCU, RegLCDs, 1); } void MCU_triggerPowerOff(void) { - I2C_writeRegIntSafe(I2C_DEV_MCU, RegPower, 1); + I2C_writeRegIntSafe(I2C_DEV_CTR_MCU, RegPower, 1); } void MCU_triggerReboot(void) { - I2C_writeRegIntSafe(I2C_DEV_MCU, RegPower, 1u << 2); + I2C_writeRegIntSafe(I2C_DEV_CTR_MCU, RegPower, 1u << 2); } u8 MCU_readBatteryLevel(void) { u8 state; - if(!I2C_readRegBuf(I2C_DEV_MCU, RegBattery, &state, 1)) + if(!I2C_readRegBuf(I2C_DEV_CTR_MCU, RegBattery, &state, 1)) return 0; return state; @@ -90,14 +90,14 @@ u8 MCU_readExternalHwState(void) { - return I2C_readReg(I2C_DEV_MCU, RegExHW); + return I2C_readReg(I2C_DEV_CTR_MCU, RegExHW); } u8 MCU_readSystemModel(void) { u8 sysinfo[0x13]; - if(!I2C_readRegBuf(I2C_DEV_MCU, RegSysModel, sysinfo, sizeof sysinfo)) + if(!I2C_readRegBuf(I2C_DEV_CTR_MCU, RegSysModel, sysinfo, sizeof sysinfo)) return 0xFF; return sysinfo[9]; @@ -107,34 +107,34 @@ { if(!rtc) return; - I2C_readRegBuf(I2C_DEV_MCU, RegRTC, rtc, 8); + I2C_readRegBuf(I2C_DEV_CTR_MCU, RegRTC, rtc, 8); } u32 MCU_readReceivedIrqs(void) { u32 data; - if(!I2C_readRegBuf(I2C_DEV_MCU, 0x10, (u8*)&data, 4)) return 0; + if(!I2C_readRegBuf(I2C_DEV_CTR_MCU, 0x10, (u8*)&data, 4)) return 0; return data; } bool MCU_setIrqBitmask(u32 mask) { - return I2C_writeRegBuf(I2C_DEV_MCU, 0x18, (const u8*)&mask, 4); + return I2C_writeRegBuf(I2C_DEV_CTR_MCU, 0x18, (const u8*)&mask, 4); } u8 MCU_readHidHeld(void) { u8 data[19]; - if(!I2C_readRegBuf(I2C_DEV_MCU, 0x7F, data, sizeof(data))) return 0xFF; + if(!I2C_readRegBuf(I2C_DEV_CTR_MCU, 0x7F, data, sizeof(data))) return 0xFF; return data[18]; } bool MCU_powerOnLcdBacklights(void) { - return I2C_writeReg(I2C_DEV_MCU, 0x22, 1<<5 | 1<<3); // bit3 = lower screen, bit5 = upper + return I2C_writeReg(I2C_DEV_CTR_MCU, 0x22, 1<<5 | 1<<3); // bit3 = lower screen, bit5 = upper } bool MCU_setPowerLedState(PwLedState state) { - return I2C_writeReg(I2C_DEV_MCU, 0x29, state); + return I2C_writeReg(I2C_DEV_CTR_MCU, 0x29, state); } diff --git a/source/arm11/hardware/spi.c b/source/arm11/hardware/spi.c index 52ce919..e336775 100644 --- a/source/arm11/hardware/spi.c +++ b/source/arm11/hardware/spi.c @@ -31,10 +31,12 @@ typedef struct { vu32 NSPI_CNT; - vu32 NSPI_DONE; + vu8 NSPI_CS; // 32 bit but can be accessed as u8 + u8 padd1[3]; vu32 NSPI_BLKLEN; vu32 NSPI_FIFO; - vu32 NSPI_STATUS; + vu8 NSPI_FIFO_STAT; // 32 bit but can be accessed as u8 + u8 padd2[3]; vu32 NSPI_AUTOPOLL; vu32 NSPI_INT_MASK; vu32 NSPI_INT_STAT; @@ -53,13 +55,13 @@ u8 csClk; } spiDevTable[] = { - {SPI_BUS3, 0u<<6 | NSPI_CLK_512KHz}, - {SPI_BUS3, 1u<<6 | 0}, // TODO: Clock - {SPI_BUS3, 2u<<6 | 0}, // TODO: Clock + {SPI_BUS3, 0u<<6 | NSPI_CLK_512KHz}, // TODO: Confirm clock + {SPI_BUS3, 1u<<6 | NSPI_CLK_1MHz}, + {SPI_BUS3, 2u<<6 | NSPI_CLK_4MHz}, // TODO: Confirm clock {SPI_BUS1, 0u<<6 | NSPI_CLK_4MHz}, - {SPI_BUS1, 1u<<6 | 0}, // TODO: Clock - {SPI_BUS1, 2u<<6 | 0}, // TODO: Clock - {SPI_BUS2, 0u<<6 | 0} // TODO: Clock + {SPI_BUS1, 1u<<6 | 0}, // Unused? + {SPI_BUS1, 2u<<6 | 0}, // Unused? + {SPI_BUS2, 0u<<6 | 0} // Unused? }; @@ -85,14 +87,14 @@ return base; } -static inline void nspiWaitBusy(const vu32 *const NSPI_CNT) +static inline void nspiWaitBusy(const SpiRegs *const regs) { - while(*NSPI_CNT & NSPI_CNT_ENABLE); + while(regs->NSPI_CNT & NSPI_ENABLE); } -static inline void nspiWaitFifoBusy(const vu32 *const NSPI_STATUS) +static inline void nspiWaitFifoBusy(const SpiRegs *const regs) { - while(*NSPI_STATUS & NSPI_STATUS_BUSY); + while(regs->NSPI_FIFO_STAT & NSPI_FIFO_BUSY); } void NSPI_init(void) @@ -141,38 +143,38 @@ void NSPI_writeRead(SpiDevice dev, const u32 *in, u32 *out, u32 inSize, u32 outSize, bool done) { SpiRegs *const regs = nspiGetBusRegsBase(spiDevTable[dev].busId); - const u32 cntParams = NSPI_CNT_ENABLE | spiDevTable[dev].csClk; + const u32 cntParams = NSPI_ENABLE | spiDevTable[dev].csClk; if(in) { regs->NSPI_BLKLEN = inSize; - regs->NSPI_CNT = cntParams | NSPI_CNT_DIRE_WRITE; + regs->NSPI_CNT = cntParams | NSPI_DIR_WRITE; u32 counter = 0; do { - if((counter & 31) == 0) nspiWaitFifoBusy(®s->NSPI_STATUS); + if((counter & 31) == 0) nspiWaitFifoBusy(regs); regs->NSPI_FIFO = *in++; counter += 4; } while(counter < inSize); - nspiWaitBusy(®s->NSPI_CNT); + nspiWaitBusy(regs); } if(out) { regs->NSPI_BLKLEN = outSize; - regs->NSPI_CNT = cntParams | NSPI_CNT_DIRE_READ; + regs->NSPI_CNT = cntParams | NSPI_DIR_READ; u32 counter = 0; do { - if((counter & 31) == 0) nspiWaitFifoBusy(®s->NSPI_STATUS); + if((counter & 31) == 0) nspiWaitFifoBusy(regs); *out++ = regs->NSPI_FIFO; counter += 4; } while(counter < outSize); - nspiWaitBusy(®s->NSPI_CNT); + nspiWaitBusy(regs); } - if(done) regs->NSPI_DONE = NSPI_DONE_DONE; + if(done) regs->NSPI_CS = NSPI_DESELECT; } diff --git a/source/arm11/menu/bootslot.c b/source/arm11/menu/bootslot.c index a6822e2..053c2ea 100644 --- a/source/arm11/menu/bootslot.c +++ b/source/arm11/menu/bootslot.c @@ -33,7 +33,7 @@ return 0; if (stored_slot == INVALID_BOOT_SLOT) - stored_slot = I2C_readReg(I2C_DEV_MCU, BOOTSLOT_STORE_REG); + stored_slot = I2C_readReg(I2C_DEV_CTR_MCU, BOOTSLOT_STORE_REG); // slot must not exceed # of boot slots if (stored_slot > N_BOOTSLOTS) @@ -53,7 +53,7 @@ if (slot != stored_slot) { stored_slot = slot; - return I2C_writeReg(I2C_DEV_MCU, BOOTSLOT_STORE_REG, (u8) slot); + return I2C_writeReg(I2C_DEV_CTR_MCU, BOOTSLOT_STORE_REG, (u8) slot); } else { diff --git a/source/arm9/hardware/spicard.c b/source/arm9/hardware/spicard.c index 7a4a25a..844ee93 100644 --- a/source/arm9/hardware/spicard.c +++ b/source/arm9/hardware/spicard.c @@ -25,26 +25,26 @@ #include "arm9/hardware/ndma.h" -#define SPICARD_REGS_BASE (IO_MEM_ARM9_ONLY + 0xD800) -#define REG_NSPI_CNT *((vu32*)(SPICARD_REGS_BASE + 0x00)) -#define REG_NSPI_DONE *((vu32*)(SPICARD_REGS_BASE + 0x04)) -#define REG_NSPI_BLKLEN *((vu32*)(SPICARD_REGS_BASE + 0x08)) -#define REG_NSPI_FIFO *((vu32*)(SPICARD_REGS_BASE + 0x0C)) -#define REG_NSPI_STATUS *((vu32*)(SPICARD_REGS_BASE + 0x10)) -#define REG_NSPI_AUTOPOLL *((vu32*)(SPICARD_REGS_BASE + 0x14)) -#define REG_NSPI_INT_MASK *((vu32*)(SPICARD_REGS_BASE + 0x18)) -#define REG_NSPI_INT_STAT *((vu32*)(SPICARD_REGS_BASE + 0x1C)) +#define SPICARD_REGS_BASE (IO_MEM_ARM9_ONLY + 0xD800) +#define REG_NSPI_CNT *((vu32*)(SPICARD_REGS_BASE + 0x00)) +#define REG_NSPI_CS *((vu8* )(SPICARD_REGS_BASE + 0x04)) // 32 bit but can be accessed as u8 +#define REG_NSPI_BLKLEN *((vu32*)(SPICARD_REGS_BASE + 0x08)) +#define REG_NSPI_FIFO *((vu32*)(SPICARD_REGS_BASE + 0x0C)) +#define REG_NSPI_FIFO_STAT *((vu8* )(SPICARD_REGS_BASE + 0x10)) // 32 bit but can be accessed as u8 +#define REG_NSPI_AUTOPOLL *((vu32*)(SPICARD_REGS_BASE + 0x14)) +#define REG_NSPI_INT_MASK *((vu32*)(SPICARD_REGS_BASE + 0x18)) +#define REG_NSPI_INT_STAT *((vu32*)(SPICARD_REGS_BASE + 0x1C)) static inline void nspiWaitBusy(void) { - while(REG_NSPI_CNT & NSPI_CNT_ENABLE); + while(REG_NSPI_CNT & NSPI_ENABLE); } static inline void nspiWaitFifoBusy(void) { - while(REG_NSPI_STATUS & NSPI_STATUS_BUSY); + while(REG_NSPI_FIFO_STAT & NSPI_FIFO_BUSY); } void SPICARD_init(void) @@ -106,12 +106,12 @@ void SPICARD_writeRead(NspiClk clk, const u32 *in, u32 *out, u32 inSize, u32 outSize, bool done) { - const u32 cntParams = NSPI_CNT_ENABLE | NSPI_CNT_BUS_1BIT | clk; + const u32 cntParams = NSPI_ENABLE | NSPI_BUS_1BIT | clk; if(in) { REG_NSPI_BLKLEN = inSize; - REG_NSPI_CNT = cntParams | NSPI_CNT_DIRE_WRITE; + REG_NSPI_CNT = cntParams | NSPI_DIR_WRITE; u32 counter = 0; do @@ -126,7 +126,7 @@ if(out) { REG_NSPI_BLKLEN = outSize; - REG_NSPI_CNT = cntParams | NSPI_CNT_DIRE_READ; + REG_NSPI_CNT = cntParams | NSPI_DIR_READ; u32 counter = 0; do @@ -139,5 +139,5 @@ nspiWaitBusy(); } - if(done) REG_NSPI_DONE = NSPI_DONE; + if(done) REG_NSPI_CS = NSPI_DESELECT; }