mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
Casio fx-CG series port (#324)
* Initial test - working on Linux
* Try to make it work with liba
* Stop using liba and the filesystem
* IT WORKS
* Key input, full res, fix some of the crashes
* Fix the hang when doing calculations
* Add some more key mappings
* Fix the square root issue
* Icons
* Better key mappings, brightness control, better gamma correction, more effficient framebuffer
* Cleanup stage 1
* Cleanup stage 2
* Make the build system build a g3a
* Make it not exit when you press the menu button
* Add Casio port to README
* Use omega-master instead of omega-dev
* Fix mistake with cherry-picking in the README
* Fix internal storage crash
* Fix compile error on Numworks calculators
* Upsilon branding
* Sharper icon
* Make the CI work
* Add power off and improve menu
* Map Alpha + up/down to the brightness shortcut
* Add missing file
* Fix web CI build
* Revert "Fix web CI build"
This reverts commit f19657d9fc.
* Change "prizm" to "fxcg"
* Add FASTLOAD option for Add-in Push
* Add some charatcers to the catalog on Casio and improve key mappings
* Build with -Os -flto
* Disable LTO for now as it's causing crashes
* Put back the fonts I accidently changed
I'd like to add an option for this though as I prefer the ones from Epsilon
This commit is contained in:
@@ -4,7 +4,9 @@
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
@@ -41,11 +43,19 @@ public:
|
||||
if (((uint64_t)mantissa >> (size()-k_mantissaNbBits-2)) & 1) {
|
||||
u.ui += 1;
|
||||
}
|
||||
return u.f;
|
||||
if (sizeof(T) == sizeof(float)) {
|
||||
return u.f32.f;
|
||||
} else {
|
||||
return u.f64.f;
|
||||
}
|
||||
}
|
||||
static int exponent(T f) {
|
||||
uint_float u;
|
||||
u.f = f;
|
||||
if (sizeof(T) == sizeof(float)) {
|
||||
u.f32.f = f;
|
||||
} else {
|
||||
u.f64.f = f;
|
||||
}
|
||||
constexpr uint16_t oneOnExponentsBits = maxExponent();
|
||||
int exp = (u.ui >> k_mantissaNbBits) & oneOnExponentsBits;
|
||||
exp -= exponentOffset();
|
||||
@@ -75,10 +85,28 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef _BIG_ENDIAN
|
||||
union uint_float {
|
||||
uint64_t ui;
|
||||
T f;
|
||||
struct {
|
||||
uint32_t padding;
|
||||
float f;
|
||||
} f32;
|
||||
struct {
|
||||
double f;
|
||||
} f64;
|
||||
};
|
||||
#else
|
||||
union uint_float {
|
||||
uint64_t ui;
|
||||
struct {
|
||||
float f;
|
||||
} f32;
|
||||
struct {
|
||||
double f;
|
||||
} f64;
|
||||
};
|
||||
#endif
|
||||
|
||||
constexpr static size_t k_signNbBits = 1;
|
||||
constexpr static size_t k_exponentNbBits = sizeof(T) == sizeof(float) ? 8 : 11;
|
||||
|
||||
@@ -5,6 +5,14 @@
|
||||
#include <assert.h>
|
||||
#include <poincare/horizontal_layout.h>
|
||||
|
||||
#ifdef _FXCG
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class ExpressionLayout;
|
||||
@@ -13,12 +21,17 @@ class LayoutNode;
|
||||
class Integer;
|
||||
struct IntegerDivision;
|
||||
|
||||
#ifdef _3DS
|
||||
#if (defined _3DS) || (defined _FXCG)
|
||||
typedef unsigned short half_native_uint_t;
|
||||
static_assert(sizeof(half_native_uint_t) == sizeof(uint16_t));
|
||||
typedef int native_int_t;
|
||||
static_assert(sizeof(native_int_t) == sizeof(int32_t));
|
||||
typedef long long int double_native_int_t;
|
||||
static_assert(sizeof(double_native_int_t) == sizeof(int64_t));
|
||||
typedef unsigned int native_uint_t;
|
||||
static_assert(sizeof(native_uint_t) == sizeof(uint32_t));
|
||||
typedef unsigned long long int double_native_uint_t;
|
||||
static_assert(sizeof(double_native_uint_t) == sizeof(uint64_t));
|
||||
#else
|
||||
typedef uint16_t half_native_uint_t;
|
||||
typedef int32_t native_int_t;
|
||||
@@ -199,7 +212,12 @@ private:
|
||||
if (i >= numberOfHalfDigits()) {
|
||||
return 0;
|
||||
}
|
||||
return (usesImmediateDigit() ? ((half_native_uint_t *)&m_digit)[i] : ((half_native_uint_t *)digits())[i]);
|
||||
native_uint_t d = usesImmediateDigit() ? m_digit : digits()[i/2];
|
||||
if (i % 2 == 0) {
|
||||
return d & 0xFFFF;
|
||||
} else {
|
||||
return d >> 16;
|
||||
}
|
||||
}
|
||||
|
||||
native_uint_t digit(uint8_t i) const {
|
||||
|
||||
@@ -138,7 +138,7 @@ private:
|
||||
private:
|
||||
uint16_t m_currentIndex;
|
||||
uint16_t m_availableIdentifiers[MaxNumberOfNodes];
|
||||
static_assert(MaxNumberOfNodes < INT16_MAX && sizeof(m_availableIdentifiers[0] == sizeof(uint16_t)), "Tree node identifiers do not have the right data size.");
|
||||
static_assert(MaxNumberOfNodes < INT16_MAX && sizeof(m_availableIdentifiers[0]) == sizeof(uint16_t), "Tree node identifiers do not have the right data size.");
|
||||
};
|
||||
|
||||
void freePoolFromNode(TreeNode * firstNodeToDiscard);
|
||||
|
||||
@@ -127,7 +127,10 @@ Integer::Integer(native_int_t i) : TreeHandle(TreeNode::NoNodeIdentifier) {
|
||||
|
||||
Integer::Integer(double_native_int_t i) {
|
||||
double_native_uint_t j = i < 0 ? -i : i;
|
||||
native_uint_t * d = (native_uint_t *)&j;
|
||||
native_uint_t d[2] = {
|
||||
static_cast<native_uint_t>(j & 0xFFFFFFFF),
|
||||
static_cast<native_uint_t>(j >> 32)
|
||||
};
|
||||
native_uint_t leastSignificantDigit = *d;
|
||||
native_uint_t mostSignificantDigit = *(d+1);
|
||||
uint8_t numberOfDigits = (mostSignificantDigit == 0) ? 1 : 2;
|
||||
@@ -165,7 +168,8 @@ Integer::Integer(const char * digits, size_t length, bool negative, Base b) :
|
||||
Integer base((int)b);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
*this = Multiplication(*this, base);
|
||||
*this = Addition(*this, Integer(integerFromCharDigit(*digits)));
|
||||
Integer toAdd = Integer(integerFromCharDigit(*digits));
|
||||
*this = Addition(*this, toAdd);
|
||||
digits++;
|
||||
}
|
||||
}
|
||||
@@ -495,7 +499,10 @@ Integer Integer::multiplication(const Integer & a, const Integer & b, bool oneDi
|
||||
* otherwise the product might end up being computed on single_native size
|
||||
* and then zero-padded. */
|
||||
double_native_uint_t p = aDigit*bDigit + carry + (double_native_uint_t)(s_workingBuffer[i+j]); // TODO: Prove it cannot overflow double_native type
|
||||
native_uint_t * l = (native_uint_t *)&p;
|
||||
native_uint_t l[2] = {
|
||||
static_cast<native_uint_t>(p & 0xFFFFFFFF),
|
||||
static_cast<native_uint_t>(p >> 32)
|
||||
};
|
||||
if (i+j < (uint8_t) k_maxNumberOfDigits+oneDigitOverflow) {
|
||||
s_workingBuffer[i+j] = l[0];
|
||||
} else {
|
||||
@@ -605,18 +612,31 @@ Integer Integer::divideByPowerOf2(uint8_t pow) const {
|
||||
// return this*(2^16)^pow
|
||||
Integer Integer::multiplyByPowerOfBase(uint8_t pow) const {
|
||||
int nbOfHalfDigits = numberOfHalfDigits();
|
||||
half_native_uint_t * digits = reinterpret_cast<half_native_uint_t *>(s_workingBuffer);
|
||||
native_uint_t * digits = s_workingBuffer;
|
||||
/* The number of half digits of the built integer is nbOfHalfDigits+pow.
|
||||
* Still, we set an extra half digit to 0 to easily convert half digits to
|
||||
* digits. */
|
||||
memset(digits, 0, sizeof(half_native_uint_t)*(nbOfHalfDigits+pow+1));
|
||||
for (uint8_t i = 0; i < nbOfHalfDigits; i++) {
|
||||
digits[i+pow] = halfDigit(i);
|
||||
memset(digits, 0, (sizeof(native_uint_t)/2)*(nbOfHalfDigits+pow+1));
|
||||
for (uint8_t i = 0; i < nbOfHalfDigits; i += 2) {
|
||||
native_uint_t toSet = halfDigit(i);
|
||||
if (i+1 < nbOfHalfDigits) {
|
||||
toSet |= (native_uint_t)halfDigit(i+1) << 16;
|
||||
}
|
||||
int index = i+pow;
|
||||
// If it's on an even index, we can just set the value
|
||||
if (index % 2 == 0) {
|
||||
digits[index/2] = toSet;
|
||||
} else {
|
||||
// If it's on an odd index, we need to shift the value
|
||||
digits[index/2] |= toSet << 16;
|
||||
digits[index/2+1] |= toSet >> 16;
|
||||
}
|
||||
}
|
||||
nbOfHalfDigits += pow;
|
||||
return BuildInteger((native_uint_t *)digits, nbOfHalfDigits%2 == 1 ? nbOfHalfDigits/2+1 : nbOfHalfDigits/2, false, true);
|
||||
return BuildInteger(digits, nbOfHalfDigits%2 == 1 ? nbOfHalfDigits/2+1 : nbOfHalfDigits/2, false, true);
|
||||
}
|
||||
|
||||
|
||||
IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denominator) {
|
||||
if (denominator.isOverflow()) {
|
||||
return {.quotient = Overflow(false), .remainder = Integer::Overflow(false)};
|
||||
@@ -679,6 +699,14 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin
|
||||
qNumberOfDigits--;
|
||||
}
|
||||
int qNumberOfDigitsInBase32 = qNumberOfDigits%2 == 1 ? qNumberOfDigits/2+1 : qNumberOfDigits/2;
|
||||
// Swap each pair of digits in qDigits if on a big-endian architecture
|
||||
#ifdef _BIG_ENDIAN
|
||||
for (int i = 0; i < qNumberOfDigitsInBase32; i++) {
|
||||
half_native_uint_t tmp = qDigits[i*2];
|
||||
qDigits[i*2] = qDigits[i*2+1];
|
||||
qDigits[i*2+1] = tmp;
|
||||
}
|
||||
#endif
|
||||
IntegerDivision div = {.quotient = BuildInteger((native_uint_t *)qDigits, qNumberOfDigitsInBase32, false), .remainder = A};
|
||||
if (pow > 0 && !div.remainder.isZero()) {
|
||||
div.remainder = div.remainder.divideByPowerOf2(pow);
|
||||
|
||||
Reference in New Issue
Block a user