Allow rebooting on Brahma 2

This commit is contained in:
d0k3 2015-12-16 15:47:09 +01:00
parent 6641948b30
commit bf944f682b
3 changed files with 193 additions and 0 deletions

150
source/i2c.c Normal file
View File

@ -0,0 +1,150 @@
#include "i2c.h"
#include "draw.h"
//-----------------------------------------------------------------------------
static const struct { u8 bus_id, reg_addr } dev_data[] = {
{0, 0x4A}, {0, 0x7A}, {0, 0x78},
{1, 0x4A}, {1, 0x78}, {1, 0x2C},
{1, 0x2E}, {1, 0x40}, {1, 0x44},
{2, 0xD6}, {2, 0xD0}, {2, 0xD2},
{2, 0xA4}, {2, 0x9A}, {2, 0xA0},
};
const inline u8 i2cGetDeviceBusId(u8 device_id) {
return dev_data[device_id].bus_id;
}
const inline u8 i2cGetDeviceRegAddr(u8 device_id) {
return dev_data[device_id].reg_addr;
}
//-----------------------------------------------------------------------------
static vu8* const reg_data_addrs[] = {
(vu8*)(I2C1_REG_OFF + I2C_REG_DATA),
(vu8*)(I2C2_REG_OFF + I2C_REG_DATA),
(vu8*)(I2C3_REG_OFF + I2C_REG_DATA),
};
inline vu8* const i2cGetDataReg(u8 bus_id) {
return reg_data_addrs[bus_id];
}
//-----------------------------------------------------------------------------
static vu8* const reg_cnt_addrs[] = {
(vu8*)(I2C1_REG_OFF + I2C_REG_CNT),
(vu8*)(I2C2_REG_OFF + I2C_REG_CNT),
(vu8*)(I2C3_REG_OFF + I2C_REG_CNT),
};
inline vu8* const i2cGetCntReg(u8 bus_id) {
return reg_cnt_addrs[bus_id];
}
//-----------------------------------------------------------------------------
inline void i2cWaitBusy(u8 bus_id) {
while (*i2cGetCntReg(bus_id) & 0x80);
}
inline bool i2cGetResult(u8 bus_id) {
i2cWaitBusy(bus_id);
return (*i2cGetCntReg(bus_id) >> 4) & 1;
}
void i2cStop(u8 bus_id, u8 arg0) {
*i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0;
i2cWaitBusy(bus_id);
*i2cGetCntReg(bus_id) = 0xC5;
}
//-----------------------------------------------------------------------------
bool i2cSelectDevice(u8 bus_id, u8 dev_reg) {
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = dev_reg;
*i2cGetCntReg(bus_id) = 0xC2;
return i2cGetResult(bus_id);
}
bool i2cSelectRegister(u8 bus_id, u8 reg) {
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = reg;
*i2cGetCntReg(bus_id) = 0xC0;
return i2cGetResult(bus_id);
}
//-----------------------------------------------------------------------------
u8 i2cReadRegister(u8 dev_id, u8 reg) {
u8 bus_id = i2cGetDeviceBusId(dev_id);
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
for (size_t i = 0; i < 8; i++) {
if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) {
if (i2cSelectDevice(bus_id, dev_addr | 1)) {
i2cWaitBusy(bus_id);
i2cStop(bus_id, 1);
i2cWaitBusy(bus_id);
return *i2cGetDataReg(bus_id);
}
}
*i2cGetCntReg(bus_id) = 0xC5;
i2cWaitBusy(bus_id);
}
return 0xff;
}
bool i2cReadRegisterBuffer(unsigned int dev_id, int reg, u8* buffer, size_t buf_size) {
u8 bus_id = i2cGetDeviceBusId(dev_id);
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
size_t j = 0;
while (!i2cSelectDevice(bus_id, dev_addr)
|| !i2cSelectRegister(bus_id, reg)
|| !i2cSelectDevice(bus_id, dev_addr | 1))
{
i2cWaitBusy(bus_id);
*i2cGetCntReg(bus_id) = 0xC5;
i2cWaitBusy(bus_id);
if (++j >= 8)
return false;
}
if (buf_size != 1) {
for (int i = 0; i < buf_size - 1; i++) {
i2cWaitBusy(bus_id);
*i2cGetCntReg(bus_id) = 0xF0;
i2cWaitBusy(bus_id);
buffer[i] = *i2cGetDataReg(bus_id);
}
}
i2cWaitBusy(bus_id);
*i2cGetCntReg(bus_id) = 0xE1;
i2cWaitBusy(bus_id);
*buffer = *i2cGetDataReg(bus_id);
return true;
}
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data) {
u8 bus_id = i2cGetDeviceBusId(dev_id);
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
for (int i = 0; i < 8; i++) {
if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) {
i2cWaitBusy(bus_id);
*i2cGetDataReg(bus_id) = data;
*i2cGetCntReg(bus_id) = 0xC1;
i2cStop(bus_id, 0);
if (i2cGetResult(bus_id))
return true;
}
*i2cGetCntReg(bus_id) = 0xC5;
i2cWaitBusy(bus_id);
}
return false;
}

35
source/i2c.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
#include "common.h"
#define I2C1_REG_OFF 0x10161000
#define I2C2_REG_OFF 0x10144000
#define I2C3_REG_OFF 0x10148000
#define I2C_REG_DATA 0
#define I2C_REG_CNT 1
#define I2C_REG_CNTEX 2
#define I2C_REG_SCL 4
#define I2C_DEV_MCU 3
#define I2C_DEV_GYRO 10
#define I2C_DEV_IR 13
const u8 i2cGetDeviceBusId(u8 device_id);
const u8 i2cGetDeviceRegAddr(u8 device_id);
vu8* const i2cGetDataReg(u8 bus_id);
vu8* const i2cGetCntReg(u8 bus_id);
void i2cWaitBusy(u8 bus_id);
bool i2cGetResult(u8 bus_id);
u8 i2cGetData(u8 bus_id);
void i2cStop(u8 bus_id, u8 arg0);
bool i2cSelectDevice(u8 bus_id, u8 dev_reg);
bool i2cSelectRegister(u8 bus_id, u8 reg);
u8 i2cReadRegister(u8 dev_id, u8 reg);
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data);
bool i2cReadRegisterBuffer(unsigned int dev_id, int reg, u8* buffer, size_t buf_size);

View File

@ -4,6 +4,7 @@
#include "draw.h"
#include "hid.h"
#include "i2c.h"
#include "fatfs/ff.h"
#include "gamecart/protocol.h"
#include "gamecart/command_ctr.h"
@ -26,6 +27,12 @@ static void wait_key(void) {
InputWait();
}
void Reboot()
{
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
while(true);
}
struct Context {
u8* buffer;
size_t buffer_size;
@ -187,5 +194,6 @@ restart_prompt:
if (!(InputWait() & BUTTON_B))
goto restart_program;
Reboot();
return 0;
}