rockbox/firmware/target/hosted/ctru/luminance-ctru.c
Mauricio Garrido 3b7dafb117 3ds: 3ds port sources. Second set of two.
This commit adds new files written exclusively for the 3ds port.

Additional comments:

1. Plugins works, but will be enabled in future commits.
2. The port has only been tested on the New 3DS.
3. Not all features of rockbox have been tested so there may be bugs or non-functional features.
4. There is a known issue where a random crash can occur when exiting the app.

Change-Id: I122d0bea9aa604e04fca45ba8287cf79e6110769
2025-10-23 20:09:12 -04:00

133 lines
3.9 KiB
C

/*
* This file is part of Luma3DS
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
/* This file is taken from Luma3DS project */
#include <3ds.h>
#include <math.h>
#include "luminance-ctru.h"
// For accessing physmem uncached (and directly)
#define PA_PTR(addr) (void *)((u32)(addr) | 1 << 31)
#ifndef PA_FROM_VA_PTR
#define PA_FROM_VA_PTR(addr) PA_PTR(svcConvertVAToPA((const void *)(addr), false))
#endif
#define REG32(addr) (*(vu32 *)(PA_PTR(addr)))
extern bool is_n3ds;
typedef struct BlPwmData
{
float coeffs[3][3];
u8 numLevels;
u8 unk;
u16 luminanceLevels[7];
u16 brightnessMax;
u16 brightnessMin;
} BlPwmData;
// Calibration, with (dubious) default values as fallback
static BlPwmData s_blPwmData = {
.coeffs = {
{ 0.00111639f, 1.41412f, 0.07178809f },
{ 0.000418169f, 0.66567f, 0.06098654f },
{ 0.00208543f, 1.55639f, 0.0385939f }
},
.numLevels = 5,
.unk = 0,
.luminanceLevels = { 20, 43, 73, 95, 117, 172, 172 },
.brightnessMax = 512,
.brightnessMin = 13,
};
static inline float getPwmRatio(u32 brightnessMax, u32 pwmCnt)
{
u32 val = (pwmCnt & 0x10000) ? pwmCnt & 0x3FF : 511; // check pwm enabled flag
return (float)brightnessMax / (val + 1);
}
// nn's asm has rounding errors (originally at 10^-3)
static inline u32 luminanceToBrightness(u32 luminance, const float coeffs[3], u32 minLuminance, float pwmRatio)
{
float x = (float)luminance;
float y = coeffs[0]*x*x + coeffs[1]*x + coeffs[2];
y = (y <= minLuminance ? (float)minLuminance : y) / pwmRatio;
return (u32)(y + 0.5f);
}
static inline u32 brightnessToLuminance(u32 brightness, const float coeffs[3], float pwmRatio)
{
// Find polynomial root of ax^2 + bx + c = y
float y = (float)brightness * pwmRatio;
float a = coeffs[0];
float b = coeffs[1];
float c = coeffs[2] - y;
float x0 = (-b + sqrtf(b*b - 4.0f*a*c)) / (a + a);
return (u32)(x0 + 0.5f);
}
static void readCalibration(void)
{
static bool calibRead = false;
if (!calibRead) {
cfguInit();
calibRead = R_SUCCEEDED(CFG_GetConfigInfoBlk8(sizeof(BlPwmData), 0x50002, &s_blPwmData));
cfguExit();
}
}
u32 getMinLuminancePreset(void)
{
readCalibration();
return s_blPwmData.luminanceLevels[0];
}
u32 getMaxLuminancePreset(void)
{
readCalibration();
return s_blPwmData.luminanceLevels[s_blPwmData.numLevels - 1];
}
u32 getCurrentLuminance(bool top)
{
u32 regbase = top ? 0x10202200 : 0x10202A00;
readCalibration();
const float *coeffs = s_blPwmData.coeffs[top ? (is_n3ds ? 2 : 1) : 0];
u32 brightness = REG32(regbase + 0x40);
float ratio = getPwmRatio(s_blPwmData.brightnessMax, REG32(regbase + 0x44));
return brightnessToLuminance(brightness, coeffs, ratio);
}