added 3ds11. untested. Porbably won#t work
This commit is contained in:
parent
d994c70468
commit
65d9d93c24
12 changed files with 420 additions and 1 deletions
3
kernel/arch/arm/3ds11/flags.cmake
Normal file
3
kernel/arch/arm/3ds11/flags.cmake
Normal file
|
@ -0,0 +1,3 @@
|
|||
SET(PLATFORM_C_FLAGS "-I../../kernel/arch/arm/3ds11/include")
|
||||
SET(PLATFORM_CXX_FLAGS "${PLATFORM_C_FLAGS}")
|
||||
SET(PLATFORM_ASM_FLAGS "${PLATFORM_C_FLAGS}")
|
36
kernel/arch/arm/3ds11/layout.ld
Normal file
36
kernel/arch/arm/3ds11/layout.ld
Normal file
|
@ -0,0 +1,36 @@
|
|||
ENTRY(_start)
|
||||
SECTIONS {
|
||||
. = 0x20000000;
|
||||
kernel_start = .;
|
||||
.text : {
|
||||
KEEP(*(.text.boot));
|
||||
*(.text)
|
||||
}
|
||||
.data : {
|
||||
start_ctors = .;
|
||||
KEEP(*(.init_array));
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)));
|
||||
KEEP(*(.ctors));
|
||||
end_ctors = .;
|
||||
start_dtors = .;
|
||||
KEEP(*(.fini_array));
|
||||
KEEP(*(.fini_array.*));
|
||||
KEEP(*(.dtors));
|
||||
end_dtors = .;
|
||||
start_eh_frame = .;
|
||||
KEEP(*(.eh_frame));
|
||||
KEEP(*(.eh_frame.*));
|
||||
QUAD(0);
|
||||
KEEP(*(.gcc_except_table));
|
||||
KEEP(*(.gcc_except_table.*));
|
||||
*(.data)
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
kernel_end = .;
|
||||
}
|
11
kernel/arch/arm/3ds11/start.cpp
Normal file
11
kernel/arch/arm/3ds11/start.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "../../../hw/3ds11/picafb/picafb.hpp"
|
||||
#include <base.hpp>
|
||||
#include <config.h>
|
||||
|
||||
PICAfb term;
|
||||
void main();
|
||||
extern "C" void start() { main(); }
|
||||
void drivers_init() {
|
||||
setMainTTY(&term);
|
||||
--term;
|
||||
}
|
25
kernel/arch/arm/3ds11/start.s
Normal file
25
kernel/arch/arm/3ds11/start.s
Normal file
|
@ -0,0 +1,25 @@
|
|||
.arm
|
||||
.arch armv6k
|
||||
.fpu vfpv2
|
||||
.align 4
|
||||
.global _start
|
||||
.extern start
|
||||
.section .text.boot
|
||||
_start:
|
||||
CPSID aif //Disable interrupts
|
||||
ldr sp, =kernel_stack
|
||||
//Enable FPU
|
||||
mov r0, #0
|
||||
mov r1, #0xF00000
|
||||
mcr p15, 0, r1, c1, c0, 2
|
||||
mcr p15, 0, r0, c7, c5, 4
|
||||
mov r1, #0x40000000
|
||||
mov r2, #0x3C00000
|
||||
fmxr fpexc, r1
|
||||
fmxr fpscr, r2
|
||||
//Start MTGos
|
||||
blx start
|
||||
|
||||
.section .bss
|
||||
.space 16384
|
||||
kernel_stack:
|
3
kernel/arch/arm/flags.cmake
Normal file
3
kernel/arch/arm/flags.cmake
Normal file
|
@ -0,0 +1,3 @@
|
|||
SET(PLATFORM_C_FLAGS "-I../../kernel/arch/arm/include")
|
||||
SET(PLATFORM_CXX_FLAGS "${PLATFORM_C_FLAGS}")
|
||||
SET(PLATFORM_ASM_FLAGS "${PLATFORM_C_FLAGS}")
|
|
@ -3,4 +3,10 @@ config["ENABLE_I2C"] = get_yes_no("Enable i2c driver", True)
|
|||
if config["ENABLE_I2C"]:
|
||||
config["PROTECT_MCU"] = get_yes_no("Prevent writes to MCU firmware (Device 3, Register 5)", True)
|
||||
config["ENABLE_SCREENINIT"] = get_yes_no("Enable screeninit.", True)
|
||||
|
||||
add_driver(False, "i2c")
|
||||
if config["ENABLE_SCREENINIT"]:
|
||||
add_driver(False, "mcu")
|
||||
add_driver(True, "framebuffer")
|
||||
add_driver(False, "picafb")
|
||||
print("Enable complete Unicode font: NO (because of the size)")
|
||||
config["ENABLE_FRAMEBUFFER_UNICODE"] = False
|
||||
|
|
66
kernel/hw/3ds11/i2c/i2c.cpp
Normal file
66
kernel/hw/3ds11/i2c/i2c.cpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include "i2c.hpp"
|
||||
struct I2CBus {
|
||||
volatile uint8_t data;
|
||||
volatile uint8_t ctl;
|
||||
uint16_t cntex;
|
||||
uint16_t scl;
|
||||
} __attribute__((packed));
|
||||
I2CBus *buses[] = {(I2CBus *)0x10161000, (I2CBus *)0x10144000, (I2CBus *)0x10148000};
|
||||
I2C::I2C() {}
|
||||
I2C::~I2C() {}
|
||||
auto I2C::waitBusy() -> void {
|
||||
while (buses[busID]->ctl & 0x80)
|
||||
;
|
||||
}
|
||||
auto I2C::getResult() -> bool {
|
||||
waitBusy();
|
||||
return buses[busID]->ctl & 0x10;
|
||||
}
|
||||
auto I2C::stop() -> bool {
|
||||
buses[busID]->ctl = 0xC0;
|
||||
waitBusy();
|
||||
buses[busID]->ctl = 0xC5;
|
||||
}
|
||||
auto I2C::selectDev(int dev) -> bool {
|
||||
static int buss[] = {1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 2, 1, 3};
|
||||
static int addr[] = {0x4a, 0x7a, 0x78, 0x4a, 0x78, 0x2C, 0x2E, 0x40, 0x44,
|
||||
0xA6, 0xD0, 0xD2, 0xA4, 0x9A, 0xA0, 0xEE, 0x40, 0x54};
|
||||
currDev = dev;
|
||||
busID = buss[dev];
|
||||
waitBusy();
|
||||
buses[busID]->data = addr[dev];
|
||||
buses[busID]->ctl = 0xC2;
|
||||
return getResult();
|
||||
}
|
||||
auto I2C::selectReg(int reg) -> bool {
|
||||
#ifdef PROTECT_MCU
|
||||
if ((currReg == 3) && (reg == 5)) return false;
|
||||
#endif
|
||||
currReg = reg;
|
||||
waitBusy();
|
||||
buses[busID]->data = (uint8_t)reg;
|
||||
buses[busID]->ctl = 0xC0;
|
||||
return getResult();
|
||||
}
|
||||
auto I2C::write(uint8_t data) -> bool {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
waitBusy();
|
||||
buses[busID]->data = data;
|
||||
buses[busID]->ctl = 0xC1;
|
||||
if (getResult()) { return true; }
|
||||
stop();
|
||||
selectDev(currDev);
|
||||
selectReg(currReg);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
auto I2C::read() -> uint8_t {
|
||||
waitBusy();
|
||||
buses[busID]->ctl = 0xE1;
|
||||
waitBusy();
|
||||
uint8_t data = buses[busID]->data;
|
||||
buses[busID]->ctl |= 0x10;
|
||||
getResult();
|
||||
stop();
|
||||
return data;
|
||||
}
|
20
kernel/hw/3ds11/i2c/i2c.hpp
Normal file
20
kernel/hw/3ds11/i2c/i2c.hpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
#include <config.h>
|
||||
#include <stdint.h>
|
||||
class I2C {
|
||||
private:
|
||||
int currDev;
|
||||
int currReg;
|
||||
int busID;
|
||||
|
||||
public:
|
||||
I2C();
|
||||
~I2C();
|
||||
auto waitBusy() -> void;
|
||||
auto getResult() -> bool;
|
||||
auto stop() -> bool;
|
||||
auto selectDev(int dev) -> bool;
|
||||
auto selectReg(int reg) -> bool;
|
||||
auto write(uint8_t data) -> bool;
|
||||
auto read() -> uint8_t;
|
||||
};
|
62
kernel/hw/3ds11/mcu/mcu.cpp
Normal file
62
kernel/hw/3ds11/mcu/mcu.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "mcu.hpp"
|
||||
namespace MCU {
|
||||
I2C access;
|
||||
uint8_t HIDStatus;
|
||||
static auto read(int reg) -> unsigned char {
|
||||
access.selectDev(3);
|
||||
access.selectReg(reg);
|
||||
return access.read();
|
||||
}
|
||||
static auto write(int reg, uint8_t value) -> void {
|
||||
access.selectDev(3);
|
||||
access.selectReg(reg);
|
||||
access.write(value);
|
||||
}
|
||||
auto getVersionLo() -> unsigned char { return read(0); }
|
||||
auto getVersionHi() -> unsigned char { return read(1); }
|
||||
auto getLCDFlickerTop() -> unsigned char { return read(3); }
|
||||
auto setLCDFlickerTop(unsigned char val) -> void { write(3, val); }
|
||||
auto getLCDFlickerBottom() -> unsigned char { return read(4); }
|
||||
auto setLCDFlickerBottom(unsigned char val) -> void { write(4, val); }
|
||||
auto get3DSlider() -> unsigned char { return read(8); }
|
||||
auto getVolume() -> unsigned char { return read(9); }
|
||||
auto getBatteryPercent() -> unsigned char { return read(11); }
|
||||
auto getSystemVoltage() -> unsigned char { return read(13); }
|
||||
auto isCharging() -> bool { return read(15) & 0x10; }
|
||||
auto isOpen() -> bool { return read(15) & 0x2; }
|
||||
auto updateHIDStatus() -> void { HIDStatus = read(16); }
|
||||
auto powerButtonPressed() -> bool { return HIDStatus & 0x1; }
|
||||
auto powerButtonLongPressed() -> bool { return HIDStatus & 0x2; }
|
||||
auto homeButtonPressed() -> bool { return HIDStatus & 0x4; }
|
||||
auto homeButtonReleased() -> bool { return HIDStatus & 0x8; }
|
||||
auto wifiEnabled() -> bool { return HIDStatus & 0x10; }
|
||||
auto closed() -> bool { return HIDStatus & 0x20; }
|
||||
auto opened() -> bool { return HIDStatus & 0x40; }
|
||||
auto poweroff() -> void { write(32, 1); }
|
||||
auto reboot() -> void { write(32, 4); }
|
||||
auto enableTopLCD() -> void { write(34, 0b100010); }
|
||||
auto disableTopLCD() -> void { write(34, 0b010010); }
|
||||
auto enableBottomLCD() -> void { write(34, 0b1010); }
|
||||
auto disableBottomLCD() -> void { write(34, 0b0110); }
|
||||
auto setWifiLED(char val) -> void { write(0x2A, (unsigned char)val); }
|
||||
auto setCameraLED(char val) -> void { write(0x2B, (unsigned char)val); }
|
||||
auto set3DLED(char val) -> void { write(0x2C, (unsigned char)val); }
|
||||
auto getRTC(RTC_date *date) -> void {
|
||||
auto bcdToVal = [](unsigned char c) -> unsigned char { return (c & 0xF) + (10 * (c >> 4)); };
|
||||
date->seconds = bcdToVal(read(0x30));
|
||||
date->minutes = bcdToVal(read(0x31));
|
||||
date->hours = bcdToVal(read(0x32));
|
||||
date->days = bcdToVal(read(0x34));
|
||||
date->months = bcdToVal(read(0x35));
|
||||
date->years = bcdToVal(read(0x36));
|
||||
}
|
||||
auto setRTC(RTC_date *date) -> void {
|
||||
auto valToBCD = [](unsigned char c) -> unsigned char { return (c % 10) + (c / 10) << 4; };
|
||||
write(0x30, valToBCD(date->seconds));
|
||||
write(0x31, valToBCD(date->minutes));
|
||||
write(0x32, valToBCD(date->hours));
|
||||
write(0x34, valToBCD(date->days));
|
||||
write(0x35, valToBCD(date->months));
|
||||
write(0x36, valToBCD(date->years));
|
||||
}
|
||||
}
|
45
kernel/hw/3ds11/mcu/mcu.hpp
Normal file
45
kernel/hw/3ds11/mcu/mcu.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
#include "../i2c/i2c.hpp"
|
||||
namespace MCU {
|
||||
extern I2C access;
|
||||
auto getVersionLo() -> unsigned char;
|
||||
auto getVersionHi() -> unsigned char;
|
||||
auto getLCDFlickerTop() -> unsigned char;
|
||||
auto setLCDFlickerTop(unsigned char) -> void;
|
||||
auto getLCDFlickerBottom() -> unsigned char;
|
||||
auto setLCDFlickerTop(unsigned char) -> void;
|
||||
auto get3DSlider() -> unsigned char;
|
||||
auto getVolume() -> unsigned char;
|
||||
auto getBatteryPercent() -> unsigned char;
|
||||
auto getSystemVoltage() -> unsigned char;
|
||||
auto isCharging() -> bool;
|
||||
auto isOpen() -> bool;
|
||||
extern uint8_t HIDStatus;
|
||||
auto updateHIDStatus() -> void;
|
||||
auto powerButtonPressed() -> bool;
|
||||
auto powerButtonLongPressed() -> bool;
|
||||
auto homeButtonPressed() -> bool;
|
||||
auto homeButtonReleased() -> bool;
|
||||
auto wifiEnabled() -> bool;
|
||||
auto closed() -> bool;
|
||||
auto opened() -> bool;
|
||||
auto poweroff() -> void;
|
||||
auto reboot() -> void;
|
||||
auto enableTopLCD() -> void;
|
||||
auto disableTopLCD() -> void;
|
||||
auto enableBottomLCD() -> void;
|
||||
auto disableBottomLCD() -> void;
|
||||
auto setWifiLED(char val) -> void;
|
||||
auto setCameraLED(char val) -> void;
|
||||
auto set3DLED(char val) -> void;
|
||||
struct RTC_date {
|
||||
unsigned char seconds;
|
||||
unsigned char minutes;
|
||||
unsigned char hours;
|
||||
unsigned char days;
|
||||
unsigned char months;
|
||||
unsigned char years;
|
||||
};
|
||||
auto getRTC(RTC_date *) -> void;
|
||||
auto setRTC(RTC_date *) -> void;
|
||||
}
|
132
kernel/hw/3ds11/picafb/picafb.cpp
Normal file
132
kernel/hw/3ds11/picafb/picafb.cpp
Normal file
|
@ -0,0 +1,132 @@
|
|||
#include "picafb.hpp"
|
||||
#include <config.h>
|
||||
#ifdef ENABLE_SCREENINIT
|
||||
#include "../mcu/mcu.hpp"
|
||||
#endif
|
||||
#define GL_RGBA8_OES 0
|
||||
#define GL_RGB8_OES 1
|
||||
#define GL_RGB565_OES 2
|
||||
#define GL_RGB5_A1_OES 3
|
||||
#define GL_RGBA4_OES 4
|
||||
union FBFormat {
|
||||
int val;
|
||||
struct {
|
||||
char format : 3;
|
||||
char unused1 : 2;
|
||||
bool enable3D : 1;
|
||||
bool mainScreen : 1;
|
||||
bool unused2 : 1;
|
||||
char noRainbowStrip : 2;
|
||||
char unused3 : 22;
|
||||
} contents;
|
||||
};
|
||||
struct PDC {
|
||||
int unused1[0x17];
|
||||
int size;
|
||||
int unused2[2];
|
||||
void *leftFB[2];
|
||||
int format;
|
||||
int unused3;
|
||||
int fbselect;
|
||||
int unused4[2];
|
||||
int rainbow;
|
||||
int unused5[2];
|
||||
int stride;
|
||||
void *rightFB[2];
|
||||
int padding[2];
|
||||
} __attribute__((packed));
|
||||
PICAfb::PICAfb() : Framebuffer(25, 30) {
|
||||
#ifdef ENABLE_SCREENINIT
|
||||
MCU::enableTopLCD();
|
||||
MCU::enableBottomLCD();
|
||||
*((uint32_t *)0x10141200) = 0x1007F; // Enable Backlights and GPU IO region
|
||||
*((uint32_t *)0x10202014) = 1;
|
||||
*((uint32_t *)0x1020200C) &= 0xFFFEFFFE;
|
||||
|
||||
*((uint32_t *)0x10202240) = 0x3F; // Top screen brightness
|
||||
*((uint32_t *)0x10202A40) = 0x3F; // Bottom screen brightness
|
||||
*((uint32_t *)0x10202244) = 0x1023E;
|
||||
*((uint32_t *)0x10202A44) = 0x1023E;
|
||||
|
||||
PDC *top = (PDC *)0x10400400, *bottom = (PDC *)0x10400500;
|
||||
top->unused1[0] = 0x000001c2;
|
||||
top->unused1[1] = 0x000000d1;
|
||||
top->unused1[2] = 0x000001c1;
|
||||
top->unused1[3] = 0x000001c1;
|
||||
top->unused1[4] = 0x00000000;
|
||||
top->unused1[5] = 0x000000cf;
|
||||
top->unused1[6] = 0x000000d1;
|
||||
top->unused1[7] = 0x01c501c1;
|
||||
top->unused1[8] = 0x00010000;
|
||||
top->unused1[9] = 0x0000019d;
|
||||
top->unused1[10] = 0x00000002;
|
||||
top->unused1[11] = 0x00000192;
|
||||
top->unused1[12] = 0x00000192;
|
||||
top->unused1[13] = 0x00000192;
|
||||
top->unused1[14] = 0x00000001;
|
||||
top->unused1[15] = 0x00000002;
|
||||
top->unused1[16] = 0x01960192;
|
||||
top->unused1[17] = 0x00000000;
|
||||
top->unused1[18] = 0x00000000;
|
||||
top->size = 0x00f00190; // 400*240
|
||||
top->unused2[0] = 0x01c100d1;
|
||||
top->unused2[1] = 0x01920002;
|
||||
top->leftFB[0] = (void *)0x18300000; // Beginning of VRAM
|
||||
FBFormat a;
|
||||
a.val = 0;
|
||||
a.contents.format = GL_RGB8_OES;
|
||||
a.contents.mainScreen = true;
|
||||
a.contents.noRainbowStrip = 3;
|
||||
a.val |= 0x80000;
|
||||
top->format = a.val;
|
||||
top->unused3 = 0x00010501;
|
||||
top->fbselect = 0;
|
||||
top->stride = 0x000002D0;
|
||||
top->padding[1] = 0x00000000;
|
||||
|
||||
// Rainbow register
|
||||
for (uint32_t i = 0; i < 256; i++) top->rainbow = 0x10101 * i;
|
||||
|
||||
bottom->unused1[0] = 0x000001c2;
|
||||
bottom->unused1[1] = 0x000000d1;
|
||||
bottom->unused1[2] = 0x000001c1;
|
||||
bottom->unused1[3] = 0x000001c1;
|
||||
bottom->unused1[4] = 0x000000cd;
|
||||
bottom->unused1[5] = 0x000000cf;
|
||||
bottom->unused1[6] = 0x000000d1;
|
||||
bottom->unused1[7] = 0x01c501c1;
|
||||
bottom->unused1[8] = 0x00010000;
|
||||
bottom->unused1[9] = 0x0000019d;
|
||||
bottom->unused1[10] = 0x00000052;
|
||||
bottom->unused1[11] = 0x00000192;
|
||||
bottom->unused1[12] = 0x00000192;
|
||||
bottom->unused1[13] = 0x0000004f;
|
||||
bottom->unused1[14] = 0x00000050;
|
||||
bottom->unused1[15] = 0x00000052;
|
||||
bottom->unused1[16] = 0x01980194;
|
||||
bottom->unused1[17] = 0x00000000;
|
||||
bottom->unused1[18] = 0x00000011;
|
||||
bottom->size = 0x00f00140; // 320*240
|
||||
bottom->unused2[0] = 0x01c100d1;
|
||||
bottom->unused2[1] = 0x01920052;
|
||||
bottom->leftFB[0] = (void *)(0x18300000 + 0x46500); // Directly at the beginning of top FB
|
||||
bottom->format = a.val;
|
||||
bottom->unused3 = 0x00010501;
|
||||
bottom->fbselect = 0;
|
||||
bottom->stride = 0x2D0;
|
||||
bottom->padding[0] = 0;
|
||||
|
||||
// Rainbow register
|
||||
for (uint32_t i = 0; i < 256; i++) top->rainbow = 0x10101 * i;
|
||||
#endif
|
||||
}
|
||||
PICAfb::~PICAfb() {}
|
||||
auto PICAfb::plotPixel(int x, int y, int col) -> void {
|
||||
unsigned char *lfb = (unsigned char *)0x18300000;
|
||||
// XXX I know it's rotated. But I need more vertical space than horizonal space.
|
||||
int off = y * 240 + x;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
lfb[off++] = col;
|
||||
col >>= 8;
|
||||
}
|
||||
}
|
10
kernel/hw/3ds11/picafb/picafb.hpp
Normal file
10
kernel/hw/3ds11/picafb/picafb.hpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
#include "../../framebuffer/framebuffer.hpp"
|
||||
class PICAfb : public Framebuffer {
|
||||
protected:
|
||||
virtual auto plotPixel(int x, int y, int col) -> void;
|
||||
|
||||
public:
|
||||
PICAfb();
|
||||
virtual ~PICAfb();
|
||||
};
|
Loading…
Reference in a new issue