diff --git a/arm11/source/hw/codec.c b/arm11/source/hw/codec.c index 53eec4b..f3eb5fe 100755 --- a/arm11/source/hw/codec.c +++ b/arm11/source/hw/codec.c @@ -25,32 +25,16 @@ #define CPAD_FACTOR (150) /* SPI stuff */ -static void CODEC_DualTX(u8 *tx0, u8 len0, u8 *tx1, u8 len1) +static void CODEC_WriteRead(u32 *txb, u8 txl, u32 *rxb, u8 rxl) { SPI_XferInfo xfers[2]; - xfers[0].buf = (u32*)tx0; - xfers[0].len = len0; + xfers[0].buf = txb; + xfers[0].len = txl; xfers[0].read = false; - xfers[1].buf = (u32*)tx1; - xfers[1].len = len1; - xfers[1].read = false; - - SPI_DoXfer(CODEC_SPI_DEV, xfers, 2); -} - -static void CODEC_WriteRead(u8 *tx_buf, u8 tx_len, - u8 *rx_buf, u8 rx_len) -{ - SPI_XferInfo xfers[2]; - - xfers[0].buf = (u32*)tx_buf; - xfers[0].len = tx_len; - xfers[0].read = false; - - xfers[1].buf = (u32*)rx_buf; - xfers[1].len = rx_len; + xfers[1].buf = rxb; + xfers[1].len = rxl; xfers[1].read = true; SPI_DoXfer(CODEC_SPI_DEV, xfers, 2); @@ -58,60 +42,49 @@ static void CODEC_WriteRead(u8 *tx_buf, u8 tx_len, static void CODEC_RegSelect(u8 reg) { - u8 buffer1[4]; - u8 buffer2[0x40]; + SPI_XferInfo xfer; + u32 cmd; - buffer1[0] = 0; - buffer2[0] = reg; + cmd = reg << 8; - CODEC_DualTX(buffer1, 1, buffer2, 1); + xfer.buf = &cmd; + xfer.len = 2; + xfer.read = false; + + SPI_DoXfer(CODEC_SPI_DEV, &xfer, 1); } -static u8 CODEC_RegRead(u8 offset) +static u8 CODEC_RegRead(u8 reg) { - u8 buffer_wr[8]; - u8 buffer_rd[0x40]; - - buffer_wr[0] = 1 | (offset << 1); - - CODEC_WriteRead(buffer_wr, 1, buffer_rd, 1); - - return buffer_rd[0]; + u32 cmd, ret; + cmd = (reg << 1) | 1; + CODEC_WriteRead(&cmd, 1, &ret, 1); + return ret; } static void CODEC_RegWrite(u8 reg, u8 val) { - u8 buffer1[8]; - u8 buffer2[0x40]; + SPI_XferInfo xfer; + u32 cmd; - buffer1[0] = (reg << 1); // Write - buffer2[0] = val; + cmd = (val << 8) | (reg << 1); - CODEC_DualTX(buffer1, 1, buffer2, 1); + xfer.buf = &cmd; + xfer.len = 2; + xfer.read = false; + + SPI_DoXfer(CODEC_SPI_DEV, &xfer, 1); } -static void CODEC_RegReadBuf(u8 offset, void *buffer, u8 size) +static void CODEC_RegReadBuf(u8 reg, u32 *out, u8 size) { - u8 buffer_wr[0x10]; - - buffer_wr[0] = 1 | (offset << 1); - - CODEC_WriteRead(buffer_wr, 1, buffer, size); + u32 cmd = (reg << 1) | 1; + CODEC_WriteRead(&cmd, 1, out, size); } -static void CODEC_RegMask(u8 offset, u8 mask0, u8 mask1) +static void CODEC_RegMask(u8 reg, u8 mask0, u8 mask1) { - u8 buffer1[4]; - u8 buffer2[0x40]; - - buffer1[0] = 1 | (offset << 1); - - CODEC_WriteRead(buffer1, 1, buffer2, 1); - - buffer1[0] = offset << 1; - buffer2[0] = (buffer2[0] & ~mask1) | (mask0 & mask1); - - CODEC_DualTX(buffer1, 1, buffer2, 1); + CODEC_RegWrite(reg, (CODEC_RegRead(reg) & ~mask1) | (mask0 & mask1)); } void CODEC_Init(void) @@ -147,7 +120,7 @@ void CODEC_Init(void) CODEC_RegMask(0x25, 0x10, 0x3C); } -static void CODEC_GetRawData(u8 *buffer) +void CODEC_GetRawData(u32 *buffer) { CODEC_RegSelect(0x67); CODEC_RegRead(0x26); @@ -157,11 +130,12 @@ static void CODEC_GetRawData(u8 *buffer) void CODEC_Get(CODEC_Input *input) { - u8 raw_data[0x34]; + u32 raw_data_buf[0x34 / 4]; + u8 *raw_data = (u8*)raw_data_buf; s16 cpad_x, cpad_y; bool ts_pressed; - CODEC_GetRawData(raw_data); + CODEC_GetRawData(raw_data_buf); cpad_x = ((raw_data[0x24] << 8 | raw_data[0x25]) & 0xFFF) - 2048; cpad_y = ((raw_data[0x14] << 8 | raw_data[0x15]) & 0xFFF) - 2048; diff --git a/arm11/source/hw/codec.h b/arm11/source/hw/codec.h index 5434ed5..b7a951c 100755 --- a/arm11/source/hw/codec.h +++ b/arm11/source/hw/codec.h @@ -9,4 +9,5 @@ typedef struct { void CODEC_Init(void); +void CODEC_GetRawData(u32 *buffer); void CODEC_Get(CODEC_Input *input); diff --git a/arm11/source/hw/spi.c b/arm11/source/hw/spi.c index 58cc2f8..ed064dd 100755 --- a/arm11/source/hw/spi.c +++ b/arm11/source/hw/spi.c @@ -15,83 +15,73 @@ #include "hw/spi.h" -#define CFG_SPI_CNT ((vu32*)0x101401C0) +#define REG_CFG_SPI_CNT ((vu16*)0x101401C0) -// TODO: CURRENTLY HARDCODED FOR DEVICE 3 (TOUCHSCREEN) -// IF ANY OTHER DEVICES ARE TO BE USED, ANOTHER BUS MUST -// BE ACCESSED, CHECK 3dbrew.org/wiki/SPI_{Registers, Services} -static const u32 SPI_Buses[] = { 0x10142800 }; -#define REG_SPI(b, n) (*(vu32*)(SPI_Buses[b] + (n))) +#define REG_SPI(bus, reg) (*((vu32*)((bus) + (reg)))) -#define REG_SPI_CNT REG_SPI(0, 0x00) -#define REG_SPI_DONE REG_SPI(0, 0x04) -#define REG_SPI_BLKLEN REG_SPI(0, 0x08) -#define REG_SPI_FIFO REG_SPI(0, 0x0C) -#define REG_SPI_STATUS REG_SPI(0, 0x10) +#define REG_SPI_BUS0 (0x10160800) +#define REG_SPI_BUS1 (0x10142800) +#define REG_SPI_BUS2 (0x10143800) -#define SPI_CNT_BUSY BIT(15) -#define SPI_CNT_START BIT(15) +#define REG_SPI_CONTROL 0x00 +#define REG_SPI_DONE 0x04 +#define REG_SPI_BLKLEN 0x08 +#define REG_SPI_FIFO 0x0C +#define REG_SPI_STAT 0x10 -#define SPI_CNT_READ (0) -#define SPI_CNT_WRITE BIT(13) - -#define SPI_CNT_RATE(n) (n) -#define SPI_CNT_CS(n) ((n) << 6) +#define SPI_CONTROL_RATE(n) (n) +#define SPI_CONTROL_CS(n) ((n) << 6) +#define SPI_DIRECTION_READ (0) +#define SPI_DIRECTION_WRITE BIT(13) +#define SPI_CONTROL_BUSY BIT(15) +#define SPI_CONTROL_START BIT(15) #define SPI_STAT_BUSY BIT(0) #define SPI_FIFO_WIDTH (32) -static u8 SPI_GetDevSelect(u32 dev) +static struct { + u32 bus; + u32 regcfg; +} SPI_Devices[] = { + {REG_SPI_BUS0, SPI_CONTROL_RATE(2) | SPI_CONTROL_CS(0)}, // device 0 + {REG_SPI_BUS0, SPI_CONTROL_RATE(0) | SPI_CONTROL_CS(1)}, + {REG_SPI_BUS0, SPI_CONTROL_RATE(0) | SPI_CONTROL_CS(2)}, + {REG_SPI_BUS1, SPI_CONTROL_RATE(5) | SPI_CONTROL_CS(0)}, + // TODO: complete this table +}; + +static void SPI_WaitBusy(u32 bus) { - static const u8 SPI_DevSelect[] = { 0, 1, 2, 0, 1, 2 }; - if (dev < countof(SPI_DevSelect)) { - return SPI_DevSelect[dev]; - } else { - return 0; - } + while(REG_SPI(bus, REG_SPI_CONTROL) & SPI_CONTROL_BUSY); } -static u8 SPI_GetDevBaudrate(u32 dev) +static void SPI_WaitFIFO(u32 bus) { - static const u8 SPI_BaudRates[] = { 2, 0, 0, 5 }; - if (dev < countof(SPI_BaudRates)) { - return SPI_BaudRates[dev]; - } else { - return 0; - } + while(REG_SPI(bus, REG_SPI_STAT) & SPI_STAT_BUSY); } -static void SPI_WaitBusy(void) +static void SPI_Done(u32 bus) { - while(REG_SPI_CNT & SPI_CNT_BUSY); + REG_SPI(bus, REG_SPI_DONE) = 0; } -static void SPI_WaitFIFO(void) -{ - while(REG_SPI_STATUS & SPI_STAT_BUSY); -} - -static void SPI_Done(void) -{ - REG_SPI_DONE = 0; -} - -static void SPI_SingleXfer(u32 reg, bool read, u32 *buffer, u32 len) +static void SPI_SingleXfer(u32 reg, u32 bus, u32 *buffer, u32 len, bool read) { u32 pos = 0; - REG_SPI_BLKLEN = len; - REG_SPI_CNT = reg | (read ? SPI_CNT_READ : SPI_CNT_WRITE) | SPI_CNT_START; + REG_SPI(bus, REG_SPI_BLKLEN) = len; + REG_SPI(bus, REG_SPI_CONTROL) = reg | + (read ? SPI_DIRECTION_READ : SPI_DIRECTION_WRITE) | SPI_CONTROL_START; do { if ((pos % SPI_FIFO_WIDTH) == 0) - SPI_WaitFIFO(); + SPI_WaitFIFO(bus); if (read) { - buffer[pos / 4] = REG_SPI_FIFO; + buffer[pos / 4] = REG_SPI(bus, REG_SPI_FIFO); } else { - REG_SPI_FIFO = buffer[pos / 4]; + REG_SPI(bus, REG_SPI_FIFO) = buffer[pos / 4]; } pos += 4; @@ -100,30 +90,27 @@ static void SPI_SingleXfer(u32 reg, bool read, u32 *buffer, u32 len) int SPI_DoXfer(u32 dev, SPI_XferInfo *xfers, u32 xfer_cnt) { - u32 dev_cfg; - int baud, cs; + u32 bus; + u32 dev_reg; - baud = SPI_GetDevBaudrate(dev); - cs = SPI_GetDevSelect(dev); - dev_cfg = SPI_CNT_RATE(baud) | SPI_CNT_CS(cs); + bus = SPI_Devices[dev].bus; + dev_reg = SPI_Devices[dev].regcfg; for (u32 i = 0; i < xfer_cnt; i++) { SPI_XferInfo *xfer = &xfers[i]; - SPI_WaitBusy(); - SPI_SingleXfer(dev_cfg, xfer->read, xfer->buf, xfer->len); + SPI_WaitBusy(bus); + SPI_SingleXfer(dev_reg, bus, xfer->buf, xfer->len, xfer->read); } - SPI_WaitBusy(); - SPI_Done(); + SPI_WaitBusy(bus); + SPI_Done(bus); return 0; } void SPI_Init(void) { - // Hack: here all registers should be set to the "new" mode - // but GM9 uses the old interface to access NVRAM - // as such, only the bus used by CODEC will be set to new - // *CFG_SPI_CNT = 7; - *CFG_SPI_CNT = BIT(1); + // This cuts off access from the old SPI + // interface used during the NDS days + *REG_CFG_SPI_CNT = 7; }