From aed18445db8c87549e7248a5533e690575c4d651 Mon Sep 17 00:00:00 2001 From: David Meenan <0b101@users.noreply.github.com> Date: Sun, 31 Mar 2019 09:03:01 -0500 Subject: [PATCH 001/130] Display MicroPython version in settings --- apps/settings/base.de.i18n | 1 + apps/settings/base.en.i18n | 1 + apps/settings/base.es.i18n | 1 + apps/settings/base.fr.i18n | 1 + apps/settings/base.pt.i18n | 1 + apps/settings/main_controller.cpp | 4 ++-- apps/settings/sub_menu/about_controller.cpp | 4 +++- apps/settings/sub_menu/about_controller.h | 2 +- 8 files changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index b0a434359..790750205 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -20,6 +20,7 @@ Cartesian = "Algebraische " Polar = "Polar " Brightness = "Helligkeit" SoftwareVersion = "Softwareversion" +MicroPythonVersion = "MicroPythonversion" SerialNumber = "Seriennummer" UpdatePopUp = "Erinnerung: Update" BetaPopUp = "Beta pop-up" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index 3b706c0e7..efa53836d 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -20,6 +20,7 @@ Cartesian = "Cartesian " Polar = "Polar " Brightness = "Brightness" SoftwareVersion = "Software version" +MicroPythonVersion = "MicroPython version" SerialNumber = "Serial number" UpdatePopUp = "Update pop-up" BetaPopUp = "Beta pop-up" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index 68d1ca4b5..80ed70628 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -20,6 +20,7 @@ Cartesian = "Binómica " Polar = "Polar " Brightness = "Brillo" SoftwareVersion = "Version de software" +MicroPythonVersion = "Version de MicroPython" SerialNumber = "Numero serie" UpdatePopUp = "Pop-up de actualizacion" BetaPopUp = "Beta pop-up" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index c2d22b74a..563df45ed 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -20,6 +20,7 @@ Cartesian = "Algébrique " Polar = "Exponentielle " Brightness = "Luminosite" SoftwareVersion = "Version du logiciel" +MicroPythonVersion = "Version du MicroPython" SerialNumber = "Numero serie" UpdatePopUp = "Rappel mise a jour" BetaPopUp = "Rappel version bêta" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index 86f277900..17aa9518a 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -20,6 +20,7 @@ Cartesian = "Cartesiana " Polar = "Polar " Brightness = "Brilho" SoftwareVersion = "Versao do software" +MicroPythonVersion = "Versao do MicroPython" SerialNumber = "Numero serie" UpdatePopUp = "Alertas de atualizacao" BetaPopUp = "Beta pop-up" diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index df748f77e..f639b1c2c 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -12,7 +12,7 @@ const SettingsMessageTree editionModeChildren[2] = {SettingsMessageTree(I18n::Me const SettingsMessageTree floatDisplayModeChildren[3] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::SignificantFigures)}; const SettingsMessageTree complexFormatChildren[3] = {SettingsMessageTree(I18n::Message::Real), SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)}; const SettingsMessageTree examChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; -const SettingsMessageTree aboutChildren[3] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; +const SettingsMessageTree aboutChildren[4] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; #ifdef EPSILON_BOOT_PROMPT const SettingsMessageTree menu[9] = @@ -31,7 +31,7 @@ const SettingsMessageTree menu[8] = #elif EPSILON_BOOT_PROMPT == EPSILON_UPDATE_PROMPT SettingsMessageTree(I18n::Message::UpdatePopUp), #endif - SettingsMessageTree(I18n::Message::About, aboutChildren, 3)}; + SettingsMessageTree(I18n::Message::About, aboutChildren, 4)}; #ifdef EPSILON_BOOT_PROMPT const SettingsMessageTree model = SettingsMessageTree(I18n::Message::SettingsApp, menu, 9); #else diff --git a/apps/settings/sub_menu/about_controller.cpp b/apps/settings/sub_menu/about_controller.cpp index a8096d0de..4afacf5bc 100644 --- a/apps/settings/sub_menu/about_controller.cpp +++ b/apps/settings/sub_menu/about_controller.cpp @@ -1,5 +1,6 @@ #include "about_controller.h" #include "../../apps_container.h" +#include "../../../python/port/genhdr/mpversion.h" #include #include @@ -55,10 +56,11 @@ void AboutController::willDisplayCellForIndex(HighlightCell * cell, int index) { MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)cell; static const char * messages[] = { Ion::softwareVersion(), + MICROPY_VERSION_STRING, Ion::serialNumber(), Ion::fccId() }; - assert(index >= 0 && index < 3); + assert(index >= 0 && index < 4); myCell->setAccessoryText(messages[index]); } diff --git a/apps/settings/sub_menu/about_controller.h b/apps/settings/sub_menu/about_controller.h index 57d66087b..5ecbeb23b 100644 --- a/apps/settings/sub_menu/about_controller.h +++ b/apps/settings/sub_menu/about_controller.h @@ -14,7 +14,7 @@ public: int reusableCellCount(int type) override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; private: - constexpr static int k_totalNumberOfCell = 3; + constexpr static int k_totalNumberOfCell = 4; MessageTableCellWithBuffer m_cells[k_totalNumberOfCell]; HardwareTest::PopUpController m_hardwareTestPopUpController; }; From de179f0af6414a75c1240457a3a5b14cfca1e48e Mon Sep 17 00:00:00 2001 From: Adrien Bertrand Date: Sun, 31 Mar 2019 09:08:57 -0500 Subject: [PATCH 002/130] Update apps/settings/base.fr.i18n Co-Authored-By: 0b101 <0b101@users.noreply.github.com> --- apps/settings/base.fr.i18n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 563df45ed..e4a6ed00a 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -20,7 +20,7 @@ Cartesian = "Algébrique " Polar = "Exponentielle " Brightness = "Luminosite" SoftwareVersion = "Version du logiciel" -MicroPythonVersion = "Version du MicroPython" +MicroPythonVersion = "Version de MicroPython" SerialNumber = "Numero serie" UpdatePopUp = "Rappel mise a jour" BetaPopUp = "Rappel version bêta" From a515160470ab719cfa922137c9cbff3cf9cda28f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 2 Dec 2019 16:30:29 +0100 Subject: [PATCH 003/130] [poincare] NAryExpressionNode: fix sortChildrenInPlace to put expressions involving matrices as last children --- poincare/src/n_ary_expression.cpp | 7 ++++++- poincare/test/expression_order.cpp | 10 ++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/poincare/src/n_ary_expression.cpp b/poincare/src/n_ary_expression.cpp index 538c1f21b..8cd1283b1 100644 --- a/poincare/src/n_ary_expression.cpp +++ b/poincare/src/n_ary_expression.cpp @@ -32,7 +32,12 @@ void NAryExpressionNode::sortChildrenInPlace(ExpressionOrder order, Context * co * multiplication) so we never swap 2 matrices. */ ExpressionNode * cj = childAtIndex(j); ExpressionNode * cj1 = childAtIndex(j+1); - if (order(cj, cj1, canBeInterrupted) > 0 && (canSwapMatrices || !(Expression(cj).deepIsMatrix(context) && Expression(cj1).deepIsMatrix(context)))) { + bool cjIsMatrix = Expression(cj).deepIsMatrix(context); + bool cj1IsMatrix = Expression(cj1).deepIsMatrix(context); + bool cj1GreaterThanCj = order(cj, cj1, canBeInterrupted) > 0; + if ((cjIsMatrix && !cj1IsMatrix) || // we always put matrices at the end of expressions + (cjIsMatrix && cj1IsMatrix && canSwapMatrices && cj1GreaterThanCj) || + (!cjIsMatrix && !cj1IsMatrix && cj1GreaterThanCj)) { reference.swapChildrenInPlace(j, j+1); isSorted = false; } diff --git a/poincare/test/expression_order.cpp b/poincare/test/expression_order.cpp index 57739d145..59ec0dc6c 100644 --- a/poincare/test/expression_order.cpp +++ b/poincare/test/expression_order.cpp @@ -216,4 +216,14 @@ QUIZ_CASE(poincare_expression_order_addition_multiplication) { assert_multiplication_or_addition_is_ordered_as(e1, e2); } + { + // ∑Matrix + 𝐢 -> 𝐢 + ∑Matrix + Expression childMatrix = Matrix::Builder(); + static_cast(childMatrix).addChildAtIndexInPlace(Rational::Builder(0), 0, 0); + Expression child1 = Sum::Builder(childMatrix, Symbol::Builder('n'), Rational::Builder(0), Rational::Builder(0)); + Expression child2 = Symbol::Builder(UCodePointMathematicalBoldSmallI); + Expression e1 = Addition::Builder(child1.clone(), child2.clone()); + Expression e2 = Addition::Builder(child2, child1); + assert_multiplication_or_addition_is_ordered_as(e1, e2); + } } From b36f9416b4d95d6f3e5683d735b3e0343c2ea307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 3 Dec 2019 11:51:47 +0100 Subject: [PATCH 004/130] [hardware_test] Keyboard test: check only a subset of keys --- apps/hardware_test/Makefile | 1 + apps/hardware_test/keyboard_model.cpp | 16 ++++++++ apps/hardware_test/keyboard_model.h | 37 +++++++++++++++++++ .../keyboard_test_controller.cpp | 6 +-- apps/hardware_test/keyboard_view.cpp | 26 ++++++------- apps/hardware_test/keyboard_view.h | 8 ++-- 6 files changed, 74 insertions(+), 20 deletions(-) create mode 100644 apps/hardware_test/keyboard_model.cpp create mode 100644 apps/hardware_test/keyboard_model.h diff --git a/apps/hardware_test/Makefile b/apps/hardware_test/Makefile index 6921f94ed..339b8887c 100644 --- a/apps/hardware_test/Makefile +++ b/apps/hardware_test/Makefile @@ -6,6 +6,7 @@ app_hardware_test_src = $(addprefix apps/hardware_test/,\ colors_lcd_test_controller.cpp \ dead_pixels_test_controller.cpp \ keyboard_test_controller.cpp \ + keyboard_model.cpp \ keyboard_view.cpp \ lcd_data_test_controller.cpp \ lcd_timing_test_controller.cpp \ diff --git a/apps/hardware_test/keyboard_model.cpp b/apps/hardware_test/keyboard_model.cpp new file mode 100644 index 000000000..0bc9b5084 --- /dev/null +++ b/apps/hardware_test/keyboard_model.cpp @@ -0,0 +1,16 @@ +#include "keyboard_model.h" + +namespace HardwareTest { + +constexpr Ion::Keyboard::Key KeyboardModel::TestedKeys[KeyboardModel::NumberOfTestedKeys]; + +bool KeyboardModel::belongsToTestedKeysSubset(Ion::Keyboard::Key key) const { + for (int i = 0; i < NumberOfTestedKeys; i++) { + if (TestedKeys[i] == key) { + return true; + } + } + return false; +} + +} diff --git a/apps/hardware_test/keyboard_model.h b/apps/hardware_test/keyboard_model.h new file mode 100644 index 000000000..8c0c8e47b --- /dev/null +++ b/apps/hardware_test/keyboard_model.h @@ -0,0 +1,37 @@ +#ifndef HARDWARE_TEST_KEYBOARD_MODEL_H +#define HARDWARE_TEST_KEYBOARD_MODEL_H + +#include + +namespace HardwareTest { + +class KeyboardModel { +public: + KeyboardModel() : m_testedKeyIndex(0) {} + Ion::Keyboard::Key testedKey() const { return TestedKeys[m_testedKeyIndex]; } + int testedKeyIndex() const { return m_testedKeyIndex; } + void setTestedKeyIndex(int i) { + assert(i >= 0 && i < NumberOfTestedKeys); + m_testedKeyIndex = i; + } + bool belongsToTestedKeysSubset(Ion::Keyboard::Key key) const; + + static constexpr int NumberOfTestedKeys = 20; + static constexpr Ion::Keyboard::Key TestedKeys[KeyboardModel::NumberOfTestedKeys] = { + Ion::Keyboard::Key::Left, Ion::Keyboard::Key::Up, Ion::Keyboard::Key::Down, Ion::Keyboard::Key::Right, Ion::Keyboard::Key::OK, Ion::Keyboard::Key::Back, + Ion::Keyboard::Key::Home, Ion::Keyboard::Key::OnOff, + Ion::Keyboard::Key::Shift, Ion::Keyboard::Key::Alpha, Ion::Keyboard::Key::XNT, Ion::Keyboard::Key::Var, Ion::Keyboard::Key::Toolbox, Ion::Keyboard::Key::Backspace, + Ion::Keyboard::Key::Power, + Ion::Keyboard::Key::Square, + Ion::Keyboard::Key::RightParenthesis, + Ion::Keyboard::Key::Division, + Ion::Keyboard::Key::Minus, + Ion::Keyboard::Key::EXE + }; +private: + int m_testedKeyIndex; +}; +} + +#endif + diff --git a/apps/hardware_test/keyboard_test_controller.cpp b/apps/hardware_test/keyboard_test_controller.cpp index 730b2340c..c787ec289 100644 --- a/apps/hardware_test/keyboard_test_controller.cpp +++ b/apps/hardware_test/keyboard_test_controller.cpp @@ -17,10 +17,10 @@ View * KeyboardTestController::view() { bool KeyboardTestController::handleEvent(Ion::Events::Event event) { Ion::Keyboard::State state = Ion::Keyboard::scan(); - Ion::Keyboard::State onlyKeyDown = Ion::Keyboard::State(Ion::Keyboard::ValidKeys[m_keyboardView.testedKeyIndex()]); + Ion::Keyboard::State onlyKeyDown = Ion::Keyboard::State(KeyboardModel::TestedKeys[m_keyboardView.testedKeyIndex()]); if (state == onlyKeyDown) { - m_keyboardView.setTestedKeyIndex(m_keyboardView.testedKeyIndex()+1); - if (m_keyboardView.testedKeyIndex() == Ion::Keyboard::NumberOfValidKeys) { + m_keyboardView.setTestedKeyIndex(m_keyboardView.testedKeyIndex() + 1); + if (m_keyboardView.testedKeyIndex() == KeyboardModel::NumberOfTestedKeys) { // Returning false will go to the next step in the WizardViewController return false; } diff --git a/apps/hardware_test/keyboard_view.cpp b/apps/hardware_test/keyboard_view.cpp index 41c2cb694..1b15f28df 100644 --- a/apps/hardware_test/keyboard_view.cpp +++ b/apps/hardware_test/keyboard_view.cpp @@ -3,17 +3,8 @@ namespace HardwareTest { -KeyboardView::KeyboardView() : - m_testedKeyIndex(0) -{ -} - -int KeyboardView::testedKeyIndex() const { - return m_testedKeyIndex; -} - void KeyboardView::setTestedKeyIndex(int i) { - m_testedKeyIndex = i; + m_keyboardModel.setTestedKeyIndex(i); markRectAsDirty(bounds()); } @@ -26,11 +17,8 @@ void KeyboardView::drawRect(KDContext * ctx, KDRect rect) const { } void KeyboardView::drawKey(int keyIndex, KDContext * ctx, KDRect rect) const { - KDColor color = keyIndex < m_testedKeyIndex ? KDColorGreen: KDColorBlack; - if (keyIndex == m_testedKeyIndex) { - color = KDColorBlue; - } Ion::Keyboard::Key key = Ion::Keyboard::ValidKeys[keyIndex]; + KDColor color = keyColor(key); /* the key is on the cross */ if ((uint8_t)key < 4) { KDCoordinate x = (uint8_t)key == 1 || (uint8_t)key == 2 ? k_margin + k_smallSquareSize : k_margin; @@ -69,4 +57,14 @@ void KeyboardView::drawKey(int keyIndex, KDContext * ctx, KDRect rect) const { } } +KDColor KeyboardView::keyColor(Ion::Keyboard::Key key) const { + if (!m_keyboardModel.belongsToTestedKeysSubset(key)) { + return Palette::GreyBright; + } + if (m_keyboardModel.testedKey() == key) { + return KDColorBlue; + } + return (uint8_t)key < (uint8_t)m_keyboardModel.testedKey() ? KDColorGreen : KDColorBlack; +} + } diff --git a/apps/hardware_test/keyboard_view.h b/apps/hardware_test/keyboard_view.h index 47d36abff..1d02b0b5f 100644 --- a/apps/hardware_test/keyboard_view.h +++ b/apps/hardware_test/keyboard_view.h @@ -2,17 +2,19 @@ #define HARDWARE_TEST_KEYBOARD_VIEW_H #include +#include "keyboard_model.h" namespace HardwareTest { class KeyboardView : public View { public: - KeyboardView(); - int testedKeyIndex() const; + KeyboardView() : m_keyboardModel() {} + int testedKeyIndex() const { return m_keyboardModel.testedKeyIndex(); } void setTestedKeyIndex(int i); void drawRect(KDContext * ctx, KDRect rect) const override; private: void drawKey(int key, KDContext * ctx, KDRect rect) const; + KDColor keyColor(Ion::Keyboard::Key key) const; constexpr static int k_margin = 4; constexpr static int k_smallSquareSize = 8; constexpr static int k_bigSquareSize = 14; @@ -20,7 +22,7 @@ private: constexpr static int k_smallRectWidth = 16; constexpr static int k_bigRectHeight = 14; constexpr static int k_bigRectWidth = 20; - int m_testedKeyIndex; + KeyboardModel m_keyboardModel; }; } From 59b6dbd74e4e170a95515f5d33f0fc5502d9e154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 3 Dec 2019 15:56:22 +0100 Subject: [PATCH 005/130] [python] micropython_port_interruptible_msleep should always call micropython_port_interrupt_if_needed even if the delay is small --- python/port/helpers.cpp | 19 ++++++++++--------- python/port/helpers.h | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/python/port/helpers.cpp b/python/port/helpers.cpp index bb30687ab..438f7ca47 100644 --- a/python/port/helpers.cpp +++ b/python/port/helpers.cpp @@ -22,21 +22,22 @@ bool micropython_port_vm_hook_loop() { return micropython_port_interrupt_if_needed(); } -bool micropython_port_interruptible_msleep(uint32_t delay) { +bool micropython_port_interruptible_msleep(int32_t delay) { + assert(delay >= 0); /* We don't use millis because the systick drifts when changing the HCLK * frequency. */ - constexpr uint32_t interruptionCheckDelay = 100; - const uint32_t numberOfInterruptionChecks = delay / interruptionCheckDelay; - uint32_t remainingInterruptionChecks = numberOfInterruptionChecks; - while (remainingInterruptionChecks > 0) { + constexpr int32_t interruptionCheckDelay = 100; + const int32_t numberOfInterruptionChecks = delay / interruptionCheckDelay; + int32_t remainingDelay = delay - numberOfInterruptionChecks * interruptionCheckDelay; + int32_t currentRemainingInterruptionChecks = numberOfInterruptionChecks; + do { // We assume the time taken by the interruption check is insignificant if (micropython_port_interrupt_if_needed()) { return true; } - remainingInterruptionChecks--; - Ion::Timing::msleep(interruptionCheckDelay); - } - Ion::Timing::msleep(delay - numberOfInterruptionChecks * interruptionCheckDelay); + Ion::Timing::msleep(currentRemainingInterruptionChecks == numberOfInterruptionChecks ? remainingDelay : interruptionCheckDelay); + currentRemainingInterruptionChecks--; + } while (currentRemainingInterruptionChecks >= 0); return false; } diff --git a/python/port/helpers.h b/python/port/helpers.h index 761f96a7d..b9ab24cb7 100644 --- a/python/port/helpers.h +++ b/python/port/helpers.h @@ -10,7 +10,7 @@ extern "C" { // These methods return true if they have been interrupted bool micropython_port_vm_hook_loop(); -bool micropython_port_interruptible_msleep(uint32_t delay); +bool micropython_port_interruptible_msleep(int32_t delay); bool micropython_port_interrupt_if_needed(); int micropython_port_random(); From 0db66f1784040dca190cf923cd9cff192a7958a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 3 Dec 2019 16:39:20 +0100 Subject: [PATCH 006/130] [python] Turtle: add TODO --- python/port/mod/turtle/turtle.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/port/mod/turtle/turtle.cpp b/python/port/mod/turtle/turtle.cpp index 7a66d4240..58b51c4c2 100644 --- a/python/port/mod/turtle/turtle.cpp +++ b/python/port/mod/turtle/turtle.cpp @@ -335,6 +335,8 @@ bool Turtle::draw(bool force) { m_drawn = true; } + /* TODO: Maybe this threshold should be in time (mileage/speed) instead of + * mileage to interrupt with the same frequency whatever the speed is. */ if (m_mileage > k_mileageLimit) { if (micropython_port_interruptible_msleep(1 + (m_speed == 0 ? 0 : 3 * (k_maxSpeed - m_speed)))) { return true; From 49aa58446bad367a627ca77bc59457ba16b82571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 3 Dec 2019 17:45:48 +0100 Subject: [PATCH 007/130] [python] modkandinsky: fill_rect and draw_string calls might take some time. As "micropython_port_vm_hook_loop" is not called while we are executing module code, we add an extra check for user interruption in module functions. --- python/port/mod/kandinsky/modkandinsky.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python/port/mod/kandinsky/modkandinsky.cpp b/python/port/mod/kandinsky/modkandinsky.cpp index eacc184ae..408292db5 100644 --- a/python/port/mod/kandinsky/modkandinsky.cpp +++ b/python/port/mod/kandinsky/modkandinsky.cpp @@ -70,6 +70,10 @@ mp_obj_t modkandinsky_draw_string(size_t n_args, const mp_obj_t * args) { KDColor backgroundColor = (n_args >= 5) ? ColorForTuple(args[4]) : KDColorWhite; MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox(); KDIonContext::sharedContext()->drawString(text, point, KDFont::LargeFont, textColor, backgroundColor); + /* drawString function might take some time to execute so we add an extra check + * for user interruption (to avoid freezing in an infinite loop calling + * 'drawString' for instance). */ + micropython_port_interrupt_if_needed(); return mp_const_none; } @@ -83,5 +87,9 @@ mp_obj_t modkandinsky_fill_rect(size_t n_args, const mp_obj_t * args) { KDColor color = ColorForTuple(args[4]); MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox(); KDIonContext::sharedContext()->fillRect(rect, color); + /* fillRect function might take some time to execute so we add an extra check + * for user interruption (to avoid freezing in an infinite loop calling + * 'fillRect' for instance). */ + micropython_port_interrupt_if_needed(); return mp_const_none; } From 986a024e1386d8d5445090dd5dfb31931298302c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Fri, 6 Dec 2019 08:35:46 +0100 Subject: [PATCH 008/130] [1.18.0] Increment Omega version --- build/config.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/config.mak b/build/config.mak index 21dcdb8e8..8de2af89d 100644 --- a/build/config.mak +++ b/build/config.mak @@ -4,7 +4,7 @@ PLATFORM ?= device DEBUG ?= 0 EPSILON_VERSION ?= 12.0.0 -EPSILON_CUSTOM_VERSION ?= 1.17.0-0 +EPSILON_CUSTOM_VERSION ?= 1.18.0-0 # USERNAME ?= N/A # Valid values are "none", "update", "beta" EPSILON_APPS ?= calculation rpn graph code statistics probability solver atom sequence regression settings From dbea83497b937afea79008067cb93bf571af009a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 6 Dec 2019 11:15:26 +0100 Subject: [PATCH 009/130] [apps/on_boarding] If POST are OK, the led is white Green is used to indicate end-of-charge, so we put the POST led in white so there is no confusion --- apps/on_boarding/power_on_self_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/on_boarding/power_on_self_test.cpp b/apps/on_boarding/power_on_self_test.cpp index f83e30347..dde93f04c 100644 --- a/apps/on_boarding/power_on_self_test.cpp +++ b/apps/on_boarding/power_on_self_test.cpp @@ -6,7 +6,7 @@ namespace OnBoarding { KDColor PowerOnSelfTest::Perform() { KDColor previousLEDColor = Ion::LED::getColor(); - KDColor resultColor = KDColorGreen; + KDColor resultColor = KDColorWhite; // Screen tests bool screenTestsOK = Shared::POSTAndHardwareTests::VBlankOK() && (Shared::POSTAndHardwareTests::TextLCDGlyphFailures() <= k_textErrorsLimit); From 4bc99cc530eccdb7218b376a46cfddb8f83b1b4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 6 Dec 2019 14:11:02 +0100 Subject: [PATCH 010/130] [apps/Makefile] Fix update prompt build make -j8 output/release/device/n0110/epsilon.onboarding.update.two_binaries made a compilation error --- apps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/Makefile b/apps/Makefile index 40605127f..ba2e1a396 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -85,7 +85,7 @@ $(BUILD_DIR)/apps/i18n.h: $(BUILD_DIR)/apps/i18n.cpp $(eval $(call depends_on_image,apps/title_bar_view.cpp,apps/exam_icon.png)) -all_app_src = $(app_src) $(epsilon_src) $(apps_launch_on_boarding_src) $(apps_launch_default_src) $(apps_prompt_none_src) $(apps_container_prompt_update) $(apps_prompt_beta_src) $(tests_src) +all_app_src = $(app_src) $(epsilon_src) $(apps_launch_on_boarding_src) $(apps_launch_default_src) $(apps_prompt_none_src) $(apps_prompt_update_src) $(apps_prompt_beta_src) $(tests_src) $(call object_for,$(all_app_src)): $(BUILD_DIR)/apps/i18n.h $(call object_for,$(all_app_src)): $(BUILD_DIR)/python/port/genhdr/qstrdefs.generated.h From 53b8a6845efb4a1f91dab909c0135ed075bca967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 6 Dec 2019 14:14:29 +0100 Subject: [PATCH 011/130] [github/workflows] Add beta build tests --- .github/workflows/ci-workflow.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 45cb09d42..d38794afc 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -19,6 +19,7 @@ jobs: - run: make -j2 MODEL=n0100 epsilon.dfu - run: make -j2 MODEL=n0100 epsilon.onboarding.dfu - run: make -j2 MODEL=n0100 epsilon.onboarding.update.dfu + - run: make -j2 MODEL=n0100 epsilon.onboarding.beta.dfu - run: make -j2 MODEL=n0100 flasher.light.dfu - run: make -j2 MODEL=n0100 flasher.verbose.dfu - uses: actions/upload-artifact@master @@ -34,6 +35,7 @@ jobs: - run: make -j2 epsilon.dfu - run: make -j2 epsilon.onboarding.dfu - run: make -j2 epsilon.onboarding.update.dfu + - run: make -j2 epsilon.onboarding.beta.dfu - run: make -j2 flasher.light.dfu - run: make -j2 flasher.verbose.dfu - run: make -j2 bench.ram.dfu From e9b5b13cfe5f59a9e5246abb9eda5c1af58dfc24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Fri, 6 Dec 2019 19:28:05 +0100 Subject: [PATCH 012/130] Public -> dev --- apps/settings/sub_menu/about_controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/settings/sub_menu/about_controller.cpp b/apps/settings/sub_menu/about_controller.cpp index 7f72069fe..8ad0bbb74 100644 --- a/apps/settings/sub_menu/about_controller.cpp +++ b/apps/settings/sub_menu/about_controller.cpp @@ -47,7 +47,7 @@ bool AboutController::handleEvent(Ion::Events::Event event) { if (childLabel == I18n::Message::CustomSoftwareVersion) { MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)m_selectableTableView.selectedCell(); if (strcmp(myCell->accessoryText(), Ion::customSoftwareVersion()) == 0) { - myCell->setAccessoryText("Public"); //Change for public/dev + myCell->setAccessoryText("Dev"); //Change for public/dev return true; } myCell->setAccessoryText(Ion::customSoftwareVersion()); From 26ce12f6d2bc783f06be483eb7566d84bad3c267 Mon Sep 17 00:00:00 2001 From: redgl0w Date: Fri, 6 Dec 2019 19:34:36 +0100 Subject: [PATCH 013/130] Applied and modified https://github.com/0b101/epsilon/commit/d50bd08444cc6e108363011b80a99bcb189639aa\#diff-4f54cda3940834a07cd7f83ea12ebd85 --- apps/apps_container.cpp | 6 ++++++ ion/include/ion/events.h | 3 +++ ion/include/ion/keyboard/layout_B2/layout_events.h | 4 ++-- ion/include/ion/keyboard/layout_B3/layout_events.h | 4 ++-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 776153935..64dae4972 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -218,6 +218,12 @@ bool AppsContainer::processEvent(Ion::Events::Event event) { suspend(true); return true; } + if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus) { + int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates; + int direction = (event == Ion::Events::BrightnessPlus) ? delta : -delta; + GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction); + return true; + } return false; } diff --git a/ion/include/ion/events.h b/ion/include/ion/events.h index 1ce72c76d..d8ea02f70 100644 --- a/ion/include/ion/events.h +++ b/ion/include/ion/events.h @@ -139,6 +139,9 @@ constexpr Event Equal = Event::ShiftKey(Keyboard::Key::Pi); constexpr Event Lower = Event::ShiftKey(Keyboard::Key::Sqrt); constexpr Event Greater = Event::ShiftKey(Keyboard::Key::Square); +constexpr Event BrightnessPlus = Event::ShiftKey(Keyboard::Key::LeftParenthesis); +constexpr Event BrightnessMinus = Event::ShiftKey(Keyboard::Key::RightParenthesis); + constexpr Event ShiftSeven = Event::ShiftKey(Keyboard::Key::Seven); constexpr Event ShiftEight = Event::ShiftKey(Keyboard::Key::Eight); constexpr Event ShiftNine = Event::ShiftKey(Keyboard::Key::Nine); diff --git a/ion/include/ion/keyboard/layout_B2/layout_events.h b/ion/include/ion/keyboard/layout_B2/layout_events.h index a0d877cd5..be88b3ba9 100644 --- a/ion/include/ion/keyboard/layout_B2/layout_events.h +++ b/ion/include/ion/keyboard/layout_B2/layout_events.h @@ -27,7 +27,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), TL(), TL(), TL(), U(), U(), U(), TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), U(), U(), U(), + TL(), TL(), TL(), TL(), TL(), U(), U(), U(), U(), U(), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), @@ -72,7 +72,7 @@ static constexpr const char * s_nameForEvent[255] = { "Arcsine", "Arccosine", "Arctangent", "Equal", "Lower", "Greater", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, "BrightnessPlus", "BrightnessMinus", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //Alpha, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, diff --git a/ion/include/ion/keyboard/layout_B3/layout_events.h b/ion/include/ion/keyboard/layout_B3/layout_events.h index 1783ff7a3..a1f9502fa 100644 --- a/ion/include/ion/keyboard/layout_B3/layout_events.h +++ b/ion/include/ion/keyboard/layout_B3/layout_events.h @@ -27,7 +27,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), TL(), TL(), TL(), U(), U(), U(), TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), U(), U(), U(), + TL(), TL(), TL(), TL(), TL(), U(), U(), U(), U(), U(), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), @@ -72,7 +72,7 @@ static constexpr const char * s_nameForEvent[255] = { "Arcsine", "Arccosine", "Arctangent", "Equal", "Lower", "Greater", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, "BrightnessPlus", "BrightnessMinus", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //Alpha, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, From 5cd3fa92c3f59317485effb5c5f740a8a12bae37 Mon Sep 17 00:00:00 2001 From: redgl0w Date: Fri, 6 Dec 2019 19:48:51 +0100 Subject: [PATCH 014/130] Corrected last commit --- ion/include/ion/events.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ion/include/ion/events.h b/ion/include/ion/events.h index d8ea02f70..9e4edc24b 100644 --- a/ion/include/ion/events.h +++ b/ion/include/ion/events.h @@ -139,8 +139,8 @@ constexpr Event Equal = Event::ShiftKey(Keyboard::Key::Pi); constexpr Event Lower = Event::ShiftKey(Keyboard::Key::Sqrt); constexpr Event Greater = Event::ShiftKey(Keyboard::Key::Square); -constexpr Event BrightnessPlus = Event::ShiftKey(Keyboard::Key::LeftParenthesis); -constexpr Event BrightnessMinus = Event::ShiftKey(Keyboard::Key::RightParenthesis); +constexpr Event BrightnessPlus = Event::ShiftKey(Keyboard::Key::Plus); +constexpr Event BrightnessMinus = Event::ShiftKey(Keyboard::Key::Minus); constexpr Event ShiftSeven = Event::ShiftKey(Keyboard::Key::Seven); constexpr Event ShiftEight = Event::ShiftKey(Keyboard::Key::Eight); From 2568a852e7b5ba90c55d515bed4537f30603d2b0 Mon Sep 17 00:00:00 2001 From: redgl0w Date: Fri, 6 Dec 2019 20:21:50 +0100 Subject: [PATCH 015/130] Changed settings reloading --- apps/settings/main_controller.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 59ac61ca8..5bf462beb 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -36,6 +36,10 @@ void MainController::didBecomeFirstResponder() { bool MainController::handleEvent(Ion::Events::Event event) { GlobalPreferences * globalPreferences = GlobalPreferences::sharedGlobalPreferences(); + if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus){ + m_selectableTableView.reloadData(); + return false; + } if (model()->children(selectedRow())->numberOfChildren() == 0) { if (model()->children(selectedRow())->label() == promptMessage()) { if (event == Ion::Events::OK || event == Ion::Events::EXE) { From 8d3e1c2154c065b50c465a0be3c5cb0de9218f64 Mon Sep 17 00:00:00 2001 From: redgl0w Date: Fri, 6 Dec 2019 20:30:55 +0100 Subject: [PATCH 016/130] Added and corrected https://github.com/Omega-Numworks/Omega/pull/80 --- ion/include/ion/events.h | 2 ++ ion/include/ion/keyboard/layout_B2/layout_events.h | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ion/include/ion/events.h b/ion/include/ion/events.h index 9e4edc24b..92905e9ca 100644 --- a/ion/include/ion/events.h +++ b/ion/include/ion/events.h @@ -142,6 +142,8 @@ constexpr Event Greater = Event::ShiftKey(Keyboard::Key::Square); constexpr Event BrightnessPlus = Event::ShiftKey(Keyboard::Key::Plus); constexpr Event BrightnessMinus = Event::ShiftKey(Keyboard::Key::Minus); +constexpr Event DoubleParenthesis = Event::ShiftKey(Keyboard::Key::LeftParenthesis); + constexpr Event ShiftSeven = Event::ShiftKey(Keyboard::Key::Seven); constexpr Event ShiftEight = Event::ShiftKey(Keyboard::Key::Eight); constexpr Event ShiftNine = Event::ShiftKey(Keyboard::Key::Nine); diff --git a/ion/include/ion/keyboard/layout_B2/layout_events.h b/ion/include/ion/keyboard/layout_B2/layout_events.h index be88b3ba9..3a1f75260 100644 --- a/ion/include/ion/keyboard/layout_B2/layout_events.h +++ b/ion/include/ion/keyboard/layout_B2/layout_events.h @@ -25,7 +25,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - TL(), TL(), TL(), U(), U(), U(), + TL(), TL(), TL(), T("(\x11)"), U(), U(), TL(), TL(), TL(), U(), U(), U(), TL(), TL(), TL(), TL(), TL(), U(), U(), U(), U(), U(), U(), U(), @@ -70,7 +70,7 @@ static constexpr const char * s_nameForEvent[255] = { nullptr, "AlphaLock", "Cut", "Copy", "Paste", "Clear", "LeftBracket", "RightBracket", "LeftBrace", "RightBrace", "Underscore", "Sto", "Arcsine", "Arccosine", "Arctangent", "Equal", "Lower", "Greater", - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, "DoubleParenthesis", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "BrightnessPlus", "BrightnessMinus", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, From 094dff8518c9acbdca0983df2c83b489f3026757 Mon Sep 17 00:00:00 2001 From: RedGl0w Date: Sat, 7 Dec 2019 12:49:58 +0100 Subject: [PATCH 017/130] https://github.com/Omega-Numworks/Omega/pull/81\#issuecomment-561861710 --- apps/apps_container.cpp | 2 +- apps/apps_container.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 64dae4972..b659db945 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -220,7 +220,7 @@ bool AppsContainer::processEvent(Ion::Events::Event event) { } if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus) { int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates; - int direction = (event == Ion::Events::BrightnessPlus) ? delta : -delta; + int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsForShiftPlusMinus*delta : -delta*NumberOfStepsForShiftPlusMinus; GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction); return true; } diff --git a/apps/apps_container.h b/apps/apps_container.h index 87c0adea6..60efccdd9 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -78,6 +78,7 @@ private: OnBoarding::App::Snapshot m_onBoardingSnapshot; HardwareTest::App::Snapshot m_hardwareTestSnapshot; USB::App::Snapshot m_usbConnectedSnapshot; + const int NumberOfStepsForShiftPlusMinus = 3; }; #endif From d3215a5e3047b3fdfb26e7ad71854cff19ee61e3 Mon Sep 17 00:00:00 2001 From: RedGl0w Date: Sat, 7 Dec 2019 12:53:21 +0100 Subject: [PATCH 018/130] Corrected shift --- apps/apps_container.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index b659db945..4a9afed0b 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -222,7 +222,6 @@ bool AppsContainer::processEvent(Ion::Events::Event event) { int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates; int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsForShiftPlusMinus*delta : -delta*NumberOfStepsForShiftPlusMinus; GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction); - return true; } return false; } From f6aab242a2777d59ddfa2e6bd587da9ab1bf7d59 Mon Sep 17 00:00:00 2001 From: RedGl0w Date: Sun, 8 Dec 2019 11:09:57 +0100 Subject: [PATCH 019/130] Corrected settings update --- apps/settings/main_controller.cpp | 7 +++++-- apps/settings/main_controller.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 5bf462beb..59d5075ec 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -37,8 +37,11 @@ void MainController::didBecomeFirstResponder() { bool MainController::handleEvent(Ion::Events::Event event) { GlobalPreferences * globalPreferences = GlobalPreferences::sharedGlobalPreferences(); if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus){ - m_selectableTableView.reloadData(); - return false; + int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates; + int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsForShiftPlusMinus*delta : -delta*NumberOfStepsForShiftPlusMinus; + GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction); + m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), 1); + return true; } if (model()->children(selectedRow())->numberOfChildren() == 0) { if (model()->children(selectedRow())->label() == promptMessage()) { diff --git a/apps/settings/main_controller.h b/apps/settings/main_controller.h index 2a371b0c9..b6bf9c7d6 100644 --- a/apps/settings/main_controller.h +++ b/apps/settings/main_controller.h @@ -42,6 +42,7 @@ private: AccessibilityController m_accessibilityController; ExamModeController m_examModeController; AboutController m_aboutController; + const int NumberOfStepsForShiftPlusMinus = 3; }; } From e1c1b4729753fafea44ba43c69fd11912fd9c78f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Sun, 8 Dec 2019 15:40:12 +0100 Subject: [PATCH 020/130] Added themes submodule --- .gitmodules | 3 +++ themes | 1 + 2 files changed, 4 insertions(+) create mode 160000 themes diff --git a/.gitmodules b/.gitmodules index 134e135f6..1e294d433 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "apps/atom"] path = apps/atom url = https://github.com/Omega-Numworks/Omega-Atom.git +[submodule "themes"] + path = themes + url = https://github.com/Omega-Numworks/Omega-Themes.git diff --git a/themes b/themes new file mode 160000 index 000000000..e09677c2e --- /dev/null +++ b/themes @@ -0,0 +1 @@ +Subproject commit e09677c2eee23130d5c13ac80f94c42e1d51b255 From 72666e927d219df384f5d7a4f8fafec6b378ff7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Sun, 8 Dec 2019 16:23:36 +0100 Subject: [PATCH 021/130] Updated themes submodule (dark mode) --- themes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes b/themes index e09677c2e..57312b33a 160000 --- a/themes +++ b/themes @@ -1 +1 @@ -Subproject commit e09677c2eee23130d5c13ac80f94c42e1d51b255 +Subproject commit 57312b33acc18d4a93210046c59940f8552ef533 From 1442e6977d847c98f66e722aa5a6fa15d87fd5e4 Mon Sep 17 00:00:00 2001 From: RedGl0w Date: Sun, 8 Dec 2019 18:18:28 +0100 Subject: [PATCH 022/130] Simplified code --- apps/apps_container.cpp | 3 ++- apps/apps_container.h | 1 - apps/settings/main_controller.cpp | 3 ++- apps/settings/main_controller.h | 1 - ion/include/ion/backlight.h | 1 + 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 4a9afed0b..c352f44c4 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -4,6 +4,7 @@ #include #include #include +#include extern "C" { #include @@ -220,7 +221,7 @@ bool AppsContainer::processEvent(Ion::Events::Event event) { } if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus) { int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates; - int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsForShiftPlusMinus*delta : -delta*NumberOfStepsForShiftPlusMinus; + int direction = (event == Ion::Events::BrightnessPlus) ? Ion::Backlight::NumberOfStepsPerShortcut*delta : -delta*Ion::Backlight::NumberOfStepsPerShortcut; GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction); } return false; diff --git a/apps/apps_container.h b/apps/apps_container.h index 60efccdd9..87c0adea6 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -78,7 +78,6 @@ private: OnBoarding::App::Snapshot m_onBoardingSnapshot; HardwareTest::App::Snapshot m_hardwareTestSnapshot; USB::App::Snapshot m_usbConnectedSnapshot; - const int NumberOfStepsForShiftPlusMinus = 3; }; #endif diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index 59d5075ec..12419bc55 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -2,6 +2,7 @@ #include "../global_preferences.h" #include #include +#include using namespace Poincare; @@ -38,7 +39,7 @@ bool MainController::handleEvent(Ion::Events::Event event) { GlobalPreferences * globalPreferences = GlobalPreferences::sharedGlobalPreferences(); if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus){ int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates; - int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsForShiftPlusMinus*delta : -delta*NumberOfStepsForShiftPlusMinus; + int direction = (event == Ion::Events::BrightnessPlus) ? Ion::Backlight::NumberOfStepsPerShortcut*delta : -delta*Ion::Backlight::NumberOfStepsPerShortcut; GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction); m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), 1); return true; diff --git a/apps/settings/main_controller.h b/apps/settings/main_controller.h index b6bf9c7d6..2a371b0c9 100644 --- a/apps/settings/main_controller.h +++ b/apps/settings/main_controller.h @@ -42,7 +42,6 @@ private: AccessibilityController m_accessibilityController; ExamModeController m_examModeController; AboutController m_aboutController; - const int NumberOfStepsForShiftPlusMinus = 3; }; } diff --git a/ion/include/ion/backlight.h b/ion/include/ion/backlight.h index cd69ee888..89a19687c 100644 --- a/ion/include/ion/backlight.h +++ b/ion/include/ion/backlight.h @@ -12,6 +12,7 @@ bool isInitialized(); void shutdown(); void setBrightness(uint8_t b); uint8_t brightness(); +const int NumberOfStepsPerShortcut = 4; } } From 890d6a5c3b16e8d7b0b5947521fee37f6a2604cd Mon Sep 17 00:00:00 2001 From: Danny Simmons Date: Sun, 8 Dec 2019 15:34:30 -0500 Subject: [PATCH 023/130] [apps/settings] Fix the I18n refrences for English+Spanish --- apps/settings/base.en.i18n | 10 +++++----- apps/settings/base.es.i18n | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index 0d62be4b8..26d80ae42 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -42,8 +42,8 @@ AccessibilityGammaRed = "Red gamma" AccessibilityGammaGreen = "Green gamma" AccessibilityGammaBlue = "Blue gamma" MathOptions = "Math options" -SymbolMultiplication = "Multiplication sign" -SymbolMultiplicationCross = "Cross" -SymbolMultiplicationMiddleDot = "Middle dot" -SymbolMultiplicationStar = "Star" -SymbolMultiplicationAutoSymbol = "Automatic" +SymbolMultiplication = "Multiply sign" +SymbolMultiplicationCross = "Cross " +SymbolMultiplicationMiddleDot = "Dot " +SymbolMultiplicationStar = "Star " +SymbolMultiplicationAutoSymbol = "Auto " diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index f4615de36..5554bb8b4 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -42,8 +42,8 @@ AccessibilityGammaRed = "Gamma roja" AccessibilityGammaGreen = "Gamma verde" AccessibilityGammaBlue = "Gamma azul" MathOptions = "Matemáticas" -SymbolMultiplication = "signo de multiplicación" -SymbolMultiplicationCross = "contrariar" -SymbolMultiplicationMiddleDot = "punto medio" -SymbolMultiplicationStar = "estrella" -SymbolMultiplicationAutoSymbol = "automático" +SymbolMultiplication = "Signo de multiplicación" +SymbolMultiplicationCross = "Contrariar " +SymbolMultiplicationMiddleDot = "Punto " +SymbolMultiplicationStar = "Estrella " +SymbolMultiplicationAutoSymbol = "Auto " From caf04ad63504edabdc534d6cd74a626dd0ec55e7 Mon Sep 17 00:00:00 2001 From: Danny Simmons Date: Sun, 8 Dec 2019 15:35:56 -0500 Subject: [PATCH 024/130] [poincare/preferences] correct some preferences references --- poincare/include/poincare/preferences.h | 6 +++--- poincare/src/preferences.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poincare/include/poincare/preferences.h b/poincare/include/poincare/preferences.h index 569718aed..95505cf55 100644 --- a/poincare/include/poincare/preferences.h +++ b/poincare/include/poincare/preferences.h @@ -36,13 +36,13 @@ public: Radian = 1, Gradian = 2 }; - enum class LEDColor { + enum class LEDColor : uint8_t { White = 0, Green = 1, Blue = 2, Yellow = 3 }; - enum class SymbolMultiplication { + enum class SymbolMultiplication : uint8_t { Cross = 0, MiddleDot = 1, Star = 2, @@ -71,7 +71,7 @@ private: ComplexFormat m_complexFormat; uint8_t m_numberOfSignificantDigits; LEDColor m_colorOfLED; - SymbolMultiplication m_symbolMultiplication; + SymbolMultiplication m_symbolMultiplication; }; } diff --git a/poincare/src/preferences.cpp b/poincare/src/preferences.cpp index 724372f79..4cdb0613f 100644 --- a/poincare/src/preferences.cpp +++ b/poincare/src/preferences.cpp @@ -14,7 +14,7 @@ Preferences::Preferences() : m_complexFormat(Preferences::ComplexFormat::Real), m_numberOfSignificantDigits(PrintFloat::k_numberOfPrintedSignificantDigits), m_colorOfLED(Preferences::LEDColor::White), - m_symbolMultiplication(Preferences::SymbolMultiplication::Cross) + m_symbolMultiplication(Preferences::SymbolMultiplication::Auto) {} Preferences * Preferences::sharedPreferences() { From b332d183fcf3ec84ab5c2db1bcdc62661f2fa8df Mon Sep 17 00:00:00 2001 From: Danny Simmons Date: Sun, 8 Dec 2019 15:37:17 -0500 Subject: [PATCH 025/130] [apps/settings] Modify preferences_controller to add symbols --- .../sub_menu/preferences_controller.cpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/apps/settings/sub_menu/preferences_controller.cpp b/apps/settings/sub_menu/preferences_controller.cpp index f335a2b32..1417a1c0a 100644 --- a/apps/settings/sub_menu/preferences_controller.cpp +++ b/apps/settings/sub_menu/preferences_controller.cpp @@ -130,6 +130,22 @@ Layout PreferencesController::layoutForPreferences(I18n::Message message) { return LayoutHelper::String(text, strlen(text), k_layoutFont); } + // Symbol controller + case I18n::Message::SymbolMultiplicationCross: // × and · aren't single characters, so they cannot be constructed into codepoints..? + { + const char * text = "×"; + return LayoutHelper::String(text, strlen(text), k_layoutFont); + } + case I18n::Message::SymbolMultiplicationMiddleDot: + { + const char * text = "·"; + return LayoutHelper::String(text, strlen(text), k_layoutFont); + } + case I18n::Message::SymbolMultiplicationStar: + return CodePointLayout::Builder('*', k_layoutFont); + case I18n::Message::SymbolMultiplicationAutoSymbol: + return CodePointLayout::Builder(' ', k_layoutFont); + default: assert(false); return Layout(); @@ -167,6 +183,8 @@ void PreferencesController::setPreferenceWithValueIndex(I18n::Message message, i preferences->setComplexFormat((Preferences::ComplexFormat)valueIndex); } else if (message == I18n::Message::LEDColor) { preferences->setColorOfLED((Preferences::LEDColor)valueIndex); + } else if (message == I18n::Message::SymbolMultiplication) { + preferences->setSymbolMultiplication((Preferences::SymbolMultiplication)valueIndex); } } @@ -187,6 +205,9 @@ int PreferencesController::valueIndexForPreference(I18n::Message message) { if (message == I18n::Message::LEDColor) { return (int)preferences->colorOfLED(); } + if (message == I18n::Message::SymbolMultiplication) { + return (int)preferences->symbolofMultiplication(); + } return 0; } From 13fe95bb9877232114aaf63756b69632d15327d1 Mon Sep 17 00:00:00 2001 From: Danny Simmons Date: Sun, 8 Dec 2019 15:38:10 -0500 Subject: [PATCH 026/130] [apps/settings] Remove symbol_controller and references to it --- apps/settings/Makefile | 1 - apps/settings/main_controller.h | 1 - .../sub_menu/math_options_controller.cpp | 5 +- .../sub_menu/math_options_controller.h | 2 - apps/settings/sub_menu/symbol_controller.cpp | 136 ------------------ apps/settings/sub_menu/symbol_controller.h | 23 --- 6 files changed, 1 insertion(+), 167 deletions(-) delete mode 100644 apps/settings/sub_menu/symbol_controller.cpp delete mode 100644 apps/settings/sub_menu/symbol_controller.h diff --git a/apps/settings/Makefile b/apps/settings/Makefile index bb3156a6d..1226acb40 100644 --- a/apps/settings/Makefile +++ b/apps/settings/Makefile @@ -15,7 +15,6 @@ app_settings_src = $(addprefix apps/settings/,\ sub_menu/preferences_controller.cpp \ sub_menu/contributors_controller.cpp \ sub_menu/math_options_controller.cpp \ - sub_menu/symbol_controller.cpp \ ) app_src += $(app_settings_src) diff --git a/apps/settings/main_controller.h b/apps/settings/main_controller.h index 2a371b0c9..bfa85be37 100644 --- a/apps/settings/main_controller.h +++ b/apps/settings/main_controller.h @@ -8,7 +8,6 @@ #include "sub_menu/exam_mode_controller.h" #include "sub_menu/language_controller.h" #include "sub_menu/math_options_controller.h" -#include "sub_menu/symbol_controller.h" namespace Settings { diff --git a/apps/settings/sub_menu/math_options_controller.cpp b/apps/settings/sub_menu/math_options_controller.cpp index c4235fbc1..5b4b42b7b 100644 --- a/apps/settings/sub_menu/math_options_controller.cpp +++ b/apps/settings/sub_menu/math_options_controller.cpp @@ -9,8 +9,7 @@ namespace Settings { MathOptionsController::MathOptionsController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate) : GenericSubController(parentResponder), m_preferencesController(this), - m_displayModeController(this, inputEventHandlerDelegate), - m_symbolController(this) + m_displayModeController(this, inputEventHandlerDelegate) { for (int i = 0; i < k_totalNumberOfCell; i++) { m_cells[i].setMessageFont(KDFont::LargeFont); @@ -22,8 +21,6 @@ bool MathOptionsController::handleEvent(Ion::Events::Event event) { GenericSubController * subController = nullptr; if (m_messageTreeModel->children(selectedRow())->label() == I18n::Message::DisplayMode) subController = &m_displayModeController; - else if (m_messageTreeModel->children(selectedRow())->label() == I18n::Message::SymbolMultiplication) - subController = &m_symbolController; else subController = &m_preferencesController; subController->setMessageTreeModel(m_messageTreeModel->children(selectedRow())); diff --git a/apps/settings/sub_menu/math_options_controller.h b/apps/settings/sub_menu/math_options_controller.h index dcd073c10..1db4c3104 100644 --- a/apps/settings/sub_menu/math_options_controller.h +++ b/apps/settings/sub_menu/math_options_controller.h @@ -4,7 +4,6 @@ #include "generic_sub_controller.h" #include #include "display_mode_controller.h" -#include "symbol_controller.h" #include "preferences_controller.h" namespace Settings { @@ -21,7 +20,6 @@ private: MessageTableCellWithChevronAndMessage m_cells[k_totalNumberOfCell]; PreferencesController m_preferencesController; DisplayModeController m_displayModeController; - SymbolController m_symbolController; }; } diff --git a/apps/settings/sub_menu/symbol_controller.cpp b/apps/settings/sub_menu/symbol_controller.cpp deleted file mode 100644 index 33cebb801..000000000 --- a/apps/settings/sub_menu/symbol_controller.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include "symbol_controller.h" -#include -#include - -using namespace Shared; -using namespace Poincare; - -namespace Settings { - -SymbolController::SymbolController(Responder * parentResponder) : - GenericSubController(parentResponder) -{ - for (int i = 0; i < k_totalNumberOfSwitchCells; i++) { - m_switchCells[i].setMessageFont(KDFont::LargeFont); - } -} - -bool SymbolController::handleEvent(Ion::Events::Event event) { - Preferences * preferences = Preferences::sharedPreferences(); - Poincare::Preferences::SymbolMultiplication oldSymbolOfMultiplication = preferences->symbolofMultiplication(); - Poincare::Preferences::SymbolMultiplication newSymbolOfMultiplication = preferences->symbolofMultiplication(); - if (event == Ion::Events::OK || event == Ion::Events::EXE){ - switch(selectedRow()){ - case 0: - { - newSymbolOfMultiplication = Poincare::Preferences::SymbolMultiplication::Cross; - break; - } - case 1: - { - newSymbolOfMultiplication = Poincare::Preferences::SymbolMultiplication::MiddleDot; - break; - } - case 2: - { - newSymbolOfMultiplication = Poincare::Preferences::SymbolMultiplication::Star; - break; - } - case 3: - { - newSymbolOfMultiplication = Poincare::Preferences::SymbolMultiplication::Auto; - break; - } - default: - { - GenericSubController::handleEvent(event); - } - } - if (oldSymbolOfMultiplication == newSymbolOfMultiplication) { - if (newSymbolOfMultiplication == Poincare::Preferences::SymbolMultiplication::Auto) { - preferences->setSymbolMultiplication(Poincare::Preferences::SymbolMultiplication::Cross); - } else { - preferences->setSymbolMultiplication(Poincare::Preferences::SymbolMultiplication::Auto); - } - } else { - preferences->setSymbolMultiplication(newSymbolOfMultiplication); - } - m_selectableTableView.reloadData(); - return true; - } else { - return GenericSubController::handleEvent(event); - } -} - -HighlightCell * SymbolController::reusableCell(int index, int type) { - assert(type == 1 || type == 2); - if (type == 2) { - assert(index >= 0 && index < k_totalNumberOfSwitchCells); - return &m_switchCells[index]; - } - return nullptr; -} - -int SymbolController::reusableCellCount(int type) { - assert(type == 1 || type == 2); - if (type == 2) { - return k_totalNumberOfSwitchCells; - } - return 0; -} - -void SymbolController::willDisplayCellForIndex(HighlightCell * cell, int index) { - GenericSubController::willDisplayCellForIndex(cell, index); - - MessageTableCellWithSwitch * mySwitchCell = (MessageTableCellWithSwitch *)cell; - - Preferences * preferences = Preferences::sharedPreferences(); - Poincare::Preferences::SymbolMultiplication symbolofMultiplication = preferences->symbolofMultiplication(); - - if (index == 0) { - SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); - if(symbolofMultiplication == Poincare::Preferences::SymbolMultiplication::Cross){ - mySwitch->setState(true); - } else { - mySwitch->setState(false); - } - } - else if (index == 1) { - SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); - if(symbolofMultiplication == Poincare::Preferences::SymbolMultiplication::MiddleDot){ - mySwitch->setState(true); - } else { - mySwitch->setState(false); - } - } - else if (index == 2) { - SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); - if (symbolofMultiplication == Poincare::Preferences::SymbolMultiplication::Star){ - mySwitch->setState(true); - } else { - mySwitch->setState(false); - } - } - else if (index == 3){ - SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); - if(symbolofMultiplication == Poincare::Preferences::SymbolMultiplication::Auto){ - mySwitch->setState(true); - } else { - mySwitch->setState(false); - } - } -} - -int SymbolController::typeAtLocation(int i, int j) { - switch (j) { - case 0: - case 1: - case 2: - case 3: - return 2; - default: - return 1; - } -} - -} diff --git a/apps/settings/sub_menu/symbol_controller.h b/apps/settings/sub_menu/symbol_controller.h deleted file mode 100644 index 2c01e1da2..000000000 --- a/apps/settings/sub_menu/symbol_controller.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SETTINGS_SYMBOLCONTROLLER_CONTROLLER_H -#define SETTINGS_SYMBOLCONTROLLER_CONTROLLER_H - -#include "generic_sub_controller.h" - -namespace Settings { - -class SymbolController : public GenericSubController { -public: - SymbolController(Responder * parentResponder); - bool handleEvent(Ion::Events::Event event) override; - HighlightCell * reusableCell(int index, int type) override; - int reusableCellCount(int type) override; - void willDisplayCellForIndex(HighlightCell * cell, int index) override; - int typeAtLocation(int i, int j) override; -private: - constexpr static int k_totalNumberOfSwitchCells = 4; - MessageTableCellWithSwitch m_switchCells[k_totalNumberOfSwitchCells]; -}; - -} - -#endif \ No newline at end of file From 79ea22bc64ebf2789b6a1ab5384924a99e0f73b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Dec 2019 09:57:08 +0100 Subject: [PATCH 027/130] [ion] N0110 board: fix MPU configuration on FMC memory bank --- ion/src/device/n0110/drivers/board.cpp | 36 ++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/ion/src/device/n0110/drivers/board.cpp b/ion/src/device/n0110/drivers/board.cpp index c605a4add..55fe11131 100644 --- a/ion/src/device/n0110/drivers/board.cpp +++ b/ion/src/device/n0110/drivers/board.cpp @@ -35,10 +35,36 @@ void initMPU() { // 2. MPU settings // 2.1 Configure a MPU region for the FMC memory area - // This is needed for interfacing with the LCD - MPU.RNR()->setREGION(0x00); + /* This is needed for interfacing with the LCD + * We define the whole FMC memory bank 1 as strongly ordered, non-executable + * and not accessible. We define the FMC command and data addresses as + * writeable non-cachable, non-buffereable and non shareable. */ + int sector = 0; + MPU.RNR()->setREGION(sector++); MPU.RBAR()->setADDR(0x60000000); - MPU.RASR()->setSIZE(MPU::RASR::RegionSize::_32MB); + MPU.RASR()->setSIZE(MPU::RASR::RegionSize::_256MB); + MPU.RASR()->setAP(MPU::RASR::AccessPermission::NoAccess); + MPU.RASR()->setXN(true); + MPU.RASR()->setTEX(2); + MPU.RASR()->setS(0); + MPU.RASR()->setC(0); + MPU.RASR()->setB(0); + MPU.RASR()->setENABLE(true); + + MPU.RNR()->setREGION(sector++); + MPU.RBAR()->setADDR(0x60000000); + MPU.RASR()->setSIZE(MPU::RASR::RegionSize::_32B); + MPU.RASR()->setXN(true); + MPU.RASR()->setAP(MPU::RASR::AccessPermission::RW); + MPU.RASR()->setTEX(2); + MPU.RASR()->setS(0); + MPU.RASR()->setC(0); + MPU.RASR()->setB(0); + MPU.RASR()->setENABLE(true); + + MPU.RNR()->setREGION(sector++); + MPU.RBAR()->setADDR(0x60000000+0x20000); + MPU.RASR()->setSIZE(MPU::RASR::RegionSize::_32B); MPU.RASR()->setXN(true); MPU.RASR()->setAP(MPU::RASR::AccessPermission::RW); MPU.RASR()->setTEX(2); @@ -56,7 +82,7 @@ void initMPU() { * strongly ordered, non-executable and not accessible. Plus, we define the * Quad-SPI region corresponding to the Expternal Chip as executable and * fully accessible (AN4861). */ - MPU.RNR()->setREGION(0x01); + MPU.RNR()->setREGION(sector++); MPU.RBAR()->setADDR(0x90000000); MPU.RASR()->setSIZE(MPU::RASR::RegionSize::_256MB); MPU.RASR()->setAP(MPU::RASR::AccessPermission::NoAccess); @@ -67,7 +93,7 @@ void initMPU() { MPU.RASR()->setB(0); MPU.RASR()->setENABLE(true); - MPU.RNR()->setREGION(0x02); + MPU.RNR()->setREGION(sector++); MPU.RBAR()->setADDR(0x90000000); MPU.RASR()->setSIZE(MPU::RASR::RegionSize::_8MB); MPU.RASR()->setAP(MPU::RASR::AccessPermission::RW); From f9fb3a963ec84ab3b1aa8642480f60d51407df89 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Mon, 9 Dec 2019 20:42:52 +0100 Subject: [PATCH 028/130] [ion/storage] Reorganised for use in a future workshop-like. --- ion/src/shared/platform_info.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/ion/src/shared/platform_info.cpp b/ion/src/shared/platform_info.cpp index 625bb363c..592be3dc2 100644 --- a/ion/src/shared/platform_info.cpp +++ b/ion/src/shared/platform_info.cpp @@ -27,19 +27,25 @@ public: constexpr PlatformInfo() : m_header(Magic), m_version{EPSILON_VERSION}, - m_customVersion{EPSILON_CUSTOM_VERSION}, -#ifdef USERNAME - m_username{USERNAME}, -#endif m_patchLevel{PATCH_LEVEL}, m_storageAddress(storageAddress), m_storageSize(Ion::Storage::k_storageSize), - m_footer(Magic) { } + m_footer(Magic), + m_ohm_header(OmegaMagic), + m_customVersion{EPSILON_CUSTOM_VERSION}, +#ifdef USERNAME + m_username{USERNAME}, +#else + m_username{"\0"}, +#endif + m_ohm_footer(OmegaMagic) { } const char * version() const { assert(m_storageAddress != nullptr); assert(m_storageSize != 0); assert(m_header == Magic); assert(m_footer == Magic); + assert(m_ohm_header == OmegaMagic); + assert(m_ohm_footer == OmegaMagic); return m_version; } const char * customVersion() const { @@ -47,6 +53,8 @@ public: assert(m_storageSize != 0); assert(m_header == Magic); assert(m_footer == Magic); + assert(m_ohm_header == OmegaMagic); + assert(m_ohm_footer == OmegaMagic); return m_customVersion; } #ifdef USERNAME @@ -55,6 +63,8 @@ public: assert(m_storageSize != 0); assert(m_header == Magic); assert(m_footer == Magic); + assert(m_ohm_header == OmegaMagic); + assert(m_ohm_footer == OmegaMagic); return m_username; } #endif @@ -63,20 +73,23 @@ public: assert(m_storageSize != 0); assert(m_header == Magic); assert(m_footer == Magic); + assert(m_ohm_header == OmegaMagic); + assert(m_ohm_footer == OmegaMagic); return m_patchLevel; } private: constexpr static uint32_t Magic = 0xDEC00DF0; + constexpr static uint32_t OmegaMagic = 0xEFBEADDE; uint32_t m_header; const char m_version[8]; const char m_patchLevel[8]; void * m_storageAddress; size_t m_storageSize; uint32_t m_footer; + uint32_t m_ohm_header; const char m_customVersion[16]; -#ifdef USERNAME const char m_username[16]; -#endif + uint32_t m_ohm_footer; }; constexpr PlatformInfo HEADER_SECTION platform_infos; From db2807c57e91c057657a48cb03862529d5a16b70 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Mon, 9 Dec 2019 22:28:22 +0100 Subject: [PATCH 029/130] [settings] Added symbolic calculation in exam mode. --- apps/settings/base.de.i18n | 1 + apps/settings/base.en.i18n | 1 + apps/settings/base.es.i18n | 1 + apps/settings/base.fr.i18n | 1 + apps/settings/base.pt.i18n | 1 + apps/settings/main_controller_prompt_none.cpp | 4 ++-- .../sub_menu/exam_mode_controller.cpp | 21 ++++++++++++++++++- apps/settings/sub_menu/exam_mode_controller.h | 1 + poincare/include/poincare/preferences.h | 5 ++++- poincare/src/preferences.cpp | 3 ++- 10 files changed, 34 insertions(+), 5 deletions(-) diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index e728ea17e..d16a57742 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -47,3 +47,4 @@ SymbolMultiplicationCross = "Kreuz" SymbolMultiplicationMiddleDot = "Mittelpunkt" SymbolMultiplicationStar = "Stern" SymbolMultiplicationAutoSymbol = "automatisch" +SymbolicEnabled = "Symbolic calc." diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index 0d62be4b8..95680b05a 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -47,3 +47,4 @@ SymbolMultiplicationCross = "Cross" SymbolMultiplicationMiddleDot = "Middle dot" SymbolMultiplicationStar = "Star" SymbolMultiplicationAutoSymbol = "Automatic" +SymbolicEnabled = "Symbolic calc." diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index f4615de36..08a43a88b 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -47,3 +47,4 @@ SymbolMultiplicationCross = "contrariar" SymbolMultiplicationMiddleDot = "punto medio" SymbolMultiplicationStar = "estrella" SymbolMultiplicationAutoSymbol = "automático" +SymbolicEnabled = "Symbolic calc." diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index bb3ad6a6e..40a9d1718 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -47,3 +47,4 @@ SymbolMultiplicationCross = "Croix" SymbolMultiplicationMiddleDot = "Point" SymbolMultiplicationStar = "Etoile" SymbolMultiplicationAutoSymbol = "Automatique" +SymbolicEnabled = "Symbolic calc." diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index f81da34d9..5b5e8f786 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -47,3 +47,4 @@ SymbolMultiplicationCross = "crómio" SymbolMultiplicationMiddleDot = "ponto médio" SymbolMultiplicationStar = "estrela" SymbolMultiplicationAutoSymbol = "automático" +SymbolicEnabled = "Symbolic calc." diff --git a/apps/settings/main_controller_prompt_none.cpp b/apps/settings/main_controller_prompt_none.cpp index a3a20e130..7ff074116 100644 --- a/apps/settings/main_controller_prompt_none.cpp +++ b/apps/settings/main_controller_prompt_none.cpp @@ -15,7 +15,7 @@ constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::M //sub-menus constexpr SettingsMessageTree s_modelMathOptionsChildren[5] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren, 4)}; -constexpr SettingsMessageTree s_modelExamChildren[2] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::ActivateExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[3] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; #ifdef USERNAME constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 5)}; @@ -27,7 +27,7 @@ constexpr SettingsMessageTree s_modelMenu[] = {SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren, 5), SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::Language), - SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 2), + SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 3), SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6), #ifdef USERNAME SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 7)}; diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index 78ba177db..b293081e0 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -15,7 +15,8 @@ ExamModeController::ExamModeController(Responder * parentResponder) : GenericSubController(parentResponder), m_preferencesController(this), m_examModeCell(I18n::Message::Default, KDFont::LargeFont), - m_ledCell(KDFont::LargeFont, KDFont::SmallFont) + m_ledCell(KDFont::LargeFont, KDFont::SmallFont), + m_symbolicCell(I18n::Message::SymbolicEnabled, KDFont::LargeFont) { } @@ -40,6 +41,12 @@ bool ExamModeController::handleEvent(Ion::Events::Event event) { stack->push(subController); return true; } + if (childLabel == I18n::Message::SymbolicEnabled) { + Preferences * preferences = Preferences::sharedPreferences(); + preferences->setExamSymbolic(!preferences->isExamSymbolic()); + m_selectableTableView.reloadData(); + return true; + } } return GenericSubController::handleEvent(event); } @@ -49,6 +56,9 @@ HighlightCell * ExamModeController::reusableCell(int index, int type) { if (type == 0) { return &m_ledCell; } + if (type == 1) { + return &m_symbolicCell; + } return &m_examModeCell; } @@ -58,6 +68,8 @@ int ExamModeController::reusableCellCount(int type) { return 1; case 1: return 1; + case 2: + return 1; default: assert(false); return 0; @@ -78,6 +90,11 @@ void ExamModeController::willDisplayCellForIndex(HighlightCell * cell, int index I18n::Message message = (I18n::Message) m_messageTreeModel->children(index)->children((int)preferences->colorOfLED())->label(); myTextCell->setSubtitle(message); } + if (thisLabel == I18n::Message::SymbolicEnabled) { + MessageTableCellWithSwitch * mySwitchCell = (MessageTableCellWithSwitch *)cell; + SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); + mySwitch->setState(preferences->isExamSymbolic()); + } } int ExamModeController::typeAtLocation(int i, int j) { @@ -86,6 +103,8 @@ int ExamModeController::typeAtLocation(int i, int j) { return 0; case 1: return 1; + case 2: + return 2; default: assert(false); return 0; diff --git a/apps/settings/sub_menu/exam_mode_controller.h b/apps/settings/sub_menu/exam_mode_controller.h index de9b9f9ef..f348414c4 100644 --- a/apps/settings/sub_menu/exam_mode_controller.h +++ b/apps/settings/sub_menu/exam_mode_controller.h @@ -19,6 +19,7 @@ private: MessageTableCell m_examModeCell; MessageTableCellWithChevronAndMessage m_ledCell; PreferencesController m_preferencesController; + MessageTableCellWithSwitch m_symbolicCell; }; } diff --git a/poincare/include/poincare/preferences.h b/poincare/include/poincare/preferences.h index 569718aed..323020bc0 100644 --- a/poincare/include/poincare/preferences.h +++ b/poincare/include/poincare/preferences.h @@ -64,6 +64,8 @@ public: void setColorOfLED(LEDColor color) { m_colorOfLED = color; } SymbolMultiplication symbolofMultiplication() const {return m_symbolMultiplication;} void setSymbolMultiplication(SymbolMultiplication symbolofMultiplication) {m_symbolMultiplication = symbolofMultiplication;} + bool isExamSymbolic() const {return m_examSymbolic;} + void setExamSymbolic(bool examSymbolic) {m_examSymbolic = examSymbolic;} private: AngleUnit m_angleUnit; PrintFloatMode m_displayMode; @@ -71,7 +73,8 @@ private: ComplexFormat m_complexFormat; uint8_t m_numberOfSignificantDigits; LEDColor m_colorOfLED; - SymbolMultiplication m_symbolMultiplication; + SymbolMultiplication m_symbolMultiplication; + bool m_examSymbolic; }; } diff --git a/poincare/src/preferences.cpp b/poincare/src/preferences.cpp index 724372f79..a644040b7 100644 --- a/poincare/src/preferences.cpp +++ b/poincare/src/preferences.cpp @@ -14,7 +14,8 @@ Preferences::Preferences() : m_complexFormat(Preferences::ComplexFormat::Real), m_numberOfSignificantDigits(PrintFloat::k_numberOfPrintedSignificantDigits), m_colorOfLED(Preferences::LEDColor::White), - m_symbolMultiplication(Preferences::SymbolMultiplication::Cross) + m_symbolMultiplication(Preferences::SymbolMultiplication::Cross), + m_examSymbolic(true) {} Preferences * Preferences::sharedPreferences() { From b31d11cd7a909a7cfe67d7f3ce722e5d5be632f8 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Mon, 9 Dec 2019 22:34:53 +0100 Subject: [PATCH 030/130] [apps/calc] Checks for exam symbolic setting. --- apps/calculation/calculation_store.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/calculation/calculation_store.cpp b/apps/calculation/calculation_store.cpp index f466c4e01..3e68f79c5 100644 --- a/apps/calculation/calculation_store.cpp +++ b/apps/calculation/calculation_store.cpp @@ -1,5 +1,6 @@ #include "calculation_store.h" #include "../shared/poincare_helpers.h" +#include "../global_preferences.h" #include #include #include @@ -91,7 +92,7 @@ ExpiringPointer CalculationStore::push(const char * text, Context * // Compute and serialize the outputs { Expression outputs[] = {Expression(), Expression()}; - PoincareHelpers::ParseAndSimplifyAndApproximate(inputSerialization, &(outputs[0]), &(outputs[1]), context, true); // Symbolic computation + PoincareHelpers::ParseAndSimplifyAndApproximate(inputSerialization, &(outputs[0]), &(outputs[1]), context, GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate ? Preferences::sharedPreferences()->isExamSymbolic() : true); // Symbolic computation for (int i = 0; i < 2; i++) { if (!serializeExpression(outputs[i], nextSerializationLocation, &newCalculationsLocation)) { /* If the exat/approximate output does not fit in the store (event if the From 01bd446d0bc69818aacdfc143c4faa27e50620be Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Mon, 9 Dec 2019 22:36:20 +0100 Subject: [PATCH 031/130] [settings] Updated messages trees for others prompts. --- apps/settings/main_controller_prompt_beta.cpp | 4 ++-- apps/settings/main_controller_prompt_update.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/settings/main_controller_prompt_beta.cpp b/apps/settings/main_controller_prompt_beta.cpp index d59366b98..5bbc5209d 100644 --- a/apps/settings/main_controller_prompt_beta.cpp +++ b/apps/settings/main_controller_prompt_beta.cpp @@ -14,7 +14,7 @@ constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::M //sub-menus constexpr SettingsMessageTree s_modelMathOptionsChildren[5] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren, 4)}; -constexpr SettingsMessageTree s_modelExamChildren[2] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::ActivateExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[3] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; #ifdef USERNAME constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 5)}; @@ -26,7 +26,7 @@ constexpr SettingsMessageTree s_modelMenu[] = {SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren, 5), SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::Language), - SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 2), + SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 3), SettingsMessageTree(I18n::Message::BetaPopUp), SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6), #ifdef USERNAME diff --git a/apps/settings/main_controller_prompt_update.cpp b/apps/settings/main_controller_prompt_update.cpp index e73a6bb36..9a7b82685 100644 --- a/apps/settings/main_controller_prompt_update.cpp +++ b/apps/settings/main_controller_prompt_update.cpp @@ -14,7 +14,7 @@ constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::M //sub-menus constexpr SettingsMessageTree s_modelMathOptionsChildren[5] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren, 4)}; -constexpr SettingsMessageTree s_modelExamChildren[2] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::ActivateExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[3] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; #ifdef USERNAME constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 5)}; @@ -26,7 +26,7 @@ constexpr SettingsMessageTree s_modelMenu[] = {SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren, 5), SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::Language), - SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 2), + SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 3), SettingsMessageTree(I18n::Message::UpdatePopUp), SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6), #ifdef USERNAME From 896d14b9c8f0f68b72dd8b2eafccc1ab3af89e9c Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Mon, 9 Dec 2019 22:39:16 +0100 Subject: [PATCH 032/130] [settings] Translated symbolic calc. --- apps/settings/base.de.i18n | 2 +- apps/settings/base.en.i18n | 2 +- apps/settings/base.es.i18n | 2 +- apps/settings/base.fr.i18n | 2 +- apps/settings/base.pt.i18n | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index d16a57742..7caa733b4 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -47,4 +47,4 @@ SymbolMultiplicationCross = "Kreuz" SymbolMultiplicationMiddleDot = "Mittelpunkt" SymbolMultiplicationStar = "Stern" SymbolMultiplicationAutoSymbol = "automatisch" -SymbolicEnabled = "Symbolic calc." +SymbolicEnabled = "Symbolische Berechnung" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index 95680b05a..b3eb15a77 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -47,4 +47,4 @@ SymbolMultiplicationCross = "Cross" SymbolMultiplicationMiddleDot = "Middle dot" SymbolMultiplicationStar = "Star" SymbolMultiplicationAutoSymbol = "Automatic" -SymbolicEnabled = "Symbolic calc." +SymbolicEnabled = "Symbolic calculation" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index 08a43a88b..5c824be69 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -47,4 +47,4 @@ SymbolMultiplicationCross = "contrariar" SymbolMultiplicationMiddleDot = "punto medio" SymbolMultiplicationStar = "estrella" SymbolMultiplicationAutoSymbol = "automático" -SymbolicEnabled = "Symbolic calc." +SymbolicEnabled = "Cálculo simbólico" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 40a9d1718..1b2e99829 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -47,4 +47,4 @@ SymbolMultiplicationCross = "Croix" SymbolMultiplicationMiddleDot = "Point" SymbolMultiplicationStar = "Etoile" SymbolMultiplicationAutoSymbol = "Automatique" -SymbolicEnabled = "Symbolic calc." +SymbolicEnabled = "Calcule symbolique" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index 5b5e8f786..ca2d855aa 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -47,4 +47,4 @@ SymbolMultiplicationCross = "crómio" SymbolMultiplicationMiddleDot = "ponto médio" SymbolMultiplicationStar = "estrela" SymbolMultiplicationAutoSymbol = "automático" -SymbolicEnabled = "Symbolic calc." +SymbolicEnabled = "Cálculo simbólico" From 70edf4420cc5467afbcd3344077e277e5b72cee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Tue, 10 Dec 2019 20:20:59 +0100 Subject: [PATCH 033/130] base.fr.i18n fixed --- apps/settings/base.fr.i18n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 1b2e99829..de3d3be95 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -47,4 +47,4 @@ SymbolMultiplicationCross = "Croix" SymbolMultiplicationMiddleDot = "Point" SymbolMultiplicationStar = "Etoile" SymbolMultiplicationAutoSymbol = "Automatique" -SymbolicEnabled = "Calcule symbolique" +SymbolicEnabled = "Calcul symbolique" From ca4de2bf38724cc1bcdb6a333014cad34f6430b4 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Tue, 10 Dec 2019 22:03:01 +0100 Subject: [PATCH 034/130] [apps/settings] Exam mode settings not editable while in exam mode. --- apps/settings/sub_menu/exam_mode_controller.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index b293081e0..61421af71 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -27,10 +27,10 @@ void ExamModeController::didEnterResponderChain(Responder * previousFirstRespond bool ExamModeController::handleEvent(Ion::Events::Event event) { I18n::Message childLabel = m_messageTreeModel->children(selectedRow())->label(); if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) { + if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { + return true; + } if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive) { - if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { - return false; - } AppsContainer::sharedAppsContainer()->displayExamModePopUp(true); return true; } From e550005e439bd17598ee17857cb90a85c8b45ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 6 Dec 2019 17:31:47 +0100 Subject: [PATCH 035/130] [settings] Enable exam mode reactivation --- apps/settings/base.de.i18n | 4 ++-- apps/settings/base.en.i18n | 2 +- apps/settings/base.es.i18n | 2 +- apps/settings/base.fr.i18n | 2 +- apps/settings/base.pt.i18n | 6 +++--- apps/settings/sub_menu/exam_mode_controller.cpp | 3 --- 6 files changed, 8 insertions(+), 11 deletions(-) diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 67b291971..a9385db05 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -7,8 +7,8 @@ EditionLinear = "Linear " Edition2D = "Natürlich " ComplexFormat = "Komplex" ExamMode = "Testmodus" -ActivateExamMode = "Start Testmodus" -ExamModeActive = "Testmodus: aktiv" +ActivateExamMode = "Starten Testmodus" +ExamModeActive = "Wieder starten Testmodus" About = "Über" Degrees = "Grad " Gradians = "Gone " diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index 543ac99f1..e5cc87cae 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -8,7 +8,7 @@ Edition2D = "Natural " ComplexFormat = "Complex format" ExamMode = "Exam mode" ActivateExamMode = "Activate exam mode" -ExamModeActive = "Exam mode: active" +ExamModeActive = "Reactivate exam mode" About = "About" Degrees = "Degrees " Gradians = "Gradians " diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index 313cf5dee..589348d3e 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -8,7 +8,7 @@ Edition2D = "Natural " ComplexFormat = "Forma compleja" ExamMode = "Modo examen" ActivateExamMode = "Activar el modo examen" -ExamModeActive = "Modo examen: activo" +ExamModeActive = "Reactivar el modo examen" About = "Acerca" Degrees = "Grados " Gradians = "Gradianes " diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index d4e04e309..5ca04b291 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -8,7 +8,7 @@ Edition2D = "Naturelle " ComplexFormat = "Forme complexe" ExamMode = "Mode examen" ActivateExamMode = "Activer le mode examen" -ExamModeActive = "Mode examen: actif" +ExamModeActive = "Réactiver le mode examen" About = "À propos" Degrees = "Degrés " Gradians = "Grades " diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index c26e8e52f..6582afeff 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -6,9 +6,9 @@ EditionMode = "Formato escrita " EditionLinear = "Em linha " Edition2D = "Natural " ComplexFormat = "Complexos" -ExamMode = "Modo de Exame" -ActivateExamMode = "Inicio modo de exame" -ExamModeActive = "Modo de exame : ativo" +ExamMode = "Modo de exame" +ActivateExamMode = "Ativar o modo de exame" +ExamModeActive = "Reativar o modo de exame" About = "Acerca" Degrees = "Graus " Gradians = "Grados " diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index 6f24abcd7..def1a10d3 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -21,9 +21,6 @@ void ExamModeController::didEnterResponderChain(Responder * previousFirstRespond bool ExamModeController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::EXE) { - if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { - return false; - } AppsContainer::sharedAppsContainer()->displayExamModePopUp(true); return true; } From ebc5843795cd1b4557687c673f3a2d974868acc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 9 Dec 2019 16:40:16 +0100 Subject: [PATCH 036/130] [apps/ion/exam_mode] Store the exam mode activation in the flash This way, it is not cleared by a reset --- apps/apps_container.cpp | 13 +++- apps/apps_container.h | 1 + apps/exam_pop_up_controller.cpp | 13 +--- apps/global_preferences.cpp | 16 ++++ apps/global_preferences.h | 19 +++-- .../sub_menu/exam_mode_controller.cpp | 2 +- apps/title_bar_view.cpp | 2 +- ion/include/ion.h | 1 + ion/include/ion/exam_mode.h | 13 ++++ ion/src/blackbox/Makefile | 1 + ion/src/device/n0100/flash.ld | 25 +++++-- ion/src/device/shared/drivers/Makefile | 1 + ion/src/device/shared/drivers/exam_mode.cpp | 73 +++++++++++++++++++ ion/src/shared/dummy/exam_mode.cpp | 14 ++++ ion/src/simulator/Makefile | 1 + 15 files changed, 166 insertions(+), 29 deletions(-) create mode 100644 ion/include/ion/exam_mode.h create mode 100644 ion/src/device/shared/drivers/exam_mode.cpp create mode 100644 ion/src/shared/dummy/exam_mode.cpp diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index adb666104..4e268205c 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -168,7 +168,7 @@ bool AppsContainer::processEvent(Ion::Events::Event event) { // Warning: if the window is dirtied, you need to call window()->redraw() if (event == Ion::Events::USBPlug) { if (Ion::USB::isPlugged()) { - if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { + if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { displayExamModePopUp(false); window()->redraw(); } else { @@ -208,6 +208,9 @@ bool AppsContainer::switchTo(App::Snapshot * snapshot) { void AppsContainer::run() { window()->setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height)); + if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { + activateExamMode(); + } refreshPreferences(); /* ExceptionCheckpoint stores the value of the stack pointer when setjump is @@ -283,7 +286,7 @@ void AppsContainer::shutdownDueToLowBattery() { } while (Ion::Battery::level() == Ion::Battery::Charge::EMPTY) { Ion::Backlight::setBrightness(0); - if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Deactivate) { + if (!GlobalPreferences::sharedGlobalPreferences()->examMode()) { /* Unless the LED is lit up for the exam mode, switch off the LED. IF the * low battery event happened during the Power-On Self-Test, a LED might * have stayed lit up. */ @@ -316,6 +319,12 @@ void AppsContainer::redrawWindow() { m_window.redraw(); } +void AppsContainer::activateExamMode() { + reset(); + Ion::LED::setColor(KDColorRed); + Ion::LED::setBlinking(1000, 0.1f); +} + void AppsContainer::examDeactivatingPopUpIsDismissed() { if (Ion::USB::isPlugged()) { Ion::USB::enable(); diff --git a/apps/apps_container.h b/apps/apps_container.h index bd0c8fb2c..834d7e336 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -46,6 +46,7 @@ public: void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus); OnBoarding::PopUpController * promptController(); void redrawWindow(); + void activateExamMode(); // Exam pop-up controller delegate void examDeactivatingPopUpIsDismissed() override; // Ion::StorageDelegate diff --git a/apps/exam_pop_up_controller.cpp b/apps/exam_pop_up_controller.cpp index 47bbe6007..38d6d90ce 100644 --- a/apps/exam_pop_up_controller.cpp +++ b/apps/exam_pop_up_controller.cpp @@ -13,10 +13,8 @@ ExamPopUpController::ExamPopUpController(ExamPopUpControllerDelegate * delegate) } void ExamPopUpController::setActivatingExamMode(bool activatingExamMode) { - if (m_isActivatingExamMode != activatingExamMode) { - m_isActivatingExamMode = activatingExamMode; - m_contentView.setMessages(activatingExamMode); - } + m_isActivatingExamMode = activatingExamMode; + m_contentView.setMessages(activatingExamMode); } View * ExamPopUpController::view() { @@ -52,13 +50,10 @@ ExamPopUpController::ContentView::ContentView(Responder * parentResponder) : }, parentResponder), KDFont::SmallFont), m_okButton(parentResponder, I18n::Message::Ok, Invocation([](void * context, void * sender) { ExamPopUpController * controller = (ExamPopUpController *)context; - GlobalPreferences::ExamMode nextExamMode = controller->isActivatingExamMode() ? GlobalPreferences::ExamMode::Activate : GlobalPreferences::ExamMode::Deactivate; - GlobalPreferences::sharedGlobalPreferences()->setExamMode(nextExamMode); + GlobalPreferences::sharedGlobalPreferences()->setExamMode(controller->isActivatingExamMode()); AppsContainer * container = AppsContainer::sharedAppsContainer(); if (controller->isActivatingExamMode()) { - container->reset(); - Ion::LED::setColor(KDColorRed); - Ion::LED::setBlinking(1000, 0.1f); + container->activateExamMode(); } else { Ion::LED::setColor(KDColorBlack); Ion::LED::updateColorWithPlugAndCharge(); diff --git a/apps/global_preferences.cpp b/apps/global_preferences.cpp index f509b7a65..b78102ba9 100644 --- a/apps/global_preferences.cpp +++ b/apps/global_preferences.cpp @@ -5,6 +5,22 @@ GlobalPreferences * GlobalPreferences::sharedGlobalPreferences() { return &globalPreferences; } +bool GlobalPreferences::examMode() const { + if (m_examMode == ExamMode::Unknown) { + m_examMode = (ExamMode)Ion::ExamMode::FetchExamMode(); + } + assert((int)m_examMode == 0 || (int)m_examMode == 1); + return (bool)m_examMode; +} + +void GlobalPreferences::setExamMode(bool activateExamMode) { + if (((bool)examMode()) == activateExamMode) { + return; + } + Ion::ExamMode::ToggleExamMode(); + m_examMode = (ExamMode)activateExamMode; +} + void GlobalPreferences::setBrightnessLevel(int brightnessLevel) { if (m_brightnessLevel != brightnessLevel) { brightnessLevel = brightnessLevel < 0 ? 0 : brightnessLevel; diff --git a/apps/global_preferences.h b/apps/global_preferences.h index 88a57109f..f9fe8e044 100644 --- a/apps/global_preferences.h +++ b/apps/global_preferences.h @@ -5,15 +5,11 @@ class GlobalPreferences { public: - enum class ExamMode { - Activate, - Deactivate - }; static GlobalPreferences * sharedGlobalPreferences(); I18n::Language language() const { return m_language; } void setLanguage(I18n::Language language) { m_language = language; } - ExamMode examMode() const { return m_examMode; } - void setExamMode(ExamMode examMode) { m_examMode = examMode; } + bool examMode() const; + void setExamMode(bool activateExamMode); bool showPopUp() const { return m_showPopUp; } void setShowPopUp(bool showPopUp) { m_showPopUp = showPopUp; } int brightnessLevel() const { return m_brightnessLevel; } @@ -22,11 +18,18 @@ public: private: GlobalPreferences() : m_language(I18n::Language::EN), - m_examMode(ExamMode::Deactivate), + m_examMode(ExamMode::Unknown), m_showPopUp(true), m_brightnessLevel(Ion::Backlight::MaxBrightness) {} I18n::Language m_language; - ExamMode m_examMode; + enum class ExamMode : uint8_t { + Deactivate = 0, + Activate = 1, + Unknown = 2 + }; + static_assert((uint8_t)GlobalPreferences::ExamMode::Deactivate == 0, "GlobalPreferences::setExamMode and examMode() are not right"); + static_assert((uint8_t)GlobalPreferences::ExamMode::Activate == 1, "GlobalPreferences::setExamMode and examMode() are not right"); + mutable ExamMode m_examMode; bool m_showPopUp; int m_brightnessLevel; }; diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index def1a10d3..1590f04c4 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -39,7 +39,7 @@ int ExamModeController::reusableCellCount(int type) { void ExamModeController::willDisplayCellForIndex(HighlightCell * cell, int index) { GenericSubController::willDisplayCellForIndex(cell, index); - if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { + if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { MessageTableCell * myCell = (MessageTableCell *)cell; myCell->setMessage(I18n::Message::ExamModeActive); } diff --git a/apps/title_bar_view.cpp b/apps/title_bar_view.cpp index 56c701077..fc5c23992 100644 --- a/apps/title_bar_view.cpp +++ b/apps/title_bar_view.cpp @@ -71,7 +71,7 @@ void TitleBarView::layoutSubviews() { m_preferenceView.setFrame(KDRect(Metric::TitleBarExternHorizontalMargin, 0, m_preferenceView.minimalSizeForOptimalDisplay().width(), bounds().height())); KDSize batterySize = m_batteryView.minimalSizeForOptimalDisplay(); m_batteryView.setFrame(KDRect(bounds().width() - batterySize.width() - Metric::TitleBarExternHorizontalMargin, (bounds().height()- batterySize.height())/2, batterySize)); - if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { + if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { m_examModeIconView.setFrame(KDRect(k_examIconMargin, (bounds().height() - k_examIconHeight)/2, k_examIconWidth, k_examIconHeight)); } else { m_examModeIconView.setFrame(KDRectZero); diff --git a/ion/include/ion.h b/ion/include/ion.h index f4686a692..dbfae79c1 100644 --- a/ion/include/ion.h +++ b/ion/include/ion.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include diff --git a/ion/include/ion/exam_mode.h b/ion/include/ion/exam_mode.h new file mode 100644 index 000000000..ef0c5c92b --- /dev/null +++ b/ion/include/ion/exam_mode.h @@ -0,0 +1,13 @@ +#ifndef ION_EXAM_MODE_H +#define ION_EXAM_MODE_H + +namespace Ion { +namespace ExamMode { + +bool FetchExamMode(); +void ToggleExamMode(); + +} +} + +#endif diff --git a/ion/src/blackbox/Makefile b/ion/src/blackbox/Makefile index 2ac36a1aa..a47729da9 100644 --- a/ion/src/blackbox/Makefile +++ b/ion/src/blackbox/Makefile @@ -17,6 +17,7 @@ ion_src += $(addprefix ion/src/shared/, \ dummy/battery.cpp \ dummy/display.cpp \ dummy/events_modifier.cpp \ + dummy/exam_mode.cpp \ dummy/fcc_id.cpp \ dummy/led.cpp \ dummy/keyboard.cpp \ diff --git a/ion/src/device/n0100/flash.ld b/ion/src/device/n0100/flash.ld index db1fc8d2a..6c449809a 100644 --- a/ion/src/device/n0100/flash.ld +++ b/ion/src/device/n0100/flash.ld @@ -9,14 +9,16 @@ * This will let us use shortcuts such as ">FLASH" to ask for a given section to * be stored in Flash. */ MEMORY { - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + FLASH_FIRST_SECTOR (rx) : ORIGIN = 0x08000000, LENGTH = 16K + FLASH_SECOND_SECTOR (rx) : ORIGIN = (0x08000000 + 16K), LENGTH = 16K + FLASH_LAST_SECTORS (rx) : ORIGIN = (0x08000000 + 32K), LENGTH = (1024K - 32K) SRAM (rw) : ORIGIN = 0x20000000, LENGTH = 256K } STACK_SIZE = 32K; SECTIONS { - .isr_vector_table ORIGIN(FLASH) : { + .isr_vector_table ORIGIN(FLASH_FIRST_SECTOR) : { /* When booting, the STM32F412 fetches the content of address 0x0, and * extracts from it various key infos: the initial value of the PC register * (program counter), the initial value of the stack pointer, and various @@ -31,30 +33,37 @@ SECTIONS { * convenient: using function pointers, we can easily point to the service * routine for each interrupt. */ KEEP(*(.isr_vector_table)) - } >FLASH + } >FLASH_FIRST_SECTOR .header : { KEEP(*(.header)) - } >FLASH + } >FLASH_FIRST_SECTOR + + .exam_mode_persistence ORIGIN(FLASH_SECOND_SECTOR): { + _exam_mode_persistence_start = .; + /* Note: We don't increment "." here, we set it. */ + . = (ORIGIN(FLASH_SECOND_SECTOR) + LENGTH(FLASH_SECOND_SECTOR)); + _exam_mode_persistence_end = .; + } >FLASH_SECOND_SECTOR .text : { . = ALIGN(4); *(.text) *(.text.*) - } >FLASH + } >FLASH_LAST_SECTORS .init_array : { . = ALIGN(4); _init_array_start = .; KEEP (*(.init_array*)) _init_array_end = .; - } >FLASH + } >FLASH_LAST_SECTORS .rodata : { . = ALIGN(4); *(.rodata) *(.rodata.*) - } >FLASH + } >FLASH_LAST_SECTORS .data : { /* The data section is written to Flash but linked as if it were in RAM. @@ -75,7 +84,7 @@ SECTIONS { *(.data) *(.data.*) _data_section_end_ram = .; - } >SRAM AT> FLASH + } >SRAM AT> FLASH_LAST_SECTORS .bss : { /* The bss section contains data for all uninitialized variables diff --git a/ion/src/device/shared/drivers/Makefile b/ion/src/device/shared/drivers/Makefile index 6def5933e..4d21b6382 100644 --- a/ion/src/device/shared/drivers/Makefile +++ b/ion/src/device/shared/drivers/Makefile @@ -6,6 +6,7 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \ crc32.cpp \ display.cpp \ events_keyboard_platform.cpp \ + exam_mode.cpp \ external_flash.cpp \ flash.cpp \ keyboard.cpp \ diff --git a/ion/src/device/shared/drivers/exam_mode.cpp b/ion/src/device/shared/drivers/exam_mode.cpp new file mode 100644 index 000000000..9d9caa322 --- /dev/null +++ b/ion/src/device/shared/drivers/exam_mode.cpp @@ -0,0 +1,73 @@ +#include +#include "flash.h" + +namespace Ion { +namespace ExamMode { + +extern "C" { + extern char _exam_mode_persistence_start; + extern char _exam_mode_persistence_end; +} + +/* The exam mode is written in flash so that it is resilient to resets. + * We erase the dedicated flash sector (all bits written to 1) and, upon + * activating or deactivating the exam mode we write one bit to 0. To determine + * if we are in exam mode, we count the number of leading 0 bits. If it is even, + * the exam mode is deactivated, if it is odd, the exam mode is activated. */ + +/* significantExamModeAddress returns the first uint32_t * in the exam mode + * flash sector that does not point to 0. If this flash sector has only 0s, it + * is erased (to 1) and significantExamModeAddress returns the start of the + * sector. */ + +uint32_t * SignificantExamModeAddress() { + uint32_t * persitence_start = (uint32_t *)&_exam_mode_persistence_start; + uint32_t * persitence_end = (uint32_t *)&_exam_mode_persistence_end; + while (persitence_start < persitence_end && *persitence_start == 0x0) { + // Skip even number of zero bits + persitence_start++; + } + if (persitence_start == persitence_end) { + assert(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_persistence_start) >= 0); + Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_persistence_start)); + return (uint32_t *)&_exam_mode_persistence_start; + } + return persitence_start; +} + +size_t firstOneBit(int i, size_t size) { + int minShift = 0; + int maxShift = size; + while (maxShift > minShift+1) { + int shift = (minShift + maxShift)/2; + int shifted = i >> shift; + if (shifted == 0) { + maxShift = shift; + } else { + minShift = shift; + } + } + return maxShift; +} + +bool FetchExamMode() { + uint32_t * readingAddress = SignificantExamModeAddress(); + size_t numberOfLeading0 = 32 - firstOneBit(*readingAddress, 32); + return numberOfLeading0 % 2 == 1; +} + +void ToggleExamMode() { + uint32_t * writingAddress = SignificantExamModeAddress(); + assert(*writingAddress != 0); + // Compute the new value with one bit switched + uint8_t numberOfLeadingZeroes = 32 - firstOneBit(*writingAddress, 32); + /* When writing in flash, we can only switch a 1 to a 0. If we want to switch + * the fifth bit in a byte, we can thus write "11110111". */ + uint32_t newValue = ~(1 << (31 - numberOfLeadingZeroes)); + + // Write the value in flash + Ion::Device::Flash::WriteMemory((uint8_t *)writingAddress, (uint8_t *)&newValue, sizeof(uint32_t)); +} + +} +} diff --git a/ion/src/shared/dummy/exam_mode.cpp b/ion/src/shared/dummy/exam_mode.cpp new file mode 100644 index 000000000..02d78e591 --- /dev/null +++ b/ion/src/shared/dummy/exam_mode.cpp @@ -0,0 +1,14 @@ +#include + +namespace Ion { +namespace ExamMode { + +bool FetchExamMode() { + return false; +} + +void ToggleExamMode() { +} + +} +} diff --git a/ion/src/simulator/Makefile b/ion/src/simulator/Makefile index e7511833d..74ae93666 100644 --- a/ion/src/simulator/Makefile +++ b/ion/src/simulator/Makefile @@ -10,6 +10,7 @@ ion_src += $(addprefix ion/src/shared/, \ dummy/backlight.cpp \ dummy/battery.cpp \ dummy/display.cpp \ + dummy/exam_mode.cpp \ dummy/fcc_id.cpp \ dummy/led.cpp \ dummy/serial_number.cpp \ From 762f67d99605e6fb05cb2df7e15bdced9d33e7a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Dec 2019 11:40:54 +0100 Subject: [PATCH 037/130] [ion/device] Flash driver handles Internal and external flash --- .../config/{flash.h => internal_flash.h} | 6 +- ion/src/device/n0100/drivers/reset.cpp | 4 +- .../config/{flash.h => internal_flash.h} | 6 +- ion/src/device/shared/drivers/Makefile | 1 + ion/src/device/shared/drivers/exam_mode.cpp | 1 + ion/src/device/shared/drivers/flash.cpp | 258 ++---------------- ion/src/device/shared/drivers/flash.h | 13 +- .../device/shared/drivers/internal_flash.cpp | 256 +++++++++++++++++ .../device/shared/drivers/internal_flash.h | 27 ++ ion/src/device/shared/usb/Makefile | 1 + ion/src/device/shared/usb/dfu_interface.cpp | 31 +-- ion/src/device/shared/usb/stack/device.cpp | 4 +- 12 files changed, 337 insertions(+), 271 deletions(-) rename ion/src/device/n0100/drivers/config/{flash.h => internal_flash.h} (79%) rename ion/src/device/n0110/drivers/config/{flash.h => internal_flash.h} (75%) create mode 100644 ion/src/device/shared/drivers/internal_flash.cpp create mode 100644 ion/src/device/shared/drivers/internal_flash.h diff --git a/ion/src/device/n0100/drivers/config/flash.h b/ion/src/device/n0100/drivers/config/internal_flash.h similarity index 79% rename from ion/src/device/n0100/drivers/config/flash.h rename to ion/src/device/n0100/drivers/config/internal_flash.h index aa23e3135..002ed92ce 100644 --- a/ion/src/device/n0100/drivers/config/flash.h +++ b/ion/src/device/n0100/drivers/config/internal_flash.h @@ -1,11 +1,11 @@ -#ifndef ION_DEVICE_N0100_CONFIG_FLASH_H -#define ION_DEVICE_N0100_CONFIG_FLASH_H +#ifndef ION_DEVICE_N0100_CONFIG_INTERNAL_FLASH_H +#define ION_DEVICE_N0100_CONFIG_INTERNAL_FLASH_H #include namespace Ion { namespace Device { -namespace Flash { +namespace InternalFlash { namespace Config { constexpr static uint32_t StartAddress = 0x08000000; diff --git a/ion/src/device/n0100/drivers/reset.cpp b/ion/src/device/n0100/drivers/reset.cpp index c64afb379..9bcc93695 100644 --- a/ion/src/device/n0100/drivers/reset.cpp +++ b/ion/src/device/n0100/drivers/reset.cpp @@ -1,5 +1,5 @@ #include -#include "config/flash.h" +#include "config/internal_flash.h" namespace Ion { namespace Device { @@ -10,7 +10,7 @@ void coreWhilePlugged() { * might be plugged in. Doing a full core reset would result in the device * entering the ST DFU bootloader. By performing a jump-reset, we mimic the * core reset without entering ST bootloader.*/ - jump(Flash::Config::StartAddress); + jump(InternalFlash::Config::StartAddress); } } diff --git a/ion/src/device/n0110/drivers/config/flash.h b/ion/src/device/n0110/drivers/config/internal_flash.h similarity index 75% rename from ion/src/device/n0110/drivers/config/flash.h rename to ion/src/device/n0110/drivers/config/internal_flash.h index 2c50a8fcf..fc494c00d 100644 --- a/ion/src/device/n0110/drivers/config/flash.h +++ b/ion/src/device/n0110/drivers/config/internal_flash.h @@ -1,11 +1,11 @@ -#ifndef ION_DEVICE_N0110_CONFIG_FLASH_H -#define ION_DEVICE_N0110_CONFIG_FLASH_H +#ifndef ION_DEVICE_N0110_CONFIG_INTERNAL_FLASH_H +#define ION_DEVICE_N0110_CONFIG_INTERNAL_FLASH_H #include namespace Ion { namespace Device { -namespace Flash { +namespace InternalFlash { namespace Config { constexpr static uint32_t StartAddress = 0x08000000; diff --git a/ion/src/device/shared/drivers/Makefile b/ion/src/device/shared/drivers/Makefile index 4d21b6382..2b3b71efb 100644 --- a/ion/src/device/shared/drivers/Makefile +++ b/ion/src/device/shared/drivers/Makefile @@ -9,6 +9,7 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \ exam_mode.cpp \ external_flash.cpp \ flash.cpp \ + internal_flash.cpp \ keyboard.cpp \ led.cpp \ power.cpp\ diff --git a/ion/src/device/shared/drivers/exam_mode.cpp b/ion/src/device/shared/drivers/exam_mode.cpp index 9d9caa322..3096ad526 100644 --- a/ion/src/device/shared/drivers/exam_mode.cpp +++ b/ion/src/device/shared/drivers/exam_mode.cpp @@ -1,5 +1,6 @@ #include #include "flash.h" +#include namespace Ion { namespace ExamMode { diff --git a/ion/src/device/shared/drivers/flash.cpp b/ion/src/device/shared/drivers/flash.cpp index 2ae24eb97..6f569cd89 100644 --- a/ion/src/device/shared/drivers/flash.cpp +++ b/ion/src/device/shared/drivers/flash.cpp @@ -1,253 +1,53 @@ #include "flash.h" -#include -#include +#include "external_flash.h" +#include "internal_flash.h" +#include +#include #include namespace Ion { namespace Device { namespace Flash { -using namespace Regs; - -static inline void wait() { - /* Issue a DSB instruction to guarantee the completion of a previous access - * to FLASH_CR register or data write operation. (RM0431) */ - Cache::dsb(); - // Wait for pending Flash operations to complete - while (FLASH.SR()->getBSY()) { - } -} - -static void open() { - // Unlock the Flash configuration register if needed - if (FLASH.CR()->getLOCK()) { - FLASH.KEYR()->set(0x45670123); - FLASH.KEYR()->set(0xCDEF89AB); - } - assert(FLASH.CR()->getLOCK() == false); - - // Set the programming parallelism - FLASH.CR()->setPSIZE(MemoryAccessWidth); -} - -static void close() { - // Clear error flags - class FLASH::SR sr(0); - // Error flags are cleared by writing 1 - sr.setERSERR(true); - sr.setPGPERR(true); - sr.setPGAERR(true); - sr.setWRPERR(true); - sr.setEOP(true); - FLASH.SR()->set(sr); - - // Lock the Flash configuration register - assert(!FLASH.CR()->getMER()); - assert(!FLASH.CR()->getSER()); - assert(!FLASH.CR()->getPG()); - FLASH.CR()->setLOCK(true); - - // Purge Data and instruction cache -#if REGS_FLASH_CONFIG_ART - if (FLASH.ACR()->getARTEN()) { - FLASH.ACR()->setARTEN(false); - FLASH.ACR()->setARTRST(true); - FLASH.ACR()->setARTRST(false); - FLASH.ACR()->setARTEN(true); - } -#else - if (FLASH.ACR()->getDCEN()) { - FLASH.ACR()->setDCEN(false); - FLASH.ACR()->setDCRST(true); - FLASH.ACR()->setDCRST(false); - FLASH.ACR()->setDCEN(true); - } - if (FLASH.ACR()->getICEN()) { - FLASH.ACR()->setICEN(false); - FLASH.ACR()->setICRST(true); - FLASH.ACR()->setICRST(false); - FLASH.ACR()->setICEN(true); - } -#endif -} - -// Compile-time log2 -static inline constexpr size_t clog2(size_t input) { - return (input == 1) ? 0 : clog2(input/2)+1; -} - -// Align a pointer to a given type's boundaries -// Returns a value that is lower or equal to input -template -static inline T * align(void * input) { - size_t k = clog2(sizeof(T)); - return reinterpret_cast(reinterpret_cast(input) & ~((1< -static inline T eat(void * ptr) { - T * pointer = *reinterpret_cast(ptr); - T result = *pointer; - *reinterpret_cast(ptr) = pointer+1; - return result; -} - -static inline ptrdiff_t byte_offset(void * p1, void * p2) { - return reinterpret_cast(p2) - reinterpret_cast(p1); -} - -template -static inline T min(T i, T j) { - return (i| - * |-- HeaderDelta ->| - */ - - MemoryAccessType * alignedDestination = align(destination); - ptrdiff_t headerDelta = byte_offset(alignedDestination, destination); - assert(headerDelta >= 0 && headerDelta < static_cast(sizeof(MemoryAccessType))); - - if (headerDelta > 0) { - // At this point, alignedDestination < destination - // We'll then retrieve the current value at alignedDestination, fill it with - // bytes from source, and write it back at alignedDestination. - - // First, retrieve the current value at alignedDestination - MemoryAccessType header = *alignedDestination; - - // Then copy headerLength bytes from source and put them in the header - uint8_t * headerStart = reinterpret_cast(&header); - // Here's where source data shall start being copied in the header - uint8_t * headerDataStart = headerStart + headerDelta; - // And here's where it should end - uint8_t * headerDataEnd = min( - headerStart + sizeof(MemoryAccessType), // Either at the end of the header - headerDataStart + length // or whenever src runs out of data - ); - for (uint8_t * h = headerDataStart; h(&source); - } - - // Then eventually write the header back into the aligned destination - *alignedDestination++ = header; - wait(); - } - - /* Step 2 - Copy the bulk of the data - * At this point, we can use aligned MemoryAccessType pointers. */ - - MemoryAccessType * lastAlignedDestination = align(destination + length); - while (alignedDestination < lastAlignedDestination) { - *alignedDestination++ = eat(&source); - wait(); - } - - /* Step 3 - Copy a footer if needed - * Some unaligned data can be pending at the end. Let's take care of it like - * we did for the header. - * - * _alignedDst _Destination+length - * | | - * --+--------+--------+--------+--------+--------+--------+-- - * | || | | | || | - *---+--------+--------+--------+--------+--------+--------+-- - * |<------------ Footer ------------->| - * |- footerLength ->| - */ - - ptrdiff_t footerLength = byte_offset(alignedDestination, destination + length); - assert(footerLength < static_cast(sizeof(MemoryAccessType))); - if (footerLength > 0) { - assert(alignedDestination == lastAlignedDestination); - - // First, retrieve the current value at alignedDestination - MemoryAccessType footer = *alignedDestination; - - /* Then copy footerLength bytes from source and put them at the beginning of - * the footer */ - uint8_t * footerPointer = reinterpret_cast(&footer); - for (ptrdiff_t i=0; i(&source); - } - - // Then eventually write the footer back into the aligned destination - *alignedDestination = footer; - wait(); - } +int TotalNumberOfSectors() { + return InternalFlash::Config::NumberOfSectors + ExternalFlash::Config::NumberOfSectors; } int SectorAtAddress(uint32_t address) { - for (int i = 0; i < Config::NumberOfSectors; i++) { - if (address >= Config::SectorAddresses[i] && address < Config::SectorAddresses[i+1]) { - return i; - } + if (address >= InternalFlash::Config::StartAddress + && address <= InternalFlash::Config::EndAddress) + { + return InternalFlash::SectorAtAddress(address); + } + if (address >= ExternalFlash::Config::StartAddress + && address <= ExternalFlash::Config::EndAddress) + { + return InternalFlash::Config::NumberOfSectors + ExternalFlash::SectorAtAddress(address - ExternalFlash::Config::StartAddress); } return -1; } void MassErase() { - open(); - FLASH.CR()->setMER(true); - FLASH.CR()->setSTRT(true); - wait(); - FLASH.CR()->setMER(false); - close(); + InternalFlash::MassErase(); + ExternalFlash::MassErase(); } void EraseSector(int i) { - assert(i >= 0 && i < Config::NumberOfSectors); - open(); - FLASH.CR()->setSNB(i); - FLASH.CR()->setSER(true); - FLASH.CR()->setSTRT(true); - wait(); - FLASH.CR()->setSNB(0); - FLASH.CR()->setSER(false); - close(); + assert(i >= 0 && i < TotalNumberOfSectors()); + if (i < InternalFlash::Config::NumberOfSectors) { + InternalFlash::EraseSector(i); + } else { + ExternalFlash::EraseSector(i - InternalFlash::Config::NumberOfSectors); + } } void WriteMemory(uint8_t * destination, uint8_t * source, size_t length) { - open(); - FLASH.CR()->setPG(true); - flash_memcpy(destination, source, length); - FLASH.CR()->setPG(false); - close(); + assert(SectorAtAddress((uint32_t)destination) >= 0); + if (SectorAtAddress((uint32_t)destination) < InternalFlash::Config::NumberOfSectors) { + InternalFlash::WriteMemory(destination, source, length); + } else { + ExternalFlash::WriteMemory(destination - ExternalFlash::Config::StartAddress, source, length); + } } } diff --git a/ion/src/device/shared/drivers/flash.h b/ion/src/device/shared/drivers/flash.h index ebb3ffc4f..4e61b1fa9 100644 --- a/ion/src/device/shared/drivers/flash.h +++ b/ion/src/device/shared/drivers/flash.h @@ -2,24 +2,19 @@ #define ION_DEVICE_SHARED_FLASH_H #include -#include +#include namespace Ion { namespace Device { namespace Flash { -void MassErase(); - +int TotalNumberOfSectors(); int SectorAtAddress(uint32_t address); + +void MassErase(); void EraseSector(int i); - void WriteMemory(uint8_t * destination, uint8_t * source, size_t length); -/* The Device is powered by a 2.8V LDO. This allows us to perform writes to the - * Flash 32 bits at once. */ -constexpr Regs::FLASH::CR::PSIZE MemoryAccessWidth = Regs::FLASH::CR::PSIZE::X32; -typedef uint32_t MemoryAccessType; - } } } diff --git a/ion/src/device/shared/drivers/internal_flash.cpp b/ion/src/device/shared/drivers/internal_flash.cpp new file mode 100644 index 000000000..9ff5e1432 --- /dev/null +++ b/ion/src/device/shared/drivers/internal_flash.cpp @@ -0,0 +1,256 @@ +#include "internal_flash.h" +#include +#include +#include + +namespace Ion { +namespace Device { +namespace InternalFlash { + +using namespace Regs; + +static inline void wait() { + /* Issue a DSB instruction to guarantee the completion of a previous access + * to FLASH_CR register or data write operation. (RM0431) */ + Cache::dsb(); + // Wait for pending Flash operations to complete + while (FLASH.SR()->getBSY()) { + } +} + +static void open() { + // Unlock the Flash configuration register if needed + if (FLASH.CR()->getLOCK()) { + FLASH.KEYR()->set(0x45670123); + FLASH.KEYR()->set(0xCDEF89AB); + } + assert(FLASH.CR()->getLOCK() == false); + + // Set the programming parallelism + FLASH.CR()->setPSIZE(MemoryAccessWidth); +} + +static void close() { + // Clear error flags + class FLASH::SR sr(0); + // Error flags are cleared by writing 1 + sr.setERSERR(true); + sr.setPGPERR(true); + sr.setPGAERR(true); + sr.setWRPERR(true); + sr.setEOP(true); + FLASH.SR()->set(sr); + + // Lock the Flash configuration register + assert(!FLASH.CR()->getMER()); + assert(!FLASH.CR()->getSER()); + assert(!FLASH.CR()->getPG()); + FLASH.CR()->setLOCK(true); + + // Purge Data and instruction cache +#if REGS_FLASH_CONFIG_ART + if (FLASH.ACR()->getARTEN()) { + FLASH.ACR()->setARTEN(false); + FLASH.ACR()->setARTRST(true); + FLASH.ACR()->setARTRST(false); + FLASH.ACR()->setARTEN(true); + } +#else + if (FLASH.ACR()->getDCEN()) { + FLASH.ACR()->setDCEN(false); + FLASH.ACR()->setDCRST(true); + FLASH.ACR()->setDCRST(false); + FLASH.ACR()->setDCEN(true); + } + if (FLASH.ACR()->getICEN()) { + FLASH.ACR()->setICEN(false); + FLASH.ACR()->setICRST(true); + FLASH.ACR()->setICRST(false); + FLASH.ACR()->setICEN(true); + } +#endif +} + +// Compile-time log2 +static inline constexpr size_t clog2(size_t input) { + return (input == 1) ? 0 : clog2(input/2)+1; +} + +// Align a pointer to a given type's boundaries +// Returns a value that is lower or equal to input +template +static inline T * align(void * input) { + size_t k = clog2(sizeof(T)); + return reinterpret_cast(reinterpret_cast(input) & ~((1< +static inline T eat(void * ptr) { + T * pointer = *reinterpret_cast(ptr); + T result = *pointer; + *reinterpret_cast(ptr) = pointer+1; + return result; +} + +static inline ptrdiff_t byte_offset(void * p1, void * p2) { + return reinterpret_cast(p2) - reinterpret_cast(p1); +} + +template +static inline T min(T i, T j) { + return (i| + * |-- HeaderDelta ->| + */ + + MemoryAccessType * alignedDestination = align(destination); + ptrdiff_t headerDelta = byte_offset(alignedDestination, destination); + assert(headerDelta >= 0 && headerDelta < static_cast(sizeof(MemoryAccessType))); + + if (headerDelta > 0) { + // At this point, alignedDestination < destination + // We'll then retrieve the current value at alignedDestination, fill it with + // bytes from source, and write it back at alignedDestination. + + // First, retrieve the current value at alignedDestination + MemoryAccessType header = *alignedDestination; + + // Then copy headerLength bytes from source and put them in the header + uint8_t * headerStart = reinterpret_cast(&header); + // Here's where source data shall start being copied in the header + uint8_t * headerDataStart = headerStart + headerDelta; + // And here's where it should end + uint8_t * headerDataEnd = min( + headerStart + sizeof(MemoryAccessType), // Either at the end of the header + headerDataStart + length // or whenever src runs out of data + ); + for (uint8_t * h = headerDataStart; h(&source); + } + + // Then eventually write the header back into the aligned destination + *alignedDestination++ = header; + wait(); + } + + /* Step 2 - Copy the bulk of the data + * At this point, we can use aligned MemoryAccessType pointers. */ + + MemoryAccessType * lastAlignedDestination = align(destination + length); + while (alignedDestination < lastAlignedDestination) { + *alignedDestination++ = eat(&source); + wait(); + } + + /* Step 3 - Copy a footer if needed + * Some unaligned data can be pending at the end. Let's take care of it like + * we did for the header. + * + * _alignedDst _Destination+length + * | | + * --+--------+--------+--------+--------+--------+--------+-- + * | || | | | || | + *---+--------+--------+--------+--------+--------+--------+-- + * |<------------ Footer ------------->| + * |- footerLength ->| + */ + + ptrdiff_t footerLength = byte_offset(alignedDestination, destination + length); + assert(footerLength < static_cast(sizeof(MemoryAccessType))); + if (footerLength > 0) { + assert(alignedDestination == lastAlignedDestination); + + // First, retrieve the current value at alignedDestination + MemoryAccessType footer = *alignedDestination; + + /* Then copy footerLength bytes from source and put them at the beginning of + * the footer */ + uint8_t * footerPointer = reinterpret_cast(&footer); + for (ptrdiff_t i=0; i(&source); + } + + // Then eventually write the footer back into the aligned destination + *alignedDestination = footer; + wait(); + } +} + +int SectorAtAddress(uint32_t address) { + for (int i = 0; i < Config::NumberOfSectors; i++) { + if (address >= Config::SectorAddresses[i] && address < Config::SectorAddresses[i+1]) { + return i; + } + } + return -1; +} + +void MassErase() { + open(); + FLASH.CR()->setMER(true); + FLASH.CR()->setSTRT(true); + wait(); + FLASH.CR()->setMER(false); + close(); +} + + +void EraseSector(int i) { + assert(i >= 0 && i < Config::NumberOfSectors); + open(); + FLASH.CR()->setSNB(i); + FLASH.CR()->setSER(true); + FLASH.CR()->setSTRT(true); + wait(); + FLASH.CR()->setSNB(0); + FLASH.CR()->setSER(false); + close(); +} + +void WriteMemory(uint8_t * destination, uint8_t * source, size_t length) { + open(); + FLASH.CR()->setPG(true); + flash_memcpy(destination, source, length); + FLASH.CR()->setPG(false); + close(); +} + +} +} +} diff --git a/ion/src/device/shared/drivers/internal_flash.h b/ion/src/device/shared/drivers/internal_flash.h new file mode 100644 index 000000000..befe83b3e --- /dev/null +++ b/ion/src/device/shared/drivers/internal_flash.h @@ -0,0 +1,27 @@ +#ifndef ION_DEVICE_SHARED_INTERNAL_FLASH_H +#define ION_DEVICE_SHARED_INTERNAL_FLASH_H + +#include +#include + +namespace Ion { +namespace Device { +namespace InternalFlash { + +void MassErase(); + +int SectorAtAddress(uint32_t address); +void EraseSector(int i); + +void WriteMemory(uint8_t * destination, uint8_t * source, size_t length); + +/* The Device is powered by a 2.8V LDO. This allows us to perform writes to the + * Flash 32 bits at once. */ +constexpr Regs::FLASH::CR::PSIZE MemoryAccessWidth = Regs::FLASH::CR::PSIZE::X32; +typedef uint32_t MemoryAccessType; + +} +} +} + +#endif diff --git a/ion/src/device/shared/usb/Makefile b/ion/src/device/shared/usb/Makefile index cf2f0cbf7..df9d1f6c2 100644 --- a/ion/src/device/shared/usb/Makefile +++ b/ion/src/device/shared/usb/Makefile @@ -55,6 +55,7 @@ dfu_src += $(addprefix ion/src/device/shared/drivers/, \ events_keyboard_platform.cpp \ external_flash.cpp \ flash.cpp \ + internal_flash.cpp \ keyboard.cpp \ led.cpp \ power.cpp\ diff --git a/ion/src/device/shared/usb/dfu_interface.cpp b/ion/src/device/shared/usb/dfu_interface.cpp index c221dae35..5316f7b46 100644 --- a/ion/src/device/shared/usb/dfu_interface.cpp +++ b/ion/src/device/shared/usb/dfu_interface.cpp @@ -1,18 +1,12 @@ #include "dfu_interface.h" -#include #include #include -#include -#include -#include #include namespace Ion { namespace Device { namespace USB { -using namespace Ion::Device::Regs; - static inline uint32_t minUint32T(uint32_t x, uint32_t y) { return x < y ? x : y; } void DFUInterface::StatusData::push(Channel * c) const { @@ -188,7 +182,7 @@ void DFUInterface::eraseCommand(uint8_t * transferBuffer, uint16_t transferBuffe if (transferBufferLength == 1) { // Mass erase - m_erasePage = Flash::Config::NumberOfSectors + ExternalFlash::Config::NumberOfSectors; + m_erasePage = Flash::TotalNumberOfSectors(); return; } @@ -200,11 +194,8 @@ void DFUInterface::eraseCommand(uint8_t * transferBuffer, uint16_t transferBuffe + (transferBuffer[3] << 16) + (transferBuffer[4] << 24); - if (eraseAddress >= Flash::Config::StartAddress && eraseAddress <= Flash::Config::EndAddress) { - m_erasePage = Flash::SectorAtAddress(eraseAddress); - } else if (eraseAddress >= ExternalFlash::Config::StartAddress && eraseAddress <= ExternalFlash::Config::EndAddress) { - m_erasePage = Flash::Config::NumberOfSectors + ExternalFlash::SectorAtAddress(eraseAddress - ExternalFlash::Config::StartAddress); - } else { + m_erasePage = Flash::SectorAtAddress(eraseAddress); + if (m_erasePage < 0) { // Unrecognized sector m_state = State::dfuERROR; m_status = Status::errTARGET; @@ -218,13 +209,10 @@ void DFUInterface::eraseMemoryIfNeeded() { return; } - if (m_erasePage == Flash::Config::NumberOfSectors + ExternalFlash::Config::NumberOfSectors) { + if (m_erasePage == Flash::TotalNumberOfSectors()) { Flash::MassErase(); - ExternalFlash::MassErase(); - } else if (m_erasePage < Flash::Config::NumberOfSectors) { - Flash::EraseSector(m_erasePage); } else { - ExternalFlash::EraseSector(m_erasePage - Flash::Config::NumberOfSectors); + Flash::EraseSector(m_erasePage); } /* Put an out of range value in m_erasePage to indicate that no erase is @@ -235,15 +223,12 @@ void DFUInterface::eraseMemoryIfNeeded() { } void DFUInterface::writeOnMemory() { - if (m_writeAddress >= Flash::Config::StartAddress && m_writeAddress <= Flash::Config::EndAddress) { - // Write to the Flash memory - Flash::WriteMemory(reinterpret_cast(m_writeAddress), m_largeBuffer, m_largeBufferLength); - } else if (m_writeAddress >= k_sramStartAddress && m_writeAddress <= k_sramEndAddress) { + if (m_writeAddress >= k_sramStartAddress && m_writeAddress <= k_sramEndAddress) { // Write on SRAM // FIXME We should check that we are not overriding the current instructions. memcpy((void *)m_writeAddress, m_largeBuffer, m_largeBufferLength); - } else if (m_writeAddress >= ExternalFlash::Config::StartAddress && m_writeAddress <= ExternalFlash::Config::EndAddress) { - ExternalFlash::WriteMemory(reinterpret_cast(m_writeAddress) - ExternalFlash::Config::StartAddress, m_largeBuffer, m_largeBufferLength); + } else if (Flash::SectorAtAddress(m_writeAddress) >= 0) { + Flash::WriteMemory(reinterpret_cast(m_writeAddress), m_largeBuffer, m_largeBufferLength); } else { // Invalid write address m_largeBufferLength = 0; diff --git a/ion/src/device/shared/usb/stack/device.cpp b/ion/src/device/shared/usb/stack/device.cpp index c0b72dc9e..294b647e1 100644 --- a/ion/src/device/shared/usb/stack/device.cpp +++ b/ion/src/device/shared/usb/stack/device.cpp @@ -1,5 +1,5 @@ #include "device.h" -#include +#include #include #include @@ -92,7 +92,7 @@ void Device::detach() { } void Device::leave(uint32_t leaveAddress) { - if (leaveAddress == Ion::Device::Flash::Config::StartAddress) { + if (leaveAddress == Ion::Device::InternalFlash::Config::StartAddress) { Ion::Device::Reset::coreWhilePlugged(); } else { Ion::Device::Reset::jump(leaveAddress); From 9f592a0bc4da0b290bcb40c9a35718aac2e009b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Tue, 10 Dec 2019 14:25:48 +0100 Subject: [PATCH 038/130] [ion/n0110] Persist exam mode through reset --- ion/src/device/n0110/flash.ld | 19 ++++++++++++++++--- .../device/shared/drivers/external_flash.cpp | 4 ++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ion/src/device/n0110/flash.ld b/ion/src/device/n0110/flash.ld index f6edcc8db..42ac5350a 100644 --- a/ion/src/device/n0110/flash.ld +++ b/ion/src/device/n0110/flash.ld @@ -12,7 +12,8 @@ MEMORY { INTERNAL_FLASH (rx) : ORIGIN = 0x00200000, LENGTH = 64K SRAM (rw) : ORIGIN = 0x20000000, LENGTH = 256K - EXTERNAL_FLASH (rx) : ORIGIN = 0x90000000, LENGTH = 8M + EXTERNAL_FLASH_FIRST_SECTOR (rx) : ORIGIN = 0x90000000, LENGTH = 4K + EXTERNAL_FLASH_NEXT_SECTORS (rx) : ORIGIN = (0x90000000 + 4K), LENGTH = (8M - 4K) /* ITCM (rwx) : ORIGIN = 0x00000000, LENGTH = 16K DTCM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K @@ -55,6 +56,13 @@ SECTIONS { *(.text._ZL22jump_to_external_flashv) } >INTERNAL_FLASH + .exam_mode_persistence ORIGIN(EXTERNAL_FLASH_FIRST_SECTOR): { + _exam_mode_persistence_start = .; + /* Note: We don't increment "." here, we set it. */ + . = (ORIGIN(EXTERNAL_FLASH_FIRST_SECTOR) + LENGTH(EXTERNAL_FLASH_FIRST_SECTOR)); + _exam_mode_persistence_end = .; + } >EXTERNAL_FLASH_FIRST_SECTOR + /* Use boot routine and required dependencies */ /* We're relying on symbols being in their own sub-section. On GCC, this is * done with -fdata-sections -ffunction-sections */ @@ -120,12 +128,12 @@ SECTIONS { . = ALIGN(4); *(.text) *(.text.*) - } >EXTERNAL_FLASH + } >EXTERNAL_FLASH_NEXT_SECTORS .rodata.external : { *(.rodata) *(.rodata.*) - } >EXTERNAL_FLASH + } >EXTERNAL_FLASH_NEXT_SECTORS .init_array : { . = ALIGN(4); @@ -202,3 +210,8 @@ NOCROSSREFS_TO(.text.external .isr_vector_table); NOCROSSREFS_TO(.rodata.external .isr_vector_table); NOCROSSREFS_TO(.text.external .header); NOCROSSREFS_TO(.rodata.external .header); + +NOCROSSREFS_TO(.exam_mode_persistence .text.internal); +NOCROSSREFS_TO(.exam_mode_persistence .rodata.internal); +NOCROSSREFS_TO(.exam_mode_persistence .isr_vector_table); +NOCROSSREFS_TO(.exam_mode_persistence .header); diff --git a/ion/src/device/shared/drivers/external_flash.cpp b/ion/src/device/shared/drivers/external_flash.cpp index d482aac98..10404c7c2 100644 --- a/ion/src/device/shared/drivers/external_flash.cpp +++ b/ion/src/device/shared/drivers/external_flash.cpp @@ -402,7 +402,7 @@ void MassErase() { set_as_memory_mapped(); } -void EraseSector(int i) { +void __attribute__((noinline)) EraseSector(int i) { assert(i >= 0 && i < Config::NumberOfSectors); unset_memory_mapped_mode(); unlockFlash(); @@ -413,7 +413,7 @@ void EraseSector(int i) { set_as_memory_mapped(); } -void WriteMemory(uint8_t * destination, const uint8_t * source, size_t length) { +void __attribute__((noinline)) WriteMemory(uint8_t * destination, const uint8_t * source, size_t length) { if (Config::NumberOfSectors == 0) { return; } From 1b7f9cf7b4524781577d05f8a7177ed9d7a90346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 11 Dec 2019 11:12:00 +0100 Subject: [PATCH 039/130] [apps/on_boarding] Fix LED clash between on boarding and exam mode --- apps/on_boarding/logo_controller.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/on_boarding/logo_controller.cpp b/apps/on_boarding/logo_controller.cpp index 197a29e7b..91ea5173e 100644 --- a/apps/on_boarding/logo_controller.cpp +++ b/apps/on_boarding/logo_controller.cpp @@ -1,5 +1,7 @@ #include "logo_controller.h" #include "power_on_self_test.h" +#include +#include #include namespace OnBoarding { @@ -45,6 +47,11 @@ void LogoController::viewWillAppear() { void LogoController::viewDidDisappear() { if (m_didPerformTests) { Ion::LED::setColor(m_previousLEDColor); + /* TODO: instead of setting again the exam mode, put the previous led color + * AND BLINKING.*/ + if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { + AppsContainer::sharedAppsContainer()->activateExamMode(); + } } ViewController::viewDidDisappear(); } From 070d362f152889fb09b61678feb26c06bdf079ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Dec 2019 17:27:39 +0100 Subject: [PATCH 040/130] [python] Improve comment --- python/port/mod/kandinsky/modkandinsky.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/python/port/mod/kandinsky/modkandinsky.cpp b/python/port/mod/kandinsky/modkandinsky.cpp index 408292db5..dafb14114 100644 --- a/python/port/mod/kandinsky/modkandinsky.cpp +++ b/python/port/mod/kandinsky/modkandinsky.cpp @@ -70,9 +70,15 @@ mp_obj_t modkandinsky_draw_string(size_t n_args, const mp_obj_t * args) { KDColor backgroundColor = (n_args >= 5) ? ColorForTuple(args[4]) : KDColorWhite; MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox(); KDIonContext::sharedContext()->drawString(text, point, KDFont::LargeFont, textColor, backgroundColor); - /* drawString function might take some time to execute so we add an extra check - * for user interruption (to avoid freezing in an infinite loop calling - * 'drawString' for instance). */ + /* Before and after execution of "modkandinsky_draw_string", + * "micropython_port_vm_hook_loop" is called by "mp_execute_bytecode" and will + * call "micropython_port_interrupt_if_needed" every 20000 calls. + * However, "drawString" function might take some time to execute leading to + * drastically decrease the frequency of calls to + * "micropython_port_vm_hook_loop" and thus to + * "micropython_port_interrupt_if_needed". So we add an extra + * check for user interruption here. This way the user can still interrupt an + * infinite loop calling 'drawString' for instance. */ micropython_port_interrupt_if_needed(); return mp_const_none; } @@ -87,9 +93,7 @@ mp_obj_t modkandinsky_fill_rect(size_t n_args, const mp_obj_t * args) { KDColor color = ColorForTuple(args[4]); MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox(); KDIonContext::sharedContext()->fillRect(rect, color); - /* fillRect function might take some time to execute so we add an extra check - * for user interruption (to avoid freezing in an infinite loop calling - * 'fillRect' for instance). */ + // Cf comment on modkandinsky_draw_string micropython_port_interrupt_if_needed(); return mp_const_none; } From 88d52c6e9c95841c8b14f44d07f8102aee2aa77d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 12 Dec 2019 15:23:29 +0100 Subject: [PATCH 041/130] [apps/apps_container] Fix screen noise before the logo on n0100 Push a white screen before fetching the examm mode, as this fetch takes some time and the screen noise becomes visible on a n0100 when downloading a new software. --- apps/apps_container.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 4e268205c..70ac5cbde 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -207,7 +207,12 @@ bool AppsContainer::switchTo(App::Snapshot * snapshot) { } void AppsContainer::run() { - window()->setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height)); + KDRect screenRect = KDRect(0, 0, Ion::Display::Width, Ion::Display::Height); + window()->setFrame(screenRect); + /* We push a white screen here, because fetching the exam mode takes some time + * and it is visible when reflashing a N0100 (there is some noise on the + * screen before the logo appears). */ + Ion::Display::pushRectUniform(screenRect, KDColorWhite); if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { activateExamMode(); } From ec4e3eca92547f2f1ccb599c10c6dd5dc811b0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Dec 2019 17:07:11 +0100 Subject: [PATCH 042/130] [ion] Linker scripts: build only 1 binary for n0100 and 2 for n0110 and ensure to fill the sector dedicated to the exam mode with 1 --- .../device/n0100/drivers/config/exam_mode.h | 30 +++++++++++++++++++ ion/src/device/n0100/flash.ld | 28 +++++++++-------- .../device/n0110/drivers/config/exam_mode.h | 28 +++++++++++++++++ ion/src/device/n0110/flash.ld | 23 +++++++------- ion/src/device/shared/drivers/exam_mode.cpp | 6 ++++ 5 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 ion/src/device/n0100/drivers/config/exam_mode.h create mode 100644 ion/src/device/n0110/drivers/config/exam_mode.h diff --git a/ion/src/device/n0100/drivers/config/exam_mode.h b/ion/src/device/n0100/drivers/config/exam_mode.h new file mode 100644 index 000000000..2988f6a09 --- /dev/null +++ b/ion/src/device/n0100/drivers/config/exam_mode.h @@ -0,0 +1,30 @@ +#ifndef ION_DEVICE_N0100_CONFIG_EXAM_MODE_H +#define ION_DEVICE_N0100_CONFIG_EXAM_MODE_H + +namespace Ion { +namespace ExamMode { +namespace Config { + +#define byte4 0xFF, 0xFF, 0xFF, 0xFF +#define byte8 byte4, byte4 +#define byte16 byte8, byte8 +#define byte32 byte16, byte16 +#define byte64 byte32, byte32 +#define byte128 byte64, byte64 +#define byte256 byte128, byte128 +#define byte512 byte256, byte256 +#define byte1K byte512, byte512 +#define byte2K byte1K, byte1K +#define byte4K byte2K, byte2K +#define byte8K byte4K, byte4K +#define byte16K byte8K, byte8K + +#define EXAM_BUFFER_CONTENT byte16K + +constexpr static int ExamModeBufferSize = 16*1024; + +} +} +} + +#endif diff --git a/ion/src/device/n0100/flash.ld b/ion/src/device/n0100/flash.ld index 6c449809a..6013e12e4 100644 --- a/ion/src/device/n0100/flash.ld +++ b/ion/src/device/n0100/flash.ld @@ -9,16 +9,16 @@ * This will let us use shortcuts such as ">FLASH" to ask for a given section to * be stored in Flash. */ MEMORY { - FLASH_FIRST_SECTOR (rx) : ORIGIN = 0x08000000, LENGTH = 16K - FLASH_SECOND_SECTOR (rx) : ORIGIN = (0x08000000 + 16K), LENGTH = 16K - FLASH_LAST_SECTORS (rx) : ORIGIN = (0x08000000 + 32K), LENGTH = (1024K - 32K) + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K SRAM (rw) : ORIGIN = 0x20000000, LENGTH = 256K } STACK_SIZE = 32K; +FLASH_SECOND_SECTOR_OFFSET = 16K; +FLASH_SECOND_SECTOR_SIZE = 16K; SECTIONS { - .isr_vector_table ORIGIN(FLASH_FIRST_SECTOR) : { + .isr_vector_table ORIGIN(FLASH) : { /* When booting, the STM32F412 fetches the content of address 0x0, and * extracts from it various key infos: the initial value of the PC register * (program counter), the initial value of the stack pointer, and various @@ -33,37 +33,39 @@ SECTIONS { * convenient: using function pointers, we can easily point to the service * routine for each interrupt. */ KEEP(*(.isr_vector_table)) - } >FLASH_FIRST_SECTOR + } >FLASH .header : { KEEP(*(.header)) - } >FLASH_FIRST_SECTOR + ASSERT ((. < ORIGIN(FLASH) + FLASH_SECOND_SECTOR_OFFSET), "Error: ISR table or HEADER overflows in the flash sector reserved for the exam mode"); + } >FLASH - .exam_mode_persistence ORIGIN(FLASH_SECOND_SECTOR): { + .exam_mode_persistence ORIGIN(FLASH) + FLASH_SECOND_SECTOR_OFFSET : { _exam_mode_persistence_start = .; + KEEP(*(.exam_mode_buffer)) /* Note: We don't increment "." here, we set it. */ - . = (ORIGIN(FLASH_SECOND_SECTOR) + LENGTH(FLASH_SECOND_SECTOR)); + . = ORIGIN(FLASH) + FLASH_SECOND_SECTOR_OFFSET + FLASH_SECOND_SECTOR_SIZE; _exam_mode_persistence_end = .; - } >FLASH_SECOND_SECTOR + } >FLASH .text : { . = ALIGN(4); *(.text) *(.text.*) - } >FLASH_LAST_SECTORS + } >FLASH .init_array : { . = ALIGN(4); _init_array_start = .; KEEP (*(.init_array*)) _init_array_end = .; - } >FLASH_LAST_SECTORS + } >FLASH .rodata : { . = ALIGN(4); *(.rodata) *(.rodata.*) - } >FLASH_LAST_SECTORS + } >FLASH .data : { /* The data section is written to Flash but linked as if it were in RAM. @@ -84,7 +86,7 @@ SECTIONS { *(.data) *(.data.*) _data_section_end_ram = .; - } >SRAM AT> FLASH_LAST_SECTORS + } >SRAM AT> FLASH .bss : { /* The bss section contains data for all uninitialized variables diff --git a/ion/src/device/n0110/drivers/config/exam_mode.h b/ion/src/device/n0110/drivers/config/exam_mode.h new file mode 100644 index 000000000..1949c9ccc --- /dev/null +++ b/ion/src/device/n0110/drivers/config/exam_mode.h @@ -0,0 +1,28 @@ +#ifndef ION_DEVICE_N0110_CONFIG_EXAM_MODE_H +#define ION_DEVICE_N0110_CONFIG_EXAM_MODE_H + +namespace Ion { +namespace ExamMode { +namespace Config { + +#define byte4 0xFF, 0xFF, 0xFF, 0xFF +#define byte8 byte4, byte4 +#define byte16 byte8, byte8 +#define byte32 byte16, byte16 +#define byte64 byte32, byte32 +#define byte128 byte64, byte64 +#define byte256 byte128, byte128 +#define byte512 byte256, byte256 +#define byte1K byte512, byte512 +#define byte2K byte1K, byte1K +#define byte4K byte2K, byte2K + +#define EXAM_BUFFER_CONTENT byte4K + +constexpr static int ExamModeBufferSize = 4*1024; + +} +} +} + +#endif diff --git a/ion/src/device/n0110/flash.ld b/ion/src/device/n0110/flash.ld index 42ac5350a..0c2366d90 100644 --- a/ion/src/device/n0110/flash.ld +++ b/ion/src/device/n0110/flash.ld @@ -12,8 +12,7 @@ MEMORY { INTERNAL_FLASH (rx) : ORIGIN = 0x00200000, LENGTH = 64K SRAM (rw) : ORIGIN = 0x20000000, LENGTH = 256K - EXTERNAL_FLASH_FIRST_SECTOR (rx) : ORIGIN = 0x90000000, LENGTH = 4K - EXTERNAL_FLASH_NEXT_SECTORS (rx) : ORIGIN = (0x90000000 + 4K), LENGTH = (8M - 4K) + EXTERNAL_FLASH (rx) : ORIGIN = 0x90000000, LENGTH = 8M /* ITCM (rwx) : ORIGIN = 0x00000000, LENGTH = 16K DTCM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K @@ -23,6 +22,7 @@ MEMORY { } STACK_SIZE = 32K; +FIRST_EXTERNAL_FLASH_SECTOR_SIZE = 4K; SECTIONS { .isr_vector_table ORIGIN(INTERNAL_FLASH) : { @@ -56,13 +56,6 @@ SECTIONS { *(.text._ZL22jump_to_external_flashv) } >INTERNAL_FLASH - .exam_mode_persistence ORIGIN(EXTERNAL_FLASH_FIRST_SECTOR): { - _exam_mode_persistence_start = .; - /* Note: We don't increment "." here, we set it. */ - . = (ORIGIN(EXTERNAL_FLASH_FIRST_SECTOR) + LENGTH(EXTERNAL_FLASH_FIRST_SECTOR)); - _exam_mode_persistence_end = .; - } >EXTERNAL_FLASH_FIRST_SECTOR - /* Use boot routine and required dependencies */ /* We're relying on symbols being in their own sub-section. On GCC, this is * done with -fdata-sections -ffunction-sections */ @@ -123,17 +116,25 @@ SECTIONS { *(.rodata._ZN3Ion6Device5Board4initEv.str1.4) } >INTERNAL_FLASH + .exam_mode_persistence ORIGIN(EXTERNAL_FLASH) : { + _exam_mode_persistence_start = .; + KEEP(*(.exam_mode_buffer)) + /* Note: We don't increment "." here, we set it. */ + . = ORIGIN(EXTERNAL_FLASH) + FIRST_EXTERNAL_FLASH_SECTOR_SIZE; + _exam_mode_persistence_end = .; + } >EXTERNAL_FLASH + /* External flash memory */ .text.external : { . = ALIGN(4); *(.text) *(.text.*) - } >EXTERNAL_FLASH_NEXT_SECTORS + } >EXTERNAL_FLASH .rodata.external : { *(.rodata) *(.rodata.*) - } >EXTERNAL_FLASH_NEXT_SECTORS + } >EXTERNAL_FLASH .init_array : { . = ALIGN(4); diff --git a/ion/src/device/shared/drivers/exam_mode.cpp b/ion/src/device/shared/drivers/exam_mode.cpp index 3096ad526..7aa737699 100644 --- a/ion/src/device/shared/drivers/exam_mode.cpp +++ b/ion/src/device/shared/drivers/exam_mode.cpp @@ -1,4 +1,5 @@ #include +#include #include "flash.h" #include @@ -10,6 +11,11 @@ extern "C" { extern char _exam_mode_persistence_end; } +char ones[Config::ExamModeBufferSize] + __attribute__((section(".exam_mode_buffer"))) + __attribute__((used)) += {EXAM_BUFFER_CONTENT}; + /* The exam mode is written in flash so that it is resilient to resets. * We erase the dedicated flash sector (all bits written to 1) and, upon * activating or deactivating the exam mode we write one bit to 0. To determine From 21756a5f4acf40ecac1ae719df9ff7aee8b89798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Dec 2019 17:13:46 +0100 Subject: [PATCH 043/130] [ion] Make name consistent --- ion/src/device/n0100/flash.ld | 6 +++--- ion/src/device/n0110/flash.ld | 14 +++++++------- ion/src/device/shared/drivers/exam_mode.cpp | 14 +++++++------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ion/src/device/n0100/flash.ld b/ion/src/device/n0100/flash.ld index 6013e12e4..e9b073bb2 100644 --- a/ion/src/device/n0100/flash.ld +++ b/ion/src/device/n0100/flash.ld @@ -40,12 +40,12 @@ SECTIONS { ASSERT ((. < ORIGIN(FLASH) + FLASH_SECOND_SECTOR_OFFSET), "Error: ISR table or HEADER overflows in the flash sector reserved for the exam mode"); } >FLASH - .exam_mode_persistence ORIGIN(FLASH) + FLASH_SECOND_SECTOR_OFFSET : { - _exam_mode_persistence_start = .; + .exam_mode_buffer ORIGIN(FLASH) + FLASH_SECOND_SECTOR_OFFSET : { + _exam_mode_buffer_start = .; KEEP(*(.exam_mode_buffer)) /* Note: We don't increment "." here, we set it. */ . = ORIGIN(FLASH) + FLASH_SECOND_SECTOR_OFFSET + FLASH_SECOND_SECTOR_SIZE; - _exam_mode_persistence_end = .; + _exam_mode_buffer_end = .; } >FLASH .text : { diff --git a/ion/src/device/n0110/flash.ld b/ion/src/device/n0110/flash.ld index 0c2366d90..7994dcd70 100644 --- a/ion/src/device/n0110/flash.ld +++ b/ion/src/device/n0110/flash.ld @@ -116,12 +116,12 @@ SECTIONS { *(.rodata._ZN3Ion6Device5Board4initEv.str1.4) } >INTERNAL_FLASH - .exam_mode_persistence ORIGIN(EXTERNAL_FLASH) : { - _exam_mode_persistence_start = .; + .exam_mode_buffer ORIGIN(EXTERNAL_FLASH) : { + _exam_mode_buffer_start = .; KEEP(*(.exam_mode_buffer)) /* Note: We don't increment "." here, we set it. */ . = ORIGIN(EXTERNAL_FLASH) + FIRST_EXTERNAL_FLASH_SECTOR_SIZE; - _exam_mode_persistence_end = .; + _exam_mode_buffer_end = .; } >EXTERNAL_FLASH /* External flash memory */ @@ -212,7 +212,7 @@ NOCROSSREFS_TO(.rodata.external .isr_vector_table); NOCROSSREFS_TO(.text.external .header); NOCROSSREFS_TO(.rodata.external .header); -NOCROSSREFS_TO(.exam_mode_persistence .text.internal); -NOCROSSREFS_TO(.exam_mode_persistence .rodata.internal); -NOCROSSREFS_TO(.exam_mode_persistence .isr_vector_table); -NOCROSSREFS_TO(.exam_mode_persistence .header); +NOCROSSREFS_TO(.exam_mode_buffer .text.internal); +NOCROSSREFS_TO(.exam_mode_buffer .rodata.internal); +NOCROSSREFS_TO(.exam_mode_buffer .isr_vector_table); +NOCROSSREFS_TO(.exam_mode_buffer .header); diff --git a/ion/src/device/shared/drivers/exam_mode.cpp b/ion/src/device/shared/drivers/exam_mode.cpp index 7aa737699..19b62b4df 100644 --- a/ion/src/device/shared/drivers/exam_mode.cpp +++ b/ion/src/device/shared/drivers/exam_mode.cpp @@ -7,8 +7,8 @@ namespace Ion { namespace ExamMode { extern "C" { - extern char _exam_mode_persistence_start; - extern char _exam_mode_persistence_end; + extern char _exam_mode_buffer_start; + extern char _exam_mode_buffer_end; } char ones[Config::ExamModeBufferSize] @@ -28,16 +28,16 @@ char ones[Config::ExamModeBufferSize] * sector. */ uint32_t * SignificantExamModeAddress() { - uint32_t * persitence_start = (uint32_t *)&_exam_mode_persistence_start; - uint32_t * persitence_end = (uint32_t *)&_exam_mode_persistence_end; + uint32_t * persitence_start = (uint32_t *)&_exam_mode_buffer_start; + uint32_t * persitence_end = (uint32_t *)&_exam_mode_buffer_end; while (persitence_start < persitence_end && *persitence_start == 0x0) { // Skip even number of zero bits persitence_start++; } if (persitence_start == persitence_end) { - assert(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_persistence_start) >= 0); - Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_persistence_start)); - return (uint32_t *)&_exam_mode_persistence_start; + assert(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_buffer_start) >= 0); + Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_buffer_start)); + return (uint32_t *)&_exam_mode_buffer_start; } return persitence_start; } From e5bb8f4b21ca525d0b7cdbb0e956b5766be4bb69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Dec 2019 17:15:20 +0100 Subject: [PATCH 044/130] [ion] Add TODOs --- ion/src/device/n0100/drivers/config/exam_mode.h | 2 ++ ion/src/device/n0110/drivers/config/exam_mode.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ion/src/device/n0100/drivers/config/exam_mode.h b/ion/src/device/n0100/drivers/config/exam_mode.h index 2988f6a09..7dfcd5517 100644 --- a/ion/src/device/n0100/drivers/config/exam_mode.h +++ b/ion/src/device/n0100/drivers/config/exam_mode.h @@ -5,6 +5,8 @@ namespace Ion { namespace ExamMode { namespace Config { +// TODO: factorize the macro with equivalent macro on N110 + #define byte4 0xFF, 0xFF, 0xFF, 0xFF #define byte8 byte4, byte4 #define byte16 byte8, byte8 diff --git a/ion/src/device/n0110/drivers/config/exam_mode.h b/ion/src/device/n0110/drivers/config/exam_mode.h index 1949c9ccc..e2a2e2aba 100644 --- a/ion/src/device/n0110/drivers/config/exam_mode.h +++ b/ion/src/device/n0110/drivers/config/exam_mode.h @@ -5,6 +5,8 @@ namespace Ion { namespace ExamMode { namespace Config { +// TODO: factorize the macro with equivalent macro on N100 + #define byte4 0xFF, 0xFF, 0xFF, 0xFF #define byte8 byte4, byte4 #define byte16 byte8, byte8 From f763563834be83ffae397e047191a86fc59703b3 Mon Sep 17 00:00:00 2001 From: Damien Nicolet Date: Fri, 13 Dec 2019 01:02:14 +0100 Subject: [PATCH 045/130] Memory optimisation --- apps/code/editor_controller.cpp | 18 +++++++++++++++++- apps/code/editor_controller.h | 4 +++- ion/include/ion/storage.h | 2 +- poincare/include/poincare/tree_pool.h | 2 +- poincare/src/trigonometry_cheat_table.cpp | 2 +- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/apps/code/editor_controller.cpp b/apps/code/editor_controller.cpp index aba355959..c799d8ff8 100644 --- a/apps/code/editor_controller.cpp +++ b/apps/code/editor_controller.cpp @@ -18,6 +18,22 @@ EditorController::EditorController(MenuController * menuController, App * python m_editorView.setTextAreaDelegates(this, this); } +#ifdef MAX_SCRIPTSIZE +void EditorController::setScript(Script script) { + m_script = script; + Script::Data scriptData = m_script.value(); + size_t s=scriptData.size,ms=sizeof(m_areaBuffer); + if (s>ms) + s=ms; + size_t availableScriptSize = s + Ion::Storage::sharedStorage()->availableSize(); + if (availableScriptSize>ms) + availableScriptSize=ms; + // assert(sizeof(m_areaBuffer) >= availableScriptSize); + // We cannot use strlcpy as the first char reprensenting the importation status can be 0. + memcpy(m_areaBuffer, (const char *)scriptData.buffer, s); + m_editorView.setText(m_areaBuffer+1, availableScriptSize-1); // 1 char is taken by the importation status flag +} +#else void EditorController::setScript(Script script) { m_script = script; Script::Data scriptData = m_script.value(); @@ -27,7 +43,7 @@ void EditorController::setScript(Script script) { memcpy(m_areaBuffer, (const char *)scriptData.buffer, scriptData.size); m_editorView.setText(m_areaBuffer+1, availableScriptSize-1); // 1 char is taken by the importation status flag } - +#endif // TODO: this should be done in textAreaDidFinishEditing maybe?? bool EditorController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::Back || event == Ion::Events::Home) { diff --git a/apps/code/editor_controller.h b/apps/code/editor_controller.h index 284bf1af3..d5b948d4e 100644 --- a/apps/code/editor_controller.h +++ b/apps/code/editor_controller.h @@ -1,6 +1,8 @@ #ifndef CODE_EDITOR_CONTROLLER_H #define CODE_EDITOR_CONTROLLER_H +#define MAX_SCRIPTSIZE 12288 + #include #include "script.h" #include "editor_view.h" @@ -39,7 +41,7 @@ private: /* m_areaBuffer first character is dedicated to the importation status. * Thereby, we avoid wasteful copy while adding the Script to the storage * (in order to add the importation status char before the areaBuffer). */ - char m_areaBuffer[Ion::Storage::k_storageSize]; // this could be slightly optimize + char m_areaBuffer[Ion::Storage::k_storageSize>MAX_SCRIPTSIZE?MAX_SCRIPTSIZE:Ion::Storage::k_storageSize]; // this could be slightly optimize Script m_script; MenuController * m_menuController; }; diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index 41c7001de..5138c1b76 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -16,7 +16,7 @@ class StorageDelegate; class Storage { public: typedef uint16_t record_size_t; - constexpr static size_t k_storageSize = 16384; + constexpr static size_t k_storageSize = 20480; static Storage * sharedStorage(); constexpr static char k_dotChar = '.'; diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index a124964e3..8e6a3d6f4 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -49,7 +49,7 @@ public: int numberOfNodes() const; private: - constexpr static int BufferSize = 32768; + constexpr static int BufferSize = 16384; constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode); static TreePool * SharedStaticPool; diff --git a/poincare/src/trigonometry_cheat_table.cpp b/poincare/src/trigonometry_cheat_table.cpp index eac4f3a4b..9eae9bc33 100644 --- a/poincare/src/trigonometry_cheat_table.cpp +++ b/poincare/src/trigonometry_cheat_table.cpp @@ -82,7 +82,7 @@ Expression TrigonometryCheatTable::simplify(const Expression e, ExpressionNode:: * For instance, when simplfy a Cosine, we always compute the value for an angle * in the top right trigonometric quadrant. */ const TrigonometryCheatTable * TrigonometryCheatTable::Table() { - static Row sTableRows[] = { + const Row sTableRows[] = { Row(Row::Pair("-90", -90.0f), Row::Pair("π*(-2)^(-1)", -1.5707963267948966f), Row::Pair("-100", -100.0f), From 2700098c0864dd25ae00e4cb554fa7af21d817e4 Mon Sep 17 00:00:00 2001 From: Damien Nicolet Date: Fri, 13 Dec 2019 01:02:14 +0100 Subject: [PATCH 046/130] External application launcher app --- apps/external/Makefile | 30 +++++ apps/external/app.cpp | 44 +++++++ apps/external/app.h | 37 ++++++ apps/external/app/sample.c | 6 + apps/external/app/sources.mak | 3 + apps/external/archive.cpp | 141 ++++++++++++++++++++++ apps/external/archive.h | 27 +++++ apps/external/base.de.i18n | 4 + apps/external/base.en.i18n | 4 + apps/external/base.es.i18n | 4 + apps/external/base.fr.i18n | 4 + apps/external/base.pt.i18n | 4 + apps/external/extapp_api.cpp | 85 +++++++++++++ apps/external/extapp_api.h | 76 ++++++++++++ apps/external/external_icon.png | Bin 0 -> 10728 bytes apps/external/main_controller.cpp | 98 +++++++++++++++ apps/external/main_controller.h | 34 ++++++ apps/external/pointer_text_table_cell.cpp | 38 ++++++ apps/external/pointer_text_table_cell.h | 20 +++ build/config.mak | 2 +- 20 files changed, 660 insertions(+), 1 deletion(-) create mode 100644 apps/external/Makefile create mode 100644 apps/external/app.cpp create mode 100644 apps/external/app.h create mode 100644 apps/external/app/sample.c create mode 100644 apps/external/app/sources.mak create mode 100644 apps/external/archive.cpp create mode 100644 apps/external/archive.h create mode 100644 apps/external/base.de.i18n create mode 100644 apps/external/base.en.i18n create mode 100644 apps/external/base.es.i18n create mode 100644 apps/external/base.fr.i18n create mode 100644 apps/external/base.pt.i18n create mode 100644 apps/external/extapp_api.cpp create mode 100644 apps/external/extapp_api.h create mode 100644 apps/external/external_icon.png create mode 100644 apps/external/main_controller.cpp create mode 100644 apps/external/main_controller.h create mode 100644 apps/external/pointer_text_table_cell.cpp create mode 100644 apps/external/pointer_text_table_cell.h diff --git a/apps/external/Makefile b/apps/external/Makefile new file mode 100644 index 000000000..b767dad8d --- /dev/null +++ b/apps/external/Makefile @@ -0,0 +1,30 @@ +apps += External::App +app_headers += apps/external/app.h + +app_external_src = $(addprefix apps/external/,\ + app.cpp \ + extapp_api.cpp \ + archive.cpp \ + main_controller.cpp \ + pointer_text_table_cell.cpp \ +) + +SFLAGS += -Iapps/external/ + +ifeq ($(PLATFORM),device) + SFLAGS += -DDEVICE +else + include apps/external/app/sources.mak +endif + +app_src += $(app_external_src) + +i18n_files += $(addprefix apps/external/,\ + base.de.i18n\ + base.en.i18n\ + base.es.i18n\ + base.fr.i18n\ + base.pt.i18n\ +) + +$(eval $(call depends_on_image,apps/external/app.cpp,apps/external/external_icon.png)) diff --git a/apps/external/app.cpp b/apps/external/app.cpp new file mode 100644 index 000000000..ac0f6141c --- /dev/null +++ b/apps/external/app.cpp @@ -0,0 +1,44 @@ +#include "app.h" +#include "external_icon.h" +#include + +namespace External { + +I18n::Message App::Descriptor::name() { + return I18n::Message::ExternalApp; +} + +I18n::Message App::Descriptor::upperName() { + return I18n::Message::ExternalAppCapital; +} + +const Image * App::Descriptor::icon() { + return ImageStore::ExternalIcon; +} + +App * App::Snapshot::unpack(Container * container) { + return new (container->currentAppBuffer()) App(this); +} + +App::Descriptor * App::Snapshot::descriptor() { + static Descriptor descriptor; + return &descriptor; +} + +void App::didBecomeActive(Window * window) { + ::App::didBecomeActive(window); + m_window = window; +} + +void App::redraw() { + m_window->redraw(true); +} + +App::App(Snapshot * snapshot) : + ::App(snapshot, &m_stackViewController), + m_mainController(&m_stackViewController, this), + m_stackViewController(&m_modalViewController, &m_mainController) +{ +} + +} diff --git a/apps/external/app.h b/apps/external/app.h new file mode 100644 index 000000000..e1dd47043 --- /dev/null +++ b/apps/external/app.h @@ -0,0 +1,37 @@ +#ifndef EXTERNAL_APP_H +#define EXTERNAL_APP_H + +#include +#include "main_controller.h" + +namespace External { + +class App : public ::App { +public: + class Descriptor : public ::App::Descriptor { + public: + I18n::Message name() override; + I18n::Message upperName() override; + const Image * icon() override; + }; + class Snapshot : public ::App::Snapshot { + public: + App * unpack(Container * container) override; + Descriptor * descriptor() override; + }; + void redraw(); + virtual void didBecomeActive(Window * window); + int heapSize() { return k_externalHeapSize; } + char * heap() { return m_externalHeap; } +private: + App(Snapshot * snapshot); + MainController m_mainController; + StackViewController m_stackViewController; + Window * m_window; + static constexpr int k_externalHeapSize = 131072; + char m_externalHeap[k_externalHeapSize]; +}; + +} + +#endif diff --git a/apps/external/app/sample.c b/apps/external/app/sample.c new file mode 100644 index 000000000..dbc13fd95 --- /dev/null +++ b/apps/external/app/sample.c @@ -0,0 +1,6 @@ +#include + +void extapp_main() { + extapp_pushRectUniform(10, 10, LCD_WIDTH-20, LCD_HEIGHT-20, 0); + extapp_msleep(1000); +} diff --git a/apps/external/app/sources.mak b/apps/external/app/sources.mak new file mode 100644 index 000000000..3f285e23a --- /dev/null +++ b/apps/external/app/sources.mak @@ -0,0 +1,3 @@ +app_external_src += $(addprefix apps/external/app/,\ + sample.c \ +) \ No newline at end of file diff --git a/apps/external/archive.cpp b/apps/external/archive.cpp new file mode 100644 index 000000000..aaa89373a --- /dev/null +++ b/apps/external/archive.cpp @@ -0,0 +1,141 @@ +#include "archive.h" +#include "extapp_api.h" + +#include +#include + +namespace External { +namespace Archive { + +#ifdef DEVICE + +struct TarHeader +{ /* byte offset */ + char name[100]; /* 0 */ + char mode[8]; /* 100 */ + char uid[8]; /* 108 */ + char gid[8]; /* 116 */ + char size[12]; /* 124 */ + char mtime[12]; /* 136 */ + char chksum[8]; /* 148 */ + char typeflag; /* 156 */ + char linkname[100]; /* 157 */ + char magic[8]; /* 257 */ + char uname[32]; /* 265 */ + char gname[32]; /* 297 */ + char devmajor[8]; /* 329 */ + char devminor[8]; /* 337 */ + char padding[167]; /* 345 */ +} __attribute__((packed)); + +static_assert(sizeof(TarHeader) == 512); + +bool isSane(const TarHeader* tar) { + return !memcmp(tar->magic, "ustar ", 8) && tar->name[0] != '\x00' && tar->name[0] != '\xFF'; +} + +bool fileAtIndex(size_t index, File &entry) { + const TarHeader* tar = reinterpret_cast(0x90200000); + unsigned size = 0; + + // Sanity check. + if (!isSane(tar)) { + return false; + } + + /** + * TAR files are comprised of a set of records aligned to 512 bytes boundary + * followed by data. + */ + while (index-- > 0) { + size = 0; + for (int i = 0; i < 11; i++) + size = size * 8 + (tar->size[i] - '0'); + + // Move to the next TAR header. + unsigned stride = (sizeof(TarHeader) + size + 511); + stride = (stride >> 9) << 9; + tar = reinterpret_cast(reinterpret_cast(tar) + stride); + + // Sanity check. + if (!isSane(tar)) { + return false; + } + } + + // File entry found, copy data out. + entry.name = tar->name; + entry.data = reinterpret_cast(tar) + sizeof(TarHeader); + entry.dataLength = size; + entry.isExecutable = (tar->mode[4] & 0x01) == 1; + + return true; +} + +extern "C" void (* const apiPointers[])(void); +typedef uint32_t (*entrypoint)(const uint32_t, const void *, void *, const uint32_t); + +uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize) { + File entry; + if(fileAtIndex(indexFromName(name), entry)) { + if(!entry.isExecutable) { + return 0; + } + uint32_t ep = *reinterpret_cast(entry.data); + if(ep >= 0x90200000 && ep < 0x90800000) { + return ((entrypoint)ep)(API_VERSION, apiPointers, heap, heapSize); + } + } + return -1; +} + +int indexFromName(const char *name) { + File entry; + + for (int i = 0; fileAtIndex(i, entry); i++) { + if (strcmp(name, entry.name) == 0) { + return i; + } + } + + return -1; +} + +size_t numberOfFiles() { + File dummy; + size_t count; + + for (count = 0; fileAtIndex(count, dummy); count++); + + return count; +} + +#else + +bool fileAtIndex(size_t index, File &entry) { + entry.name = "App"; + entry.data = NULL; + entry.dataLength = 0; + entry.isExecutable = true; + return true; +} + +extern "C" void extapp_main(void); + +uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize) { + extapp_main(); + return 0; +} + +int indexFromName(const char *name) { + return 0; +} + +size_t numberOfFiles() { + return 1; +} + +#endif + +} +} diff --git a/apps/external/archive.h b/apps/external/archive.h new file mode 100644 index 000000000..80b71d0e1 --- /dev/null +++ b/apps/external/archive.h @@ -0,0 +1,27 @@ +#ifndef EXTERNAL_ARCHIVE_H +#define EXTERNAL_ARCHIVE_H + +#include +#include + +namespace External { +namespace Archive { + +constexpr int MaxNameLength = 40; + +struct File { + const char *name; + const uint8_t *data; + size_t dataLength; + bool isExecutable; +}; + +bool fileAtIndex(size_t index, File &entry); +int indexFromName(const char *name); +size_t numberOfFiles(); +uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize); + +} +} + +#endif diff --git a/apps/external/base.de.i18n b/apps/external/base.de.i18n new file mode 100644 index 000000000..6072a563a --- /dev/null +++ b/apps/external/base.de.i18n @@ -0,0 +1,4 @@ +ExternalApp = "External" +ExternalAppCapital = "EXTERNAL" +ExternalAppApiMismatch = "API mismatch" +ExternalAppExecError = "Cannot execute file" diff --git a/apps/external/base.en.i18n b/apps/external/base.en.i18n new file mode 100644 index 000000000..6072a563a --- /dev/null +++ b/apps/external/base.en.i18n @@ -0,0 +1,4 @@ +ExternalApp = "External" +ExternalAppCapital = "EXTERNAL" +ExternalAppApiMismatch = "API mismatch" +ExternalAppExecError = "Cannot execute file" diff --git a/apps/external/base.es.i18n b/apps/external/base.es.i18n new file mode 100644 index 000000000..6072a563a --- /dev/null +++ b/apps/external/base.es.i18n @@ -0,0 +1,4 @@ +ExternalApp = "External" +ExternalAppCapital = "EXTERNAL" +ExternalAppApiMismatch = "API mismatch" +ExternalAppExecError = "Cannot execute file" diff --git a/apps/external/base.fr.i18n b/apps/external/base.fr.i18n new file mode 100644 index 000000000..6072a563a --- /dev/null +++ b/apps/external/base.fr.i18n @@ -0,0 +1,4 @@ +ExternalApp = "External" +ExternalAppCapital = "EXTERNAL" +ExternalAppApiMismatch = "API mismatch" +ExternalAppExecError = "Cannot execute file" diff --git a/apps/external/base.pt.i18n b/apps/external/base.pt.i18n new file mode 100644 index 000000000..6072a563a --- /dev/null +++ b/apps/external/base.pt.i18n @@ -0,0 +1,4 @@ +ExternalApp = "External" +ExternalAppCapital = "EXTERNAL" +ExternalAppApiMismatch = "API mismatch" +ExternalAppExecError = "Cannot execute file" diff --git a/apps/external/extapp_api.cpp b/apps/external/extapp_api.cpp new file mode 100644 index 000000000..1e7fd7aeb --- /dev/null +++ b/apps/external/extapp_api.cpp @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include "extapp_api.h" + +#include + +extern "C" { + #include +} + +uint64_t extapp_millis() { + return Ion::Timing::millis(); +} + +void extapp_msleep(uint32_t ms) { + Ion::Timing::msleep(ms); +} + +uint64_t extapp_scanKeyboard() { + return Ion::Keyboard::scan(); +} + +void extapp_pushRect(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t * pixels) { + KDRect rect(x, y, w, h); + + Ion::Display::pushRect(rect, reinterpret_cast(pixels)); +} + +void extapp_pushRectUniform(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color) { + KDRect rect(x, y, w, h); + + Ion::Display::pushRectUniform(rect, KDColor::RGB16(color)); +} + +int16_t extapp_drawTextLarge(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg) { + KDPoint point(x, y); + + auto ctx = KDIonContext::sharedContext(); + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,0)); + ctx->drawString(text, point, KDFont::LargeFont, KDColor::RGB16(fg), KDColor::RGB16(bg)); + + return point.x(); +} + +int16_t extapp_drawTextSmall(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg) { + KDPoint point(x, y); + + auto ctx = KDIonContext::sharedContext(); + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,0)); + ctx->drawString(text, point, KDFont::SmallFont, KDColor::RGB16(fg), KDColor::RGB16(bg)); + + return point.x(); +} + +void extapp_waitForVBlank() { + Ion::Display::waitForVBlank(); +} + +void extapp_clipboardStore(const char *text) { + Clipboard::sharedClipboard()->store(text); +} + +const char * extapp_clipboardText() { + return Clipboard::sharedClipboard()->storedText(); +} + +extern "C" void (* const apiPointers[])(void) = { + (void (*)(void)) extapp_millis, + (void (*)(void)) extapp_msleep, + (void (*)(void)) extapp_scanKeyboard, + (void (*)(void)) extapp_pushRect, + (void (*)(void)) extapp_pushRectUniform, + (void (*)(void)) extapp_drawTextLarge, + (void (*)(void)) extapp_drawTextSmall, + (void (*)(void)) extapp_waitForVBlank, + (void (*)(void)) extapp_clipboardStore, + (void (*)(void)) extapp_clipboardText, + (void (*)(void)) nullptr +}; diff --git a/apps/external/extapp_api.h b/apps/external/extapp_api.h new file mode 100644 index 000000000..12ae53ba6 --- /dev/null +++ b/apps/external/extapp_api.h @@ -0,0 +1,76 @@ +#ifndef EXTERNAL_API_H +#define EXTERNAL_API_H + +#include + +#define API_VERSION 1 + +#ifdef __cplusplus +#define EXTERNC extern "C" +#else +#define EXTERNC +#endif + +#define LCD_WIDTH 320 +#define LCD_HEIGHT 240 + +#define KEY_Left ((uint64_t)1 << 0) +#define KEY_Up ((uint64_t)1 << 1) +#define KEY_Down ((uint64_t)1 << 2) +#define KEY_Right ((uint64_t)1 << 3) +#define KEY_OK ((uint64_t)1 << 4) +#define KEY_Back ((uint64_t)1 << 5) +#define KEY_Home ((uint64_t)1 << 6) +#define KEY_OnOff (((uint64_t)1 << 7) || ((uint64_t)1 << 8)) +#define KEY_Shift ((uint64_t)1 << 12) +#define KEY_Alpha ((uint64_t)1 << 13) +#define KEY_XNT ((uint64_t)1 << 14) +#define KEY_Var ((uint64_t)1 << 15) +#define KEY_Toolbox ((uint64_t)1 << 16) +#define KEY_Backspace ((uint64_t)1 << 17) +#define KEY_Exp ((uint64_t)1 << 18) +#define KEY_Ln ((uint64_t)1 << 19) +#define KEY_Log ((uint64_t)1 << 20) +#define KEY_Imaginary ((uint64_t)1 << 21) +#define KEY_Comma ((uint64_t)1 << 22) +#define KEY_Power ((uint64_t)1 << 23) +#define KEY_Sine ((uint64_t)1 << 24) +#define KEY_Cosine ((uint64_t)1 << 25) +#define KEY_Tangent ((uint64_t)1 << 26) +#define KEY_Pi ((uint64_t)1 << 27) +#define KEY_Sqrt ((uint64_t)1 << 28) +#define KEY_Square ((uint64_t)1 << 29) +#define KEY_Seven ((uint64_t)1 << 30) +#define KEY_Eight ((uint64_t)1 << 31) +#define KEY_Nine ((uint64_t)1 << 32) +#define KEY_LeftParenthesis ((uint64_t)1 << 33) +#define KEY_RightParenthesis ((uint64_t)1 << 34) +#define KEY_Four ((uint64_t)1 << 36) +#define KEY_Five ((uint64_t)1 << 37) +#define KEY_Six ((uint64_t)1 << 38) +#define KEY_Multiplication ((uint64_t)1 << 39) +#define KEY_Division ((uint64_t)1 << 40) +#define KEY_One ((uint64_t)1 << 42) +#define KEY_Two ((uint64_t)1 << 43) +#define KEY_Three ((uint64_t)1 << 44) +#define KEY_Plus ((uint64_t)1 << 45) +#define KEY_Minus ((uint64_t)1 << 46) +#define KEY_Zero ((uint64_t)1 << 48) +#define KEY_Dot ((uint64_t)1 << 49) +#define KEY_EE ((uint64_t)1 << 50) +#define KEY_Ans ((uint64_t)1 << 51) +#define KEY_EXE ((uint64_t)1 << 52) +#define KEY_None ((uint64_t)1 << 54) + +EXTERNC uint64_t extapp_millis(); +EXTERNC void extapp_msleep(uint32_t ms); +EXTERNC uint64_t extapp_scanKeyboard(); +EXTERNC void extapp_pushRect(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t * pixels); +EXTERNC void extapp_pushRectUniform(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color); +EXTERNC int16_t extapp_drawTextLarge(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg); +EXTERNC int16_t extapp_drawTextSmall(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg); +EXTERNC void extapp_waitForVBlank(); +EXTERNC void extapp_clipboardStore(const char *text); +EXTERNC const char * extapp_clipboardText(); + +#endif diff --git a/apps/external/external_icon.png b/apps/external/external_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..297dc31c6cc743585cee6e411c74e158a91a2949 GIT binary patch literal 10728 zcmVP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3;sa$UI*h5us}UIKDh4q}ye;N|-}xQ`T*G&LS; zYDDVs2B6V>LIX7WKmR`FU;HVlWD`@Vx#ev66I*P)^G&tSpXaNy@&0}Pg!1~C`~0~H zZ#Q{93cB+7XWp;tJD;atH`*&aBXXoql@GBhViR|lw{3TAW&t3XCem6=VN96qboBhWT5&vmF{`nBU zb5=cPKeOwRJZdq&CiOOz`yCfD;TZ01ng0s^C%!NDzs7&nb~{y76`9`C`BR z(ZU8+Fx@a$CfMzG9x;;pm0RJibFj&9X|zwhxUyakAVj=7F&MHqI-6ZcE<0PiFU}Fi z%KCIh?nCs06>!NUzZj*Dfl4U8dcB)_io4hPN(yz8 zLW(J+oJy*xrJh5MIpv&77EbjNN)&LFQfg_X*HB|kHP=#WZM8Sw0x*_L%dNE9TI-#c z_Skt==laeE!;diHNF$Fj>S&`+(r3n*W}ao%*=ApUg#`qdl~-AHwbi%Vq|%N%?Yzsb zyX}6+wG&P}>Eu&RJ?-@ORdcVh{j_RdSMJZN=3cAj??UOi@@v)jxRkd?IKfHMnz3R& zI##@B1xRSGHM7;l=(TcMGuwPHAtcWzlNM(=tr#m9xAW<^_qF@Aa=%?SLv;V{y7`}0 z&S>fWA1i0HbRSmk`?~$GYO7zk4R?W5g~Swu43r-ibzgfPDvuKgeox?5owJ4jd<4gc zeQAMf;H5A^T)IIt_Ix$`9dk)(_u`093ESu8HmFy98DmvKw)#3_+!#+5FT$ED64cdC zttYlIk2hz}Q_?tda((0a?3%7GZVy6bYgppWTt5%s+gJ0OA0%5`JQi@@Cjq>SBHK{& zW#dVYn)^uJ^jSZAra40uoPHyB%=ak5icnf#XtL{q?Jx`!J%C zd}Cb*`A|4RpUkvu0G|s&W|>wVvmF2@ZvOb=cMWq5a!z@?lbdIn#Y6f@@wmJy8fTpx zPDqU`Sq!AdQr6gOue4(*$JI)$jb2xQUt-@qggxWRrdgk3+RKNO1}jDIfv|S+Bp1NL zfqpt|?3VUq{%J*$H^<|VQbJ4+vN@K{I9=i$$!uFl+#Fdmimlom&f1Q5v~JVzsjoV^ zrxxw(@i5-#V$alZ(vlJ*YRCW8;{NuljpV-~4jzS=S3@vlimdNi?DnMZ%vDmLkgwk! zGAqcimK$*E4h`-<&g7iz7?iFpkTucciE#H|`8`CJd!jI@rMmXnBQ8H`-=+7(q*-dQ z8&!V}wbpH4lS({=l;S7%^Vf$cK7AZ^0@lJxX-%I)Xq$w{U;y~cA}-e4@YzoH$%rwg z2XKdRTA71fB>1Ef(T{uq*D((jsdP$d(v-ZF%ldrth`PNx_dg zOWQ*)>28(2Q~;;#ZN~(dijtu3oGY4Qn!aa|T-l}0l+S9Va_RE0Y+k9KQ1WI_WXtxo z#mH#(q+m!UbWrZ6tOR%+vyYIn98j96KCvkTEP1jWIwn%dcRwbtJudYyk0Y;>-&Qi8 zakrz8nc)|!Q`cNwvDy1nMo8Y0Z>&=5!=_0@yvmJ9^1=}gKTPBPd+Z&1INLm*OEuh| z+|SDdm|5eQw8lFyXC8ilJkaehnMs^&rV{6%3IVp-Ora>0pNUm&W06f1dn z!a60HVRv|^5i)ZZS|nlfp!;5U3q>7}PknEglC*0u4)~3NO0C5L3f4K|i4_eO%3f5z zl}JtzqH2!BSjytQd56-QAgqjKtbl0A68$)nR79eP0P;K$teO-jvm(%_73~8nb&E{N01diS!h<45 z28fQ3%^h%G5CrKZ+51KNc!b;(pOxifxZF|mIB#m zR2b5a9xDa1Pvf;ggwBMd-_I}-(SS#%kn@U!By>=SHxF0@WGG@OuB6V#0`3s0sNHx* zq~_x8EH{bKmLb*DLdp~mFo5Dgoy{;{q#={iDOvI!!dU_SJs!z{Cht=>kSElLQ@tIe zU&!^?0>w_{8^(4)!#vIA@aPk%H;rInUxMWsBr%upFN;PKzxY@Uyb>|RRASJWopd*{ zH&nX2Nuo70?SwA zGtSOHdpw$@1yckm0jo8@Bc{6mV4gp6a|vb|;42vh{J14AFr?>Eq5v#qXnsK4bGf7-0VlX~m%r$VPj~gXt?M&tn&vZm8TsZpO%p zBpm(NnYmD3%v4z1B2)6-5g!yjkU0tqKC62Z2GY5nHLggg}qS@89E zZ6q#4RsgnuN3v7YLkV?tDVpJ`#TzcdPyoPC7}FihN-WHZ)PQtI8E-^c`t`ziUO{CH2=cgg z6+D?Ev8rMsRB<-H5x2~M)kBQ32zxwQj=XEJ`kCEPNpCKDsB^jhGopeJ4W&oSq0P+f_6M{UfD1i#>eUOox7{O?sT(V7*-&SRh zUpjIw2jH%xI*U<&6>M%Aor(lcmy%Q&xrMDbPeg>|_Ci7+Ji|tHc_cL)J(hn4G zQSvO4=hbpgNFiYaWrm}zPHx`B9+yR9kP$$<+|T`zA8qzcyhZXlr?0|C!EvC1A32F0E(&68K-5i+1AGAJ<-RKqfw3mnv5K@0&Sz5v z40;gAFb1{RTT|QFKu>7Fon)i9tEdNEPaUuzKbgRX2OhC1V>#L88{vhbMq-wPYocbc>D-QkTM4NFpLdBbjP1Z>V?01R(k$Kf z4K#eG@$oBJV>e-2=wB8Vl4LC0(8LgTnA**`{)p)z(x1SsY%O};zeCM0uxiy43}u#H~p={D(*v$KFf+S@?4j58{`yk-r9p2Sz)RiO9DZXeET3VV@_e=Oq%*XNs7X^wj|~>8Z@)_1KAt#B&f20 zmBchxA2Bghb2KXF8v_0sOg2o9cico9%3{+ zGDjO5G!`+1YVl&HVWEIPcz6MJ>*@*+4J!j(rH;lG0JR7bw6pdwF1e=oL0X-IRHXf)O2Sp3QVo*#f zH%B*+I1@5>ShCD%mB++7WJVe@F@k0aVn!{)JW@vmt~s?&!kXHM^kXDQD7CRVZg9Ae z3p@&%tqvIVtXfg;2HnKp#EhjV*FH}b?~+PD6fT2wyu?)WQv%3pVRH8R>2tNO8ZLXm zvgk38l*twSUyjk-nL73Zq2w{(8yU|6;ICFYu6m4MzQNub{+75$*+lT^z#m&J@}(x9 zp)3_ZQd0dH;x}g#XoByhXm`A8yJ?pQL^6MjImvtlzI-M>;eJ_J19u;)d%|i_{N)<} zzw>Ej2-r{oWf2L4_Uw=W9Ebp;1`?&&Y>J3Nb;dJL+gryyqNldpSh>@{SZuF;u`90# zQ;mw&jj**>oqP(t`5gPd6Z%)Pa#x}#s2#uqNQO5O_goAA8z*qpsz}!M+7R5>kd0El zlU5hQ;GWN0(#>Ag{ftbKYo87h6VHTH=J+;*5J=Bv3|Q=hwcJ<6Y_}5uL#p9@w37FB zLSUu;aFiJR@%GlwFQpKu@_;^P#kY~_$C#h>v{}*9L4rqi6ipe`PX^(@U%w`W7y^=9 zyCQWXr#hw%g)Vn*U|!^P9l>{?8Hb3A$_Oja;>38=PXu+;u*EqSYQbu&Be=a~T;lB- zxup?#;8&(o`-NzjL+&HRi&GL-q*unw9YxABQ}Py6K^npw$ZyJt)uv{aH4hO1SA1SZ zM$BPKNtml~$oZ3joY`5%=CQUG3FOoU@bdd36lPVl+hGDeUy3YrM!VHgd>TQF0VRX0 zl$;NqiiYoyWyo(J-`avjh4u$unl<%SCngA(fC)-g8^f>~ zD{3QQawo9R6QYom*9K0Ll>}I0(1be8(s?XP4Ls2>b56T>>ib>geB2fgnq?fo4ELstHfHirPXbqn_ij)IC|& zL(|@kPiXYJVeX0BH0n;3wuoU zsRtGn7^AZ`8B^jVtHOG!U!J_fGQ6FE#eR1gllE>4>$KxU_e}C=Wi+&7{;?WLIKu=} zS>|o1cm@cT2M@__)p3~*G9?&-^(EC1rqfQKgFa8l`Oa8lSJ8h^7&VzW3I7|&ttki9WYKs&(;;7GoEW^t<;3&tL zkla{a%qJJ7DY;o4!;8U?<%5K%Su~4wZxuUD4Uoc6q0^3-REe*m#ex_d*fnz9$|nbA zowSESuL#oapo4bzap_;PW z71nD?ozQV5fLBSxs;P^K(MLHO3@0dybjX#wKi?_wZgrZ(E;O6j6Y$bQI<8Cs!;4>%o%|TanPO zwIYfPYiTEpeGrT|T?r>?sJPXQK^#623m>du%f@TJIVmA^$RlaD|V=##D^e( z!OOu*V4RMyRHwdU7mib$358eiR4AyUc_9mkRerT_N`(^Mooc~mq2sf*8Baz% zrr61lNSLJHU3*M)lIyrHKn&2@e4`!;30EUgi3QmJcNa+!jY4|_#V>8*L~5@<{1pL5 zDx+kyU4vhkrbq(J>w=Cl$-aImUHG&^oU`BbZ8_`Xu z8dIrvZx%mW0794nAVS-(20mv4%7uVJ4U(BdEiYmfT;h|W76nYF-c53WG#U*(QgjRf zAaML!bry60hY_jI?%;v3NR!CzP>8GHQLw0aFB0b!8&!}cW}fy#nqXlRZaxlLI-7jX zR5QL~>RfN>RAqy+y4-tYo@6NcpAn~|tuiijHgw1*UUpo2v1&|@Y7chUCaOXHvq~pI zb5Vy2nAGGY2opGDV{ez#rA`2_o^I(Zt?SA=vnan+wXa4!CU|5|fCkgr?m?T9DihUy z8U%t*#}-lSU|qA3w3lWL04G`BNLnj`Q6fM@7O@pQWq z%6*$%PLc=ZpLNKgN}a+xMO7d=VG`KAK$P#H;ev+55xFk#tD>1izz`i9C4qkPUdI@j z{E0kHCLI*rjRcoV#F(^H=DHhK!UVzp8{-^Mx^afDiI>N83E%UY0KA^9b$2)Jr^ZN zL9Zwg#+zV;BQ;=9u=vuMqT1a(R5t-n77`)|fz)J)68Cr5fvlNX$w&zo^|FC<3>k8c z!p3EHOK_585L1VocqJa)CnvhcAf8Bmkwh4A6t~c4N^{Rp=G2L#{leN9+Qe1w}(`259v|G+9Y`{{?oPQ zUL32Ar@nP|ThPrRILJwDhZ3M2L><*GX#miSBn>-2RoDr#hpWxe{^N$*2F4%R+in*X zF!hx2p+N9mF<=Te8lNY%(K`}Z%`LbnbQtm;7Bw=971I@48llGIuji|TSBEvp(n><2 z_Xn^j0Z^m$7ETTghe_1IGFG>B9re_%wFSjULo)ZsH;tnMPulrY$3Z&eo;n(Ui>#KK zfSZs>pd;xWK}WEQGqvR%p0h{V<3&D3?XcgVsWlq*`2B&ucJO05$%2SUOyi6xX()D} z3YBvfyZ-E>eMp#Z83eP8?hNp7H}j`XJp%X>lI`P3l#xQX-vx0AVCjiL)=pb)`Byff zzWXxjIyH6Wx;n35Wu|Q9H>VEAAU3?(Xn1w0Zzn141w+?rAX>mCabL+sd|}nXvCn}I z$n%;{udO4lyiE?dDH+nEBlT4$Rgh5|&w~=3=r$yu(TP!u%*#3^oR_vDHJlOeDIaaJ zF61zpEZ&pv0kn{@mz7da16`^nccf^Oj?ZaV-2)UJ+c5aa6p7X(4)WNcjF{E&?55Mi zQYG5jj<^q8(B1Q@(cDqrF{>f?oUdWrf0*nT8Vl4Sc$!YlHx!vcPEjm)COhrpdK8D0 ziqHu*)`@LceYrhhB)`<;yF?>wtDPmr^(B^{Kyukx+CXm~z8`YdM@I-eLTHVr8{kpv z6g}RcU!Ms`zV0#i0pxQd1Cfq;0+36|X~)l}Yht`WL|q>4rb=-hLBBeYb)*GtiWe*m zcjRK$9+w0kgs_FDeCK7LC>

&S~~iQ`N~1bucNjq_fyq%>aA2jv8SkmI`_9V!iPi ze2;kU`0^8r)6ldVNJ=REecQNk9elVl1DXEZW$q(%q9+NyB-0k)wlb=<#JyX=F>3R& zZXI6%8qo^cFAg`6>fJ zlc1;kEk5!xO0(#(HVmETZcb-l(BM@^RD##mXLL^=9{B;|pa-JSM!4NTQ9+Q^rQZhB zPW0W2M+9#5D}(keb&z$3s07xDwp(d)+ovTRk9pmE{+F9S-fRBJ%^&YI|K#S6_nLol z^T&J5Ke_p*VBZrbLFlRT+-*{bxfXTZrO-zk4|^fEcwA|Z*4C*9?0~4to1k_oN>)ut z=|LUKOwnJY11gUiWMmPVb`A6yIN0h>4>cd3`olw$_A&Q8u>12B_5NZ2tM=t%slu+t zSgmjk21Z4YhWrvNlyMi$-Qy$nmD|f}Gje+a=ieQvA(U4D_t7tMo!oHd+5m53YeT!} z%ne0%F0ZQAMgU7T;Gv_1&BTfOm|TF~D{9PWGXqLSN)=HMe__Fuc23bLX}a|h+zvbJVbMUJF}Vp0&hi6TMgR=IsgCxglR)VP)S2WAaHVT zW@&6?001bFeUUv#!$2IxUsI)`6$d*=amY}eEQpG9)G8FALZ}s5buhW~3z`^`6cQHp zmtPS>ujoS*AtVr!nPtpMQX0PF>mC8V-o<&A|G7U$zgn;u5D%`NWw!wLy zIKs-ZN_iQ*eDdehvkz*bk z&>*{h@IUz7tyP?y@RGtwp!>yfK1P7hF3_wy&iAq7G*5uwGjOH1{TmG+@kx5Ut;LRj zfo`FnJLa_+EpV2qvfx%m#ch&2ywU5&WAWL1PZ-9eCV6;Tp zYd-Jp>Fn*_Gp+u90K0&4#PqpjT>t<824YJ`L;&^x_5k!Xt|#RH000SaNLh0L02dMf z02dMgXP?qi00007bV*G`2jdGG2o4O5R&{#-012c?L_t(&-qo6GOk3v}$A9Pe9NS=s zAvO>QS91vz!X>1TrB%}9(xmr`wpOd!N!wJZ+Ene+_GOziX;Y<1)4uG(CUsNSZPmJ) zR;5wXbjgyC8@WINfdZi+1PE7$1Z-pb*yo&maByOx@Jf*@cp7{b4(a~6VARTV{1h=F-ck{}2ejmAYFBftd$0Rn*l zUsaN28CjOY*V6nSMNtR_g9$NnyWM>B@nL$dUgyz<8lK+28>3NvXyE1rGY?R_-@X#1 zL!TYve0w)8_ZWs7hy8g+_Z(_f?NQ$)K;=-Q`wqvF2P_BaXB%}<#waoHR6;M zb5eHuWs#<72p*5;fjW7-y_XriLLgz85s!(%5;w{mlIJnEV@Rg}?CSF5N?2S{Bb6kos zw|Pqq4o4wp&UZ$=Us#YAah+l|$DEs)VU24&;#yFl!u$=?FOWpzmO65CY|G-iCcxEH zl`T%41OZ2J!B-#L_=Gd6J0DwS+*~zqs-__zM7`JE*~_^L?cwS}RaH)%Imf`@&1Jn) zig#l5CI@AuMGTFM#dI1EqFI+4lgWr62t5DP6I4}}18}LMi^E6H@WDS0a`4k*CaM>EY$4ZQQ~-zUVYqO=f22{1T379QKT zdppnU-*ZoLUavPPea^OJCJe6U>L5K=2P4L=4~?*WTVulSzj|$GG5@}6?ArNQ;x@Oi zTEB5~JfUX{29dYE^D6c%8z)*?Iez+LD4x|Z{Rp9jkR6@4ol9gm~rV z*m?1}edxMQXIBrseb*?+&!uT=Lt@}YM#t#v{({yEos^XpGCVTQ*hJzxZ8jS5`no z&WETK1Lr8pqp7iucmMPuLnEP*==E2gW&hqCy!-yYR<*5{bov#m15uct$K=$lFff42 zS9-A7GS^JOD#j!BXf!e9B+G7NU0UkB6s@Y9+qY*{p~Dqi8E~Q~#0}-2{_ULpvADCNu zyNm{&TvMgh@m@)WoN6&hU>2&qo z;Ljf(pr)#n*T4A;rnynXfCt@RLKmgGKN($0K{Z;JFS(CDIYL{<(k0G}%fowr{ZGvM zjkT4$_H;AW?r%rE@7wT0ax*x4*xSG+0>l`Efq-aZVcWtajT_tzxO-c zdV#5_X=-aKd8DcWP16`2nMfGi8?Qc3O;IN1iBo7MD~^|*WY!x*c3q13OxnOtD9Cw} zoTe%SO~HKqk4Q5g;mi9mo{hWiO6(<4M^AtlU)Ct}_4VlhpB-)Ca@RebFDc9=&62{E zo`HmbtiEU$$>9od&YQL8*jh;_Rj$dHs&G-I!0OIYt41++Ods_vJ$#J??+MM zKLij62GMnu%*wq4jkVm)e1XA09-aLo*b8g1&K`=toY7~IbQ_+OVh{ubT_x*ID{0<= z&{(``X*QeK@mSNM2^({>=sV-r&hjf9HS){9+?j!#nVD8l8s#>I|a za_pHj)s`o``_`F1km_wmF*-2$x{-oC_{}?joy$+Z%=a}p7Y6rlJimvM`#x4&>F(vw zkuxFn9GMJ*1@J2hnwZ>42U%%HR@zs-o{L2_m5vBt0Gq2T$<4OKZ0!lG?!ld;!DU#} zqkGG&=#{uE%gb^Os|v1vU}({qFuz~nT8u9lVx8If`~6=PdLZa z#8ePO1kHyr(2J;!M(n#{+=?nKuDXMgEiQ0Ee}BKe7LFVWx<;<^AZf0@qlwv!pEx8o<-Mn za&mIkOlAWheuUa zxpnInqoboVHa1dHQnDbtL|L__X$%YuFgQ4f)9J+H@vJFHilT_cV!>{=Q(Rn(!{LbP a@&6BvAL9gKturJ50000 +#include +#include +#include "archive.h" +#include "app.h" + +using namespace Poincare; + +namespace External { + +using namespace Archive; + +MainController::MainController(Responder * parentResponder, ::App * app) : + ViewController(parentResponder), + m_selectableTableView(this) +{ + m_app = app; +} + +View * MainController::view() { + return &m_selectableTableView; +} + +void MainController::didBecomeFirstResponder() { + if (selectedRow() < 0) { + selectCellAtLocation(0, 0); + } + Container::activeApp()->setFirstResponder(&m_selectableTableView); +} + +bool MainController::handleEvent(Ion::Events::Event event) { + if (numberOfRows() > 0 && (event == Ion::Events::OK || event == Ion::Events::EXE)) { + uint32_t res = executeFile(m_cells[selectedRow()].text(), ((App *)m_app)->heap(), ((App *)m_app)->heapSize()); + ((App*)m_app)->redraw(); + switch(res) { + case 0: + break; + case 1: + Container::activeApp()->displayWarning(I18n::Message::ExternalAppApiMismatch); + break; + case 2: + Container::activeApp()->displayWarning(I18n::Message::StorageMemoryFull1); + break; + default: + Container::activeApp()->displayWarning(I18n::Message::ExternalAppExecError); + break; + } + return true; + } + return false; +} + +int MainController::numberOfRows() const { + return k_numberOfCells; +}; + +KDCoordinate MainController::rowHeight(int j) { + return Metric::ParameterCellHeight; +} + +KDCoordinate MainController::cumulatedHeightFromIndex(int j) { + return j*rowHeight(0); +} + +int MainController::indexFromCumulatedHeight(KDCoordinate offsetY) { + return offsetY/rowHeight(0); +} + +HighlightCell * MainController::reusableCell(int index, int type) { + assert(index < k_numberOfCells); + return &m_cells[index]; +} + +int MainController::reusableCellCount(int type) { + return k_numberOfCells; +} + +int MainController::typeAtLocation(int i, int j) { + return 0; +} + +void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) { + PointerTextTableCell * myTextCell = (PointerTextTableCell *)cell; + struct File f; + if(fileAtIndex(index, f)) { + myTextCell->setText(f.name); + myTextCell->setTextColor(f.isExecutable ? KDColorBlack : Palette::GreyDark); + } +} + +void MainController::viewWillAppear() { + int count = numberOfFiles(); + k_numberOfCells = count <= k_maxNumberOfCells ? count : k_maxNumberOfCells; + m_selectableTableView.reloadData(); +} + +} diff --git a/apps/external/main_controller.h b/apps/external/main_controller.h new file mode 100644 index 000000000..bdb6d275b --- /dev/null +++ b/apps/external/main_controller.h @@ -0,0 +1,34 @@ +#ifndef EXTERNAL_MAIN_CONTROLLER_H +#define EXTERNAL_MAIN_CONTROLLER_H + +#include +#include "pointer_text_table_cell.h" + +namespace External { + +class MainController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource { +public: + MainController(Responder * parentResponder, App * app); + View * view() override; + bool handleEvent(Ion::Events::Event event) override; + void didBecomeFirstResponder() override; + int numberOfRows() const override; + KDCoordinate rowHeight(int j) override; + KDCoordinate cumulatedHeightFromIndex(int j) override; + int indexFromCumulatedHeight(KDCoordinate offsetY) override; + HighlightCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + int typeAtLocation(int i, int j) override; + void willDisplayCellForIndex(HighlightCell * cell, int index) override; + void viewWillAppear() override; +private: + App * m_app; + SelectableTableView m_selectableTableView; + int k_numberOfCells = 1; + constexpr static int k_maxNumberOfCells = 16; + PointerTextTableCell m_cells[k_maxNumberOfCells]; +}; + +} + +#endif diff --git a/apps/external/pointer_text_table_cell.cpp b/apps/external/pointer_text_table_cell.cpp new file mode 100644 index 000000000..00967fafb --- /dev/null +++ b/apps/external/pointer_text_table_cell.cpp @@ -0,0 +1,38 @@ +#include "pointer_text_table_cell.h" +#include +#include +#include + +PointerTextTableCell::PointerTextTableCell(const char * text, const KDFont * font, Layout layout) : + TableCell(layout), + m_pointerTextView(font, text, 0, 0.5, KDColorBlack, KDColorWhite) +{ +} + +View * PointerTextTableCell::labelView() const { + return (View *)&m_pointerTextView; +} + +const char * PointerTextTableCell::text() const { + return m_pointerTextView.text(); +} + +void PointerTextTableCell::setHighlighted(bool highlight) { + HighlightCell::setHighlighted(highlight); + KDColor backgroundColor = highlight? Palette::ListCellBackgroundSelected : Palette::ListCellBackground; + m_pointerTextView.setBackgroundColor(backgroundColor); +} + +void PointerTextTableCell::setText(const char * text) { + m_pointerTextView.setText(text); + layoutSubviews(); +} + +void PointerTextTableCell::setTextColor(KDColor color) { + m_pointerTextView.setTextColor(color); +} + +void PointerTextTableCell::setTextFont(const KDFont * font) { + m_pointerTextView.setFont(font); + layoutSubviews(); +} diff --git a/apps/external/pointer_text_table_cell.h b/apps/external/pointer_text_table_cell.h new file mode 100644 index 000000000..be011b76e --- /dev/null +++ b/apps/external/pointer_text_table_cell.h @@ -0,0 +1,20 @@ +#ifndef ESCHER_POINTER_TEXT_TABLE_CELL_H +#define ESCHER_POINTER_TEXT_TABLE_CELL_H + +#include +#include + +class PointerTextTableCell : public TableCell { +public: + PointerTextTableCell(const char * text = "", const KDFont * font = KDFont::SmallFont, Layout layout = Layout::Horizontal); + View * labelView() const override; + const char * text() const override; + virtual void setHighlighted(bool highlight) override; + void setText(const char * text); + virtual void setTextColor(KDColor color); + void setTextFont(const KDFont * font); +private: + PointerTextView m_pointerTextView; +}; + +#endif diff --git a/build/config.mak b/build/config.mak index 8de2af89d..a59637cc0 100644 --- a/build/config.mak +++ b/build/config.mak @@ -7,7 +7,7 @@ EPSILON_VERSION ?= 12.0.0 EPSILON_CUSTOM_VERSION ?= 1.18.0-0 # USERNAME ?= N/A # Valid values are "none", "update", "beta" -EPSILON_APPS ?= calculation rpn graph code statistics probability solver atom sequence regression settings +EPSILON_APPS ?= calculation rpn graph code statistics probability solver atom sequence regression settings external EPSILON_I18N ?= en fr es de pt EPSILON_GETOPT ?= 0 ESCHER_LOG_EVENTS_BINARY ?= 0 From 472929c0284a2ac6a7e1d8881a91cec4510fa0fe Mon Sep 17 00:00:00 2001 From: Damien Nicolet Date: Fri, 13 Dec 2019 01:02:14 +0100 Subject: [PATCH 047/130] External API for KhiCAS --- apps/external/extapp_api.cpp | 82 +++ ion/include/ion/events.h | 24 +- .../ion/keyboard/layout_B2/layout_events.h | 16 +- .../ion/keyboard/layout_B3/layout_events.h | 12 +- ion/include/ion/storage.h | 1 - kandinsky/include/kandinsky/color.h | 2 +- kandinsky/include/kandinsky/context.h | 5 +- kandinsky/include/kandinsky/ion_context.h | 1 - python/port/genhdr/qstrdefs.in.h | 2 + python/port/helpers.cpp | 3 + python/port/mod/kandinsky/modkandinsky.cpp | 139 ++++- python/port/mod/kandinsky/modkandinsky.h | 2 + .../port/mod/kandinsky/modkandinsky_table.c | 4 + python/port/port.cpp | 498 +++++++++++++++++- python/port/port.h | 208 ++++++++ 15 files changed, 958 insertions(+), 41 deletions(-) diff --git a/apps/external/extapp_api.cpp b/apps/external/extapp_api.cpp index 1e7fd7aeb..03cbef00a 100644 --- a/apps/external/extapp_api.cpp +++ b/apps/external/extapp_api.cpp @@ -81,5 +81,87 @@ extern "C" void (* const apiPointers[])(void) = { (void (*)(void)) extapp_waitForVBlank, (void (*)(void)) extapp_clipboardStore, (void (*)(void)) extapp_clipboardText, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + + // khicas from here, subject to change + (void (*)(void)) numworks_draw_string, + (void (*)(void)) numworks_draw_string_small, + (void (*)(void)) numworks_set_pixel, + (void (*)(void)) numworks_fill_rect, + (void (*)(void)) numworks_get_pixel, + (void (*)(void)) numworks_hide_graph, + (void (*)(void)) numworks_wait_1ms, + (void (*)(void)) waitforvblank, + (void (*)(void)) statuslinemsg, + (void (*)(void)) statusline, + (void (*)(void)) getkey, + (void (*)(void)) GetKey, + (void (*)(void)) alphawasactive, + (void (*)(void)) lock_alpha, + (void (*)(void)) reset_kbd, + (void (*)(void)) back_key_pressed, + (void (*)(void)) enable_back_interrupt, + (void (*)(void)) disable_back_interrupt, + (void (*)(void)) os_set_angle_unit, + (void (*)(void)) os_get_angle_unit, + (void (*)(void)) os_file_browser, + (void (*)(void)) file_exists, + (void (*)(void)) erase_file, + (void (*)(void)) read_file, + (void (*)(void)) write_file, + (void (*)(void)) mp_hal_input, (void (*)(void)) nullptr }; diff --git a/ion/include/ion/events.h b/ion/include/ion/events.h index 92905e9ca..ec55f9ea4 100644 --- a/ion/include/ion/events.h +++ b/ion/include/ion/events.h @@ -138,6 +138,25 @@ constexpr Event Arctangent = Event::ShiftKey(Keyboard::Key::Tangent); constexpr Event Equal = Event::ShiftKey(Keyboard::Key::Pi); constexpr Event Lower = Event::ShiftKey(Keyboard::Key::Sqrt); constexpr Event Greater = Event::ShiftKey(Keyboard::Key::Square); +constexpr Event shiftans = Event::ShiftKey(Keyboard::Key::Ans); +constexpr Event shiftplus = Event::ShiftKey(Keyboard::Key::Plus); +constexpr Event shiftfois = Event::ShiftKey(Keyboard::Key::Multiplication); +constexpr Event shiftdiv = Event::ShiftKey(Keyboard::Key::Division); +constexpr Event shiftminus = Event::ShiftKey(Keyboard::Key::Minus); +constexpr Event shift1 = Event::ShiftKey(Keyboard::Key::One); +constexpr Event shift2 = Event::ShiftKey(Keyboard::Key::Two); +constexpr Event shift3 = Event::ShiftKey(Keyboard::Key::Three); +constexpr Event shift4 = Event::ShiftKey(Keyboard::Key::Four); +constexpr Event shift5 = Event::ShiftKey(Keyboard::Key::Five); +constexpr Event shift6 = Event::ShiftKey(Keyboard::Key::Six); +constexpr Event shift7 = Event::ShiftKey(Keyboard::Key::Seven); +constexpr Event shift8 = Event::ShiftKey(Keyboard::Key::Eight); +constexpr Event shift9 = Event::ShiftKey(Keyboard::Key::Nine); +constexpr Event shift0 = Event::ShiftKey(Keyboard::Key::Zero); +constexpr Event shiftdot = Event::ShiftKey(Keyboard::Key::Dot); +constexpr Event shiftee = Event::ShiftKey(Keyboard::Key::EE); +constexpr Event shiftlp = Event::ShiftKey(Keyboard::Key::LeftParenthesis); +constexpr Event shiftrp = Event::ShiftKey(Keyboard::Key::RightParenthesis); constexpr Event BrightnessPlus = Event::ShiftKey(Keyboard::Key::Plus); constexpr Event BrightnessMinus = Event::ShiftKey(Keyboard::Key::Minus); @@ -161,7 +180,6 @@ constexpr Event ShiftThree = Event::ShiftKey(Keyboard::Key::Three); constexpr Event Colon = Event::AlphaKey(Keyboard::Key::XNT); constexpr Event SemiColon = Event::AlphaKey(Keyboard::Key::Var); constexpr Event DoubleQuotes = Event::AlphaKey(Keyboard::Key::Toolbox); -constexpr Event Percent = Event::AlphaKey(Keyboard::Key::Backspace); constexpr Event LowerA = Event::AlphaKey(Keyboard::Key::Exp); constexpr Event LowerB = Event::AlphaKey(Keyboard::Key::Ln); @@ -197,8 +215,11 @@ constexpr Event Space = Event::AlphaKey(Keyboard::Key::Minus); constexpr Event Question = Event::AlphaKey(Keyboard::Key::Zero); constexpr Event Exclamation = Event::AlphaKey(Keyboard::Key::Dot); +constexpr Event alphaans = Event::AlphaKey(Keyboard::Key::Ans); // Shift + Alpha +constexpr Event Percent = Event::ShiftAlphaKey(Keyboard::Key::Back); +constexpr Event SimpleQuote = Event::ShiftAlphaKey(Keyboard::Key::Toolbox); constexpr Event UpperA = Event::ShiftAlphaKey(Keyboard::Key::Exp); constexpr Event UpperB = Event::ShiftAlphaKey(Keyboard::Key::Ln); @@ -231,6 +252,7 @@ constexpr Event UpperX = Event::ShiftAlphaKey(Keyboard::Key::Two); constexpr Event UpperY = Event::ShiftAlphaKey(Keyboard::Key::Three); constexpr Event UpperZ = Event::ShiftAlphaKey(Keyboard::Key::Plus); +constexpr Event shiftalphaans = Event::ShiftAlphaKey(Keyboard::Key::Ans); // Special constexpr Event None = Event::Special(0); diff --git a/ion/include/ion/keyboard/layout_B2/layout_events.h b/ion/include/ion/keyboard/layout_B2/layout_events.h index 3a1f75260..01338d947 100644 --- a/ion/include/ion/keyboard/layout_B2/layout_events.h +++ b/ion/include/ion/keyboard/layout_B2/layout_events.h @@ -25,30 +25,30 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - TL(), TL(), TL(), T("(\x11)"), U(), U(), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), TL(), TL(), U(), - U(), U(), U(), U(), U(), U(), + T("17"), T("18"), T("19"), T("20"), T("21"), U(), + T("14"), T("15"), T("16"), T("factor(\x11)"), T("%"), U(), + T("11"), T("12"), T("13"), T("normal(\x11)"), T("\\"), U(), + T("10"), T("11"), T("12"), T("20"), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), T(":"), T(";"), T("\""), T("%"), + U(), U(), T(":"), T(";"), T("\""), U(), T("a"), T("b"), T("c"), T("d"), T("e"), T("f"), T("g"), T("h"), T("i"), T("j"), T("k"), T("l"), T("m"), T("n"), T("o"), T("p"), T("q"), U(), T("r"), T("s"), T("t"), T("u"), T("v"), U(), T("w"), T("x"), T("y"), T("z"), T(" "), U(), - T("?"), T("!"), U(), U(), U(), U(), + T("?"), T("!"), U(), TL(), U(), U(), // Shift+Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), U(), T("'"), T("%"), T("A"), T("B"), T("C"), T("D"), T("E"), T("F"), T("G"), T("H"), T("I"), T("J"), T("K"), T("L"), T("M"), T("N"), T("O"), T("P"), T("Q"), U(), T("R"), T("S"), T("T"), T("U"), T("V"), U(), T("W"), T("X"), T("Y"), T("Z"), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), TL(), U(), U(), }; #if DEBUG diff --git a/ion/include/ion/keyboard/layout_B3/layout_events.h b/ion/include/ion/keyboard/layout_B3/layout_events.h index a1f9502fa..fc9f20fe2 100644 --- a/ion/include/ion/keyboard/layout_B3/layout_events.h +++ b/ion/include/ion/keyboard/layout_B3/layout_events.h @@ -25,14 +25,14 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), TL(), TL(), U(), - U(), U(), U(), U(), U(), U(), + T("17"), T("18"), T("19"), T("20"), T("21"), U(), + T("14"), T("15"), T("16"), T("factor(\x11)"), T("%"), U(), + T("11"), T("12"), T("13"), T("normal(\x11)"), T("\\"), U(), + T("10"), T("11"), T("12"), T("20"), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), T(":"), T(";"), T("\""), T("%"), + U(), U(), T(":"), T(";"), T("\""), U(), T("a"), T("b"), T("c"), T("d"), T("e"), T("f"), T("g"), T("h"), T("i"), T("j"), T("k"), T("l"), T("m"), T("n"), T("o"), T("p"), T("q"), U(), @@ -42,7 +42,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { // Shift+Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), U(), T("'"), T("%"), T("A"), T("B"), T("C"), T("D"), T("E"), T("F"), T("G"), T("H"), T("I"), T("J"), T("K"), T("L"), T("M"), T("N"), T("O"), T("P"), T("Q"), U(), diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index 5138c1b76..fedd6ba35 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -115,7 +115,6 @@ public: void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension); void destroyRecordsWithExtension(const char * extension); -private: constexpr static uint32_t Magic = 0xEE0BDDBA; constexpr static size_t k_maxRecordSize = (1 << sizeof(record_size_t)*8); diff --git a/kandinsky/include/kandinsky/color.h b/kandinsky/include/kandinsky/color.h index 8e1cafa50..d15835ae7 100644 --- a/kandinsky/include/kandinsky/color.h +++ b/kandinsky/include/kandinsky/color.h @@ -34,8 +34,8 @@ public: static KDColor blend(KDColor first, KDColor second, uint8_t alpha); KDColor invert() const { return KDColor(~m_value); } operator uint16_t() const { return m_value; } -private: constexpr KDColor(uint16_t value) : m_value(value) {} +private: uint16_t m_value; }; diff --git a/kandinsky/include/kandinsky/context.h b/kandinsky/include/kandinsky/context.h index bcfc4ee74..9e267cea0 100644 --- a/kandinsky/include/kandinsky/context.h +++ b/kandinsky/include/kandinsky/context.h @@ -33,13 +33,10 @@ public: void fillRectWithPixels(KDRect rect, const KDColor * pixels, KDColor * workingBuffer); void blendRectWithMask(KDRect rect, KDColor color, const uint8_t * mask, KDColor * workingBuffer); void strokeRect(KDRect rect, KDColor color); - + KDContext(KDPoint origin, KDRect clippingRect); virtual void pushRect(KDRect, const KDColor * pixels) = 0; virtual void pushRectUniform(KDRect rect, KDColor color) = 0; virtual void pullRect(KDRect rect, KDColor * pixels) = 0; -protected: - KDContext(KDPoint origin, KDRect clippingRect); -private: KDRect absoluteFillRect(KDRect rect); KDPoint pushOrPullString(const char * text, KDPoint p, const KDFont * font, KDColor textColor, KDColor backgroundColor, int maxByteLength, bool push, int * result = nullptr); KDPoint m_origin; diff --git a/kandinsky/include/kandinsky/ion_context.h b/kandinsky/include/kandinsky/ion_context.h index 5cfd6cd9e..0dc1774fb 100644 --- a/kandinsky/include/kandinsky/ion_context.h +++ b/kandinsky/include/kandinsky/ion_context.h @@ -27,7 +27,6 @@ public: bool zoomInhibit; bool gammaEnabled; int zoomPosition; -private: KDIonContext(); void pushRect(KDRect rect, const KDColor * pixels) override; void pushRectUniform(KDRect rect, KDColor color) override; diff --git a/python/port/genhdr/qstrdefs.in.h b/python/port/genhdr/qstrdefs.in.h index 58c36bc71..5b96067ed 100644 --- a/python/port/genhdr/qstrdefs.in.h +++ b/python/port/genhdr/qstrdefs.in.h @@ -129,6 +129,8 @@ Q(.) Q(EE) Q(Ans) Q(EXE) +Q(get_key) +Q(Pause) // Turtle QSTRs Q(turtle) diff --git a/python/port/helpers.cpp b/python/port/helpers.cpp index 438f7ca47..71fb5e879 100644 --- a/python/port/helpers.cpp +++ b/python/port/helpers.cpp @@ -1,5 +1,8 @@ #include "helpers.h" #include +#ifdef SIMULATOR +#include +#endif extern "C" { #include "mphalport.h" } diff --git a/python/port/mod/kandinsky/modkandinsky.cpp b/python/port/mod/kandinsky/modkandinsky.cpp index 469fdb86b..6b8a3db5c 100644 --- a/python/port/mod/kandinsky/modkandinsky.cpp +++ b/python/port/mod/kandinsky/modkandinsky.cpp @@ -8,19 +8,22 @@ extern "C" { #include "port.h" static KDColor ColorForTuple(mp_obj_t tuple) { - size_t len; - mp_obj_t * elem; + if (MP_OBJ_IS_SMALL_INT(tuple)) // BP change: accept int for color + return MP_OBJ_SMALL_INT_VALUE(tuple); - mp_obj_get_array(tuple, &len, &elem); - if (len != 3) { - mp_raise_TypeError("color needs 3 components"); - } + size_t len; + mp_obj_t * elem; - return KDColor::RGB888( - mp_obj_get_int(elem[0]), - mp_obj_get_int(elem[1]), - mp_obj_get_int(elem[2]) - ); + mp_obj_get_array(tuple, &len, &elem); + if (len != 3) { + mp_raise_TypeError("color needs 3 components"); + } + + return KDColor::RGB888( + mp_obj_get_int(elem[0]), + mp_obj_get_int(elem[1]), + mp_obj_get_int(elem[2]) + ); } static mp_obj_t TupleForRGB(uint8_t r, uint8_t g, uint8_t b) { @@ -179,3 +182,117 @@ mp_obj_t modkandinsky_get_keys() { return result; } + +/* C-- SDK (c) B. Parisse, 2019 */ +mp_obj_t modkandinsky_Pause(mp_obj_t x) { + double d=mp_obj_get_float(x); + numworks_wait_1ms(d*1000); + return mp_const_none; +} + +#define LCD_WIDTH_PX 320 +#define LCD_HEIGHT_PX 222 + +void numworks_set_pixel(int x, int y, int color) { + if (x<0 || x>=LCD_WIDTH_PX || y<0 || y>=LCD_HEIGHT_PX) + return; + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,0)); + KDColor c(color); + KDPoint point(x,y+18); + KDIonContext::sharedContext()->pushRect(KDRect(point, 1, 1), &c); + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +void numworks_fill_rect(int x,int y,int w,int h,int c){ + KDColor color = c; + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,0)); +#if 1 + if (x<0){ + w += x; + x=0; + } + if (y<0){ + h += y; + y=0; + } + if (h+y>=LCD_HEIGHT_PX) + h=LCD_HEIGHT_PX-y; + if (x+w>=LCD_WIDTH_PX) + w=LCD_WIDTH_PX-x; + if (h<=0 || w<=0) + return; + KDRect rect(x,y+18,w,h); + KDIonContext::sharedContext()->pushRectUniform(rect,color); +#else + KDRect rect(x,y,w,h); + KDIonContext::sharedContext()->fillRect(rect, color); +#endif + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +int numworks_get_pixel(int x, int y) { + KDPoint point(x,y); + KDColor c = KDIonContext::sharedContext()->getPixel(point); + return c; +} + +int numworks_draw_string(int x,int y,int c,int bg,const char * text,bool fake){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + KDPoint point(x,y); + if (ptr) + ptr->displaySandbox(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,18,320,fake?0:222)); + ctx->setOrigin(KDPoint(0,18)); + point=KDIonContext::sharedContext()->drawString(text, point, KDFont::LargeFont, c, bg); + ctx->setClippingRect(save); + ctx->setOrigin(o); + return point.x(); +} + +int numworks_draw_string_small(int x,int y,int c,int bg,const char * text,bool fake){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + KDPoint point(x,y); + if (ptr) + ptr->displaySandbox(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,18,320,fake?0:222)); + ctx->setOrigin(KDPoint(0,18)); + point=ctx->drawString(text, point, KDFont::SmallFont, c, bg); + ctx->setClippingRect(save); + ctx->setOrigin(o); + return point.x(); +} + +void numworks_hide_graph(){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + if (ptr) + ptr->hideSandbox(); +} + +void numworks_show_graph(){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + if (ptr) + ptr->displaySandbox(); +} + +// Python module get_key() addition +mp_obj_t modkandinsky_get_key() { + micropython_port_interrupt_if_needed(); + int key=getkey(false); // no suspend + return mp_obj_new_int(key); +} diff --git a/python/port/mod/kandinsky/modkandinsky.h b/python/port/mod/kandinsky/modkandinsky.h index 4191155bc..15bc28a31 100644 --- a/python/port/mod/kandinsky/modkandinsky.h +++ b/python/port/mod/kandinsky/modkandinsky.h @@ -7,3 +7,5 @@ mp_obj_t modkandinsky_draw_string(size_t n_args, const mp_obj_t *args); mp_obj_t modkandinsky_fill_rect(size_t n_args, const mp_obj_t *args); mp_obj_t modkandinsky_wait_vblank(); mp_obj_t modkandinsky_get_keys(); +mp_obj_t modkandinsky_get_key(); +mp_obj_t modkandinsky_Pause(mp_obj_t x) ; diff --git a/python/port/mod/kandinsky/modkandinsky_table.c b/python/port/mod/kandinsky/modkandinsky_table.c index 253f856a7..cf8490c6f 100644 --- a/python/port/mod/kandinsky/modkandinsky_table.c +++ b/python/port/mod/kandinsky/modkandinsky_table.c @@ -7,6 +7,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_draw_string_obj, 3, 5, m STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_fill_rect_obj, 5, 5, modkandinsky_fill_rect); STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_wait_vblank_obj, modkandinsky_wait_vblank); STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_get_keys_obj, modkandinsky_get_keys); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_get_key_obj, modkandinsky_get_key); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(modkandinsky_Pause_obj, modkandinsky_Pause); STATIC const mp_rom_map_elem_t modkandinsky_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_kandinsky) }, @@ -17,6 +19,8 @@ STATIC const mp_rom_map_elem_t modkandinsky_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_fill_rect), (mp_obj_t)&modkandinsky_fill_rect_obj }, { MP_ROM_QSTR(MP_QSTR_wait_vblank), (mp_obj_t)&modkandinsky_wait_vblank_obj }, { MP_ROM_QSTR(MP_QSTR_get_keys), (mp_obj_t)&modkandinsky_get_keys_obj }, + { MP_ROM_QSTR(MP_QSTR_get_key), (mp_obj_t)&modkandinsky_get_key_obj }, + { MP_ROM_QSTR(MP_QSTR_Pause), (mp_obj_t)&modkandinsky_Pause_obj }, }; STATIC MP_DEFINE_CONST_DICT(modkandinsky_module_globals, modkandinsky_module_globals_table); diff --git a/python/port/port.cpp b/python/port/port.cpp index 163aefd24..0a1735bdd 100644 --- a/python/port/port.cpp +++ b/python/port/port.cpp @@ -1,6 +1,14 @@ +#ifdef SIMULATOR +#include +#endif +#include #include "port.h" -#include +#include +#include +#include +#include "../../apps/apps_container.h" +#include "../../apps/global_preferences.h" #include #include @@ -78,9 +86,9 @@ void MicroPython::ExecutionEnvironment::runCode(const char * str) { /* End of mp_obj_print_exception. */ } - assert(sCurrentExecutionEnvironment == this); - sCurrentExecutionEnvironment = nullptr; -} + assert(sCurrentExecutionEnvironment == this); + sCurrentExecutionEnvironment = nullptr; + } void MicroPython::ExecutionEnvironment::interrupt() { mp_keyboard_interrupt(); @@ -197,11 +205,485 @@ mp_import_stat_t mp_import_stat(const char *path) { } void mp_hal_stdout_tx_strn_cooked(const char * str, size_t len) { - assert(sCurrentExecutionEnvironment != nullptr); - sCurrentExecutionEnvironment->printText(str, len); + if (sCurrentExecutionEnvironment != nullptr) + sCurrentExecutionEnvironment->printText(str, len); } const char * mp_hal_input(const char * prompt) { - assert(sCurrentExecutionEnvironment != nullptr); - return sCurrentExecutionEnvironment->inputText(prompt); + if (sCurrentExecutionEnvironment != nullptr) + return sCurrentExecutionEnvironment->inputText(prompt); + return 0; } + +/* C-- SDK , (c) B. Parisse 2019 */ + +const char * read_file(const char * filename){ +#if 1 + Ion::Storage * s=Ion::Storage::sharedStorage(); + const Ion::Storage::Record r=s->recordNamed(filename); + if (r.isNull()) + return 0; + Ion::Storage::Record::Data d=r.value(); + const char * ptr=(const char *)d.buffer; + if (ptr) + return ptr+1; + else + return 0; +#endif + if (sScriptProvider != nullptr) + return sScriptProvider->contentOfScript(filename); + return "undef"; +} + +bool write_file(const char * filename,const char * content,size_t len){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + auto res=s->createRecordWithFullName(filename,content,strlen(content)+1); + if (res==Ion::Storage::Record::ErrorStatus::NameTaken){ + auto r=s->recordNamed(filename); + Ion::Storage::Record::Data d; + d.buffer=content; + d.size=(len?len:strlen(content))+1; + return r.setValue(d)==Ion::Storage::Record::ErrorStatus::None; + } + if (res==Ion::Storage::Record::ErrorStatus::None) + return write_file(filename,content,len); + return false; +} + +bool file_exists(const char * filename){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + return s->isFullNameTaken(filename); +} + +bool erase_file(const char * filename){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + auto r= s->recordNamed(filename); + if (r.isNull()) + return false; + r.destroy(); + return true; +} + + +#if 1 +int os_file_browser(const char ** filenames,int maxrecords,const char * extension){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + int n=s->numberOfRecordsWithExtension(extension); + if (!n) return 0; + if (n>maxrecords) n=maxrecords; + for (int i=0;irecordWithExtensionAtIndex(extension, i); + filenames[i]=r.fullName(); + } + filenames[n]=0; + return n; +} + // const char * ptr=(const char *)r.value().buffer; + /* storage.h + Ion::Storage::Record::Data structure avec 2 membres + const void * buffer et size_t size + + Record(const char * fullName = nullptr); + Record(const char * basename, const char * extension); + Data value(); + Ion::Storage::Record::ErrorStatus setValue(Ion::Storage::Record::Data); + void destroy(void); + + // Record creation + Record::ErrorStatus createRecordWithFullName(const char * fullName, const void * data, size_t size); + Record::ErrorStatus createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size); + + // Record getters + Record recordWithExtensionAtIndex(const char * extension, int index); + Record recordNamed(const char * fullName); + Record recordBaseNamedWithExtension(const char * baseName, const char * extension); + Record recordBaseNamedWithExtensions(const char * baseName, const char * const extension[], size_t numberOfExtensions); + + // Record destruction + void destroyAllRecords(); + void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension); + void destroyRecordsWithExtension(const char * extension); + + + */ +#endif + +void statuslinemsg(const char * msg){ + AppsContainer::sharedAppsContainer()->reloadTitleBarView(); + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + if (ptr) + ptr->displaySandbox(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,280,18)); + ctx->setOrigin(KDPoint(0,0)); + KDRect rect(0,0,280,18); + KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + if (strlen(msg)>25) + ctx->drawString(msg, KDPoint(0,0), KDFont::SmallFont, 0, 64934); + else + ctx->drawString(msg, KDPoint(0,0), KDFont::LargeFont, 0, 64934); + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +bool os_set_angle_unit(int mode){ + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + if (mode==0){ // rad + preferences->setAngleUnit(Poincare::Preferences::AngleUnit::Radian); + return true; + } + if (mode==1){ // deg + preferences->setAngleUnit(Poincare::Preferences::AngleUnit::Degree); + return true; + } + return false; + if (mode==2){ // grad + return true; + } +} + +int os_get_angle_unit(){ + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + if (preferences->angleUnit()==Poincare::Preferences::AngleUnit::Radian) + return 0; + if (preferences->angleUnit()==Poincare::Preferences::AngleUnit::Degree) + return 1; + return 2; +} + +#ifdef SIMULATOR +#define TICKS_PER_MINUTE 60000 +#else +#define TICKS_PER_MINUTE 11862 +extern const void * _stack_start; +extern const void * _heap_start; +#endif +//int time_shift=0; // set it via time() command in KhiCAS +void statusline(int mode, size_t heap){ + AppsContainer::sharedAppsContainer()->reloadTitleBarView(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,18)); + ctx->setOrigin(KDPoint(0,0)); + KDRect rect(0,0,mode==1?320:280,18); + KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + const char * text=0; + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + if (preferences->angleUnit() == Poincare::Preferences::AngleUnit::Radian) + text="rad"; + else + text="deg"; + // ctx->drawString(text, KDPoint(5,1), KDFont::SmallFont, 0, 63488 /* Palette::Red*/); + ctx->drawString(text, KDPoint(5,1), KDFont::SmallFont, 0, 64934); +#ifdef GIAC_LINKED + if (khicas_eval) + text="KHICAS"; + else + text="PYTHON"; +#else + text="KHICAS"; +#endif + ctx->drawString(text, KDPoint(70,1), KDFont::SmallFont, 0, 64934); + char bufheap[16]; +#if 0 //ndef SIMULATOR +#endif + int x; + x=(heap&0xf0000000)>>28; + bufheap[0]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf000000)>>24; + bufheap[1]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf00000)>>20; + bufheap[2]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf0000)>>16; + bufheap[3]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf000)>>12; + bufheap[4]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf00)>>8; + bufheap[5]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf0)>>4; + bufheap[6]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf); + bufheap[7]=(x>9?'a'+(x-10):'0'+x); + bufheap[8]=0; + if(heap != 0) ctx->drawString(bufheap,KDPoint(130,1),KDFont::SmallFont, 0, 64934); +#ifdef GIAC_SHOWTIME + int d=(Ion::Timing::millis()/TICKS_PER_MINUTE +time_shift) % (24*60); // minutes + char buf[32]={0,0,0,0}; + int h=d/60; + buf[0]='0'+h/10; + buf[1]='0'+(h%10); + buf[2]=':'; + ctx->drawString(buf, KDPoint(148,1), KDFont::SmallFont, 0, 64934); + int mn=d%60; + buf[0]='0'+mn/10; + buf[1]='0'+(mn%10); + buf[2]=0; + ctx->drawString(buf, KDPoint(168,1), KDFont::SmallFont, 0, 64934); +#endif + text=" "; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::Shift) + text="shift "; + else { + if (Ion::Events::isAlphaActive()){ + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::AlphaLock) + text="alphal"; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::ShiftAlphaLock) + text="ALPHAL"; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::Alpha) + text="1alpha"; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::ShiftAlpha) + text="1ALPHA"; + } + } + ctx->drawString(text, KDPoint(232,1), KDFont::SmallFont, 0, 64934 /* Palette::YellowDark*/); + if (mode==1){ + if (Ion::USB::isPlugged()) + text="charge"; + else { + auto c=Ion::Battery::level(); + if (c==Ion::Battery::Charge::EMPTY) + text="empty "; + if (c==Ion::Battery::Charge::LOW) + text="low "; + if (c==Ion::Battery::Charge::FULL) + text="full "; + } + ctx->drawString(text, KDPoint(280,1), KDFont::SmallFont, 0, 64934 /* Palette::YellowDark*/); + } + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +bool isalphaactive(){ + return Ion::Events::isAlphaActive(); +} + +void lock_alpha(){ + Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock); + statusline(0,0); +} + +void reset_kbd(){ + Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default); + statusline(0,0); +} + +bool alphawasactive_=false; +bool alphawasactive(){ + return alphawasactive_; +} + +bool waitforvblank(){ + return Ion::Display::waitForVBlank(); +} + +bool back_key_pressed() { + static int c = 0; + + ++c ; + if (c<400 || (c & 0xf)!= 0) { + return false; + } +#ifdef SIMULATOR + Fl::wait(0.00001); +#endif + + Ion::Keyboard::State scan = Ion::Keyboard::scan(); + // if (scan!=16) std::cerr << scan << '\n'; + Ion::Keyboard::Key interruptKey = static_cast(mp_interrupt_char); + if (scan.keyDown(interruptKey) + // || scan.keyDown(static_cast(16)) + ) + return true; + return false; +} + +int getkey_raw(bool allow_suspend){ + int key=-1; + size_t t1=Ion::Timing::millis(); + for (;;){ + int timeout=10000; + alphawasactive_=Ion::Events::isAlphaActive(); + Ion::Events::Event event=Ion::Events::getEvent(&timeout); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,18)); + KDRect rect(90,63,140,75); + if (event==Ion::Events::None){ + size_t t2=Ion::Timing::millis(); + if (t2-t1>2*TICKS_PER_MINUTE){ + // KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + event=Ion::Events::OnOff; + } + } + else + t1=Ion::Timing::millis(); + if (event == Ion::Events::USBPlug) { + statusline(0,0); + // KDIonContext::sharedContext()->pushRectUniform(rect,33333); + if (Ion::USB::isPlugged()) { + if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { + Ion::LED::setColor(KDColorBlack); + Ion::LED::updateColorWithPlugAndCharge(); + GlobalPreferences::sharedGlobalPreferences()->setExamMode(false); + // displayExamModePopUp(false); + } else { + Ion::USB::enable(); + } + Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); + } else { + Ion::USB::disable(); + } + } + if (event == Ion::Events::USBEnumeration || event == Ion::Events::USBPlug || event == Ion::Events::BatteryCharging) { + Ion::LED::updateColorWithPlugAndCharge(); + } + if (event == Ion::Events::USBEnumeration + ) { + KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + if (Ion::USB::isPlugged()) { + /* Just after a software update, the battery timer does not have time to + * fire before the calculator enters DFU mode. As the DFU mode blocks the + * event loop, we update the battery state "manually" here. + * We do it before switching to USB application to redraw the battery + * pictogram. */ + // updateBatteryState(); + KDIonContext::sharedContext()->pushRectUniform(rect,22222); + auto ctx=KDIonContext::sharedContext(); + int y=58; + ctx->drawString("Connecte ! ", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + y+=18; + ctx->drawString(" DFU mode ", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + y+=18; + ctx->drawString("Back quitte", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + y-=18; + Ion::USB::DFU(); + KDIonContext::sharedContext()->pushRectUniform(rect,44444); + ctx->drawString("Deconnecte!", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + // Update LED when exiting DFU mode + Ion::LED::updateColorWithPlugAndCharge(); + } else { + /* Sometimes, the device gets an ENUMDNE interrupts when being unplugged + * from a non-USB communicating host (e.g. a USB charger). The interrupt + * must me cleared: if not the next enumeration attempts will not be + * detected. */ + Ion::USB::clearEnumerationInterrupt(); + } + } + if (event.isKeyboardEvent()) { + // m_backlightDimmingTimer.reset(); + // m_suspendTimer.reset(); + Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); + } + ctx->setClippingRect(save); + ctx->setOrigin(o); + + if (event==Ion::Events::Shift || event==Ion::Events::Alpha){ + statusline(0,0); + continue; + } + if (event.isKeyboardEvent()){ + key=event.id(); + if (key==17 || key==4 || key==5 || key==52) + reset_kbd(); + if (allow_suspend && (key==7 || key==8) ){ // power + Ion::Power::suspend(true); + numworks_fill_rect(0,0,320,240,65535); + Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); + AppsContainer::sharedAppsContainer()->reloadTitleBarView(); + //AppsContainer::sharedAppsContainer()->redrawWindow(); + statusline(1,0); + //continue; + } + else + statusline(0,0); + break; + } + } + return key; +} + +const short int translated_keys[]= + { + // non shifted + KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_XTT,KEY_CTRL_VARS,KEY_CTRL_CATALOG,KEY_CTRL_DEL, + KEY_CHAR_EXPN,KEY_CHAR_LN,KEY_CHAR_LOG,KEY_CHAR_IMGNRY,',',KEY_CHAR_POW, + KEY_CHAR_SIN,KEY_CHAR_COS,KEY_CHAR_TAN,KEY_CHAR_PI,KEY_CHAR_ROOT,KEY_CHAR_SQUARE, + '7','8','9','(',')',-1, + '4','5','6','*','/',-1, + '1','2','3','+','-',-1, + '0','.',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, + // shifted + KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_CUT,KEY_CTRL_CLIP,KEY_CTRL_PASTE,KEY_CTRL_AC, + KEY_CHAR_LBRCKT,KEY_CHAR_RBRCKT,KEY_CHAR_LBRACE,KEY_CHAR_RBRACE,'_',KEY_CHAR_STORE, + KEY_CHAR_ASIN,KEY_CHAR_ACOS,KEY_CHAR_ATAN,'=','<','>', + KEY_CTRL_F7,KEY_CTRL_F8,KEY_CTRL_F9,KEY_CTRL_F13,KEY_CTRL_F14,-1, + KEY_CTRL_F4,KEY_CTRL_F5,KEY_CTRL_F6,KEY_CHAR_FACTOR,'%',-1, + KEY_CTRL_F1,KEY_CTRL_F2,KEY_CTRL_F3,KEY_CHAR_NORMAL,'\\',-1, + KEY_CTRL_F10,KEY_CTRL_F11,KEY_CTRL_F12,KEY_SHIFT_ANS,KEY_CTRL_EXE,-1, + // alpha + KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','"',KEY_CTRL_DEL, + 'a','b','c','d','e','f', + 'g','h','i','j','k','l', + 'm','n','o','p','q',-1, + 'r','s','t','u','v',-1, + 'w','x','y','z',' ',-1, + '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, + // alpha shifted + KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','\'','%', + 'A','B','C','D','E','F', + 'G','H','I','J','K','L', + 'M','N','O','P','Q',-1, + 'R','S','T','U','V',-1, + 'W','X','Y','Z',' ',-1, + '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, + }; + +int getkey(bool allow_suspend){ + int k=getkey_raw(allow_suspend); + // translate + return translated_keys[k]; +} + +// Casio prototype +void GetKey(int * key){ + *key=getkey(true); +} + + +void numworks_wait_1ms(int ms){ + for (int i=0;i(Ion::Keyboard::Key::Back); + if (scan.keyDown(interruptKey)) + return; + Ion::Timing::msleep(128); + } + Ion::Timing::msleep(ms % 128); +} + +void enable_back_interrupt(){ + mp_interrupt_char = (int)Ion::Keyboard::Key::Back; +} + +void disable_back_interrupt(){ + mp_interrupt_char = -1; +} + diff --git a/python/port/port.h b/python/port/port.h index f0b3a0407..869b6f937 100644 --- a/python/port/port.h +++ b/python/port/port.h @@ -36,4 +36,212 @@ void registerScriptProvider(ScriptProvider * s); }; +extern "C" { +/* + basic SDK for direct control of the calculator like in KhiCAS + */ + bool waitforvblank(); + int os_file_browser(const char ** filenames,int maxrecords,const char * extension); + void numworks_hide_graph(); + void numworks_show_graph(); + void enable_back_interrupt(); + void disable_back_interrupt(); + int os_get_angle_unit(); + bool os_set_angle_unit(int mode); + const char * read_file(const char * filename); + bool write_file(const char * filename,const char * content,size_t len); +int getkey_raw(bool allow_suspend); // Numworks scan code +int getkey(bool allow_suspend); // transformed +void GetKey(int * key); // Casio like +bool isalphaactive(); +bool alphawasactive(); // alpha status before getkey +bool back_key_pressed() ; +void lock_alpha(); +void reset_kbd(); +void statusline(int mode=0, size_t=0); // display status line +void statuslinemsg(const char * msg); // display a message in statusline +void numworks_fill_rect(int x,int y,int w,int h,int c); // y=0 is automatically translated by 18 for statusline +void numworks_set_pixel(int x,int y,int c); +int numworks_get_pixel(int x,int y); +/* draw_string returns new x position, use fake=true to compute without drawing */ +int numworks_draw_string(int x,int y,int c,int bg,const char * s,bool fake=false); +int numworks_draw_string_small(int x,int y,int c,int bg,const char * s,bool fake=false); +// scriptstore +bool file_exists(const char * filename); +bool erase_file(const char * filename); +const char * read_file(const char * filename); +bool write_file(const char * filename,const char * s,size_t len=0); +int giac_filebrowser(char * filename,const char * extension,const char * title); +void numworks_wait_1ms(int ms); +//double millis(); +//extern int time_shift; // shift for the clock + + +// Character codes +#define KEY_CHAR_0 0x30 +#define KEY_CHAR_1 0x31 +#define KEY_CHAR_2 0x32 +#define KEY_CHAR_3 0x33 +#define KEY_CHAR_4 0x34 +#define KEY_CHAR_5 0x35 +#define KEY_CHAR_6 0x36 +#define KEY_CHAR_7 0x37 +#define KEY_CHAR_8 0x38 +#define KEY_CHAR_9 0x39 +#define KEY_CHAR_DP 0x2e +#define KEY_CHAR_EXP 0x0f +#define KEY_CHAR_PMINUS 30200 +#define KEY_CHAR_PLUS 43 +#define KEY_CHAR_MINUS 45 +#define KEY_CHAR_MULT 42 +#define KEY_CHAR_DIV 47 +#define KEY_CHAR_FRAC 0xbb +#define KEY_CHAR_LPAR 0x28 +#define KEY_CHAR_RPAR 0x29 +#define KEY_CHAR_COMMA 0x2c +#define KEY_CHAR_STORE 0x0e +#define KEY_CHAR_LOG 0x95 +#define KEY_CHAR_LN 0x85 +#define KEY_CHAR_SIN 0x81 +#define KEY_CHAR_COS 0x82 +#define KEY_CHAR_TAN 0x83 +#define KEY_CHAR_SQUARE 0x8b +#define KEY_CHAR_POW 0xa8 +#define KEY_CHAR_IMGNRY 0x7f50 +#define KEY_CHAR_LIST 0x7f51 +#define KEY_CHAR_MAT 0x7f40 +#define KEY_CHAR_EQUAL 0x3d +#define KEY_CHAR_PI 0xd0 +#define KEY_CHAR_ANS 0xc0 +#define KEY_SHIFT_ANS 0xc1 +#define KEY_CHAR_LBRCKT 0x5b +#define KEY_CHAR_RBRCKT 0x5d +#define KEY_CHAR_LBRACE 0x7b +#define KEY_CHAR_RBRACE 0x7d +#define KEY_CHAR_CR 0x0d +#define KEY_CHAR_CUBEROOT 0x96 +#define KEY_CHAR_RECIP 0x9b +#define KEY_CHAR_ANGLE 0x7f54 +#define KEY_CHAR_EXPN10 0xb5 +#define KEY_CHAR_EXPN 0xa5 +#define KEY_CHAR_ASIN 0x91 +#define KEY_CHAR_ACOS 0x92 +#define KEY_CHAR_ATAN 0x93 +#define KEY_CHAR_ROOT 0x86 +#define KEY_CHAR_POWROOT 0xb8 +#define KEY_CHAR_SPACE 0x20 +#define KEY_CHAR_DQUATE 0x22 +#define KEY_CHAR_VALR 0xcd +#define KEY_CHAR_THETA 0xce +#define KEY_CHAR_FACTOR 0xda +#define KEY_CHAR_NORMAL 0xdb +#define KEY_CHAR_A 0x41 +#define KEY_CHAR_B 0x42 +#define KEY_CHAR_C 0x43 +#define KEY_CHAR_D 0x44 +#define KEY_CHAR_E 0x45 +#define KEY_CHAR_F 0x46 +#define KEY_CHAR_G 0x47 +#define KEY_CHAR_H 0x48 +#define KEY_CHAR_I 0x49 +#define KEY_CHAR_J 0x4a +#define KEY_CHAR_K 0x4b +#define KEY_CHAR_L 0x4c +#define KEY_CHAR_M 0x4d +#define KEY_CHAR_N 0x4e +#define KEY_CHAR_O 0x4f +#define KEY_CHAR_P 0x50 +#define KEY_CHAR_Q 0x51 +#define KEY_CHAR_R 0x52 +#define KEY_CHAR_S 0x53 +#define KEY_CHAR_T 0x54 +#define KEY_CHAR_U 0x55 +#define KEY_CHAR_V 0x56 +#define KEY_CHAR_W 0x57 +#define KEY_CHAR_X 0x58 +#define KEY_CHAR_Y 0x59 +#define KEY_CHAR_Z 0x5a + + +// Control codes +#define KEY_CTRL_NOP 30202 +#define KEY_CTRL_EXE 30201 +#define KEY_CTRL_DEL 30025 +#define KEY_CTRL_AC 30070 +#define KEY_CTRL_FD 30046 +#define KEY_CTRL_UNDO 30045 +#define KEY_CTRL_XTT 30001 +#define KEY_CTRL_EXIT 5 +#define KEY_CTRL_OK 4 +#define KEY_CTRL_SHIFT 30006 +#define KEY_CTRL_ALPHA 30007 +#define KEY_CTRL_OPTN 30008 +#define KEY_CTRL_VARS 30030 +#define KEY_CTRL_UP 1 +#define KEY_CTRL_DOWN 2 +#define KEY_CTRL_LEFT 0 +#define KEY_CTRL_RIGHT 3 +#define KEY_CTRL_F1 30009 +#define KEY_CTRL_F2 30010 +#define KEY_CTRL_F3 30011 +#define KEY_CTRL_F4 30012 +#define KEY_CTRL_F5 30013 +#define KEY_CTRL_F6 30014 +#define KEY_CTRL_F7 30015 +#define KEY_CTRL_F8 30016 +#define KEY_CTRL_F9 30017 +#define KEY_CTRL_F10 30018 +#define KEY_CTRL_F11 30019 +#define KEY_CTRL_F12 30020 +#define KEY_CTRL_F13 30021 +#define KEY_CTRL_F14 30022 +#define KEY_CTRL_CATALOG 30100 +#define KEY_CTRL_CAPTURE 30055 +#define KEY_CTRL_CLIP 30050 +#define KEY_CTRL_CUT 30250 +#define KEY_CTRL_PASTE 30036 +#define KEY_CTRL_INS 30033 +#define KEY_CTRL_MIXEDFRAC 30054 +#define KEY_CTRL_FRACCNVRT 30026 +#define KEY_CTRL_QUIT 30029 +#define KEY_CTRL_PRGM 30028 +#define KEY_CTRL_SETUP 30037 +#define KEY_CTRL_PAGEUP 30052 +#define KEY_CTRL_PAGEDOWN 30053 +#define KEY_CTRL_MENU 30003 +#define KEY_SHIFT_OPTN 30059 +#define KEY_CTRL_RESERVE1 30060 +#define KEY_CTRL_RESERVE2 30061 +#define KEY_SHIFT_LEFT 30062 +#define KEY_SHIFT_RIGHT 30063 + +#define KEY_PRGM_ACON 10 +#define KEY_PRGM_DOWN 37 +#define KEY_PRGM_EXIT 47 +#define KEY_PRGM_F1 79 +#define KEY_PRGM_F2 69 +#define KEY_PRGM_F3 59 +#define KEY_PRGM_F4 49 +#define KEY_PRGM_F5 39 +#define KEY_PRGM_F6 29 +#define KEY_PRGM_LEFT 38 +#define KEY_PRGM_NONE 0 +#define KEY_PRGM_RETURN 31 +#define KEY_PRGM_RIGHT 27 +#define KEY_PRGM_UP 28 +#define KEY_PRGM_1 72 +#define KEY_PRGM_2 62 +#define KEY_PRGM_3 52 +#define KEY_PRGM_4 73 +#define KEY_PRGM_5 63 +#define KEY_PRGM_6 53 +#define KEY_PRGM_7 74 +#define KEY_PRGM_8 64 +#define KEY_PRGM_9 54 +#define KEY_PRGM_A 76 +#define KEY_PRGM_F 26 +#define KEY_PRGM_ALPHA 77 +#define KEY_PRGM_SHIFT 78 +#define KEY_PRGM_MENU 48 +} #endif From 6762bb05aff002a76b4e99062454fc054c9354f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 13 Dec 2019 10:05:43 +0100 Subject: [PATCH 048/130] [ion/cache] Add missing memory barrier __asm volatile("nop") creates a memory barrier that prevents a crash on the flasher. Scenario: On the n0110, build flasher.bin, flash it at 0x20030000, build bench.bin, flash it using the flasher at 0x20008000 -> the flasher cannot make the device jump to the bench and crashes in the method Ion::Device::Reset::Jump, inside Ion::Device::Cache::disableDCache(). --- ion/src/device/n0110/drivers/cache.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ion/src/device/n0110/drivers/cache.cpp b/ion/src/device/n0110/drivers/cache.cpp index 1614d528b..af907386f 100644 --- a/ion/src/device/n0110/drivers/cache.cpp +++ b/ion/src/device/n0110/drivers/cache.cpp @@ -41,6 +41,7 @@ void privateCleanInvalidateDisableDCache(bool clean, bool invalidate, bool disab dcisw.setWAY(w); CORTEX.DCISW()->set(dcisw); } + __asm volatile("nop"); } while (w-- != 0); } while (sets-- != 0); From 5ae425f1049a2b91b453ce2c95d27023f5f5ada2 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Sat, 14 Dec 2019 15:51:12 +0100 Subject: [PATCH 049/130] [apps/settings] Fixed compilation error Co-Authored-By: Quentin --- apps/settings/sub_menu/exam_mode_controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index 61421af71..24d6f93c3 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -27,7 +27,7 @@ void ExamModeController::didEnterResponderChain(Responder * previousFirstRespond bool ExamModeController::handleEvent(Ion::Events::Event event) { I18n::Message childLabel = m_messageTreeModel->children(selectedRow())->label(); if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) { - if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) { + if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { return true; } if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive) { From ef8cd53cec87d9cb7be84d30f07d5b3e411dc566 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Sun, 15 Dec 2019 09:26:07 +0100 Subject: [PATCH 050/130] [apps/title bar] Added indicator for symbolic calculation in exam mode. --- apps/shared.de.i18n | 1 + apps/shared.en.i18n | 1 + apps/shared.es.i18n | 1 + apps/shared.fr.i18n | 1 + apps/shared.pt.i18n | 1 + apps/title_bar_view.cpp | 11 ++++++++++- 6 files changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/shared.de.i18n b/apps/shared.de.i18n index 6309dac2a..386c32c9a 100644 --- a/apps/shared.de.i18n +++ b/apps/shared.de.i18n @@ -61,6 +61,7 @@ StorageMemoryFull1 = "Der Speicher ist voll. Löschen Sie" StorageMemoryFull2 = "von Daten und versuchen Sie es erneut." StoreExpressionNotAllowed = "'store' ist verboten" SyntaxError = "Syntaxfehler" +Sym = "sym" TEnd = "T Endwert" ThetaEnd = "θ Endwert" ThetaStart = "θ Startwert" diff --git a/apps/shared.en.i18n b/apps/shared.en.i18n index 952b615b8..abefd01cf 100644 --- a/apps/shared.en.i18n +++ b/apps/shared.en.i18n @@ -61,6 +61,7 @@ Step = "Step" StorageMemoryFull1 = "The memory is full." StorageMemoryFull2 = "Erase data and try again." SyntaxError = "Syntax error" +Sym = "sym" TEnd = "T end" ThetaEnd = "θ end" ThetaStart = "θ start" diff --git a/apps/shared.es.i18n b/apps/shared.es.i18n index 53570691e..fb670a6a9 100644 --- a/apps/shared.es.i18n +++ b/apps/shared.es.i18n @@ -61,6 +61,7 @@ StorageMemoryFull1 = "La memoria está llena." StorageMemoryFull2 = "Borre datos e intente de nuevo." StoreExpressionNotAllowed = "'store' no está permitido" SyntaxError = "Error sintáctico" +Sym = "sim" TEnd = "T fin" ThetaEnd = "θ fin" ThetaStart = "θ inicio" diff --git a/apps/shared.fr.i18n b/apps/shared.fr.i18n index 15e2d760c..30c3c7f1c 100644 --- a/apps/shared.fr.i18n +++ b/apps/shared.fr.i18n @@ -61,6 +61,7 @@ StorageMemoryFull1 = "La mémoire est pleine." StorageMemoryFull2 = "Effacez des données et réessayez." StoreExpressionNotAllowed = "'store' n'est pas autorisé" SyntaxError = "Attention à la syntaxe" +Sym = "sym" TEnd = "T fin" ThetaEnd = "θ fin" ThetaStart = "θ début" diff --git a/apps/shared.pt.i18n b/apps/shared.pt.i18n index 9d624d78d..be721eb4e 100644 --- a/apps/shared.pt.i18n +++ b/apps/shared.pt.i18n @@ -61,6 +61,7 @@ StorageMemoryFull1 = "A memoria esta cheia." StorageMemoryFull2 = "Apage dados e tente novamente." StoreExpressionNotAllowed = "'store' não está permitido" SyntaxError = "Erro de sintaxe" +Sym = "sim" TEnd = "T fim" ThetaEnd = "θ fim" ThetaStart = "θ inicio" diff --git a/apps/title_bar_view.cpp b/apps/title_bar_view.cpp index d1f2ce4de..8e64ba19e 100644 --- a/apps/title_bar_view.cpp +++ b/apps/title_bar_view.cpp @@ -85,6 +85,14 @@ void TitleBarView::refreshPreferences() { char buffer[bufferSize]; int numberOfChar = 0; Preferences * preferences = Preferences::sharedPreferences(); + if (GlobalPreferences::sharedGlobalPreferences()->examMode() && Preferences::sharedPreferences()->isExamSymbolic()) { + // Display "cas" if in exam mode with symbolic computation enabled + numberOfChar += strlcpy(buffer+numberOfChar, I18n::translate(I18n::Message::Sym), bufferSize - numberOfChar); + assert(numberOfChar < bufferSize-1); + assert(UTF8Decoder::CharSizeOfCodePoint('/') == 1); + buffer[numberOfChar++] = '/'; + } + assert(numberOfChar <= bufferSize); { // Display Sci/ or Eng/ if the print float mode is not decimal const Preferences::PrintFloatMode printFloatMode = preferences->displayMode(); @@ -93,7 +101,7 @@ void TitleBarView::refreshPreferences() { assert(printFloatMode == Preferences::PrintFloatMode::Scientific || printFloatMode == Preferences::PrintFloatMode::Engineering); I18n::Message printMessage = printFloatMode == Preferences::PrintFloatMode::Scientific ? I18n::Message::Sci : I18n::Message::Eng; - numberOfChar += strlcpy(buffer, I18n::translate(printMessage), bufferSize); + numberOfChar += strlcpy(buffer+numberOfChar, I18n::translate(printMessage), bufferSize - numberOfChar); assert(numberOfChar < bufferSize-1); assert(UTF8Decoder::CharSizeOfCodePoint('/') == 1); buffer[numberOfChar++] = '/'; @@ -108,6 +116,7 @@ void TitleBarView::refreshPreferences() { (angleUnit == Preferences::AngleUnit::Radian ? I18n::Message::Rad : I18n::Message::Gon); numberOfChar += strlcpy(buffer+numberOfChar, I18n::translate(angleMessage), bufferSize - numberOfChar); } + m_preferenceView.setText(buffer); // Layout the exam mode icon if needed layoutSubviews(); From e347dd5616ca0e8788964701203c7665455bdca2 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Sun, 15 Dec 2019 10:32:43 +0100 Subject: [PATCH 051/130] [preferences/exam] Allowed reactivation of exam mode Settings are not modifiable when reactiving exam mode. Decided to do it like that for consistency with the TI-Nspire CAS models. Should be ok with exam mode specs (at least for france). --- apps/settings/sub_menu/exam_mode_controller.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index 426bb9fc8..5e4bbf10b 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -28,6 +28,8 @@ bool ExamModeController::handleEvent(Ion::Events::Event event) { I18n::Message childLabel = m_messageTreeModel->children(selectedRow())->label(); if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) { if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { + if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive) + AppsContainer::sharedAppsContainer()->displayExamModePopUp(true); return true; } if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive) { From 03584eda4ddc4207a44a7a93ded0eecff35913df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Sun, 15 Dec 2019 14:23:37 +0100 Subject: [PATCH 052/130] Fixed an compilation issue --- ion/src/device/n0110/drivers/led.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion/src/device/n0110/drivers/led.cpp b/ion/src/device/n0110/drivers/led.cpp index f196187af..e24aed2ea 100644 --- a/ion/src/device/n0110/drivers/led.cpp +++ b/ion/src/device/n0110/drivers/led.cpp @@ -9,7 +9,7 @@ namespace LED { KDColor updateColorWithPlugAndCharge() { KDColor ledColor = getColor(); - if (GlobalPreferences::sharedGlobalPreferences()->examMode() != GlobalPreferences::ExamMode::Activate) { // If exam mode is on, we do not update the LED with the plugged/charging state + if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { // If exam mode is on, we do not update the LED with the plugged/charging state if (USB::isPlugged()) { ledColor = Battery::isCharging() ? KDColorOrange : KDColorGreen; } else { From c66aeba14e242b48657c4f972e89a45c5d8184a8 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Sun, 15 Dec 2019 15:43:02 +0100 Subject: [PATCH 053/130] [build] Excluded .exam_mode_buffer from internal bin. --- build/targets.device.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/targets.device.mak b/build/targets.device.mak index 716b58b38..84204d6be 100644 --- a/build/targets.device.mak +++ b/build/targets.device.mak @@ -65,7 +65,7 @@ $(BUILD_DIR)/bench.flash.$(EXE): $(call object_for,$(bench_src)) %.two_binaries: %.elf @echo "Building an internal and an external binary for $<" $(Q) $(OBJCOPY) -O binary -j .text.external -j .rodata.external $< $(basename $<).external.bin - $(Q) $(OBJCOPY) -O binary -R .text.external -R .rodata.external $< $(basename $<).internal.bin + $(Q) $(OBJCOPY) -O binary -R .text.external -R .rodata.external -R .exam_mode_buffer $< $(basename $<).internal.bin @echo "Padding $(basename $<).external.bin and $(basename $<).internal.bin" $(Q) printf "\xFF\xFF\xFF\xFF" >> $(basename $<).external.bin $(Q) printf "\xFF\xFF\xFF\xFF" >> $(basename $<).internal.bin From 8ffd812e415c23a7edad0d90a4ab35705ed15acb Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Sun, 15 Dec 2019 16:16:39 +0100 Subject: [PATCH 054/130] [build] Fixed binpack. --- build/targets.device.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/targets.device.mak b/build/targets.device.mak index 84204d6be..99e47264f 100644 --- a/build/targets.device.mak +++ b/build/targets.device.mak @@ -64,7 +64,7 @@ $(BUILD_DIR)/bench.flash.$(EXE): $(call object_for,$(bench_src)) .PHONY: %.two_binaries %.two_binaries: %.elf @echo "Building an internal and an external binary for $<" - $(Q) $(OBJCOPY) -O binary -j .text.external -j .rodata.external $< $(basename $<).external.bin + $(Q) $(OBJCOPY) -O binary -j .text.external -j .rodata.external -j .exam_mode_buffer $< $(basename $<).external.bin $(Q) $(OBJCOPY) -O binary -R .text.external -R .rodata.external -R .exam_mode_buffer $< $(basename $<).internal.bin @echo "Padding $(basename $<).external.bin and $(basename $<).internal.bin" $(Q) printf "\xFF\xFF\xFF\xFF" >> $(basename $<).external.bin From 34e6141bdb8fcbc788c8d68dd8ef18c06a0be770 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sun, 15 Dec 2019 09:34:40 -0500 Subject: [PATCH 055/130] [ion/regs] Avoid code duplication --- ion/src/device/shared/regs/cortex.h | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/ion/src/device/shared/regs/cortex.h b/ion/src/device/shared/regs/cortex.h index b89351ebe..15d6e4ace 100644 --- a/ion/src/device/shared/regs/cortex.h +++ b/ion/src/device/shared/regs/cortex.h @@ -100,25 +100,20 @@ public: using Register32::Register32; }; - class DCISW : public Register32 { + class DCSW : public Register32 { public: - DCISW() : Register32(0) {} + DCSW() : Register32(0) {} REGS_FIELD(SET, uint16_t, 13, 5); REGS_FIELD(WAY, uint8_t, 31, 30); }; - class DCCSW : public Register32 { - public: - DCCSW() : Register32(0) {} - REGS_FIELD(SET, uint16_t, 13, 5); - REGS_FIELD(WAY, uint8_t, 31, 30); + class DCISW : public DCSW { }; - class DCCISW : public Register32 { - public: - DCCISW() : Register32(0) {} - REGS_FIELD(SET, uint16_t, 13, 5); - REGS_FIELD(WAY, uint8_t, 31, 30); + class DCCSW : public DCSW { + }; + + class DCCISW : public DCSW { }; #endif From d25346d82f2643415ed2c230002341bdf2575e26 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sun, 15 Dec 2019 17:01:03 -0500 Subject: [PATCH 056/130] [ion/cache] Use DCSW to reduce code duplication --- ion/src/device/n0110/drivers/cache.cpp | 29 +++++++++++--------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/ion/src/device/n0110/drivers/cache.cpp b/ion/src/device/n0110/drivers/cache.cpp index af907386f..3210383d8 100644 --- a/ion/src/device/n0110/drivers/cache.cpp +++ b/ion/src/device/n0110/drivers/cache.cpp @@ -23,24 +23,19 @@ void privateCleanInvalidateDisableDCache(bool clean, bool invalidate, bool disab do { uint32_t w = ways; do { - if (clean) { - if (invalidate) { - class CORTEX::DCCISW dccisw; - dccisw.setSET(sets); - dccisw.setWAY(w); - CORTEX.DCCISW()->set(dccisw); - } else { - class CORTEX::DCCSW dccsw; - dccsw.setSET(sets); - dccsw.setWAY(w); - CORTEX.DCCSW()->set(dccsw); - } - } else if (invalidate) { - class CORTEX::DCISW dcisw; - dcisw.setSET(sets); - dcisw.setWAY(w); - CORTEX.DCISW()->set(dcisw); + class CORTEX::DCSW dcsw; + dcsw.setSET(sets); + dcsw.setWAY(w); + volatile CORTEX::DCSW * target = nullptr; + if (clean && invalidate) { + target = CORTEX.DCCISW(); + } else if (clean) { + target = CORTEX.DCCSW(); + } else { + assert(invalidate); + target = CORTEX.DCISW(); } + target->set(dcsw); __asm volatile("nop"); } while (w-- != 0); } while (sets-- != 0); From 67302a90c7fd4cd8ca91aac0350ec094fae368e3 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sun, 15 Dec 2019 17:02:01 -0500 Subject: [PATCH 057/130] [ion/cache] Follow CMSIS' order --- ion/src/device/n0110/drivers/cache.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ion/src/device/n0110/drivers/cache.cpp b/ion/src/device/n0110/drivers/cache.cpp index 3210383d8..f14bee613 100644 --- a/ion/src/device/n0110/drivers/cache.cpp +++ b/ion/src/device/n0110/drivers/cache.cpp @@ -7,19 +7,19 @@ namespace Cache { using namespace Regs; void privateCleanInvalidateDisableDCache(bool clean, bool invalidate, bool disable) { + // Select Level 1 data cache CORTEX.CSSELR()->set(0); dsb(); - // Associativity = 6 - - uint32_t sets = CORTEX.CCSIDR()->getNUMSETS(); - uint32_t ways = CORTEX.CCSIDR()->getASSOCIATIVITY(); - + // Disable D-Cache if (disable) { CORTEX.CCR()->setDC(false); dsb(); } + uint32_t sets = CORTEX.CCSIDR()->getNUMSETS(); + uint32_t ways = CORTEX.CCSIDR()->getASSOCIATIVITY(); + do { uint32_t w = ways; do { From 273834ee84814ba543d17c6c2b8a1a4d2c3ed2fa Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Sun, 15 Dec 2019 17:13:27 -0500 Subject: [PATCH 058/130] [ion/cache] Improve cache cleaning - Avoid fetching CCSIDR twice - Use for loop instead of do/while - Only compute the target register once - Avoid an useless nop --- ion/src/device/n0110/drivers/cache.cpp | 39 +++++++++++++------------- ion/src/device/shared/regs/cortex.h | 1 + 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/ion/src/device/n0110/drivers/cache.cpp b/ion/src/device/n0110/drivers/cache.cpp index f14bee613..87b1a36f2 100644 --- a/ion/src/device/n0110/drivers/cache.cpp +++ b/ion/src/device/n0110/drivers/cache.cpp @@ -17,28 +17,29 @@ void privateCleanInvalidateDisableDCache(bool clean, bool invalidate, bool disab dsb(); } - uint32_t sets = CORTEX.CCSIDR()->getNUMSETS(); - uint32_t ways = CORTEX.CCSIDR()->getASSOCIATIVITY(); + // Pick the right DC??SW register according to invalidate/disable parameters + volatile CORTEX::DCSW * target = nullptr; + if (clean && invalidate) { + target = CORTEX.DCCISW(); + } else if (clean) { + target = CORTEX.DCCSW(); + } else { + assert(invalidate); + target = CORTEX.DCISW(); + } - do { - uint32_t w = ways; - do { + class CORTEX::CCSIDR ccsidr = CORTEX.CCSIDR()->get(); + uint32_t sets = ccsidr.getNUMSETS(); + uint32_t ways = ccsidr.getASSOCIATIVITY(); + + for (int set = sets; set >= 0; set--) { + for (int way = ways; way >= 0; way--) { class CORTEX::DCSW dcsw; - dcsw.setSET(sets); - dcsw.setWAY(w); - volatile CORTEX::DCSW * target = nullptr; - if (clean && invalidate) { - target = CORTEX.DCCISW(); - } else if (clean) { - target = CORTEX.DCCSW(); - } else { - assert(invalidate); - target = CORTEX.DCISW(); - } + dcsw.setSET(set); + dcsw.setWAY(way); target->set(dcsw); - __asm volatile("nop"); - } while (w-- != 0); - } while (sets-- != 0); + } + } dsb(); isb(); diff --git a/ion/src/device/shared/regs/cortex.h b/ion/src/device/shared/regs/cortex.h index 15d6e4ace..2c71c0fa2 100644 --- a/ion/src/device/shared/regs/cortex.h +++ b/ion/src/device/shared/regs/cortex.h @@ -72,6 +72,7 @@ public: #if REGS_CORTEX_CONFIG_CACHE class CCSIDR : public Register32 { public: + using Register32::Register32; REGS_FIELD(ASSOCIATIVITY, uint16_t, 12, 3); REGS_FIELD(NUMSETS, uint16_t, 27, 13); }; From 8583ddafcac98804b17ac6aca707fd82bd97785b Mon Sep 17 00:00:00 2001 From: Damien Nicolet Date: Wed, 18 Dec 2019 22:03:05 +0100 Subject: [PATCH 059/130] External application, API v2 --- apps/code/editor_controller.cpp | 18 +- apps/code/editor_controller.h | 4 +- apps/external/Makefile | 3 +- apps/external/extapp_api.cpp | 326 ++++++++---- apps/external/extapp_api.h | 282 ++++++++-- ion/include/ion/storage.h | 1 + kandinsky/include/kandinsky/color.h | 2 +- kandinsky/include/kandinsky/context.h | 5 +- kandinsky/include/kandinsky/ion_context.h | 1 + python/port/genhdr/qstrdefs.in.h | 2 - python/port/helpers.cpp | 3 - python/port/mod/kandinsky/modkandinsky.cpp | 139 +---- python/port/mod/kandinsky/modkandinsky.h | 2 - .../port/mod/kandinsky/modkandinsky_table.c | 4 - python/port/port.cpp | 498 +----------------- python/port/port.h | 208 -------- 16 files changed, 495 insertions(+), 1003 deletions(-) diff --git a/apps/code/editor_controller.cpp b/apps/code/editor_controller.cpp index c799d8ff8..aba355959 100644 --- a/apps/code/editor_controller.cpp +++ b/apps/code/editor_controller.cpp @@ -18,22 +18,6 @@ EditorController::EditorController(MenuController * menuController, App * python m_editorView.setTextAreaDelegates(this, this); } -#ifdef MAX_SCRIPTSIZE -void EditorController::setScript(Script script) { - m_script = script; - Script::Data scriptData = m_script.value(); - size_t s=scriptData.size,ms=sizeof(m_areaBuffer); - if (s>ms) - s=ms; - size_t availableScriptSize = s + Ion::Storage::sharedStorage()->availableSize(); - if (availableScriptSize>ms) - availableScriptSize=ms; - // assert(sizeof(m_areaBuffer) >= availableScriptSize); - // We cannot use strlcpy as the first char reprensenting the importation status can be 0. - memcpy(m_areaBuffer, (const char *)scriptData.buffer, s); - m_editorView.setText(m_areaBuffer+1, availableScriptSize-1); // 1 char is taken by the importation status flag -} -#else void EditorController::setScript(Script script) { m_script = script; Script::Data scriptData = m_script.value(); @@ -43,7 +27,7 @@ void EditorController::setScript(Script script) { memcpy(m_areaBuffer, (const char *)scriptData.buffer, scriptData.size); m_editorView.setText(m_areaBuffer+1, availableScriptSize-1); // 1 char is taken by the importation status flag } -#endif + // TODO: this should be done in textAreaDidFinishEditing maybe?? bool EditorController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::Back || event == Ion::Events::Home) { diff --git a/apps/code/editor_controller.h b/apps/code/editor_controller.h index d5b948d4e..284bf1af3 100644 --- a/apps/code/editor_controller.h +++ b/apps/code/editor_controller.h @@ -1,8 +1,6 @@ #ifndef CODE_EDITOR_CONTROLLER_H #define CODE_EDITOR_CONTROLLER_H -#define MAX_SCRIPTSIZE 12288 - #include #include "script.h" #include "editor_view.h" @@ -41,7 +39,7 @@ private: /* m_areaBuffer first character is dedicated to the importation status. * Thereby, we avoid wasteful copy while adding the Script to the storage * (in order to add the importation status char before the areaBuffer). */ - char m_areaBuffer[Ion::Storage::k_storageSize>MAX_SCRIPTSIZE?MAX_SCRIPTSIZE:Ion::Storage::k_storageSize]; // this could be slightly optimize + char m_areaBuffer[Ion::Storage::k_storageSize]; // this could be slightly optimize Script m_script; MenuController * m_menuController; }; diff --git a/apps/external/Makefile b/apps/external/Makefile index b767dad8d..f2680b165 100644 --- a/apps/external/Makefile +++ b/apps/external/Makefile @@ -11,10 +11,11 @@ app_external_src = $(addprefix apps/external/,\ SFLAGS += -Iapps/external/ +EXTAPP_PATH ?= apps/external/app/ ifeq ($(PLATFORM),device) SFLAGS += -DDEVICE else - include apps/external/app/sources.mak + include $(EXTAPP_PATH)/sources.mak endif app_src += $(app_external_src) diff --git a/apps/external/extapp_api.cpp b/apps/external/extapp_api.cpp index 03cbef00a..248fc6ee2 100644 --- a/apps/external/extapp_api.cpp +++ b/apps/external/extapp_api.cpp @@ -4,7 +4,10 @@ #include #include #include +#include "archive.h" #include "extapp_api.h" +#include "../apps_container.h" +#include "../global_preferences.h" #include @@ -36,30 +39,36 @@ void extapp_pushRectUniform(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16 Ion::Display::pushRectUniform(rect, KDColor::RGB16(color)); } -int16_t extapp_drawTextLarge(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg) { +void extapp_pullRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t * pixels) { + KDRect rect(x, y, w, h); + + Ion::Display::pullRect(rect, (KDColor *) pixels); +} + +int16_t extapp_drawTextLarge(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake) { KDPoint point(x, y); auto ctx = KDIonContext::sharedContext(); - ctx->setClippingRect(KDRect(0,0,320,240)); - ctx->setOrigin(KDPoint(0,0)); - ctx->drawString(text, point, KDFont::LargeFont, KDColor::RGB16(fg), KDColor::RGB16(bg)); + ctx->setClippingRect(KDRect(0, 0, 320, fake ? 0 : 240)); + ctx->setOrigin(KDPoint(0, 0)); + point = ctx->drawString(text, point, KDFont::LargeFont, KDColor::RGB16(fg), KDColor::RGB16(bg)); return point.x(); } -int16_t extapp_drawTextSmall(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg) { +int16_t extapp_drawTextSmall(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake) { KDPoint point(x, y); auto ctx = KDIonContext::sharedContext(); - ctx->setClippingRect(KDRect(0,0,320,240)); - ctx->setOrigin(KDPoint(0,0)); - ctx->drawString(text, point, KDFont::SmallFont, KDColor::RGB16(fg), KDColor::RGB16(bg)); + ctx->setClippingRect(KDRect(0, 0, 320, fake ? 0 : 240)); + ctx->setOrigin(KDPoint(0, 0)); + point = ctx->drawString(text, point, KDFont::SmallFont, KDColor::RGB16(fg), KDColor::RGB16(bg)); return point.x(); } -void extapp_waitForVBlank() { - Ion::Display::waitForVBlank(); +bool extapp_waitForVBlank() { + return Ion::Display::waitForVBlank(); } void extapp_clipboardStore(const char *text) { @@ -70,98 +79,231 @@ const char * extapp_clipboardText() { return Clipboard::sharedClipboard()->storedText(); } +int extapp_fileListWithExtension(const char ** filenames, int maxrecords, const char * extension, int storage) { + if(storage == EXTAPP_RAM_FILE_SYSTEM) { + int n = Ion::Storage::sharedStorage()->numberOfRecordsWithExtension(extension); + if (n > maxrecords) { + n = maxrecords; + } + for(int i = 0; i < n; i++) { + filenames[i] = Ion::Storage::sharedStorage()->recordWithExtensionAtIndex(extension, i).fullName(); + } + return n; + } else if(storage == EXTAPP_FLASH_FILE_SYSTEM) { + // TODO: filter by extension + int n = External::Archive::numberOfFiles(); + if (n > maxrecords) { + n = maxrecords; + } + for(int i = 0; i < n; i++) { + External::Archive::File entry; + External::Archive::fileAtIndex(i, entry); + filenames[i] = entry.name; + } + return n; + } else { + return 0; + } +} + +bool extapp_fileExists(const char * filename, int storage) { + if(storage == EXTAPP_RAM_FILE_SYSTEM) { + return !Ion::Storage::sharedStorage()->recordNamed(filename).isNull(); + } else if(storage == EXTAPP_FLASH_FILE_SYSTEM) { + return External::Archive::indexFromName(filename) >= 0; + } else { + return false; + } +} + +bool extapp_fileErase(const char * filename, int storage) { + if(storage == EXTAPP_RAM_FILE_SYSTEM) { + Ion::Storage::Record record = Ion::Storage::sharedStorage()->recordNamed(filename); + if(record.isNull()) { + return false; + } else { + record.destroy(); + return true; + } + } else { + return false; + } +} + +const char * extapp_fileRead(const char * filename, size_t *len, int storage) { + if(storage == EXTAPP_RAM_FILE_SYSTEM) { + const Ion::Storage::Record record = Ion::Storage::sharedStorage()->recordNamed(filename); + if (record.isNull()) { + return NULL; + } else { + if(len) { + *len = record.value().size; + } + return (const char *) record.value().buffer; + } + } else if(storage == EXTAPP_FLASH_FILE_SYSTEM) { + int index = External::Archive::indexFromName(filename); + if (index >= 0) { + External::Archive::File entry; + External::Archive::fileAtIndex(index, entry); + if(len) { + *len = entry.dataLength; + } + return (const char *)entry.data; + } else { + return NULL; + } + } else { + return NULL; + } +} + +bool extapp_fileWrite(const char * filename, const char * content, size_t len, int storage) { + if(storage == EXTAPP_RAM_FILE_SYSTEM) { + Ion::Storage::Record::ErrorStatus status = Ion::Storage::sharedStorage()->createRecordWithFullName(filename, content, len); + if (status == Ion::Storage::Record::ErrorStatus::NameTaken) { + Ion::Storage::Record::Data data; + data.buffer = content; + data.size = len; + return Ion::Storage::sharedStorage()->recordNamed(filename).setValue(data) == Ion::Storage::Record::ErrorStatus::None; + } else if (status == Ion::Storage::Record::ErrorStatus::None) { + return true; + } else { + return false; + } + } else { + return false; + } +} + +static void reloadTitleBar() { + AppsContainer::sharedAppsContainer()->setShiftAlphaStatus(Ion::Events::shiftAlphaStatus()); + AppsContainer::sharedAppsContainer()->refreshPreferences(); + AppsContainer::sharedAppsContainer()->updateBatteryState(); + AppsContainer::sharedAppsContainer()->reloadTitleBarView(); + AppsContainer::sharedAppsContainer()->redrawWindow(); +} + +void extapp_lockAlpha() { + Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock); + reloadTitleBar(); +} + +void extapp_resetKeyboard() { + Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default); + reloadTitleBar(); +} + +const int16_t translated_keys[] = +{ + // non shifted + KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_XTT,KEY_CTRL_VARS,KEY_CTRL_CATALOG,KEY_CTRL_DEL, + KEY_CHAR_EXPN,KEY_CHAR_LN,KEY_CHAR_LOG,KEY_CHAR_IMGNRY,',',KEY_CHAR_POW, + KEY_CHAR_SIN,KEY_CHAR_COS,KEY_CHAR_TAN,KEY_CHAR_PI,KEY_CHAR_ROOT,KEY_CHAR_SQUARE, + '7','8','9','(',')',-1, + '4','5','6','*','/',-1, + '1','2','3','+','-',-1, + '0','.',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, + // shifted + KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_CUT,KEY_CTRL_CLIP,KEY_CTRL_PASTE,KEY_CTRL_AC, + KEY_CHAR_LBRCKT,KEY_CHAR_RBRCKT,KEY_CHAR_LBRACE,KEY_CHAR_RBRACE,'_',KEY_CHAR_STORE, + KEY_CHAR_ASIN,KEY_CHAR_ACOS,KEY_CHAR_ATAN,'=','<','>', + KEY_CTRL_F7,KEY_CTRL_F8,KEY_CTRL_F9,KEY_CTRL_F13,KEY_CTRL_F14,-1, + KEY_CTRL_F4,KEY_CTRL_F5,KEY_CTRL_F6,KEY_CHAR_FACTOR,'%',-1, + KEY_CTRL_F1,KEY_CTRL_F2,KEY_CTRL_F3,KEY_CHAR_NORMAL,'\\',-1, + KEY_CTRL_F10,KEY_CTRL_F11,KEY_CTRL_F12,KEY_SHIFT_ANS,KEY_CTRL_EXE,-1, + // alpha + KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','"',KEY_CTRL_DEL, + 'a','b','c','d','e','f', + 'g','h','i','j','k','l', + 'm','n','o','p','q',-1, + 'r','s','t','u','v',-1, + 'w','x','y','z',' ',-1, + '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, + // alpha shifted + KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','\'','%', + 'A','B','C','D','E','F', + 'G','H','I','J','K','L', + 'M','N','O','P','Q',-1, + 'R','S','T','U','V',-1, + 'W','X','Y','Z',' ',-1, + '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, +}; + +#ifdef SIMULATOR +#define TICKS_PER_MINUTE 60000 +#else +#define TICKS_PER_MINUTE 11862 +#endif + +int extapp_getKey(bool allowSuspend, bool *alphaWasActive) { + int key = -1; + size_t t1 = Ion::Timing::millis(); + for (;;) { + int timeout = 10000; + if(alphaWasActive) { + *alphaWasActive = Ion::Events::isAlphaActive(); + } + Ion::Events::Event event = Ion::Events::getEvent(&timeout); + reloadTitleBar(); + if (event == Ion::Events::None) { + size_t t2 = Ion::Timing::millis(); + if (t2 - t1 > 2 * TICKS_PER_MINUTE) { + event = Ion::Events::OnOff; + } + } else { + t1 = Ion::Timing::millis(); + } + if (event.isKeyboardEvent()) { + Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); + } + if (event == Ion::Events::Shift || event == Ion::Events::Alpha) { + continue; + } + if (event.isKeyboardEvent()) { + key = event.id(); + if (key == 17 || key == 4 || key == 5 || key == 52) { + extapp_resetKeyboard(); + } + if (allowSuspend && (key == 7 || key == 8)) { // power + Ion::Power::suspend(true); + extapp_pushRectUniform(0, 0, 320, 240, 65535); + Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); + reloadTitleBar(); + } + break; + } + } + return translated_keys[key]; +} + extern "C" void (* const apiPointers[])(void) = { (void (*)(void)) extapp_millis, (void (*)(void)) extapp_msleep, (void (*)(void)) extapp_scanKeyboard, (void (*)(void)) extapp_pushRect, (void (*)(void)) extapp_pushRectUniform, + (void (*)(void)) extapp_pullRect, (void (*)(void)) extapp_drawTextLarge, (void (*)(void)) extapp_drawTextSmall, (void (*)(void)) extapp_waitForVBlank, (void (*)(void)) extapp_clipboardStore, (void (*)(void)) extapp_clipboardText, + (void (*)(void)) extapp_fileListWithExtension, + (void (*)(void)) extapp_fileExists, + (void (*)(void)) extapp_fileErase, + (void (*)(void)) extapp_fileRead, + (void (*)(void)) extapp_fileWrite, + (void (*)(void)) extapp_lockAlpha, + (void (*)(void)) extapp_resetKeyboard, + (void (*)(void)) extapp_getKey, (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - (void (*)(void)) nullptr, - - // khicas from here, subject to change - (void (*)(void)) numworks_draw_string, - (void (*)(void)) numworks_draw_string_small, - (void (*)(void)) numworks_set_pixel, - (void (*)(void)) numworks_fill_rect, - (void (*)(void)) numworks_get_pixel, - (void (*)(void)) numworks_hide_graph, - (void (*)(void)) numworks_wait_1ms, - (void (*)(void)) waitforvblank, - (void (*)(void)) statuslinemsg, - (void (*)(void)) statusline, - (void (*)(void)) getkey, - (void (*)(void)) GetKey, - (void (*)(void)) alphawasactive, - (void (*)(void)) lock_alpha, - (void (*)(void)) reset_kbd, - (void (*)(void)) back_key_pressed, - (void (*)(void)) enable_back_interrupt, - (void (*)(void)) disable_back_interrupt, - (void (*)(void)) os_set_angle_unit, - (void (*)(void)) os_get_angle_unit, - (void (*)(void)) os_file_browser, - (void (*)(void)) file_exists, - (void (*)(void)) erase_file, - (void (*)(void)) read_file, - (void (*)(void)) write_file, - (void (*)(void)) mp_hal_input, - (void (*)(void)) nullptr }; diff --git a/apps/external/extapp_api.h b/apps/external/extapp_api.h index 12ae53ba6..b17b86436 100644 --- a/apps/external/extapp_api.h +++ b/apps/external/extapp_api.h @@ -2,8 +2,10 @@ #define EXTERNAL_API_H #include +#include +#include -#define API_VERSION 1 +#define API_VERSION 2 #ifdef __cplusplus #define EXTERNC extern "C" @@ -14,63 +16,241 @@ #define LCD_WIDTH 320 #define LCD_HEIGHT 240 -#define KEY_Left ((uint64_t)1 << 0) -#define KEY_Up ((uint64_t)1 << 1) -#define KEY_Down ((uint64_t)1 << 2) -#define KEY_Right ((uint64_t)1 << 3) -#define KEY_OK ((uint64_t)1 << 4) -#define KEY_Back ((uint64_t)1 << 5) -#define KEY_Home ((uint64_t)1 << 6) -#define KEY_OnOff (((uint64_t)1 << 7) || ((uint64_t)1 << 8)) -#define KEY_Shift ((uint64_t)1 << 12) -#define KEY_Alpha ((uint64_t)1 << 13) -#define KEY_XNT ((uint64_t)1 << 14) -#define KEY_Var ((uint64_t)1 << 15) -#define KEY_Toolbox ((uint64_t)1 << 16) -#define KEY_Backspace ((uint64_t)1 << 17) -#define KEY_Exp ((uint64_t)1 << 18) -#define KEY_Ln ((uint64_t)1 << 19) -#define KEY_Log ((uint64_t)1 << 20) -#define KEY_Imaginary ((uint64_t)1 << 21) -#define KEY_Comma ((uint64_t)1 << 22) -#define KEY_Power ((uint64_t)1 << 23) -#define KEY_Sine ((uint64_t)1 << 24) -#define KEY_Cosine ((uint64_t)1 << 25) -#define KEY_Tangent ((uint64_t)1 << 26) -#define KEY_Pi ((uint64_t)1 << 27) -#define KEY_Sqrt ((uint64_t)1 << 28) -#define KEY_Square ((uint64_t)1 << 29) -#define KEY_Seven ((uint64_t)1 << 30) -#define KEY_Eight ((uint64_t)1 << 31) -#define KEY_Nine ((uint64_t)1 << 32) -#define KEY_LeftParenthesis ((uint64_t)1 << 33) -#define KEY_RightParenthesis ((uint64_t)1 << 34) -#define KEY_Four ((uint64_t)1 << 36) -#define KEY_Five ((uint64_t)1 << 37) -#define KEY_Six ((uint64_t)1 << 38) -#define KEY_Multiplication ((uint64_t)1 << 39) -#define KEY_Division ((uint64_t)1 << 40) -#define KEY_One ((uint64_t)1 << 42) -#define KEY_Two ((uint64_t)1 << 43) -#define KEY_Three ((uint64_t)1 << 44) -#define KEY_Plus ((uint64_t)1 << 45) -#define KEY_Minus ((uint64_t)1 << 46) -#define KEY_Zero ((uint64_t)1 << 48) -#define KEY_Dot ((uint64_t)1 << 49) -#define KEY_EE ((uint64_t)1 << 50) -#define KEY_Ans ((uint64_t)1 << 51) -#define KEY_EXE ((uint64_t)1 << 52) -#define KEY_None ((uint64_t)1 << 54) +#define EXTAPP_RAM_FILE_SYSTEM 0 +#define EXTAPP_FLASH_FILE_SYSTEM 1 + +#define SCANCODE_Left ((uint64_t)1 << 0) +#define SCANCODE_Up ((uint64_t)1 << 1) +#define SCANCODE_Down ((uint64_t)1 << 2) +#define SCANCODE_Right ((uint64_t)1 << 3) +#define SCANCODE_OK ((uint64_t)1 << 4) +#define SCANCODE_Back ((uint64_t)1 << 5) +#define SCANCODE_Home ((uint64_t)1 << 6) +#define SCANCODE_OnOff (((uint64_t)1 << 7) || ((uint64_t)1 << 8)) +#define SCANCODE_Shift ((uint64_t)1 << 12) +#define SCANCODE_Alpha ((uint64_t)1 << 13) +#define SCANCODE_XNT ((uint64_t)1 << 14) +#define SCANCODE_Var ((uint64_t)1 << 15) +#define SCANCODE_Toolbox ((uint64_t)1 << 16) +#define SCANCODE_Backspace ((uint64_t)1 << 17) +#define SCANCODE_Exp ((uint64_t)1 << 18) +#define SCANCODE_Ln ((uint64_t)1 << 19) +#define SCANCODE_Log ((uint64_t)1 << 20) +#define SCANCODE_Imaginary ((uint64_t)1 << 21) +#define SCANCODE_Comma ((uint64_t)1 << 22) +#define SCANCODE_Power ((uint64_t)1 << 23) +#define SCANCODE_Sine ((uint64_t)1 << 24) +#define SCANCODE_Cosine ((uint64_t)1 << 25) +#define SCANCODE_Tangent ((uint64_t)1 << 26) +#define SCANCODE_Pi ((uint64_t)1 << 27) +#define SCANCODE_Sqrt ((uint64_t)1 << 28) +#define SCANCODE_Square ((uint64_t)1 << 29) +#define SCANCODE_Seven ((uint64_t)1 << 30) +#define SCANCODE_Eight ((uint64_t)1 << 31) +#define SCANCODE_Nine ((uint64_t)1 << 32) +#define SCANCODE_LeftParenthesis ((uint64_t)1 << 33) +#define SCANCODE_RightParenthesis ((uint64_t)1 << 34) +#define SCANCODE_Four ((uint64_t)1 << 36) +#define SCANCODE_Five ((uint64_t)1 << 37) +#define SCANCODE_Six ((uint64_t)1 << 38) +#define SCANCODE_Multiplication ((uint64_t)1 << 39) +#define SCANCODE_Division ((uint64_t)1 << 40) +#define SCANCODE_One ((uint64_t)1 << 42) +#define SCANCODE_Two ((uint64_t)1 << 43) +#define SCANCODE_Three ((uint64_t)1 << 44) +#define SCANCODE_Plus ((uint64_t)1 << 45) +#define SCANCODE_Minus ((uint64_t)1 << 46) +#define SCANCODE_Zero ((uint64_t)1 << 48) +#define SCANCODE_Dot ((uint64_t)1 << 49) +#define SCANCODE_EE ((uint64_t)1 << 50) +#define SCANCODE_Ans ((uint64_t)1 << 51) +#define SCANCODE_EXE ((uint64_t)1 << 52) +#define SCANCODE_None ((uint64_t)1 << 54) + +// Character codes +#define KEY_CHAR_0 0x30 +#define KEY_CHAR_1 0x31 +#define KEY_CHAR_2 0x32 +#define KEY_CHAR_3 0x33 +#define KEY_CHAR_4 0x34 +#define KEY_CHAR_5 0x35 +#define KEY_CHAR_6 0x36 +#define KEY_CHAR_7 0x37 +#define KEY_CHAR_8 0x38 +#define KEY_CHAR_9 0x39 +#define KEY_CHAR_DP 0x2e +#define KEY_CHAR_EXP 0x0f +#define KEY_CHAR_PMINUS 30200 +#define KEY_CHAR_PLUS 43 +#define KEY_CHAR_MINUS 45 +#define KEY_CHAR_MULT 42 +#define KEY_CHAR_DIV 47 +#define KEY_CHAR_FRAC 0xbb +#define KEY_CHAR_LPAR 0x28 +#define KEY_CHAR_RPAR 0x29 +#define KEY_CHAR_COMMA 0x2c +#define KEY_CHAR_STORE 0x0e +#define KEY_CHAR_LOG 0x95 +#define KEY_CHAR_LN 0x85 +#define KEY_CHAR_SIN 0x81 +#define KEY_CHAR_COS 0x82 +#define KEY_CHAR_TAN 0x83 +#define KEY_CHAR_SQUARE 0x8b +#define KEY_CHAR_POW 0xa8 +#define KEY_CHAR_IMGNRY 0x7f50 +#define KEY_CHAR_LIST 0x7f51 +#define KEY_CHAR_MAT 0x7f40 +#define KEY_CHAR_EQUAL 0x3d +#define KEY_CHAR_PI 0xd0 +#define KEY_CHAR_ANS 0xc0 +#define KEY_SHIFT_ANS 0xc1 +#define KEY_CHAR_LBRCKT 0x5b +#define KEY_CHAR_RBRCKT 0x5d +#define KEY_CHAR_LBRACE 0x7b +#define KEY_CHAR_RBRACE 0x7d +#define KEY_CHAR_CR 0x0d +#define KEY_CHAR_CUBEROOT 0x96 +#define KEY_CHAR_RECIP 0x9b +#define KEY_CHAR_ANGLE 0x7f54 +#define KEY_CHAR_EXPN10 0xb5 +#define KEY_CHAR_EXPN 0xa5 +#define KEY_CHAR_ASIN 0x91 +#define KEY_CHAR_ACOS 0x92 +#define KEY_CHAR_ATAN 0x93 +#define KEY_CHAR_ROOT 0x86 +#define KEY_CHAR_POWROOT 0xb8 +#define KEY_CHAR_SPACE 0x20 +#define KEY_CHAR_DQUATE 0x22 +#define KEY_CHAR_VALR 0xcd +#define KEY_CHAR_THETA 0xce +#define KEY_CHAR_FACTOR 0xda +#define KEY_CHAR_NORMAL 0xdb +#define KEY_CHAR_A 0x41 +#define KEY_CHAR_B 0x42 +#define KEY_CHAR_C 0x43 +#define KEY_CHAR_D 0x44 +#define KEY_CHAR_E 0x45 +#define KEY_CHAR_F 0x46 +#define KEY_CHAR_G 0x47 +#define KEY_CHAR_H 0x48 +#define KEY_CHAR_I 0x49 +#define KEY_CHAR_J 0x4a +#define KEY_CHAR_K 0x4b +#define KEY_CHAR_L 0x4c +#define KEY_CHAR_M 0x4d +#define KEY_CHAR_N 0x4e +#define KEY_CHAR_O 0x4f +#define KEY_CHAR_P 0x50 +#define KEY_CHAR_Q 0x51 +#define KEY_CHAR_R 0x52 +#define KEY_CHAR_S 0x53 +#define KEY_CHAR_T 0x54 +#define KEY_CHAR_U 0x55 +#define KEY_CHAR_V 0x56 +#define KEY_CHAR_W 0x57 +#define KEY_CHAR_X 0x58 +#define KEY_CHAR_Y 0x59 +#define KEY_CHAR_Z 0x5a + +// Control codes +#define KEY_CTRL_NOP 30202 +#define KEY_CTRL_EXE 30201 +#define KEY_CTRL_DEL 30025 +#define KEY_CTRL_AC 30070 +#define KEY_CTRL_FD 30046 +#define KEY_CTRL_UNDO 30045 +#define KEY_CTRL_XTT 30001 +#define KEY_CTRL_EXIT 5 +#define KEY_CTRL_OK 4 +#define KEY_CTRL_SHIFT 30006 +#define KEY_CTRL_ALPHA 30007 +#define KEY_CTRL_OPTN 30008 +#define KEY_CTRL_VARS 30030 +#define KEY_CTRL_UP 1 +#define KEY_CTRL_DOWN 2 +#define KEY_CTRL_LEFT 0 +#define KEY_CTRL_RIGHT 3 +#define KEY_CTRL_F1 30009 +#define KEY_CTRL_F2 30010 +#define KEY_CTRL_F3 30011 +#define KEY_CTRL_F4 30012 +#define KEY_CTRL_F5 30013 +#define KEY_CTRL_F6 30014 +#define KEY_CTRL_F7 30015 +#define KEY_CTRL_F8 30016 +#define KEY_CTRL_F9 30017 +#define KEY_CTRL_F10 30018 +#define KEY_CTRL_F11 30019 +#define KEY_CTRL_F12 30020 +#define KEY_CTRL_F13 30021 +#define KEY_CTRL_F14 30022 +#define KEY_CTRL_CATALOG 30100 +#define KEY_CTRL_CAPTURE 30055 +#define KEY_CTRL_CLIP 30050 +#define KEY_CTRL_CUT 30250 +#define KEY_CTRL_PASTE 30036 +#define KEY_CTRL_INS 30033 +#define KEY_CTRL_MIXEDFRAC 30054 +#define KEY_CTRL_FRACCNVRT 30026 +#define KEY_CTRL_QUIT 30029 +#define KEY_CTRL_PRGM 30028 +#define KEY_CTRL_SETUP 30037 +#define KEY_CTRL_PAGEUP 30052 +#define KEY_CTRL_PAGEDOWN 30053 +#define KEY_CTRL_MENU 30003 +#define KEY_SHIFT_OPTN 30059 +#define KEY_CTRL_RESERVE1 30060 +#define KEY_CTRL_RESERVE2 30061 +#define KEY_SHIFT_LEFT 30062 +#define KEY_SHIFT_RIGHT 30063 + +#define KEY_PRGM_ACON 10 +#define KEY_PRGM_DOWN 37 +#define KEY_PRGM_EXIT 47 +#define KEY_PRGM_F1 79 +#define KEY_PRGM_F2 69 +#define KEY_PRGM_F3 59 +#define KEY_PRGM_F4 49 +#define KEY_PRGM_F5 39 +#define KEY_PRGM_F6 29 +#define KEY_PRGM_LEFT 38 +#define KEY_PRGM_NONE 0 +#define KEY_PRGM_RETURN 31 +#define KEY_PRGM_RIGHT 27 +#define KEY_PRGM_UP 28 +#define KEY_PRGM_1 72 +#define KEY_PRGM_2 62 +#define KEY_PRGM_3 52 +#define KEY_PRGM_4 73 +#define KEY_PRGM_5 63 +#define KEY_PRGM_6 53 +#define KEY_PRGM_7 74 +#define KEY_PRGM_8 64 +#define KEY_PRGM_9 54 +#define KEY_PRGM_A 76 +#define KEY_PRGM_F 26 +#define KEY_PRGM_ALPHA 77 +#define KEY_PRGM_SHIFT 78 +#define KEY_PRGM_MENU 48 EXTERNC uint64_t extapp_millis(); EXTERNC void extapp_msleep(uint32_t ms); EXTERNC uint64_t extapp_scanKeyboard(); EXTERNC void extapp_pushRect(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t * pixels); EXTERNC void extapp_pushRectUniform(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color); -EXTERNC int16_t extapp_drawTextLarge(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg); -EXTERNC int16_t extapp_drawTextSmall(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg); -EXTERNC void extapp_waitForVBlank(); +EXTERNC void extapp_pullRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t * pixels); +EXTERNC int16_t extapp_drawTextLarge(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake); +EXTERNC int16_t extapp_drawTextSmall(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake); +EXTERNC bool extapp_waitForVBlank(); EXTERNC void extapp_clipboardStore(const char *text); EXTERNC const char * extapp_clipboardText(); +EXTERNC int extapp_fileListWithExtension(const char ** filenames, int maxrecords, const char * extension, int storage); +EXTERNC bool extapp_fileExists(const char * filename, int storage); +EXTERNC bool extapp_fileErase(const char * filename, int storage); +EXTERNC const char * extapp_fileRead(const char * filename, size_t *len, int storage); +EXTERNC bool extapp_fileWrite(const char * filename, const char * content, size_t len, int storage); +EXTERNC void extapp_lockAlpha(); +EXTERNC void extapp_resetKeyboard(); +EXTERNC int extapp_getKey(bool allowSuspend, bool *alphaWasActive); #endif diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index fedd6ba35..5138c1b76 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -115,6 +115,7 @@ public: void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension); void destroyRecordsWithExtension(const char * extension); +private: constexpr static uint32_t Magic = 0xEE0BDDBA; constexpr static size_t k_maxRecordSize = (1 << sizeof(record_size_t)*8); diff --git a/kandinsky/include/kandinsky/color.h b/kandinsky/include/kandinsky/color.h index d15835ae7..8e1cafa50 100644 --- a/kandinsky/include/kandinsky/color.h +++ b/kandinsky/include/kandinsky/color.h @@ -34,8 +34,8 @@ public: static KDColor blend(KDColor first, KDColor second, uint8_t alpha); KDColor invert() const { return KDColor(~m_value); } operator uint16_t() const { return m_value; } - constexpr KDColor(uint16_t value) : m_value(value) {} private: + constexpr KDColor(uint16_t value) : m_value(value) {} uint16_t m_value; }; diff --git a/kandinsky/include/kandinsky/context.h b/kandinsky/include/kandinsky/context.h index 9e267cea0..bcfc4ee74 100644 --- a/kandinsky/include/kandinsky/context.h +++ b/kandinsky/include/kandinsky/context.h @@ -33,10 +33,13 @@ public: void fillRectWithPixels(KDRect rect, const KDColor * pixels, KDColor * workingBuffer); void blendRectWithMask(KDRect rect, KDColor color, const uint8_t * mask, KDColor * workingBuffer); void strokeRect(KDRect rect, KDColor color); - KDContext(KDPoint origin, KDRect clippingRect); + virtual void pushRect(KDRect, const KDColor * pixels) = 0; virtual void pushRectUniform(KDRect rect, KDColor color) = 0; virtual void pullRect(KDRect rect, KDColor * pixels) = 0; +protected: + KDContext(KDPoint origin, KDRect clippingRect); +private: KDRect absoluteFillRect(KDRect rect); KDPoint pushOrPullString(const char * text, KDPoint p, const KDFont * font, KDColor textColor, KDColor backgroundColor, int maxByteLength, bool push, int * result = nullptr); KDPoint m_origin; diff --git a/kandinsky/include/kandinsky/ion_context.h b/kandinsky/include/kandinsky/ion_context.h index 0dc1774fb..5cfd6cd9e 100644 --- a/kandinsky/include/kandinsky/ion_context.h +++ b/kandinsky/include/kandinsky/ion_context.h @@ -27,6 +27,7 @@ public: bool zoomInhibit; bool gammaEnabled; int zoomPosition; +private: KDIonContext(); void pushRect(KDRect rect, const KDColor * pixels) override; void pushRectUniform(KDRect rect, KDColor color) override; diff --git a/python/port/genhdr/qstrdefs.in.h b/python/port/genhdr/qstrdefs.in.h index 5b96067ed..58c36bc71 100644 --- a/python/port/genhdr/qstrdefs.in.h +++ b/python/port/genhdr/qstrdefs.in.h @@ -129,8 +129,6 @@ Q(.) Q(EE) Q(Ans) Q(EXE) -Q(get_key) -Q(Pause) // Turtle QSTRs Q(turtle) diff --git a/python/port/helpers.cpp b/python/port/helpers.cpp index 71fb5e879..438f7ca47 100644 --- a/python/port/helpers.cpp +++ b/python/port/helpers.cpp @@ -1,8 +1,5 @@ #include "helpers.h" #include -#ifdef SIMULATOR -#include -#endif extern "C" { #include "mphalport.h" } diff --git a/python/port/mod/kandinsky/modkandinsky.cpp b/python/port/mod/kandinsky/modkandinsky.cpp index 7c8c3b674..9ca3232d5 100644 --- a/python/port/mod/kandinsky/modkandinsky.cpp +++ b/python/port/mod/kandinsky/modkandinsky.cpp @@ -8,22 +8,19 @@ extern "C" { #include "port.h" static KDColor ColorForTuple(mp_obj_t tuple) { - if (MP_OBJ_IS_SMALL_INT(tuple)) // BP change: accept int for color - return MP_OBJ_SMALL_INT_VALUE(tuple); + size_t len; + mp_obj_t * elem; - size_t len; - mp_obj_t * elem; + mp_obj_get_array(tuple, &len, &elem); + if (len != 3) { + mp_raise_TypeError("color needs 3 components"); + } - mp_obj_get_array(tuple, &len, &elem); - if (len != 3) { - mp_raise_TypeError("color needs 3 components"); - } - - return KDColor::RGB888( - mp_obj_get_int(elem[0]), - mp_obj_get_int(elem[1]), - mp_obj_get_int(elem[2]) - ); + return KDColor::RGB888( + mp_obj_get_int(elem[0]), + mp_obj_get_int(elem[1]), + mp_obj_get_int(elem[2]) + ); } static mp_obj_t TupleForRGB(uint8_t r, uint8_t g, uint8_t b) { @@ -186,117 +183,3 @@ mp_obj_t modkandinsky_get_keys() { return result; } - -/* C-- SDK (c) B. Parisse, 2019 */ -mp_obj_t modkandinsky_Pause(mp_obj_t x) { - double d=mp_obj_get_float(x); - numworks_wait_1ms(d*1000); - return mp_const_none; -} - -#define LCD_WIDTH_PX 320 -#define LCD_HEIGHT_PX 222 - -void numworks_set_pixel(int x, int y, int color) { - if (x<0 || x>=LCD_WIDTH_PX || y<0 || y>=LCD_HEIGHT_PX) - return; - auto ctx=KDIonContext::sharedContext(); - KDRect save=ctx->m_clippingRect; - KDPoint o=ctx->m_origin; - ctx->setClippingRect(KDRect(0,0,320,240)); - ctx->setOrigin(KDPoint(0,0)); - KDColor c(color); - KDPoint point(x,y+18); - KDIonContext::sharedContext()->pushRect(KDRect(point, 1, 1), &c); - ctx->setClippingRect(save); - ctx->setOrigin(o); -} - -void numworks_fill_rect(int x,int y,int w,int h,int c){ - KDColor color = c; - auto ctx=KDIonContext::sharedContext(); - KDRect save=ctx->m_clippingRect; - KDPoint o=ctx->m_origin; - ctx->setClippingRect(KDRect(0,0,320,240)); - ctx->setOrigin(KDPoint(0,0)); -#if 1 - if (x<0){ - w += x; - x=0; - } - if (y<0){ - h += y; - y=0; - } - if (h+y>=LCD_HEIGHT_PX) - h=LCD_HEIGHT_PX-y; - if (x+w>=LCD_WIDTH_PX) - w=LCD_WIDTH_PX-x; - if (h<=0 || w<=0) - return; - KDRect rect(x,y+18,w,h); - KDIonContext::sharedContext()->pushRectUniform(rect,color); -#else - KDRect rect(x,y,w,h); - KDIonContext::sharedContext()->fillRect(rect, color); -#endif - ctx->setClippingRect(save); - ctx->setOrigin(o); -} - -int numworks_get_pixel(int x, int y) { - KDPoint point(x,y); - KDColor c = KDIonContext::sharedContext()->getPixel(point); - return c; -} - -int numworks_draw_string(int x,int y,int c,int bg,const char * text,bool fake){ - auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); - KDPoint point(x,y); - if (ptr) - ptr->displaySandbox(); - auto ctx=KDIonContext::sharedContext(); - KDRect save=ctx->m_clippingRect; - KDPoint o=ctx->m_origin; - ctx->setClippingRect(KDRect(0,18,320,fake?0:222)); - ctx->setOrigin(KDPoint(0,18)); - point=KDIonContext::sharedContext()->drawString(text, point, KDFont::LargeFont, c, bg); - ctx->setClippingRect(save); - ctx->setOrigin(o); - return point.x(); -} - -int numworks_draw_string_small(int x,int y,int c,int bg,const char * text,bool fake){ - auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); - KDPoint point(x,y); - if (ptr) - ptr->displaySandbox(); - auto ctx=KDIonContext::sharedContext(); - KDRect save=ctx->m_clippingRect; - KDPoint o=ctx->m_origin; - ctx->setClippingRect(KDRect(0,18,320,fake?0:222)); - ctx->setOrigin(KDPoint(0,18)); - point=ctx->drawString(text, point, KDFont::SmallFont, c, bg); - ctx->setClippingRect(save); - ctx->setOrigin(o); - return point.x(); -} - -void numworks_hide_graph(){ - auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); - if (ptr) - ptr->hideSandbox(); -} - -void numworks_show_graph(){ - auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); - if (ptr) - ptr->displaySandbox(); -} - -// Python module get_key() addition -mp_obj_t modkandinsky_get_key() { - micropython_port_interrupt_if_needed(); - int key=getkey(false); // no suspend - return mp_obj_new_int(key); -} diff --git a/python/port/mod/kandinsky/modkandinsky.h b/python/port/mod/kandinsky/modkandinsky.h index 15bc28a31..4191155bc 100644 --- a/python/port/mod/kandinsky/modkandinsky.h +++ b/python/port/mod/kandinsky/modkandinsky.h @@ -7,5 +7,3 @@ mp_obj_t modkandinsky_draw_string(size_t n_args, const mp_obj_t *args); mp_obj_t modkandinsky_fill_rect(size_t n_args, const mp_obj_t *args); mp_obj_t modkandinsky_wait_vblank(); mp_obj_t modkandinsky_get_keys(); -mp_obj_t modkandinsky_get_key(); -mp_obj_t modkandinsky_Pause(mp_obj_t x) ; diff --git a/python/port/mod/kandinsky/modkandinsky_table.c b/python/port/mod/kandinsky/modkandinsky_table.c index cf8490c6f..253f856a7 100644 --- a/python/port/mod/kandinsky/modkandinsky_table.c +++ b/python/port/mod/kandinsky/modkandinsky_table.c @@ -7,8 +7,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_draw_string_obj, 3, 5, m STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_fill_rect_obj, 5, 5, modkandinsky_fill_rect); STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_wait_vblank_obj, modkandinsky_wait_vblank); STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_get_keys_obj, modkandinsky_get_keys); -STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_get_key_obj, modkandinsky_get_key); -STATIC MP_DEFINE_CONST_FUN_OBJ_1(modkandinsky_Pause_obj, modkandinsky_Pause); STATIC const mp_rom_map_elem_t modkandinsky_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_kandinsky) }, @@ -19,8 +17,6 @@ STATIC const mp_rom_map_elem_t modkandinsky_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_fill_rect), (mp_obj_t)&modkandinsky_fill_rect_obj }, { MP_ROM_QSTR(MP_QSTR_wait_vblank), (mp_obj_t)&modkandinsky_wait_vblank_obj }, { MP_ROM_QSTR(MP_QSTR_get_keys), (mp_obj_t)&modkandinsky_get_keys_obj }, - { MP_ROM_QSTR(MP_QSTR_get_key), (mp_obj_t)&modkandinsky_get_key_obj }, - { MP_ROM_QSTR(MP_QSTR_Pause), (mp_obj_t)&modkandinsky_Pause_obj }, }; STATIC MP_DEFINE_CONST_DICT(modkandinsky_module_globals, modkandinsky_module_globals_table); diff --git a/python/port/port.cpp b/python/port/port.cpp index 0a1735bdd..163aefd24 100644 --- a/python/port/port.cpp +++ b/python/port/port.cpp @@ -1,14 +1,6 @@ -#ifdef SIMULATOR -#include -#endif -#include #include "port.h" -#include -#include -#include -#include "../../apps/apps_container.h" -#include "../../apps/global_preferences.h" +#include #include #include @@ -86,9 +78,9 @@ void MicroPython::ExecutionEnvironment::runCode(const char * str) { /* End of mp_obj_print_exception. */ } - assert(sCurrentExecutionEnvironment == this); - sCurrentExecutionEnvironment = nullptr; - } + assert(sCurrentExecutionEnvironment == this); + sCurrentExecutionEnvironment = nullptr; +} void MicroPython::ExecutionEnvironment::interrupt() { mp_keyboard_interrupt(); @@ -205,485 +197,11 @@ mp_import_stat_t mp_import_stat(const char *path) { } void mp_hal_stdout_tx_strn_cooked(const char * str, size_t len) { - if (sCurrentExecutionEnvironment != nullptr) - sCurrentExecutionEnvironment->printText(str, len); + assert(sCurrentExecutionEnvironment != nullptr); + sCurrentExecutionEnvironment->printText(str, len); } const char * mp_hal_input(const char * prompt) { - if (sCurrentExecutionEnvironment != nullptr) - return sCurrentExecutionEnvironment->inputText(prompt); - return 0; + assert(sCurrentExecutionEnvironment != nullptr); + return sCurrentExecutionEnvironment->inputText(prompt); } - -/* C-- SDK , (c) B. Parisse 2019 */ - -const char * read_file(const char * filename){ -#if 1 - Ion::Storage * s=Ion::Storage::sharedStorage(); - const Ion::Storage::Record r=s->recordNamed(filename); - if (r.isNull()) - return 0; - Ion::Storage::Record::Data d=r.value(); - const char * ptr=(const char *)d.buffer; - if (ptr) - return ptr+1; - else - return 0; -#endif - if (sScriptProvider != nullptr) - return sScriptProvider->contentOfScript(filename); - return "undef"; -} - -bool write_file(const char * filename,const char * content,size_t len){ - Ion::Storage * s=Ion::Storage::sharedStorage(); - auto res=s->createRecordWithFullName(filename,content,strlen(content)+1); - if (res==Ion::Storage::Record::ErrorStatus::NameTaken){ - auto r=s->recordNamed(filename); - Ion::Storage::Record::Data d; - d.buffer=content; - d.size=(len?len:strlen(content))+1; - return r.setValue(d)==Ion::Storage::Record::ErrorStatus::None; - } - if (res==Ion::Storage::Record::ErrorStatus::None) - return write_file(filename,content,len); - return false; -} - -bool file_exists(const char * filename){ - Ion::Storage * s=Ion::Storage::sharedStorage(); - return s->isFullNameTaken(filename); -} - -bool erase_file(const char * filename){ - Ion::Storage * s=Ion::Storage::sharedStorage(); - auto r= s->recordNamed(filename); - if (r.isNull()) - return false; - r.destroy(); - return true; -} - - -#if 1 -int os_file_browser(const char ** filenames,int maxrecords,const char * extension){ - Ion::Storage * s=Ion::Storage::sharedStorage(); - int n=s->numberOfRecordsWithExtension(extension); - if (!n) return 0; - if (n>maxrecords) n=maxrecords; - for (int i=0;irecordWithExtensionAtIndex(extension, i); - filenames[i]=r.fullName(); - } - filenames[n]=0; - return n; -} - // const char * ptr=(const char *)r.value().buffer; - /* storage.h - Ion::Storage::Record::Data structure avec 2 membres - const void * buffer et size_t size - - Record(const char * fullName = nullptr); - Record(const char * basename, const char * extension); - Data value(); - Ion::Storage::Record::ErrorStatus setValue(Ion::Storage::Record::Data); - void destroy(void); - - // Record creation - Record::ErrorStatus createRecordWithFullName(const char * fullName, const void * data, size_t size); - Record::ErrorStatus createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size); - - // Record getters - Record recordWithExtensionAtIndex(const char * extension, int index); - Record recordNamed(const char * fullName); - Record recordBaseNamedWithExtension(const char * baseName, const char * extension); - Record recordBaseNamedWithExtensions(const char * baseName, const char * const extension[], size_t numberOfExtensions); - - // Record destruction - void destroyAllRecords(); - void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension); - void destroyRecordsWithExtension(const char * extension); - - - */ -#endif - -void statuslinemsg(const char * msg){ - AppsContainer::sharedAppsContainer()->reloadTitleBarView(); - auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); - if (ptr) - ptr->displaySandbox(); - auto ctx=KDIonContext::sharedContext(); - KDRect save=ctx->m_clippingRect; - KDPoint o=ctx->m_origin; - ctx->setClippingRect(KDRect(0,0,280,18)); - ctx->setOrigin(KDPoint(0,0)); - KDRect rect(0,0,280,18); - KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); - if (strlen(msg)>25) - ctx->drawString(msg, KDPoint(0,0), KDFont::SmallFont, 0, 64934); - else - ctx->drawString(msg, KDPoint(0,0), KDFont::LargeFont, 0, 64934); - ctx->setClippingRect(save); - ctx->setOrigin(o); -} - -bool os_set_angle_unit(int mode){ - Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); - if (mode==0){ // rad - preferences->setAngleUnit(Poincare::Preferences::AngleUnit::Radian); - return true; - } - if (mode==1){ // deg - preferences->setAngleUnit(Poincare::Preferences::AngleUnit::Degree); - return true; - } - return false; - if (mode==2){ // grad - return true; - } -} - -int os_get_angle_unit(){ - Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); - if (preferences->angleUnit()==Poincare::Preferences::AngleUnit::Radian) - return 0; - if (preferences->angleUnit()==Poincare::Preferences::AngleUnit::Degree) - return 1; - return 2; -} - -#ifdef SIMULATOR -#define TICKS_PER_MINUTE 60000 -#else -#define TICKS_PER_MINUTE 11862 -extern const void * _stack_start; -extern const void * _heap_start; -#endif -//int time_shift=0; // set it via time() command in KhiCAS -void statusline(int mode, size_t heap){ - AppsContainer::sharedAppsContainer()->reloadTitleBarView(); - auto ctx=KDIonContext::sharedContext(); - KDRect save=ctx->m_clippingRect; - KDPoint o=ctx->m_origin; - ctx->setClippingRect(KDRect(0,0,320,18)); - ctx->setOrigin(KDPoint(0,0)); - KDRect rect(0,0,mode==1?320:280,18); - KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); - const char * text=0; - Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); - if (preferences->angleUnit() == Poincare::Preferences::AngleUnit::Radian) - text="rad"; - else - text="deg"; - // ctx->drawString(text, KDPoint(5,1), KDFont::SmallFont, 0, 63488 /* Palette::Red*/); - ctx->drawString(text, KDPoint(5,1), KDFont::SmallFont, 0, 64934); -#ifdef GIAC_LINKED - if (khicas_eval) - text="KHICAS"; - else - text="PYTHON"; -#else - text="KHICAS"; -#endif - ctx->drawString(text, KDPoint(70,1), KDFont::SmallFont, 0, 64934); - char bufheap[16]; -#if 0 //ndef SIMULATOR -#endif - int x; - x=(heap&0xf0000000)>>28; - bufheap[0]=(x>9?'a'+(x-10):'0'+x); - x=(heap&0xf000000)>>24; - bufheap[1]=(x>9?'a'+(x-10):'0'+x); - x=(heap&0xf00000)>>20; - bufheap[2]=(x>9?'a'+(x-10):'0'+x); - x=(heap&0xf0000)>>16; - bufheap[3]=(x>9?'a'+(x-10):'0'+x); - x=(heap&0xf000)>>12; - bufheap[4]=(x>9?'a'+(x-10):'0'+x); - x=(heap&0xf00)>>8; - bufheap[5]=(x>9?'a'+(x-10):'0'+x); - x=(heap&0xf0)>>4; - bufheap[6]=(x>9?'a'+(x-10):'0'+x); - x=(heap&0xf); - bufheap[7]=(x>9?'a'+(x-10):'0'+x); - bufheap[8]=0; - if(heap != 0) ctx->drawString(bufheap,KDPoint(130,1),KDFont::SmallFont, 0, 64934); -#ifdef GIAC_SHOWTIME - int d=(Ion::Timing::millis()/TICKS_PER_MINUTE +time_shift) % (24*60); // minutes - char buf[32]={0,0,0,0}; - int h=d/60; - buf[0]='0'+h/10; - buf[1]='0'+(h%10); - buf[2]=':'; - ctx->drawString(buf, KDPoint(148,1), KDFont::SmallFont, 0, 64934); - int mn=d%60; - buf[0]='0'+mn/10; - buf[1]='0'+(mn%10); - buf[2]=0; - ctx->drawString(buf, KDPoint(168,1), KDFont::SmallFont, 0, 64934); -#endif - text=" "; - if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::Shift) - text="shift "; - else { - if (Ion::Events::isAlphaActive()){ - if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::AlphaLock) - text="alphal"; - if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::ShiftAlphaLock) - text="ALPHAL"; - if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::Alpha) - text="1alpha"; - if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::ShiftAlpha) - text="1ALPHA"; - } - } - ctx->drawString(text, KDPoint(232,1), KDFont::SmallFont, 0, 64934 /* Palette::YellowDark*/); - if (mode==1){ - if (Ion::USB::isPlugged()) - text="charge"; - else { - auto c=Ion::Battery::level(); - if (c==Ion::Battery::Charge::EMPTY) - text="empty "; - if (c==Ion::Battery::Charge::LOW) - text="low "; - if (c==Ion::Battery::Charge::FULL) - text="full "; - } - ctx->drawString(text, KDPoint(280,1), KDFont::SmallFont, 0, 64934 /* Palette::YellowDark*/); - } - ctx->setClippingRect(save); - ctx->setOrigin(o); -} - -bool isalphaactive(){ - return Ion::Events::isAlphaActive(); -} - -void lock_alpha(){ - Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock); - statusline(0,0); -} - -void reset_kbd(){ - Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default); - statusline(0,0); -} - -bool alphawasactive_=false; -bool alphawasactive(){ - return alphawasactive_; -} - -bool waitforvblank(){ - return Ion::Display::waitForVBlank(); -} - -bool back_key_pressed() { - static int c = 0; - - ++c ; - if (c<400 || (c & 0xf)!= 0) { - return false; - } -#ifdef SIMULATOR - Fl::wait(0.00001); -#endif - - Ion::Keyboard::State scan = Ion::Keyboard::scan(); - // if (scan!=16) std::cerr << scan << '\n'; - Ion::Keyboard::Key interruptKey = static_cast(mp_interrupt_char); - if (scan.keyDown(interruptKey) - // || scan.keyDown(static_cast(16)) - ) - return true; - return false; -} - -int getkey_raw(bool allow_suspend){ - int key=-1; - size_t t1=Ion::Timing::millis(); - for (;;){ - int timeout=10000; - alphawasactive_=Ion::Events::isAlphaActive(); - Ion::Events::Event event=Ion::Events::getEvent(&timeout); - auto ctx=KDIonContext::sharedContext(); - KDRect save=ctx->m_clippingRect; - KDPoint o=ctx->m_origin; - ctx->setClippingRect(KDRect(0,0,320,240)); - ctx->setOrigin(KDPoint(0,18)); - KDRect rect(90,63,140,75); - if (event==Ion::Events::None){ - size_t t2=Ion::Timing::millis(); - if (t2-t1>2*TICKS_PER_MINUTE){ - // KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); - event=Ion::Events::OnOff; - } - } - else - t1=Ion::Timing::millis(); - if (event == Ion::Events::USBPlug) { - statusline(0,0); - // KDIonContext::sharedContext()->pushRectUniform(rect,33333); - if (Ion::USB::isPlugged()) { - if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { - Ion::LED::setColor(KDColorBlack); - Ion::LED::updateColorWithPlugAndCharge(); - GlobalPreferences::sharedGlobalPreferences()->setExamMode(false); - // displayExamModePopUp(false); - } else { - Ion::USB::enable(); - } - Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); - } else { - Ion::USB::disable(); - } - } - if (event == Ion::Events::USBEnumeration || event == Ion::Events::USBPlug || event == Ion::Events::BatteryCharging) { - Ion::LED::updateColorWithPlugAndCharge(); - } - if (event == Ion::Events::USBEnumeration - ) { - KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); - if (Ion::USB::isPlugged()) { - /* Just after a software update, the battery timer does not have time to - * fire before the calculator enters DFU mode. As the DFU mode blocks the - * event loop, we update the battery state "manually" here. - * We do it before switching to USB application to redraw the battery - * pictogram. */ - // updateBatteryState(); - KDIonContext::sharedContext()->pushRectUniform(rect,22222); - auto ctx=KDIonContext::sharedContext(); - int y=58; - ctx->drawString("Connecte ! ", KDPoint(100,y), KDFont::LargeFont, 65535, 0); - y+=18; - ctx->drawString(" DFU mode ", KDPoint(100,y), KDFont::LargeFont, 65535, 0); - y+=18; - ctx->drawString("Back quitte", KDPoint(100,y), KDFont::LargeFont, 65535, 0); - y-=18; - Ion::USB::DFU(); - KDIonContext::sharedContext()->pushRectUniform(rect,44444); - ctx->drawString("Deconnecte!", KDPoint(100,y), KDFont::LargeFont, 65535, 0); - // Update LED when exiting DFU mode - Ion::LED::updateColorWithPlugAndCharge(); - } else { - /* Sometimes, the device gets an ENUMDNE interrupts when being unplugged - * from a non-USB communicating host (e.g. a USB charger). The interrupt - * must me cleared: if not the next enumeration attempts will not be - * detected. */ - Ion::USB::clearEnumerationInterrupt(); - } - } - if (event.isKeyboardEvent()) { - // m_backlightDimmingTimer.reset(); - // m_suspendTimer.reset(); - Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); - } - ctx->setClippingRect(save); - ctx->setOrigin(o); - - if (event==Ion::Events::Shift || event==Ion::Events::Alpha){ - statusline(0,0); - continue; - } - if (event.isKeyboardEvent()){ - key=event.id(); - if (key==17 || key==4 || key==5 || key==52) - reset_kbd(); - if (allow_suspend && (key==7 || key==8) ){ // power - Ion::Power::suspend(true); - numworks_fill_rect(0,0,320,240,65535); - Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); - AppsContainer::sharedAppsContainer()->reloadTitleBarView(); - //AppsContainer::sharedAppsContainer()->redrawWindow(); - statusline(1,0); - //continue; - } - else - statusline(0,0); - break; - } - } - return key; -} - -const short int translated_keys[]= - { - // non shifted - KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, - KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, - KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_XTT,KEY_CTRL_VARS,KEY_CTRL_CATALOG,KEY_CTRL_DEL, - KEY_CHAR_EXPN,KEY_CHAR_LN,KEY_CHAR_LOG,KEY_CHAR_IMGNRY,',',KEY_CHAR_POW, - KEY_CHAR_SIN,KEY_CHAR_COS,KEY_CHAR_TAN,KEY_CHAR_PI,KEY_CHAR_ROOT,KEY_CHAR_SQUARE, - '7','8','9','(',')',-1, - '4','5','6','*','/',-1, - '1','2','3','+','-',-1, - '0','.',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, - // shifted - KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, - KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, - KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_CUT,KEY_CTRL_CLIP,KEY_CTRL_PASTE,KEY_CTRL_AC, - KEY_CHAR_LBRCKT,KEY_CHAR_RBRCKT,KEY_CHAR_LBRACE,KEY_CHAR_RBRACE,'_',KEY_CHAR_STORE, - KEY_CHAR_ASIN,KEY_CHAR_ACOS,KEY_CHAR_ATAN,'=','<','>', - KEY_CTRL_F7,KEY_CTRL_F8,KEY_CTRL_F9,KEY_CTRL_F13,KEY_CTRL_F14,-1, - KEY_CTRL_F4,KEY_CTRL_F5,KEY_CTRL_F6,KEY_CHAR_FACTOR,'%',-1, - KEY_CTRL_F1,KEY_CTRL_F2,KEY_CTRL_F3,KEY_CHAR_NORMAL,'\\',-1, - KEY_CTRL_F10,KEY_CTRL_F11,KEY_CTRL_F12,KEY_SHIFT_ANS,KEY_CTRL_EXE,-1, - // alpha - KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, - KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, - KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','"',KEY_CTRL_DEL, - 'a','b','c','d','e','f', - 'g','h','i','j','k','l', - 'm','n','o','p','q',-1, - 'r','s','t','u','v',-1, - 'w','x','y','z',' ',-1, - '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, - // alpha shifted - KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, - KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, - KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','\'','%', - 'A','B','C','D','E','F', - 'G','H','I','J','K','L', - 'M','N','O','P','Q',-1, - 'R','S','T','U','V',-1, - 'W','X','Y','Z',' ',-1, - '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, - }; - -int getkey(bool allow_suspend){ - int k=getkey_raw(allow_suspend); - // translate - return translated_keys[k]; -} - -// Casio prototype -void GetKey(int * key){ - *key=getkey(true); -} - - -void numworks_wait_1ms(int ms){ - for (int i=0;i(Ion::Keyboard::Key::Back); - if (scan.keyDown(interruptKey)) - return; - Ion::Timing::msleep(128); - } - Ion::Timing::msleep(ms % 128); -} - -void enable_back_interrupt(){ - mp_interrupt_char = (int)Ion::Keyboard::Key::Back; -} - -void disable_back_interrupt(){ - mp_interrupt_char = -1; -} - diff --git a/python/port/port.h b/python/port/port.h index 869b6f937..f0b3a0407 100644 --- a/python/port/port.h +++ b/python/port/port.h @@ -36,212 +36,4 @@ void registerScriptProvider(ScriptProvider * s); }; -extern "C" { -/* - basic SDK for direct control of the calculator like in KhiCAS - */ - bool waitforvblank(); - int os_file_browser(const char ** filenames,int maxrecords,const char * extension); - void numworks_hide_graph(); - void numworks_show_graph(); - void enable_back_interrupt(); - void disable_back_interrupt(); - int os_get_angle_unit(); - bool os_set_angle_unit(int mode); - const char * read_file(const char * filename); - bool write_file(const char * filename,const char * content,size_t len); -int getkey_raw(bool allow_suspend); // Numworks scan code -int getkey(bool allow_suspend); // transformed -void GetKey(int * key); // Casio like -bool isalphaactive(); -bool alphawasactive(); // alpha status before getkey -bool back_key_pressed() ; -void lock_alpha(); -void reset_kbd(); -void statusline(int mode=0, size_t=0); // display status line -void statuslinemsg(const char * msg); // display a message in statusline -void numworks_fill_rect(int x,int y,int w,int h,int c); // y=0 is automatically translated by 18 for statusline -void numworks_set_pixel(int x,int y,int c); -int numworks_get_pixel(int x,int y); -/* draw_string returns new x position, use fake=true to compute without drawing */ -int numworks_draw_string(int x,int y,int c,int bg,const char * s,bool fake=false); -int numworks_draw_string_small(int x,int y,int c,int bg,const char * s,bool fake=false); -// scriptstore -bool file_exists(const char * filename); -bool erase_file(const char * filename); -const char * read_file(const char * filename); -bool write_file(const char * filename,const char * s,size_t len=0); -int giac_filebrowser(char * filename,const char * extension,const char * title); -void numworks_wait_1ms(int ms); -//double millis(); -//extern int time_shift; // shift for the clock - - -// Character codes -#define KEY_CHAR_0 0x30 -#define KEY_CHAR_1 0x31 -#define KEY_CHAR_2 0x32 -#define KEY_CHAR_3 0x33 -#define KEY_CHAR_4 0x34 -#define KEY_CHAR_5 0x35 -#define KEY_CHAR_6 0x36 -#define KEY_CHAR_7 0x37 -#define KEY_CHAR_8 0x38 -#define KEY_CHAR_9 0x39 -#define KEY_CHAR_DP 0x2e -#define KEY_CHAR_EXP 0x0f -#define KEY_CHAR_PMINUS 30200 -#define KEY_CHAR_PLUS 43 -#define KEY_CHAR_MINUS 45 -#define KEY_CHAR_MULT 42 -#define KEY_CHAR_DIV 47 -#define KEY_CHAR_FRAC 0xbb -#define KEY_CHAR_LPAR 0x28 -#define KEY_CHAR_RPAR 0x29 -#define KEY_CHAR_COMMA 0x2c -#define KEY_CHAR_STORE 0x0e -#define KEY_CHAR_LOG 0x95 -#define KEY_CHAR_LN 0x85 -#define KEY_CHAR_SIN 0x81 -#define KEY_CHAR_COS 0x82 -#define KEY_CHAR_TAN 0x83 -#define KEY_CHAR_SQUARE 0x8b -#define KEY_CHAR_POW 0xa8 -#define KEY_CHAR_IMGNRY 0x7f50 -#define KEY_CHAR_LIST 0x7f51 -#define KEY_CHAR_MAT 0x7f40 -#define KEY_CHAR_EQUAL 0x3d -#define KEY_CHAR_PI 0xd0 -#define KEY_CHAR_ANS 0xc0 -#define KEY_SHIFT_ANS 0xc1 -#define KEY_CHAR_LBRCKT 0x5b -#define KEY_CHAR_RBRCKT 0x5d -#define KEY_CHAR_LBRACE 0x7b -#define KEY_CHAR_RBRACE 0x7d -#define KEY_CHAR_CR 0x0d -#define KEY_CHAR_CUBEROOT 0x96 -#define KEY_CHAR_RECIP 0x9b -#define KEY_CHAR_ANGLE 0x7f54 -#define KEY_CHAR_EXPN10 0xb5 -#define KEY_CHAR_EXPN 0xa5 -#define KEY_CHAR_ASIN 0x91 -#define KEY_CHAR_ACOS 0x92 -#define KEY_CHAR_ATAN 0x93 -#define KEY_CHAR_ROOT 0x86 -#define KEY_CHAR_POWROOT 0xb8 -#define KEY_CHAR_SPACE 0x20 -#define KEY_CHAR_DQUATE 0x22 -#define KEY_CHAR_VALR 0xcd -#define KEY_CHAR_THETA 0xce -#define KEY_CHAR_FACTOR 0xda -#define KEY_CHAR_NORMAL 0xdb -#define KEY_CHAR_A 0x41 -#define KEY_CHAR_B 0x42 -#define KEY_CHAR_C 0x43 -#define KEY_CHAR_D 0x44 -#define KEY_CHAR_E 0x45 -#define KEY_CHAR_F 0x46 -#define KEY_CHAR_G 0x47 -#define KEY_CHAR_H 0x48 -#define KEY_CHAR_I 0x49 -#define KEY_CHAR_J 0x4a -#define KEY_CHAR_K 0x4b -#define KEY_CHAR_L 0x4c -#define KEY_CHAR_M 0x4d -#define KEY_CHAR_N 0x4e -#define KEY_CHAR_O 0x4f -#define KEY_CHAR_P 0x50 -#define KEY_CHAR_Q 0x51 -#define KEY_CHAR_R 0x52 -#define KEY_CHAR_S 0x53 -#define KEY_CHAR_T 0x54 -#define KEY_CHAR_U 0x55 -#define KEY_CHAR_V 0x56 -#define KEY_CHAR_W 0x57 -#define KEY_CHAR_X 0x58 -#define KEY_CHAR_Y 0x59 -#define KEY_CHAR_Z 0x5a - - -// Control codes -#define KEY_CTRL_NOP 30202 -#define KEY_CTRL_EXE 30201 -#define KEY_CTRL_DEL 30025 -#define KEY_CTRL_AC 30070 -#define KEY_CTRL_FD 30046 -#define KEY_CTRL_UNDO 30045 -#define KEY_CTRL_XTT 30001 -#define KEY_CTRL_EXIT 5 -#define KEY_CTRL_OK 4 -#define KEY_CTRL_SHIFT 30006 -#define KEY_CTRL_ALPHA 30007 -#define KEY_CTRL_OPTN 30008 -#define KEY_CTRL_VARS 30030 -#define KEY_CTRL_UP 1 -#define KEY_CTRL_DOWN 2 -#define KEY_CTRL_LEFT 0 -#define KEY_CTRL_RIGHT 3 -#define KEY_CTRL_F1 30009 -#define KEY_CTRL_F2 30010 -#define KEY_CTRL_F3 30011 -#define KEY_CTRL_F4 30012 -#define KEY_CTRL_F5 30013 -#define KEY_CTRL_F6 30014 -#define KEY_CTRL_F7 30015 -#define KEY_CTRL_F8 30016 -#define KEY_CTRL_F9 30017 -#define KEY_CTRL_F10 30018 -#define KEY_CTRL_F11 30019 -#define KEY_CTRL_F12 30020 -#define KEY_CTRL_F13 30021 -#define KEY_CTRL_F14 30022 -#define KEY_CTRL_CATALOG 30100 -#define KEY_CTRL_CAPTURE 30055 -#define KEY_CTRL_CLIP 30050 -#define KEY_CTRL_CUT 30250 -#define KEY_CTRL_PASTE 30036 -#define KEY_CTRL_INS 30033 -#define KEY_CTRL_MIXEDFRAC 30054 -#define KEY_CTRL_FRACCNVRT 30026 -#define KEY_CTRL_QUIT 30029 -#define KEY_CTRL_PRGM 30028 -#define KEY_CTRL_SETUP 30037 -#define KEY_CTRL_PAGEUP 30052 -#define KEY_CTRL_PAGEDOWN 30053 -#define KEY_CTRL_MENU 30003 -#define KEY_SHIFT_OPTN 30059 -#define KEY_CTRL_RESERVE1 30060 -#define KEY_CTRL_RESERVE2 30061 -#define KEY_SHIFT_LEFT 30062 -#define KEY_SHIFT_RIGHT 30063 - -#define KEY_PRGM_ACON 10 -#define KEY_PRGM_DOWN 37 -#define KEY_PRGM_EXIT 47 -#define KEY_PRGM_F1 79 -#define KEY_PRGM_F2 69 -#define KEY_PRGM_F3 59 -#define KEY_PRGM_F4 49 -#define KEY_PRGM_F5 39 -#define KEY_PRGM_F6 29 -#define KEY_PRGM_LEFT 38 -#define KEY_PRGM_NONE 0 -#define KEY_PRGM_RETURN 31 -#define KEY_PRGM_RIGHT 27 -#define KEY_PRGM_UP 28 -#define KEY_PRGM_1 72 -#define KEY_PRGM_2 62 -#define KEY_PRGM_3 52 -#define KEY_PRGM_4 73 -#define KEY_PRGM_5 63 -#define KEY_PRGM_6 53 -#define KEY_PRGM_7 74 -#define KEY_PRGM_8 64 -#define KEY_PRGM_9 54 -#define KEY_PRGM_A 76 -#define KEY_PRGM_F 26 -#define KEY_PRGM_ALPHA 77 -#define KEY_PRGM_SHIFT 78 -#define KEY_PRGM_MENU 48 -} #endif From b155af0c0dda42826bef77756522755a21d224e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Wed, 18 Dec 2019 10:55:59 +0100 Subject: [PATCH 060/130] [ion/external_flash] Finer flash sectors Instead of 128 sectors of 64K, there are now 8 sectors of 4K, 1 of 32K and 127 of 64K. This makes a more finely erasable flash, which is needed for the exam mode. --- .../n0100/drivers/config/external_flash.h | 5 ++- .../n0110/drivers/config/external_flash.h | 7 +++- ion/src/device/n0110/drivers/config/usb.h | 2 +- .../device/shared/drivers/external_flash.cpp | 36 +++++++++++++++++-- .../device/shared/drivers/external_flash.h | 7 +++- 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/ion/src/device/n0100/drivers/config/external_flash.h b/ion/src/device/n0100/drivers/config/external_flash.h index 79d39f768..2fa895a21 100644 --- a/ion/src/device/n0100/drivers/config/external_flash.h +++ b/ion/src/device/n0100/drivers/config/external_flash.h @@ -22,7 +22,10 @@ using namespace Regs; constexpr static uint32_t StartAddress = 0xFFFFFFFF; constexpr static uint32_t EndAddress = 0xFFFFFFFF; -constexpr static int NumberOfSectors = 0; +constexpr static int NumberOf4KSectors = 0; +constexpr static int NumberOf32KSectors = 0; +constexpr static int NumberOf64KSectors = 0; +constexpr static int NumberOfSectors = NumberOf4KSectors + NumberOf32KSectors + NumberOf64KSectors; constexpr static AFGPIOPin Pins[] = {}; } diff --git a/ion/src/device/n0110/drivers/config/external_flash.h b/ion/src/device/n0110/drivers/config/external_flash.h index 98c3ef9f0..f245dca20 100644 --- a/ion/src/device/n0110/drivers/config/external_flash.h +++ b/ion/src/device/n0110/drivers/config/external_flash.h @@ -22,7 +22,12 @@ using namespace Regs; constexpr static uint32_t StartAddress = 0x90000000; constexpr static uint32_t EndAddress = 0x90800000; -constexpr static int NumberOfSectors = 128; + +constexpr static int NumberOf4KSectors = 8; +constexpr static int NumberOf32KSectors = 1; +constexpr static int NumberOf64KSectors = 128 - 1; +constexpr static int NumberOfSectors = NumberOf4KSectors + NumberOf32KSectors + NumberOf64KSectors; + constexpr static AFGPIOPin Pins[] = { AFGPIOPin(GPIOB, 2, GPIO::AFR::AlternateFunction::AF9, GPIO::PUPDR::Pull::None, GPIO::OSPEEDR::OutputSpeed::Fast), AFGPIOPin(GPIOB, 6, GPIO::AFR::AlternateFunction::AF10, GPIO::PUPDR::Pull::None, GPIO::OSPEEDR::OutputSpeed::Fast), diff --git a/ion/src/device/n0110/drivers/config/usb.h b/ion/src/device/n0110/drivers/config/usb.h index 7477f0846..bbd3fa5a1 100644 --- a/ion/src/device/n0110/drivers/config/usb.h +++ b/ion/src/device/n0110/drivers/config/usb.h @@ -14,7 +14,7 @@ constexpr static AFGPIOPin VbusPin = AFGPIOPin(GPIOA, 9, GPIO::AFR::AlternateFun constexpr static AFGPIOPin DmPin = AFGPIOPin(GPIOA, 11, GPIO::AFR::AlternateFunction::AF10, GPIO::PUPDR::Pull::None, GPIO::OSPEEDR::OutputSpeed::Fast); constexpr static AFGPIOPin DpPin = AFGPIOPin(GPIOA, 12, GPIO::AFR::AlternateFunction::AF10, GPIO::PUPDR::Pull::None, GPIO::OSPEEDR::OutputSpeed::Fast); -constexpr static const char * InterfaceStringDescriptor = "@Flash/0x08000000/04*016Kg/0x90000000/64*064Kg,64*064Kg"; +constexpr static const char * InterfaceStringDescriptor = "@Flash/0x08000000/04*016Kg/0x90000000/08*004Kg,01*032Kg,63*064Kg,64*064Kg"; } } diff --git a/ion/src/device/shared/drivers/external_flash.cpp b/ion/src/device/shared/drivers/external_flash.cpp index 10404c7c2..a2b6cfe59 100644 --- a/ion/src/device/shared/drivers/external_flash.cpp +++ b/ion/src/device/shared/drivers/external_flash.cpp @@ -71,6 +71,8 @@ enum class Command : uint8_t { Reset = 0x99, // Erase the whole chip or a 64-Kbyte block as being "1" ChipErase = 0xC7, + Erase4KbyteBlock = 0x20, + Erase32KbyteBlock = 0x52, Erase64KbyteBlock = 0xD8, SetReadParameters = 0xC0, DeepPowerDown = 0xB9, @@ -79,6 +81,8 @@ enum class Command : uint8_t { }; static constexpr uint8_t NumberOfAddressBitsIn64KbyteBlock = 16; +static constexpr uint8_t NumberOfAddressBitsIn32KbyteBlock = 15; +static constexpr uint8_t NumberOfAddressBitsIn4KbyteBlock = 12; class ExternalFlashStatusRegister { public: @@ -367,10 +371,23 @@ void shutdown() { } int SectorAtAddress(uint32_t address) { + /* WARNING: this code assumes that the flash sectors are of increasing size: + * first all 4K sectors, then all 32K sectors, and finally all 64K sectors. */ int i = address >> NumberOfAddressBitsIn64KbyteBlock; - if (i >= Config::NumberOfSectors) { + if (i > Config::NumberOf64KSectors) { return -1; } + if (i >= 1) { + return Config::NumberOf4KSectors + Config::NumberOf32KSectors + i - 1; + } + i = address >> NumberOfAddressBitsIn32KbyteBlock; + if (i >= 1) { + i = Config::NumberOf4KSectors + i - 1; + assert(i >= 0 && i <= Config::NumberOf32KSectors); + return i; + } + i = address >> NumberOfAddressBitsIn4KbyteBlock; + assert(i <= Config::NumberOf4KSectors); return i; } @@ -408,7 +425,22 @@ void __attribute__((noinline)) EraseSector(int i) { unlockFlash(); send_command(Command::WriteEnable); wait(); - send_write_command(Command::Erase64KbyteBlock, reinterpret_cast(i << NumberOfAddressBitsIn64KbyteBlock), nullptr, 0); + /* WARNING: this code assumes that the flash sectors are of increasing size: + * first all 4K sectors, then all 32K sectors, and finally all 64K sectors. */ + if (i < Config::NumberOf4KSectors) { + send_write_command(Command::Erase4KbyteBlock, reinterpret_cast(i << NumberOfAddressBitsIn4KbyteBlock), nullptr, 0); + } else if (i < Config::NumberOf4KSectors + Config::NumberOf32KSectors) { + /* If the sector is the number Config::NumberOf4KSectors, we want to write + * at the address 1 << NumberOfAddressBitsIn32KbyteBlock, hence the formula + * (i - Config::NumberOf4KSectors + 1). */ + send_write_command(Command::Erase32KbyteBlock, reinterpret_cast((i - Config::NumberOf4KSectors + 1) << NumberOfAddressBitsIn32KbyteBlock), nullptr, 0); + } else { + /* If the sector is the number + * Config::NumberOf4KSectors - Config::NumberOf32KSectors, we want to write + * at the address 1 << NumberOfAddressBitsIn32KbyteBlock, hence the formula + * (i - Config::NumberOf4KSectors - Config::NumberOf32KSectors + 1). */ + send_write_command(Command::Erase64KbyteBlock, reinterpret_cast((i - Config::NumberOf4KSectors - Config::NumberOf32KSectors + 1) << NumberOfAddressBitsIn64KbyteBlock), nullptr, 0); + } wait(); set_as_memory_mapped(); } diff --git a/ion/src/device/shared/drivers/external_flash.h b/ion/src/device/shared/drivers/external_flash.h index 8a0ad3b62..f2c1ddd6f 100644 --- a/ion/src/device/shared/drivers/external_flash.h +++ b/ion/src/device/shared/drivers/external_flash.h @@ -15,7 +15,12 @@ * 2^7 64KiB blocks 0x..0000 - 0x..FFFF * 2^7 * 2 32KiB blocks 0x..0000 - 0x..7FFF or 0x..8000 - 0x..FFFF * 2^7 * 2 * 2^3 4KiB blocks 0x...000 - 0x...FFF - * 2^7 * 2 * 2^3 * 2^4 256B pages 0x....00 - 0x....FF */ + * 2^7 * 2 * 2^3 * 2^4 256B pages 0x....00 - 0x....FF + * + * To be able to erase a small sector for the exam mode, we say that the flash + * is cut into 8 + 1 + 2^7-1 = 136 sectors: 8 sectors of 4Kb, 1 sector of 32Kb + * and 2^7-1 sectors of 64Kb. These sectors are the smallest erasable units. If + * need be, we can define more sectors to erase even more finely the flash. */ namespace Ion { namespace Device { From 6a7ca3263006f94a46e3051ecbf46c027e027366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 28 Oct 2019 11:59:53 +0100 Subject: [PATCH 061/130] [apps/home] Add messages: ForbidenAppInExamMode --- apps/home/base.de.i18n | 2 ++ apps/home/base.en.i18n | 2 ++ apps/home/base.es.i18n | 2 ++ apps/home/base.fr.i18n | 2 ++ apps/home/base.pt.i18n | 2 ++ 5 files changed, 10 insertions(+) diff --git a/apps/home/base.de.i18n b/apps/home/base.de.i18n index f762d3e57..a8f33d6cb 100644 --- a/apps/home/base.de.i18n +++ b/apps/home/base.de.i18n @@ -1,2 +1,4 @@ Apps = "Anwendungen" AppsCapital = "ANWENDUNGEN" +ForbidenAppInExamMode1 = "" +ForbidenAppInExamMode2 = "" diff --git a/apps/home/base.en.i18n b/apps/home/base.en.i18n index b7ab1ab2f..158fa3bda 100644 --- a/apps/home/base.en.i18n +++ b/apps/home/base.en.i18n @@ -1,2 +1,4 @@ Apps = "Applications" AppsCapital = "APPLICATIONS" +ForbidenAppInExamMode1 = "This application is" +ForbidenAppInExamMode2 = "forbidden in exam mode" diff --git a/apps/home/base.es.i18n b/apps/home/base.es.i18n index 7ad2abcbf..8f48d86c5 100644 --- a/apps/home/base.es.i18n +++ b/apps/home/base.es.i18n @@ -1,2 +1,4 @@ Apps = "Aplicaciones" AppsCapital = "APLICACIONES" +ForbidenAppInExamMode1 = "" +ForbidenAppInExamMode2 = "" diff --git a/apps/home/base.fr.i18n b/apps/home/base.fr.i18n index b7ab1ab2f..200c6f577 100644 --- a/apps/home/base.fr.i18n +++ b/apps/home/base.fr.i18n @@ -1,2 +1,4 @@ Apps = "Applications" AppsCapital = "APPLICATIONS" +ForbidenAppInExamMode1 = "" +ForbidenAppInExamMode2 = "" diff --git a/apps/home/base.pt.i18n b/apps/home/base.pt.i18n index aa255ea6b..2720ea295 100644 --- a/apps/home/base.pt.i18n +++ b/apps/home/base.pt.i18n @@ -1,2 +1,4 @@ Apps = "Aplicações" AppsCapital = "APLICAÇÕES" +ForbidenAppInExamMode1 = "" +ForbidenAppInExamMode2 = "" From 510151c7db9db1853431c18edf115de11137952f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 28 Oct 2019 12:01:36 +0100 Subject: [PATCH 062/130] [apps/home] Prevent from entering Python application in exam mode --- apps/home/controller.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index c59612d7a..221ba5ec9 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -1,6 +1,7 @@ #include "controller.h" #include "app.h" #include "../apps_container.h" +#include "../global_preferences.h" extern "C" { #include } @@ -57,9 +58,15 @@ Controller::Controller(Responder * parentResponder, SelectableTableViewDataSourc bool Controller::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::EXE) { AppsContainer * container = AppsContainer::sharedAppsContainer(); - bool switched = container->switchTo(container->appSnapshotAtIndex(selectionDataSource()->selectedRow()*k_numberOfColumns+selectionDataSource()->selectedColumn()+1)); - assert(switched); - (void) switched; // Silence compilation warning about unused variable. + ::App::Snapshot * selectedSnapshot = container->appSnapshotAtIndex(selectionDataSource()->selectedRow()*k_numberOfColumns+selectionDataSource()->selectedColumn()+1); + // TODO: check that we are in Dutch exam mode + if (GlobalPreferences::sharedGlobalPreferences()->examMode() && selectedSnapshot->descriptor()->name() == I18n::Message::CodeApp) { + App::app()->displayWarning(I18n::Message::ForbidenAppInExamMode1, I18n::Message::ForbidenAppInExamMode2); + } else { + bool switched = container->switchTo(selectedSnapshot); + assert(switched); + (void) switched; // Silence compilation warning about unused variable. + } return true; } From 82fb00689e025310a7d3d499279c321b3b004dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 28 Oct 2019 15:22:54 +0100 Subject: [PATCH 063/130] [apps/settings] Message: add messages to activate Dutch exam mode --- apps/settings/base.de.i18n | 2 ++ apps/settings/base.en.i18n | 2 ++ apps/settings/base.es.i18n | 2 ++ apps/settings/base.fr.i18n | 2 ++ apps/settings/base.pt.i18n | 2 ++ 5 files changed, 10 insertions(+) diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index a9385db05..0f3e127e1 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -9,6 +9,8 @@ ComplexFormat = "Komplex" ExamMode = "Testmodus" ActivateExamMode = "Starten Testmodus" ExamModeActive = "Wieder starten Testmodus" +ActivateDutchExamMode = "" +DutchExamModeActive = "" About = "Über" Degrees = "Grad " Gradians = "Gone " diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index e5cc87cae..7f7309985 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -9,6 +9,8 @@ ComplexFormat = "Complex format" ExamMode = "Exam mode" ActivateExamMode = "Activate exam mode" ExamModeActive = "Reactivate exam mode" +ActivateDutchExamMode = "Activate Dutch exam mode" +DutchExamModeActive = "Reactivate Dutch exam mode" About = "About" Degrees = "Degrees " Gradians = "Gradians " diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index 589348d3e..aaf71e055 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -9,6 +9,8 @@ ComplexFormat = "Forma compleja" ExamMode = "Modo examen" ActivateExamMode = "Activar el modo examen" ExamModeActive = "Reactivar el modo examen" +ActivateDutchExamMode = "" +DutchExamModeActive = "" About = "Acerca" Degrees = "Grados " Gradians = "Gradianes " diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 5ca04b291..e8782094c 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -9,6 +9,8 @@ ComplexFormat = "Forme complexe" ExamMode = "Mode examen" ActivateExamMode = "Activer le mode examen" ExamModeActive = "Réactiver le mode examen" +ActivateDutchExamMode = "" +DutchExamModeActive = "" About = "À propos" Degrees = "Degrés " Gradians = "Grades " diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index 6582afeff..18d8b0ca4 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -9,6 +9,8 @@ ComplexFormat = "Complexos" ExamMode = "Modo de exame" ActivateExamMode = "Ativar o modo de exame" ExamModeActive = "Reativar o modo de exame" +ActivateDutchExamMode = "" +DutchExamModeActive = "" About = "Acerca" Degrees = "Graus " Gradians = "Grados " From f4de842a865c8e00c82a40b92d17fca3268527f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Dec 2019 11:44:13 +0100 Subject: [PATCH 064/130] [ion] Change exam mode to have 3 states (off, standard, Dutch) --- ion/include/ion/exam_mode.h | 8 +++- ion/src/device/shared/drivers/exam_mode.cpp | 48 +++++++++++++-------- ion/src/shared/dummy/exam_mode.cpp | 4 +- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/ion/include/ion/exam_mode.h b/ion/include/ion/exam_mode.h index ef0c5c92b..801dd4d1e 100644 --- a/ion/include/ion/exam_mode.h +++ b/ion/include/ion/exam_mode.h @@ -1,11 +1,15 @@ #ifndef ION_EXAM_MODE_H #define ION_EXAM_MODE_H +extern "C" { +#include +} + namespace Ion { namespace ExamMode { -bool FetchExamMode(); -void ToggleExamMode(); +uint8_t FetchExamMode(); +void IncrementExamMode(uint8_t delta); } } diff --git a/ion/src/device/shared/drivers/exam_mode.cpp b/ion/src/device/shared/drivers/exam_mode.cpp index 19b62b4df..806729c01 100644 --- a/ion/src/device/shared/drivers/exam_mode.cpp +++ b/ion/src/device/shared/drivers/exam_mode.cpp @@ -18,14 +18,17 @@ char ones[Config::ExamModeBufferSize] /* The exam mode is written in flash so that it is resilient to resets. * We erase the dedicated flash sector (all bits written to 1) and, upon - * activating or deactivating the exam mode we write one bit to 0. To determine - * if we are in exam mode, we count the number of leading 0 bits. If it is even, - * the exam mode is deactivated, if it is odd, the exam mode is activated. */ + * deactivating or activating standard or Dutch exam mode we write one or two + * bits to 0. To determine in which exam mode we are, we count the number of + * leading 0 bits. If it is equal to: + * - 0[3]: the exam mode is off; + * - 1[3]: the standard exam mode is activated; + * - 2[3]: the Dutch exam mode is activated. */ /* significantExamModeAddress returns the first uint32_t * in the exam mode - * flash sector that does not point to 0. If this flash sector has only 0s, it - * is erased (to 1) and significantExamModeAddress returns the start of the - * sector. */ + * flash sector that does not point to 0. If this flash sector has only 0s or + * if it has only one 1, it is erased (to 1) and significantExamModeAddress + * returns the start of the sector. */ uint32_t * SignificantExamModeAddress() { uint32_t * persitence_start = (uint32_t *)&_exam_mode_buffer_start; @@ -34,7 +37,9 @@ uint32_t * SignificantExamModeAddress() { // Skip even number of zero bits persitence_start++; } - if (persitence_start == persitence_end) { + if (persitence_start == persitence_end + // we can't toggle from 0[3] to 2[3] when there is only one 1 bit in the whole sector + || (persitence_start + 1 == persitence_end && *persitence_start == 1)) { assert(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_buffer_start) >= 0); Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_buffer_start)); return (uint32_t *)&_exam_mode_buffer_start; @@ -57,23 +62,32 @@ size_t firstOneBit(int i, size_t size) { return maxShift; } -bool FetchExamMode() { +uint8_t FetchExamMode() { uint32_t * readingAddress = SignificantExamModeAddress(); - size_t numberOfLeading0 = 32 - firstOneBit(*readingAddress, 32); - return numberOfLeading0 % 2 == 1; + // Count the number of 0[3] before reading address + uint32_t nbOfZerosBefore = ((readingAddress - (uint32_t *)&_exam_mode_buffer_start)/4 * 2) % 3; + // Count the number of 0[3] at reading address + size_t numberOfLeading0 = (32 - firstOneBit(*readingAddress, 32)) % 3; + return (nbOfZerosBefore + numberOfLeading0) % 3; } -void ToggleExamMode() { +void IncrementExamMode(uint8_t delta) { + assert(delta == 1 || delta == 2); uint32_t * writingAddress = SignificantExamModeAddress(); assert(*writingAddress != 0); - // Compute the new value with one bit switched - uint8_t numberOfLeadingZeroes = 32 - firstOneBit(*writingAddress, 32); + size_t nbOfOnes = firstOneBit(*writingAddress, 32); + // Compute the new value with two bits switched to 0. + /* We write in a uint64_t instead of uint32_t, in case there was only one bit + * left to 1 in writingAddress. */ /* When writing in flash, we can only switch a 1 to a 0. If we want to switch - * the fifth bit in a byte, we can thus write "11110111". */ - uint32_t newValue = ~(1 << (31 - numberOfLeadingZeroes)); - + * the fifth and sixth bit in a byte, we can thus write "11100111". */ + uint64_t deltaOnes = (1 << delta) - 1; + uint64_t newValue = ~(deltaOnes << (32 + nbOfOnes - delta)); // Write the value in flash - Ion::Device::Flash::WriteMemory((uint8_t *)writingAddress, (uint8_t *)&newValue, sizeof(uint32_t)); + /* Avoid writing out of sector */ + assert(writingAddress < (uint32_t *)&_exam_mode_buffer_end - 1 || *writingAddress > 1); + size_t writtenFlash = *writingAddress == 1 ? sizeof(uint64_t) : sizeof(uint32_t); + Ion::Device::Flash::WriteMemory((uint8_t *)writingAddress, (uint8_t *)&newValue, writtenFlash); } } diff --git a/ion/src/shared/dummy/exam_mode.cpp b/ion/src/shared/dummy/exam_mode.cpp index 02d78e591..e9a32a539 100644 --- a/ion/src/shared/dummy/exam_mode.cpp +++ b/ion/src/shared/dummy/exam_mode.cpp @@ -3,11 +3,11 @@ namespace Ion { namespace ExamMode { -bool FetchExamMode() { +uint8_t FetchExamMode() { return false; } -void ToggleExamMode() { +void IncrementExamMode(uint8_t delta) { } } From da735b93a4af731c9e56bc6608e0d56fe34380ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Dec 2019 11:44:52 +0100 Subject: [PATCH 065/130] [apps] GlobalPreferences: change exam mode API --- apps/apps_container.cpp | 8 +++++--- apps/exam_pop_up_controller.cpp | 3 ++- apps/global_preferences.cpp | 18 ++++++++++------- apps/global_preferences.h | 20 ++++++++++--------- apps/home/controller.cpp | 3 +-- apps/on_boarding/logo_controller.cpp | 2 +- .../sub_menu/exam_mode_controller.cpp | 3 ++- apps/title_bar_view.cpp | 2 +- 8 files changed, 34 insertions(+), 25 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 70ac5cbde..bee6ddd4e 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -168,7 +168,8 @@ bool AppsContainer::processEvent(Ion::Events::Event event) { // Warning: if the window is dirtied, you need to call window()->redraw() if (event == Ion::Events::USBPlug) { if (Ion::USB::isPlugged()) { - if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { + // TODO + if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { displayExamModePopUp(false); window()->redraw(); } else { @@ -213,7 +214,8 @@ void AppsContainer::run() { * and it is visible when reflashing a N0100 (there is some noise on the * screen before the logo appears). */ Ion::Display::pushRectUniform(screenRect, KDColorWhite); - if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { + // TODO + if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { activateExamMode(); } refreshPreferences(); @@ -291,7 +293,7 @@ void AppsContainer::shutdownDueToLowBattery() { } while (Ion::Battery::level() == Ion::Battery::Charge::EMPTY) { Ion::Backlight::setBrightness(0); - if (!GlobalPreferences::sharedGlobalPreferences()->examMode()) { + if (!GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { /* Unless the LED is lit up for the exam mode, switch off the LED. IF the * low battery event happened during the Power-On Self-Test, a LED might * have stayed lit up. */ diff --git a/apps/exam_pop_up_controller.cpp b/apps/exam_pop_up_controller.cpp index 38d6d90ce..a51286e81 100644 --- a/apps/exam_pop_up_controller.cpp +++ b/apps/exam_pop_up_controller.cpp @@ -50,7 +50,8 @@ ExamPopUpController::ContentView::ContentView(Responder * parentResponder) : }, parentResponder), KDFont::SmallFont), m_okButton(parentResponder, I18n::Message::Ok, Invocation([](void * context, void * sender) { ExamPopUpController * controller = (ExamPopUpController *)context; - GlobalPreferences::sharedGlobalPreferences()->setExamMode(controller->isActivatingExamMode()); + // TODO + GlobalPreferences::sharedGlobalPreferences()->setExamMode(controller->isActivatingExamMode() ? GlobalPreferences::ExamMode::Dutch : GlobalPreferences::ExamMode::Off); AppsContainer * container = AppsContainer::sharedAppsContainer(); if (controller->isActivatingExamMode()) { container->activateExamMode(); diff --git a/apps/global_preferences.cpp b/apps/global_preferences.cpp index b78102ba9..52572a469 100644 --- a/apps/global_preferences.cpp +++ b/apps/global_preferences.cpp @@ -5,20 +5,24 @@ GlobalPreferences * GlobalPreferences::sharedGlobalPreferences() { return &globalPreferences; } -bool GlobalPreferences::examMode() const { +GlobalPreferences::ExamMode GlobalPreferences::examMode() const { if (m_examMode == ExamMode::Unknown) { m_examMode = (ExamMode)Ion::ExamMode::FetchExamMode(); } - assert((int)m_examMode == 0 || (int)m_examMode == 1); - return (bool)m_examMode; + assert((int)m_examMode >= 0 && (int)m_examMode <= 2); + return m_examMode; } -void GlobalPreferences::setExamMode(bool activateExamMode) { - if (((bool)examMode()) == activateExamMode) { +void GlobalPreferences::setExamMode(ExamMode mode) { + if (examMode() == mode) { return; } - Ion::ExamMode::ToggleExamMode(); - m_examMode = (ExamMode)activateExamMode; + assert(mode != ExamMode::Unknown); + int8_t deltaMode = (int8_t)mode - (int8_t)examMode(); + deltaMode = deltaMode < 0 ? deltaMode + 3 : deltaMode; + assert(deltaMode > 0); + Ion::ExamMode::IncrementExamMode(deltaMode); + m_examMode = mode; } void GlobalPreferences::setBrightnessLevel(int brightnessLevel) { diff --git a/apps/global_preferences.h b/apps/global_preferences.h index f9fe8e044..a7d0790ea 100644 --- a/apps/global_preferences.h +++ b/apps/global_preferences.h @@ -5,11 +5,18 @@ class GlobalPreferences { public: + enum class ExamMode : int8_t { + Unknown = -1, + Off = 0, + Standard = 1, + Dutch = 2 + }; static GlobalPreferences * sharedGlobalPreferences(); I18n::Language language() const { return m_language; } void setLanguage(I18n::Language language) { m_language = language; } - bool examMode() const; - void setExamMode(bool activateExamMode); + bool isInExamMode() const { return (int8_t)examMode() > 0; } + ExamMode examMode() const; + void setExamMode(ExamMode examMode); bool showPopUp() const { return m_showPopUp; } void setShowPopUp(bool showPopUp) { m_showPopUp = showPopUp; } int brightnessLevel() const { return m_brightnessLevel; } @@ -22,13 +29,8 @@ private: m_showPopUp(true), m_brightnessLevel(Ion::Backlight::MaxBrightness) {} I18n::Language m_language; - enum class ExamMode : uint8_t { - Deactivate = 0, - Activate = 1, - Unknown = 2 - }; - static_assert((uint8_t)GlobalPreferences::ExamMode::Deactivate == 0, "GlobalPreferences::setExamMode and examMode() are not right"); - static_assert((uint8_t)GlobalPreferences::ExamMode::Activate == 1, "GlobalPreferences::setExamMode and examMode() are not right"); + static_assert((int8_t)GlobalPreferences::ExamMode::Off == 0, "GlobalPreferences::isInExamMode() is not right"); + static_assert((int8_t)GlobalPreferences::ExamMode::Unknown < 0, "GlobalPreferences::isInExamMode() is not right"); mutable ExamMode m_examMode; bool m_showPopUp; int m_brightnessLevel; diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index 221ba5ec9..00c2f287a 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -59,8 +59,7 @@ bool Controller::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::EXE) { AppsContainer * container = AppsContainer::sharedAppsContainer(); ::App::Snapshot * selectedSnapshot = container->appSnapshotAtIndex(selectionDataSource()->selectedRow()*k_numberOfColumns+selectionDataSource()->selectedColumn()+1); - // TODO: check that we are in Dutch exam mode - if (GlobalPreferences::sharedGlobalPreferences()->examMode() && selectedSnapshot->descriptor()->name() == I18n::Message::CodeApp) { + if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Dutch && selectedSnapshot->descriptor()->name() == I18n::Message::CodeApp) { App::app()->displayWarning(I18n::Message::ForbidenAppInExamMode1, I18n::Message::ForbidenAppInExamMode2); } else { bool switched = container->switchTo(selectedSnapshot); diff --git a/apps/on_boarding/logo_controller.cpp b/apps/on_boarding/logo_controller.cpp index 91ea5173e..56aabfb2d 100644 --- a/apps/on_boarding/logo_controller.cpp +++ b/apps/on_boarding/logo_controller.cpp @@ -49,7 +49,7 @@ void LogoController::viewDidDisappear() { Ion::LED::setColor(m_previousLEDColor); /* TODO: instead of setting again the exam mode, put the previous led color * AND BLINKING.*/ - if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { + if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { // TODO AppsContainer::sharedAppsContainer()->activateExamMode(); } } diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index 1590f04c4..83709a5b4 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -39,7 +39,8 @@ int ExamModeController::reusableCellCount(int type) { void ExamModeController::willDisplayCellForIndex(HighlightCell * cell, int index) { GenericSubController::willDisplayCellForIndex(cell, index); - if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { + // TODO + if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { MessageTableCell * myCell = (MessageTableCell *)cell; myCell->setMessage(I18n::Message::ExamModeActive); } diff --git a/apps/title_bar_view.cpp b/apps/title_bar_view.cpp index fc5c23992..53cee9ab5 100644 --- a/apps/title_bar_view.cpp +++ b/apps/title_bar_view.cpp @@ -71,7 +71,7 @@ void TitleBarView::layoutSubviews() { m_preferenceView.setFrame(KDRect(Metric::TitleBarExternHorizontalMargin, 0, m_preferenceView.minimalSizeForOptimalDisplay().width(), bounds().height())); KDSize batterySize = m_batteryView.minimalSizeForOptimalDisplay(); m_batteryView.setFrame(KDRect(bounds().width() - batterySize.width() - Metric::TitleBarExternHorizontalMargin, (bounds().height()- batterySize.height())/2, batterySize)); - if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { + if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { m_examModeIconView.setFrame(KDRect(k_examIconMargin, (bounds().height() - k_examIconHeight)/2, k_examIconWidth, k_examIconHeight)); } else { m_examModeIconView.setFrame(KDRectZero); From 5491dee5ce0743a909ec79c2a45cf6f4e51ad157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 12 Dec 2019 13:22:10 +0100 Subject: [PATCH 066/130] [calculation][solver] Do not display exact solutions in Dutch exam mode --- apps/calculation/calculation.cpp | 5 ++++- apps/solver/equation_store.cpp | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 25b71a71d..711408b3e 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -1,5 +1,6 @@ #include "calculation.h" #include "../shared/poincare_helpers.h" +#include "../global_preferences.h" #include #include #include @@ -123,7 +124,9 @@ Calculation::DisplayOutput Calculation::displayOutput(Context * context) { } if (shouldOnlyDisplayExactOutput()) { m_displayOutput = DisplayOutput::ExactOnly; - } else if (input().recursivelyMatches( + // Force all results to be ApproximateOnly in Dutch exam mode + } else if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Dutch || + input().recursivelyMatches( [](const Expression e, Context * c) { constexpr int approximateOnlyTypesCount = 9; /* If the input contains the following types, we only display the diff --git a/apps/solver/equation_store.cpp b/apps/solver/equation_store.cpp index ea3112b53..0691c77c0 100644 --- a/apps/solver/equation_store.cpp +++ b/apps/solver/equation_store.cpp @@ -1,6 +1,7 @@ #include "equation_store.h" #include "../constant.h" #include "../shared/poincare_helpers.h" +#include "../global_preferences.h" #include #include @@ -193,6 +194,8 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { } } // Create the results' layouts + // In Dutch exam mode, display only approximate solutions + bool forbidExactSolutions = GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Dutch; int solutionIndex = 0; int initialNumberOfSolutions = m_numberOfSolutions <= k_maxNumberOfExactSolutions ? m_numberOfSolutions : -1; // We iterate through the solutions and the potential delta @@ -211,7 +214,9 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) { char approximateBuffer[::Constant::MaxSerializedExpressionSize]; m_exactSolutionExactLayouts[solutionIndex].serializeForParsing(exactBuffer, ::Constant::MaxSerializedExpressionSize); m_exactSolutionApproximateLayouts[solutionIndex].serializeForParsing(approximateBuffer, ::Constant::MaxSerializedExpressionSize); - m_exactSolutionIdentity[solutionIndex] = strcmp(exactBuffer, approximateBuffer) == 0; + /* Cheat: declare exact and approximate solutions to be identical in + * Dutch exam mode to display only the approximate solutions. */ + m_exactSolutionIdentity[solutionIndex] = forbidExactSolutions || strcmp(exactBuffer, approximateBuffer) == 0; if (!m_exactSolutionIdentity[solutionIndex]) { char buffer[::Constant::MaxSerializedExpressionSize]; m_exactSolutionEquality[solutionIndex] = exactSolutions[i].isEqualToItsApproximationLayout(exactSolutionsApproximations[i], buffer, ::Constant::MaxSerializedExpressionSize, preferences->complexFormat(), preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), context); From 49d2a248da530e6824fab50ddf5e72244002e7c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Dec 2019 11:05:05 +0100 Subject: [PATCH 067/130] [settings] Fix messages for Dutch exam mode --- apps/settings/base.de.i18n | 1 - apps/settings/base.en.i18n | 3 +-- apps/settings/base.es.i18n | 1 - apps/settings/base.fr.i18n | 1 - apps/settings/base.pt.i18n | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 0f3e127e1..263451755 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -10,7 +10,6 @@ ExamMode = "Testmodus" ActivateExamMode = "Starten Testmodus" ExamModeActive = "Wieder starten Testmodus" ActivateDutchExamMode = "" -DutchExamModeActive = "" About = "Über" Degrees = "Grad " Gradians = "Gone " diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index 7f7309985..26bb775c4 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -7,10 +7,9 @@ EditionLinear = "Linear " Edition2D = "Natural " ComplexFormat = "Complex format" ExamMode = "Exam mode" -ActivateExamMode = "Activate exam mode" +ActivateExamMode = "Activate standard exam mode" ExamModeActive = "Reactivate exam mode" ActivateDutchExamMode = "Activate Dutch exam mode" -DutchExamModeActive = "Reactivate Dutch exam mode" About = "About" Degrees = "Degrees " Gradians = "Gradians " diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index aaf71e055..698f978ba 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -10,7 +10,6 @@ ExamMode = "Modo examen" ActivateExamMode = "Activar el modo examen" ExamModeActive = "Reactivar el modo examen" ActivateDutchExamMode = "" -DutchExamModeActive = "" About = "Acerca" Degrees = "Grados " Gradians = "Gradianes " diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index e8782094c..f625ffc86 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -10,7 +10,6 @@ ExamMode = "Mode examen" ActivateExamMode = "Activer le mode examen" ExamModeActive = "Réactiver le mode examen" ActivateDutchExamMode = "" -DutchExamModeActive = "" About = "À propos" Degrees = "Degrés " Gradians = "Grades " diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index 18d8b0ca4..f872bcf5c 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -10,7 +10,6 @@ ExamMode = "Modo de exame" ActivateExamMode = "Ativar o modo de exame" ExamModeActive = "Reativar o modo de exame" ActivateDutchExamMode = "" -DutchExamModeActive = "" About = "Acerca" Degrees = "Graus " Gradians = "Grados " From 6cd98a3a484b5cb415383d34fea42141e0217749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Dec 2019 11:31:40 +0100 Subject: [PATCH 068/130] [apps] AppsContainer::activateExamMode can make the LED blink in orange or red according to the chosen exam mode --- apps/apps_container.cpp | 8 ++++---- apps/apps_container.h | 3 ++- apps/exam_pop_up_controller.cpp | 5 +++-- apps/on_boarding/logo_controller.cpp | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index bee6ddd4e..bd60f10fd 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -214,9 +214,8 @@ void AppsContainer::run() { * and it is visible when reflashing a N0100 (there is some noise on the * screen before the logo appears). */ Ion::Display::pushRectUniform(screenRect, KDColorWhite); - // TODO if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { - activateExamMode(); + activateExamMode(GlobalPreferences::sharedGlobalPreferences()->examMode()); } refreshPreferences(); @@ -326,9 +325,10 @@ void AppsContainer::redrawWindow() { m_window.redraw(); } -void AppsContainer::activateExamMode() { +void AppsContainer::activateExamMode(GlobalPreferences::ExamMode examMode) { + assert(examMode == GlobalPreferences::ExamMode::Standard || examMode == GlobalPreferences::ExamMode::Dutch); reset(); - Ion::LED::setColor(KDColorRed); + Ion::LED::setColor(examMode == GlobalPreferences::ExamMode::Dutch ? KDColorOrange : KDColorRed); Ion::LED::setBlinking(1000, 0.1f); } diff --git a/apps/apps_container.h b/apps/apps_container.h index 834d7e336..4cd05c7f8 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -13,6 +13,7 @@ #include "exam_pop_up_controller_delegate.h" #include "battery_timer.h" #include "suspend_timer.h" +#include "global_preferences.h" #include "backlight_dimming_timer.h" #include "shared/global_context.h" #include "on_boarding/pop_up_controller.h" @@ -46,7 +47,7 @@ public: void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus); OnBoarding::PopUpController * promptController(); void redrawWindow(); - void activateExamMode(); + void activateExamMode(GlobalPreferences::ExamMode examMode); // Exam pop-up controller delegate void examDeactivatingPopUpIsDismissed() override; // Ion::StorageDelegate diff --git a/apps/exam_pop_up_controller.cpp b/apps/exam_pop_up_controller.cpp index a51286e81..6ed85321c 100644 --- a/apps/exam_pop_up_controller.cpp +++ b/apps/exam_pop_up_controller.cpp @@ -51,10 +51,11 @@ ExamPopUpController::ContentView::ContentView(Responder * parentResponder) : m_okButton(parentResponder, I18n::Message::Ok, Invocation([](void * context, void * sender) { ExamPopUpController * controller = (ExamPopUpController *)context; // TODO - GlobalPreferences::sharedGlobalPreferences()->setExamMode(controller->isActivatingExamMode() ? GlobalPreferences::ExamMode::Dutch : GlobalPreferences::ExamMode::Off); + GlobalPreferences::ExamMode mode = controller->isActivatingExamMode() ? GlobalPreferences::ExamMode::Dutch : GlobalPreferences::ExamMode::Off; + GlobalPreferences::sharedGlobalPreferences()->setExamMode(mode); AppsContainer * container = AppsContainer::sharedAppsContainer(); if (controller->isActivatingExamMode()) { - container->activateExamMode(); + container->activateExamMode(mode); } else { Ion::LED::setColor(KDColorBlack); Ion::LED::updateColorWithPlugAndCharge(); diff --git a/apps/on_boarding/logo_controller.cpp b/apps/on_boarding/logo_controller.cpp index 56aabfb2d..13df87e4d 100644 --- a/apps/on_boarding/logo_controller.cpp +++ b/apps/on_boarding/logo_controller.cpp @@ -49,8 +49,8 @@ void LogoController::viewDidDisappear() { Ion::LED::setColor(m_previousLEDColor); /* TODO: instead of setting again the exam mode, put the previous led color * AND BLINKING.*/ - if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { // TODO - AppsContainer::sharedAppsContainer()->activateExamMode(); + if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { + AppsContainer::sharedAppsContainer()->activateExamMode(GlobalPreferences::sharedGlobalPreferences()->examMode()); } } ViewController::viewDidDisappear(); From 6ecfe9c5dbd68a3052c775ebaa860589e6ab81d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Dec 2019 11:51:24 +0100 Subject: [PATCH 069/130] [apps] Two exam modes in settings: Standard & Dutch --- apps/apps_container.cpp | 7 ++-- apps/apps_container.h | 2 +- apps/exam_pop_up_controller.cpp | 33 ++++++++++--------- apps/exam_pop_up_controller.h | 9 ++--- apps/settings/main_controller_prompt_beta.cpp | 4 +-- apps/settings/main_controller_prompt_none.cpp | 4 +-- .../main_controller_prompt_update.cpp | 4 +-- .../sub_menu/exam_mode_controller.cpp | 21 ++++++++---- apps/settings/sub_menu/exam_mode_controller.h | 4 ++- 9 files changed, 50 insertions(+), 38 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index bd60f10fd..952f83db3 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -168,9 +168,8 @@ bool AppsContainer::processEvent(Ion::Events::Event event) { // Warning: if the window is dirtied, you need to call window()->redraw() if (event == Ion::Events::USBPlug) { if (Ion::USB::isPlugged()) { - // TODO if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { - displayExamModePopUp(false); + displayExamModePopUp(GlobalPreferences::ExamMode::Off); window()->redraw(); } else { Ion::USB::enable(); @@ -276,8 +275,8 @@ void AppsContainer::reloadTitleBarView() { m_window.reloadTitleBarView(); } -void AppsContainer::displayExamModePopUp(bool activate) { - m_examPopUpController.setActivatingExamMode(activate); +void AppsContainer::displayExamModePopUp(GlobalPreferences::ExamMode mode) { + m_examPopUpController.setTargetExamMode(mode); s_activeApp->displayModalViewController(&m_examPopUpController, 0.f, 0.f, Metric::ExamPopUpTopMargin, Metric::PopUpRightMargin, Metric::ExamPopUpBottomMargin, Metric::PopUpLeftMargin); } diff --git a/apps/apps_container.h b/apps/apps_container.h index 4cd05c7f8..f4c683d5a 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -42,7 +42,7 @@ public: bool updateBatteryState(); void refreshPreferences(); void reloadTitleBarView(); - void displayExamModePopUp(bool activate); + void displayExamModePopUp(GlobalPreferences::ExamMode mode); void shutdownDueToLowBattery(); void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus); OnBoarding::PopUpController * promptController(); diff --git a/apps/exam_pop_up_controller.cpp b/apps/exam_pop_up_controller.cpp index 6ed85321c..651171bd2 100644 --- a/apps/exam_pop_up_controller.cpp +++ b/apps/exam_pop_up_controller.cpp @@ -7,14 +7,14 @@ ExamPopUpController::ExamPopUpController(ExamPopUpControllerDelegate * delegate) : ViewController(nullptr), m_contentView(this), - m_isActivatingExamMode(false), + m_targetExamMode(GlobalPreferences::ExamMode::Unknown), m_delegate(delegate) { } -void ExamPopUpController::setActivatingExamMode(bool activatingExamMode) { - m_isActivatingExamMode = activatingExamMode; - m_contentView.setMessages(activatingExamMode); +void ExamPopUpController::setTargetExamMode(GlobalPreferences::ExamMode mode) { + m_targetExamMode = mode; + m_contentView.setMessagesForExamMode(mode); } View * ExamPopUpController::view() { @@ -22,7 +22,7 @@ View * ExamPopUpController::view() { } void ExamPopUpController::viewDidDisappear() { - if (m_isActivatingExamMode == false) { + if (m_targetExamMode == GlobalPreferences::ExamMode::Off) { m_delegate->examDeactivatingPopUpIsDismissed(); } } @@ -50,15 +50,15 @@ ExamPopUpController::ContentView::ContentView(Responder * parentResponder) : }, parentResponder), KDFont::SmallFont), m_okButton(parentResponder, I18n::Message::Ok, Invocation([](void * context, void * sender) { ExamPopUpController * controller = (ExamPopUpController *)context; - // TODO - GlobalPreferences::ExamMode mode = controller->isActivatingExamMode() ? GlobalPreferences::ExamMode::Dutch : GlobalPreferences::ExamMode::Off; + GlobalPreferences::ExamMode mode = controller->targetExamMode(); + assert(mode != GlobalPreferences::ExamMode::Unknown); GlobalPreferences::sharedGlobalPreferences()->setExamMode(mode); AppsContainer * container = AppsContainer::sharedAppsContainer(); - if (controller->isActivatingExamMode()) { - container->activateExamMode(mode); - } else { + if (mode == GlobalPreferences::ExamMode::Off) { Ion::LED::setColor(KDColorBlack); Ion::LED::updateColorWithPlugAndCharge(); + } else { + container->activateExamMode(mode); } container->refreshPreferences(); Container::activeApp()->dismissModalViewController(); @@ -88,15 +88,16 @@ int ExamPopUpController::ContentView::selectedButton() { return 1; } -void ExamPopUpController::ContentView::setMessages(bool activingExamMode) { - if (activingExamMode) { - m_messageTextView1.setMessage(I18n::Message::ActiveExamModeMessage1); - m_messageTextView2.setMessage(I18n::Message::ActiveExamModeMessage2); - m_messageTextView3.setMessage(I18n::Message::ActiveExamModeMessage3); - } else { +void ExamPopUpController::ContentView::setMessagesForExamMode(GlobalPreferences::ExamMode mode) { + if (mode == GlobalPreferences::ExamMode::Off) { m_messageTextView1.setMessage(I18n::Message::ExitExamMode1); m_messageTextView2.setMessage(I18n::Message::ExitExamMode2); m_messageTextView3.setMessage(I18n::Message::Default); + } else { + // TODO different messages for Dutch + m_messageTextView1.setMessage(I18n::Message::ActiveExamModeMessage1); + m_messageTextView2.setMessage(I18n::Message::ActiveExamModeMessage2); + m_messageTextView3.setMessage(I18n::Message::ActiveExamModeMessage3); } } diff --git a/apps/exam_pop_up_controller.h b/apps/exam_pop_up_controller.h index ad888cff9..0249e9d3f 100644 --- a/apps/exam_pop_up_controller.h +++ b/apps/exam_pop_up_controller.h @@ -3,6 +3,7 @@ #include #include "exam_pop_up_controller_delegate.h" +#include "global_preferences.h" class HighContrastButton : public Button { public: @@ -13,8 +14,8 @@ public: class ExamPopUpController : public ViewController { public: ExamPopUpController(ExamPopUpControllerDelegate * delegate); - void setActivatingExamMode(bool activingExamMode); - bool isActivatingExamMode() const { return m_isActivatingExamMode; } + void setTargetExamMode(GlobalPreferences::ExamMode mode); + GlobalPreferences::ExamMode targetExamMode() const { return m_targetExamMode; } // View Controller View * view() override; void viewDidDisappear() override; @@ -28,7 +29,7 @@ private: void drawRect(KDContext * ctx, KDRect rect) const override; void setSelectedButton(int selectedButton); int selectedButton(); - void setMessages(bool activingExamMode); + void setMessagesForExamMode(GlobalPreferences::ExamMode mode); private: constexpr static KDCoordinate k_buttonMargin = 10; constexpr static KDCoordinate k_buttonHeight = 20; @@ -45,7 +46,7 @@ private: MessageTextView m_messageTextView3; }; ContentView m_contentView; - bool m_isActivatingExamMode; + GlobalPreferences::ExamMode m_targetExamMode; ExamPopUpControllerDelegate * m_delegate; }; diff --git a/apps/settings/main_controller_prompt_beta.cpp b/apps/settings/main_controller_prompt_beta.cpp index ac36893e2..0ba86a359 100644 --- a/apps/settings/main_controller_prompt_beta.cpp +++ b/apps/settings/main_controller_prompt_beta.cpp @@ -7,7 +7,7 @@ constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18 constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)}; constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::Engineering), SettingsMessageTree(I18n::Message::SignificantFigures)}; constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessageTree(I18n::Message::Real), SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)}; -constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[2] = {SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; constexpr SettingsMessageTree s_modelAboutChildren[3] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; constexpr SettingsMessageTree s_modelMenu[] = @@ -17,7 +17,7 @@ constexpr SettingsMessageTree s_modelMenu[] = SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::Language), - SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 1), + SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 2), SettingsMessageTree(I18n::Message::BetaPopUp), SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 3)}; diff --git a/apps/settings/main_controller_prompt_none.cpp b/apps/settings/main_controller_prompt_none.cpp index a159b6e96..9595b235c 100644 --- a/apps/settings/main_controller_prompt_none.cpp +++ b/apps/settings/main_controller_prompt_none.cpp @@ -8,7 +8,7 @@ constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18 constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)}; constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::Engineering), SettingsMessageTree(I18n::Message::SignificantFigures)}; constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessageTree(I18n::Message::Real), SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)}; -constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[2] = {SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; constexpr SettingsMessageTree s_modelAboutChildren[3] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; constexpr SettingsMessageTree s_modelMenu[] = @@ -18,7 +18,7 @@ constexpr SettingsMessageTree s_modelMenu[] = SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::Language), - SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 1), + SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 2), SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 3)}; constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 8); diff --git a/apps/settings/main_controller_prompt_update.cpp b/apps/settings/main_controller_prompt_update.cpp index 5e45f8821..1bd728f3e 100644 --- a/apps/settings/main_controller_prompt_update.cpp +++ b/apps/settings/main_controller_prompt_update.cpp @@ -7,7 +7,7 @@ constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18 constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)}; constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::Engineering), SettingsMessageTree(I18n::Message::SignificantFigures)}; constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessageTree(I18n::Message::Real), SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)}; -constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[2] = {SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; constexpr SettingsMessageTree s_modelAboutChildren[3] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; constexpr SettingsMessageTree s_modelMenu[] = @@ -17,7 +17,7 @@ constexpr SettingsMessageTree s_modelMenu[] = SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::Language), - SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 1), + SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 2), SettingsMessageTree(I18n::Message::UpdatePopUp), SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 3)}; diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index 83709a5b4..025464e9a 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -1,6 +1,7 @@ #include "exam_mode_controller.h" #include "../../global_preferences.h" #include "../../apps_container.h" +#include #include #include @@ -11,35 +12,43 @@ namespace Settings { ExamModeController::ExamModeController(Responder * parentResponder) : GenericSubController(parentResponder), - m_cell(I18n::Message::ExamModeActive, KDFont::LargeFont) + m_cell{MessageTableCell(I18n::Message::ExamModeActive, KDFont::LargeFont), MessageTableCell(I18n::Message::ActivateDutchExamMode, KDFont::LargeFont)} { } void ExamModeController::didEnterResponderChain(Responder * previousFirstResponder) { + selectCellAtLocation(0, 0); m_selectableTableView.reloadData(); } bool ExamModeController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::EXE) { - AppsContainer::sharedAppsContainer()->displayExamModePopUp(true); + GlobalPreferences::ExamMode mode = m_messageTreeModel->children(selectedRow())->label() == I18n::Message::ActivateExamMode ? GlobalPreferences::ExamMode::Standard : GlobalPreferences::ExamMode::Dutch; + AppsContainer::sharedAppsContainer()->displayExamModePopUp(mode); return true; } return GenericSubController::handleEvent(event); } +int ExamModeController::numberOfRows() const { + if (GlobalPreferences::sharedGlobalPreferences()->language() != I18n::Language::EN || GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { + return 1; + } + return GenericSubController::numberOfRows(); +} + HighlightCell * ExamModeController::reusableCell(int index, int type) { assert(type == 0); - assert(index == 0); - return &m_cell; + assert(index >= 0 && index < k_maxNumberOfCells); + return &m_cell[index]; } int ExamModeController::reusableCellCount(int type) { - return 1; + return k_maxNumberOfCells; } void ExamModeController::willDisplayCellForIndex(HighlightCell * cell, int index) { GenericSubController::willDisplayCellForIndex(cell, index); - // TODO if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { MessageTableCell * myCell = (MessageTableCell *)cell; myCell->setMessage(I18n::Message::ExamModeActive); diff --git a/apps/settings/sub_menu/exam_mode_controller.h b/apps/settings/sub_menu/exam_mode_controller.h index 22a0da0c7..5b0164c0c 100644 --- a/apps/settings/sub_menu/exam_mode_controller.h +++ b/apps/settings/sub_menu/exam_mode_controller.h @@ -10,11 +10,13 @@ public: ExamModeController(Responder * parentResponder); void didEnterResponderChain(Responder * previousFirstResponder) override; bool handleEvent(Ion::Events::Event event) override; + int numberOfRows() const override; HighlightCell * reusableCell(int index, int type) override; int reusableCellCount(int type) override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; private: - MessageTableCell m_cell; + static constexpr int k_maxNumberOfCells = 2; + MessageTableCell m_cell[k_maxNumberOfCells]; }; } From de34c0b8db9f70f16219af53b622390881d752c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Dec 2019 14:23:24 +0100 Subject: [PATCH 070/130] [apps] Change pop-up message for Dutch exam mode --- apps/exam_pop_up_controller.cpp | 8 ++++++-- apps/shared.de.i18n | 3 +++ apps/shared.en.i18n | 3 +++ apps/shared.es.i18n | 3 +++ apps/shared.fr.i18n | 3 +++ apps/shared.pt.i18n | 3 +++ 6 files changed, 21 insertions(+), 2 deletions(-) diff --git a/apps/exam_pop_up_controller.cpp b/apps/exam_pop_up_controller.cpp index 651171bd2..dfe068ef2 100644 --- a/apps/exam_pop_up_controller.cpp +++ b/apps/exam_pop_up_controller.cpp @@ -93,11 +93,15 @@ void ExamPopUpController::ContentView::setMessagesForExamMode(GlobalPreferences: m_messageTextView1.setMessage(I18n::Message::ExitExamMode1); m_messageTextView2.setMessage(I18n::Message::ExitExamMode2); m_messageTextView3.setMessage(I18n::Message::Default); - } else { - // TODO different messages for Dutch + } else if (mode == GlobalPreferences::ExamMode::Standard) { m_messageTextView1.setMessage(I18n::Message::ActiveExamModeMessage1); m_messageTextView2.setMessage(I18n::Message::ActiveExamModeMessage2); m_messageTextView3.setMessage(I18n::Message::ActiveExamModeMessage3); + } else { + assert(mode == GlobalPreferences::ExamMode::Dutch); + m_messageTextView1.setMessage(I18n::Message::ActiveDutchExamModeMessage1); + m_messageTextView2.setMessage(I18n::Message::ActiveDutchExamModeMessage2); + m_messageTextView3.setMessage(I18n::Message::ActiveDutchExamModeMessage3); } } diff --git a/apps/shared.de.i18n b/apps/shared.de.i18n index 6309dac2a..ff08c00ff 100644 --- a/apps/shared.de.i18n +++ b/apps/shared.de.i18n @@ -2,6 +2,9 @@ ActivateDeactivate = "Aktivieren/Deaktivieren" ActiveExamModeMessage1 = "Alle Ihre Daten werden " ActiveExamModeMessage2 = "gelöscht, wenn Sie den " ActiveExamModeMessage3 = "Testmodus einschalten." +ActiveDutchExamModeMessage1 = "" +ActiveDutchExamModeMessage2 = "" +ActiveDutchExamModeMessage3 = "" Axis = "Achsen" Cancel = "Abbrechen" ClearColumn = "Spalte löschen" diff --git a/apps/shared.en.i18n b/apps/shared.en.i18n index 952b615b8..d5a6d108a 100644 --- a/apps/shared.en.i18n +++ b/apps/shared.en.i18n @@ -2,6 +2,9 @@ ActivateDeactivate = "Turn on/off" ActiveExamModeMessage1 = "All your data will be " ActiveExamModeMessage2 = "deleted when you activate " ActiveExamModeMessage3 = "the exam mode." +ActiveDutchExamModeMessage1 = "All your data will be deleted when" +ActiveDutchExamModeMessage2 = "you activate the exam mode. Python" +ActiveDutchExamModeMessage3 = "application will be unaccessible." Axis = "Axes" Cancel = "Cancel" ClearColumn = "Clear column" diff --git a/apps/shared.es.i18n b/apps/shared.es.i18n index 53570691e..18ac4dc39 100644 --- a/apps/shared.es.i18n +++ b/apps/shared.es.i18n @@ -2,6 +2,9 @@ ActivateDeactivate = "Activar/Desactivar" ActiveExamModeMessage1 = "Todos sus datos se " ActiveExamModeMessage2 = "eliminaran al activar " ActiveExamModeMessage3 = "el modo examen." +ActiveDutchExamModeMessage1 = "" +ActiveDutchExamModeMessage2 = "" +ActiveDutchExamModeMessage3 = "" Axis = "Ejes" Cancel = "Cancelar" ClearColumn = "Borrar la columna" diff --git a/apps/shared.fr.i18n b/apps/shared.fr.i18n index 15e2d760c..b3f6fc997 100644 --- a/apps/shared.fr.i18n +++ b/apps/shared.fr.i18n @@ -2,6 +2,9 @@ ActivateDeactivate = "Activer/Désactiver" ActiveExamModeMessage1 = "Toutes vos données seront " ActiveExamModeMessage2 = "supprimées si vous activez " ActiveExamModeMessage3 = "le mode examen." +ActiveDutchExamModeMessage1 = "" +ActiveDutchExamModeMessage2 = "" +ActiveDutchExamModeMessage3 = "" Axis = "Axes" Cancel = "Annuler" ClearColumn = "Effacer la colonne" diff --git a/apps/shared.pt.i18n b/apps/shared.pt.i18n index 9d624d78d..911100216 100644 --- a/apps/shared.pt.i18n +++ b/apps/shared.pt.i18n @@ -2,6 +2,9 @@ ActivateDeactivate = "Activar/Desactivar" ActiveExamModeMessage1 = "Todos os seus dados serão " ActiveExamModeMessage2 = "apagados se você ligar " ActiveExamModeMessage3 = "o modo de exame." +ActiveDutchExamModeMessage1 = "" +ActiveDutchExamModeMessage2 = "" +ActiveDutchExamModeMessage3 = "" Axis = "Eixos" Cancel = "Cancelar" ClearColumn = "Excluir coluna" From a3774fb51036c4c6b9ef28b4dc14562c6711043b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Dec 2019 14:24:02 +0100 Subject: [PATCH 071/130] [settings] Exam mode: reactivate the current exam mode (stick to Dutch exam mode if it is already on) --- apps/settings/sub_menu/exam_mode_controller.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index 025464e9a..f4921ff2f 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -23,7 +23,13 @@ void ExamModeController::didEnterResponderChain(Responder * previousFirstRespond bool ExamModeController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::EXE) { - GlobalPreferences::ExamMode mode = m_messageTreeModel->children(selectedRow())->label() == I18n::Message::ActivateExamMode ? GlobalPreferences::ExamMode::Standard : GlobalPreferences::ExamMode::Dutch; + GlobalPreferences::ExamMode mode = GlobalPreferences::ExamMode::Standard; + if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { + // If the exam mode is already on, this re-activate the same exam mode + mode = GlobalPreferences::sharedGlobalPreferences()->examMode(); + } else if (m_messageTreeModel->children(selectedRow())->label() == I18n::Message::ActivateDutchExamMode) { + mode = GlobalPreferences::ExamMode::Dutch; + } AppsContainer::sharedAppsContainer()->displayExamModePopUp(mode); return true; } From 8c6a2836de11958b4b9fa01935a21172ece1f73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Dec 2019 14:32:44 +0100 Subject: [PATCH 072/130] [settings] Fix row initialization in sub menus --- apps/settings/sub_menu/exam_mode_controller.cpp | 11 ++++++++--- apps/settings/sub_menu/exam_mode_controller.h | 2 +- apps/settings/sub_menu/generic_sub_controller.cpp | 10 +++++----- apps/settings/sub_menu/generic_sub_controller.h | 3 ++- apps/settings/sub_menu/preferences_controller.cpp | 3 +-- apps/settings/sub_menu/preferences_controller.h | 3 ++- 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index f4921ff2f..03a30422e 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -16,9 +16,14 @@ ExamModeController::ExamModeController(Responder * parentResponder) : { } -void ExamModeController::didEnterResponderChain(Responder * previousFirstResponder) { - selectCellAtLocation(0, 0); - m_selectableTableView.reloadData(); +int ExamModeController::initialSelectedRow() const { + int row = selectedRow(); + if (row >= numberOfRows()) { + return numberOfRows()-1; + } else if (row < 0) { + return 0; + } + return row; } bool ExamModeController::handleEvent(Ion::Events::Event event) { diff --git a/apps/settings/sub_menu/exam_mode_controller.h b/apps/settings/sub_menu/exam_mode_controller.h index 5b0164c0c..2627c7f29 100644 --- a/apps/settings/sub_menu/exam_mode_controller.h +++ b/apps/settings/sub_menu/exam_mode_controller.h @@ -8,13 +8,13 @@ namespace Settings { class ExamModeController : public GenericSubController { public: ExamModeController(Responder * parentResponder); - void didEnterResponderChain(Responder * previousFirstResponder) override; bool handleEvent(Ion::Events::Event event) override; int numberOfRows() const override; HighlightCell * reusableCell(int index, int type) override; int reusableCellCount(int type) override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; private: + int initialSelectedRow() const override; static constexpr int k_maxNumberOfCells = 2; MessageTableCell m_cell[k_maxNumberOfCells]; }; diff --git a/apps/settings/sub_menu/generic_sub_controller.cpp b/apps/settings/sub_menu/generic_sub_controller.cpp index 96c0a39a4..67af6c918 100644 --- a/apps/settings/sub_menu/generic_sub_controller.cpp +++ b/apps/settings/sub_menu/generic_sub_controller.cpp @@ -26,8 +26,12 @@ View * GenericSubController::view() { return &m_selectableTableView; } +void GenericSubController::didEnterResponderChain(Responder * previousFirstResponder) { + selectCellAtLocation(0, initialSelectedRow()); + m_selectableTableView.reloadData(); +} + void GenericSubController::didBecomeFirstResponder() { - selectCellAtLocation(0, 0); Container::activeApp()->setFirstResponder(&m_selectableTableView); } @@ -75,10 +79,6 @@ void GenericSubController::setMessageTreeModel(const MessageTree * messageTreeMo m_messageTreeModel = (MessageTree *)messageTreeModel; } -void GenericSubController::viewWillAppear() { - m_selectableTableView.reloadData(); -} - void GenericSubController::viewDidDisappear() { m_selectableTableView.deselectTable(); } diff --git a/apps/settings/sub_menu/generic_sub_controller.h b/apps/settings/sub_menu/generic_sub_controller.h index 132cc1773..445857c41 100644 --- a/apps/settings/sub_menu/generic_sub_controller.h +++ b/apps/settings/sub_menu/generic_sub_controller.h @@ -11,6 +11,7 @@ public: GenericSubController(Responder * parentResponder); const char * title() override; View * view() override; + void didEnterResponderChain(Responder * previousFirstResponder) override; void didBecomeFirstResponder() override; bool handleEvent(Ion::Events::Event event) override; int numberOfRows() const override; @@ -20,10 +21,10 @@ public: int typeAtLocation(int i, int j) override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; void setMessageTreeModel(const MessageTree * messageTreeModel); - void viewWillAppear() override; void viewDidDisappear() override; protected: StackViewController * stackController() const; + virtual int initialSelectedRow() const { return 0; } constexpr static KDCoordinate k_topBottomMargin = 13; SelectableTableView m_selectableTableView; MessageTree * m_messageTreeModel; diff --git a/apps/settings/sub_menu/preferences_controller.cpp b/apps/settings/sub_menu/preferences_controller.cpp index 6d964fd7a..609b190a2 100644 --- a/apps/settings/sub_menu/preferences_controller.cpp +++ b/apps/settings/sub_menu/preferences_controller.cpp @@ -23,7 +23,6 @@ PreferencesController::PreferencesController(Responder * parentResponder) : } void PreferencesController::didBecomeFirstResponder() { - selectCellAtLocation(0, valueIndexForPreference(m_messageTreeModel->label())); Container::activeApp()->setFirstResponder(&m_selectableTableView); } @@ -145,7 +144,7 @@ void PreferencesController::setPreferenceWithValueIndex(I18n::Message message, i } } -int PreferencesController::valueIndexForPreference(I18n::Message message) { +int PreferencesController::valueIndexForPreference(I18n::Message message) const { Preferences * preferences = Preferences::sharedPreferences(); if (message == I18n::Message::AngleUnit) { return (int)preferences->angleUnit(); diff --git a/apps/settings/sub_menu/preferences_controller.h b/apps/settings/sub_menu/preferences_controller.h index c2a860cf7..ba21cfc5c 100644 --- a/apps/settings/sub_menu/preferences_controller.h +++ b/apps/settings/sub_menu/preferences_controller.h @@ -18,9 +18,10 @@ protected: constexpr static int k_totalNumberOfCell = 3; private: constexpr static const KDFont * k_layoutFont = KDFont::SmallFont; + int initialSelectedRow() const override { return valueIndexForPreference(m_messageTreeModel->label()); } Poincare::Layout layoutForPreferences(I18n::Message message); void setPreferenceWithValueIndex(I18n::Message message, int valueIndex); - int valueIndexForPreference(I18n::Message message); + int valueIndexForPreference(I18n::Message message) const; MessageTableCellWithExpression m_cells[k_totalNumberOfCell]; }; From 7fc730597ccaa7615d2d8ace78ffe947e6a3ff4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Dec 2019 14:33:41 +0100 Subject: [PATCH 073/130] [apps] Fix exam mode messages --- apps/settings/base.en.i18n | 2 +- apps/shared.en.i18n | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index 26bb775c4..3683e54ce 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -7,7 +7,7 @@ EditionLinear = "Linear " Edition2D = "Natural " ComplexFormat = "Complex format" ExamMode = "Exam mode" -ActivateExamMode = "Activate standard exam mode" +ActivateExamMode = "Activate exam mode" ExamModeActive = "Reactivate exam mode" ActivateDutchExamMode = "Activate Dutch exam mode" About = "About" diff --git a/apps/shared.en.i18n b/apps/shared.en.i18n index d5a6d108a..49bec75e6 100644 --- a/apps/shared.en.i18n +++ b/apps/shared.en.i18n @@ -4,7 +4,7 @@ ActiveExamModeMessage2 = "deleted when you activate " ActiveExamModeMessage3 = "the exam mode." ActiveDutchExamModeMessage1 = "All your data will be deleted when" ActiveDutchExamModeMessage2 = "you activate the exam mode. Python" -ActiveDutchExamModeMessage3 = "application will be unaccessible." +ActiveDutchExamModeMessage3 = "application will be unavailable." Axis = "Axes" Cancel = "Cancel" ClearColumn = "Clear column" From f5e7c016e8d1342cfe44613ea0d0e2714ced4031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Dec 2019 16:58:45 +0100 Subject: [PATCH 074/130] [apps] GlobalPreferences: avoid multiple calls to examMode() --- apps/global_preferences.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/global_preferences.cpp b/apps/global_preferences.cpp index 52572a469..7a0763e49 100644 --- a/apps/global_preferences.cpp +++ b/apps/global_preferences.cpp @@ -14,11 +14,12 @@ GlobalPreferences::ExamMode GlobalPreferences::examMode() const { } void GlobalPreferences::setExamMode(ExamMode mode) { - if (examMode() == mode) { + ExamMode currentMode = examMode(); + if (currentMode == mode) { return; } assert(mode != ExamMode::Unknown); - int8_t deltaMode = (int8_t)mode - (int8_t)examMode(); + int8_t deltaMode = (int8_t)mode - (int8_t)currentMode; deltaMode = deltaMode < 0 ? deltaMode + 3 : deltaMode; assert(deltaMode > 0); Ion::ExamMode::IncrementExamMode(deltaMode); From 2fc8799feefbdc3413b2906c58c98be359d6616e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Dec 2019 16:59:07 +0100 Subject: [PATCH 075/130] [ion] Exam mode on device: Fix FetchExamMode and IncrementExamMode --- ion/src/device/shared/drivers/exam_mode.cpp | 91 +++++++++++++-------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/ion/src/device/shared/drivers/exam_mode.cpp b/ion/src/device/shared/drivers/exam_mode.cpp index 806729c01..96e10a2d0 100644 --- a/ion/src/device/shared/drivers/exam_mode.cpp +++ b/ion/src/device/shared/drivers/exam_mode.cpp @@ -3,14 +3,14 @@ #include "flash.h" #include -namespace Ion { -namespace ExamMode { - extern "C" { extern char _exam_mode_buffer_start; extern char _exam_mode_buffer_end; } +namespace Ion { +namespace ExamMode { + char ones[Config::ExamModeBufferSize] __attribute__((section(".exam_mode_buffer"))) __attribute__((used)) @@ -30,26 +30,11 @@ char ones[Config::ExamModeBufferSize] * if it has only one 1, it is erased (to 1) and significantExamModeAddress * returns the start of the sector. */ -uint32_t * SignificantExamModeAddress() { - uint32_t * persitence_start = (uint32_t *)&_exam_mode_buffer_start; - uint32_t * persitence_end = (uint32_t *)&_exam_mode_buffer_end; - while (persitence_start < persitence_end && *persitence_start == 0x0) { - // Skip even number of zero bits - persitence_start++; - } - if (persitence_start == persitence_end - // we can't toggle from 0[3] to 2[3] when there is only one 1 bit in the whole sector - || (persitence_start + 1 == persitence_end && *persitence_start == 1)) { - assert(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_buffer_start) >= 0); - Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_buffer_start)); - return (uint32_t *)&_exam_mode_buffer_start; - } - return persitence_start; -} +constexpr static size_t numberOfBitsInByte = 8; -size_t firstOneBit(int i, size_t size) { +size_t firstOneBitInByte(int i) { int minShift = 0; - int maxShift = size; + int maxShift = numberOfBitsInByte; while (maxShift > minShift+1) { int shift = (minShift + maxShift)/2; int shifted = i >> shift; @@ -62,32 +47,68 @@ size_t firstOneBit(int i, size_t size) { return maxShift; } +uint8_t * SignificantExamModeAddress() { + uint32_t * persitence_start_32 = (uint32_t *)&_exam_mode_buffer_start; + uint32_t * persitence_end_32 = (uint32_t *)&_exam_mode_buffer_end; + while (persitence_start_32 < persitence_end_32 && *persitence_start_32 == 0x0) { + // Scan by groups of 32 bits to reach first non-zero bit + persitence_start_32++; + } + uint8_t * persitence_start_8 = (uint8_t *)persitence_start_32; + uint8_t * persitence_end_8 = (uint8_t *)persitence_end_32; + while (persitence_start_8 < persitence_end_8 && *persitence_start_8 == 0x0) { + // Scan by groups of 8 bits to reach first non-zero bit + persitence_start_8++; + } + if (persitence_start_8 == persitence_end_8 + // we can't toggle from 0[3] to 2[3] when there is only one 1 bit in the whole sector + || (persitence_start_8 + 1 == persitence_end_8 && *persitence_start_8 == 1)) { + assert(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_buffer_start) >= 0); + Ion::Device::Flash::EraseSector(Ion::Device::Flash::SectorAtAddress((uint32_t)&_exam_mode_buffer_start)); + return (uint8_t *)&_exam_mode_buffer_start; + } + + return persitence_start_8; +} + uint8_t FetchExamMode() { - uint32_t * readingAddress = SignificantExamModeAddress(); + uint8_t * readingAddress = SignificantExamModeAddress(); // Count the number of 0[3] before reading address - uint32_t nbOfZerosBefore = ((readingAddress - (uint32_t *)&_exam_mode_buffer_start)/4 * 2) % 3; + uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)&_exam_mode_buffer_start) * 2) % 3; // Count the number of 0[3] at reading address - size_t numberOfLeading0 = (32 - firstOneBit(*readingAddress, 32)) % 3; + size_t numberOfLeading0 = (numberOfBitsInByte - firstOneBitInByte(*readingAddress)) % 3; return (nbOfZerosBefore + numberOfLeading0) % 3; } void IncrementExamMode(uint8_t delta) { assert(delta == 1 || delta == 2); - uint32_t * writingAddress = SignificantExamModeAddress(); + uint8_t * writingAddress = SignificantExamModeAddress(); assert(*writingAddress != 0); - size_t nbOfOnes = firstOneBit(*writingAddress, 32); - // Compute the new value with two bits switched to 0. - /* We write in a uint64_t instead of uint32_t, in case there was only one bit + size_t nbOfTargetedOnes = firstOneBitInByte(*writingAddress); + + // Compute the new value with delta bits switched to 0. + /* We write in 2 bytes instead of 1, in case there was only one bit * left to 1 in writingAddress. */ - /* When writing in flash, we can only switch a 1 to a 0. If we want to switch - * the fifth and sixth bit in a byte, we can thus write "11100111". */ - uint64_t deltaOnes = (1 << delta) - 1; - uint64_t newValue = ~(deltaOnes << (32 + nbOfOnes - delta)); + nbOfTargetedOnes += numberOfBitsInByte; + nbOfTargetedOnes -= delta; + constexpr size_t newValueSize = sizeof(uint16_t)/sizeof(uint8_t); + uint8_t newValue[newValueSize]; + if (nbOfTargetedOnes > numberOfBitsInByte) { + size_t nbOfTargetedOnesInFirstByte = nbOfTargetedOnes - numberOfBitsInByte; + assert(nbOfTargetedOnesInFirstByte <= numberOfBitsInByte); + newValue[0] = ((uint16_t)1 << nbOfTargetedOnesInFirstByte) - 1; + newValue[1] = 0xFF; + } else { + assert(nbOfTargetedOnes <= numberOfBitsInByte); + newValue[0] = 0; + newValue[1] = ((uint16_t)1 << nbOfTargetedOnes) - 1; + } + // Write the value in flash /* Avoid writing out of sector */ - assert(writingAddress < (uint32_t *)&_exam_mode_buffer_end - 1 || *writingAddress > 1); - size_t writtenFlash = *writingAddress == 1 ? sizeof(uint64_t) : sizeof(uint32_t); - Ion::Device::Flash::WriteMemory((uint8_t *)writingAddress, (uint8_t *)&newValue, writtenFlash); + size_t writtenFlash = *writingAddress == 1 ? sizeof(uint16_t) : sizeof(uint8_t); + assert(writingAddress < (uint8_t *)&_exam_mode_buffer_end - 1 || (writingAddress == (uint8_t *)&_exam_mode_buffer_end - 1 && writtenFlash == 1)); + Ion::Device::Flash::WriteMemory(writingAddress, newValue, writtenFlash); } } From 2ccdc2d0dc1032433ebd0aec614bbb4e51560118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 17 Dec 2019 17:35:00 +0100 Subject: [PATCH 076/130] [apps] Fix messages regarding Dutch exam mode in non-English languages --- apps/home/base.de.i18n | 4 ++-- apps/home/base.es.i18n | 4 ++-- apps/home/base.fr.i18n | 4 ++-- apps/home/base.pt.i18n | 4 ++-- apps/settings/base.de.i18n | 2 +- apps/settings/base.es.i18n | 2 +- apps/settings/base.fr.i18n | 2 +- apps/settings/base.pt.i18n | 2 +- apps/shared.de.i18n | 6 +++--- apps/shared.es.i18n | 6 +++--- apps/shared.fr.i18n | 6 +++--- apps/shared.pt.i18n | 6 +++--- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/apps/home/base.de.i18n b/apps/home/base.de.i18n index a8f33d6cb..7cb389438 100644 --- a/apps/home/base.de.i18n +++ b/apps/home/base.de.i18n @@ -1,4 +1,4 @@ Apps = "Anwendungen" AppsCapital = "ANWENDUNGEN" -ForbidenAppInExamMode1 = "" -ForbidenAppInExamMode2 = "" +ForbidenAppInExamMode1 = "This application is" +ForbidenAppInExamMode2 = "forbidden in exam mode" diff --git a/apps/home/base.es.i18n b/apps/home/base.es.i18n index 8f48d86c5..4f04ddc56 100644 --- a/apps/home/base.es.i18n +++ b/apps/home/base.es.i18n @@ -1,4 +1,4 @@ Apps = "Aplicaciones" AppsCapital = "APLICACIONES" -ForbidenAppInExamMode1 = "" -ForbidenAppInExamMode2 = "" +ForbidenAppInExamMode1 = "This application is" +ForbidenAppInExamMode2 = "forbidden in exam mode" diff --git a/apps/home/base.fr.i18n b/apps/home/base.fr.i18n index 200c6f577..158fa3bda 100644 --- a/apps/home/base.fr.i18n +++ b/apps/home/base.fr.i18n @@ -1,4 +1,4 @@ Apps = "Applications" AppsCapital = "APPLICATIONS" -ForbidenAppInExamMode1 = "" -ForbidenAppInExamMode2 = "" +ForbidenAppInExamMode1 = "This application is" +ForbidenAppInExamMode2 = "forbidden in exam mode" diff --git a/apps/home/base.pt.i18n b/apps/home/base.pt.i18n index 2720ea295..e6816935c 100644 --- a/apps/home/base.pt.i18n +++ b/apps/home/base.pt.i18n @@ -1,4 +1,4 @@ Apps = "Aplicações" AppsCapital = "APLICAÇÕES" -ForbidenAppInExamMode1 = "" -ForbidenAppInExamMode2 = "" +ForbidenAppInExamMode1 = "This application is" +ForbidenAppInExamMode2 = "forbidden in exam mode" diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 263451755..248ffa473 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -9,7 +9,7 @@ ComplexFormat = "Komplex" ExamMode = "Testmodus" ActivateExamMode = "Starten Testmodus" ExamModeActive = "Wieder starten Testmodus" -ActivateDutchExamMode = "" +ActivateDutchExamMode = "Activate Dutch exam mode" About = "Über" Degrees = "Grad " Gradians = "Gone " diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index 698f978ba..06240e3f3 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -9,7 +9,7 @@ ComplexFormat = "Forma compleja" ExamMode = "Modo examen" ActivateExamMode = "Activar el modo examen" ExamModeActive = "Reactivar el modo examen" -ActivateDutchExamMode = "" +ActivateDutchExamMode = "Activate Dutch exam mode" About = "Acerca" Degrees = "Grados " Gradians = "Gradianes " diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index f625ffc86..c11f9fa9a 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -9,7 +9,7 @@ ComplexFormat = "Forme complexe" ExamMode = "Mode examen" ActivateExamMode = "Activer le mode examen" ExamModeActive = "Réactiver le mode examen" -ActivateDutchExamMode = "" +ActivateDutchExamMode = "Activate Dutch exam mode" About = "À propos" Degrees = "Degrés " Gradians = "Grades " diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index f872bcf5c..e2783fc7f 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -9,7 +9,7 @@ ComplexFormat = "Complexos" ExamMode = "Modo de exame" ActivateExamMode = "Ativar o modo de exame" ExamModeActive = "Reativar o modo de exame" -ActivateDutchExamMode = "" +ActivateDutchExamMode = "Activate Dutch exam mode" About = "Acerca" Degrees = "Graus " Gradians = "Grados " diff --git a/apps/shared.de.i18n b/apps/shared.de.i18n index ff08c00ff..185b2f13b 100644 --- a/apps/shared.de.i18n +++ b/apps/shared.de.i18n @@ -2,9 +2,9 @@ ActivateDeactivate = "Aktivieren/Deaktivieren" ActiveExamModeMessage1 = "Alle Ihre Daten werden " ActiveExamModeMessage2 = "gelöscht, wenn Sie den " ActiveExamModeMessage3 = "Testmodus einschalten." -ActiveDutchExamModeMessage1 = "" -ActiveDutchExamModeMessage2 = "" -ActiveDutchExamModeMessage3 = "" +ActiveDutchExamModeMessage1 = "All your data will be deleted when" +ActiveDutchExamModeMessage2 = "you activate the exam mode. Python" +ActiveDutchExamModeMessage3 = "application will be unavailable." Axis = "Achsen" Cancel = "Abbrechen" ClearColumn = "Spalte löschen" diff --git a/apps/shared.es.i18n b/apps/shared.es.i18n index 18ac4dc39..ae9a65d72 100644 --- a/apps/shared.es.i18n +++ b/apps/shared.es.i18n @@ -2,9 +2,9 @@ ActivateDeactivate = "Activar/Desactivar" ActiveExamModeMessage1 = "Todos sus datos se " ActiveExamModeMessage2 = "eliminaran al activar " ActiveExamModeMessage3 = "el modo examen." -ActiveDutchExamModeMessage1 = "" -ActiveDutchExamModeMessage2 = "" -ActiveDutchExamModeMessage3 = "" +ActiveDutchExamModeMessage1 = "All your data will be deleted when" +ActiveDutchExamModeMessage2 = "you activate the exam mode. Python" +ActiveDutchExamModeMessage3 = "application will be unavailable." Axis = "Ejes" Cancel = "Cancelar" ClearColumn = "Borrar la columna" diff --git a/apps/shared.fr.i18n b/apps/shared.fr.i18n index b3f6fc997..a03e1ecc6 100644 --- a/apps/shared.fr.i18n +++ b/apps/shared.fr.i18n @@ -2,9 +2,9 @@ ActivateDeactivate = "Activer/Désactiver" ActiveExamModeMessage1 = "Toutes vos données seront " ActiveExamModeMessage2 = "supprimées si vous activez " ActiveExamModeMessage3 = "le mode examen." -ActiveDutchExamModeMessage1 = "" -ActiveDutchExamModeMessage2 = "" -ActiveDutchExamModeMessage3 = "" +ActiveDutchExamModeMessage1 = "All your data will be deleted when" +ActiveDutchExamModeMessage2 = "you activate the exam mode. Python" +ActiveDutchExamModeMessage3 = "application will be unavailable." Axis = "Axes" Cancel = "Annuler" ClearColumn = "Effacer la colonne" diff --git a/apps/shared.pt.i18n b/apps/shared.pt.i18n index 911100216..42e1752af 100644 --- a/apps/shared.pt.i18n +++ b/apps/shared.pt.i18n @@ -2,9 +2,9 @@ ActivateDeactivate = "Activar/Desactivar" ActiveExamModeMessage1 = "Todos os seus dados serão " ActiveExamModeMessage2 = "apagados se você ligar " ActiveExamModeMessage3 = "o modo de exame." -ActiveDutchExamModeMessage1 = "" -ActiveDutchExamModeMessage2 = "" -ActiveDutchExamModeMessage3 = "" +ActiveDutchExamModeMessage1 = "All your data will be deleted when" +ActiveDutchExamModeMessage2 = "you activate the exam mode. Python" +ActiveDutchExamModeMessage3 = "application will be unavailable." Axis = "Eixos" Cancel = "Cancelar" ClearColumn = "Excluir coluna" From 9d154e4e971a650ae5a29edeb436e31a96813c85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 18 Dec 2019 10:29:34 +0100 Subject: [PATCH 077/130] [ion] Exam mode: add assertion --- ion/src/device/shared/drivers/exam_mode.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ion/src/device/shared/drivers/exam_mode.cpp b/ion/src/device/shared/drivers/exam_mode.cpp index 96e10a2d0..3ae01315c 100644 --- a/ion/src/device/shared/drivers/exam_mode.cpp +++ b/ion/src/device/shared/drivers/exam_mode.cpp @@ -50,6 +50,7 @@ size_t firstOneBitInByte(int i) { uint8_t * SignificantExamModeAddress() { uint32_t * persitence_start_32 = (uint32_t *)&_exam_mode_buffer_start; uint32_t * persitence_end_32 = (uint32_t *)&_exam_mode_buffer_end; + assert(persitence_end_32 - persitence_start_32 % 4 == 0); while (persitence_start_32 < persitence_end_32 && *persitence_start_32 == 0x0) { // Scan by groups of 32 bits to reach first non-zero bit persitence_start_32++; From 7d8bd450478bcaa6a8326fddf1d90b99a2d4325e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 18 Dec 2019 12:05:45 +0100 Subject: [PATCH 078/130] [build] Fix target two_binaries --- build/targets.device.mak | 28 ---------------------------- build/targets.device.n0110.mak | 28 ++++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/build/targets.device.mak b/build/targets.device.mak index 67265897b..3a54b7554 100644 --- a/build/targets.device.mak +++ b/build/targets.device.mak @@ -60,31 +60,3 @@ $(BUILD_DIR)/bench.flash.$(EXE): LDSCRIPT = ion/src/$(PLATFORM)/$(MODEL)/interna bench_src = $(ion_xip_src) $(liba_src) $(kandinsky_src) $(poincare_src) $(libaxx_src) $(app_shared_src) $(ion_target_device_bench_src) $(BUILD_DIR)/bench.ram.$(EXE): $(call object_for,$(bench_src)) $(BUILD_DIR)/bench.flash.$(EXE): $(call object_for,$(bench_src)) - -.PHONY: %.two_binaries -%.two_binaries: %.elf - @echo "Building an internal and an external binary for $<" - $(Q) $(OBJCOPY) -O binary -j .text.external -j .rodata.external $< $(basename $<).external.bin - $(Q) $(OBJCOPY) -O binary -R .text.external -R .rodata.external $< $(basename $<).internal.bin - @echo "Padding $(basename $<).external.bin and $(basename $<).internal.bin" - $(Q) printf "\xFF\xFF\xFF\xFF" >> $(basename $<).external.bin - $(Q) printf "\xFF\xFF\xFF\xFF" >> $(basename $<).internal.bin - -.PHONY: binpack -binpack: - rm -rf build/binpack - mkdir -p build/binpack - make clean - make -j8 $(BUILD_DIR)/flasher.light.bin - cp $(BUILD_DIR)/flasher.light.bin build/binpack - make clean - make -j8 $(BUILD_DIR)/bench.flash.bin - make -j8 $(BUILD_DIR)/bench.ram.bin - cp $(BUILD_DIR)/bench.ram.bin $(BUILD_DIR)/bench.flash.bin build/binpack - make clean - make -j8 $(BUILD_DIR)/epsilon.onboarding.update.two_binaries - cp $(BUILD_DIR)/epsilon.onboarding.update.internal.bin $(BUILD_DIR)/epsilon.onboarding.update.external.bin build/binpack - make clean - cd build && for binary in flasher.light.bin bench.flash.bin bench.ram.bin epsilon.onboarding.internal.bin epsilon.onboarding.external.bin; do shasum -a 256 -b binpack/$${binary} > binpack/$${binary}.sha256;done - cd build && tar cvfz binpack-`git rev-parse HEAD | head -c 7`.tgz binpack - rm -rf build/binpack diff --git a/build/targets.device.n0110.mak b/build/targets.device.n0110.mak index 3abc930e4..7c22b862b 100644 --- a/build/targets.device.n0110.mak +++ b/build/targets.device.n0110.mak @@ -19,3 +19,31 @@ $(BUILD_DIR)/test.external_flash.write.$(EXE): $(BUILD_DIR)/quiz/src/test_ion_ex sleep 2; \ fi $(Q) $(PYTHON) build/device/dfu.py -u $(word 1,$^) + +.PHONY: %.two_binaries +%.two_binaries: %.elf + @echo "Building an internal and an external binary for $<" + $(Q) $(OBJCOPY) -O binary -j .text.external -j .rodata.external -j .exam_mode_buffer $(BUILD_DIR)/$< $(BUILD_DIR)/$(basename $<).external.bin + $(Q) $(OBJCOPY) -O binary -R .text.external -R .rodata.external -R .exam_mode_buffer $(BUILD_DIR)/$< $(BUILD_DIR)/$(basename $<).internal.bin + @echo "Padding $(basename $<).external.bin and $(basename $<).internal.bin" + $(Q) printf "\xFF\xFF\xFF\xFF" >> $(basename $<).external.bin + $(Q) printf "\xFF\xFF\xFF\xFF" >> $(basename $<).internal.bin + +.PHONY: binpack +binpack: + rm -rf build/binpack + mkdir -p build/binpack + make clean + make -j8 $(BUILD_DIR)/flasher.light.bin + cp $(BUILD_DIR)/flasher.light.bin build/binpack + make clean + make -j8 $(BUILD_DIR)/bench.flash.bin + make -j8 $(BUILD_DIR)/bench.ram.bin + cp $(BUILD_DIR)/bench.ram.bin $(BUILD_DIR)/bench.flash.bin build/binpack + make clean + make -j8 $(BUILD_DIR)/epsilon.onboarding.update.two_binaries + cp $(BUILD_DIR)/epsilon.onboarding.update.internal.bin $(BUILD_DIR)/epsilon.onboarding.update.external.bin build/binpack + make clean + cd build && for binary in flasher.light.bin bench.flash.bin bench.ram.bin epsilon.onboarding.internal.bin epsilon.onboarding.external.bin; do shasum -a 256 -b binpack/$${binary} > binpack/$${binary}.sha256;done + cd build && tar cvfz binpack-`git rev-parse HEAD | head -c 7`.tgz binpack + rm -rf build/binpack From 01ab6b5aebee1126626cf5226d930dcd5a8675d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Dec 2019 15:09:46 +0100 Subject: [PATCH 079/130] [build] Fix test.elf build --- apps/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/Makefile b/apps/Makefile index ba2e1a396..c6b21fa79 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -92,6 +92,10 @@ $(call object_for,$(all_app_src)): $(BUILD_DIR)/python/port/genhdr/qstrdefs.gene apps_tests_src = $(app_calculation_test_src) $(app_probability_test_src) $(app_regression_test_src) $(app_sequence_test_src) $(app_shared_test_src) $(app_statistics_test_src) $(app_solver_test_src) +apps_tests_src += $(addprefix apps/,\ + global_preferences.cpp \ +) + # Configure variants apps_all_src = $(app_src) apps_all_src += $(apps_launch_default_src) $(apps_launch_on_boarding_src From 96c63bd4a53dc438fcd7332bd0d353c2c809f968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Dec 2019 15:10:32 +0100 Subject: [PATCH 080/130] [apps][ion] Yellow LED is equivalent to Dutch exam mode, do not update the LED color (with plugging/charging events) if the displayed color was Red or Yellow --- apps/apps_container.cpp | 2 +- ion/src/device/n0110/drivers/led.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 952f83db3..8d96b2b02 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -327,7 +327,7 @@ void AppsContainer::redrawWindow() { void AppsContainer::activateExamMode(GlobalPreferences::ExamMode examMode) { assert(examMode == GlobalPreferences::ExamMode::Standard || examMode == GlobalPreferences::ExamMode::Dutch); reset(); - Ion::LED::setColor(examMode == GlobalPreferences::ExamMode::Dutch ? KDColorOrange : KDColorRed); + Ion::LED::setColor(examMode == GlobalPreferences::ExamMode::Dutch ? KDColorYellow : KDColorRed); Ion::LED::setBlinking(1000, 0.1f); } diff --git a/ion/src/device/n0110/drivers/led.cpp b/ion/src/device/n0110/drivers/led.cpp index d29cc8494..83cf62083 100644 --- a/ion/src/device/n0110/drivers/led.cpp +++ b/ion/src/device/n0110/drivers/led.cpp @@ -7,7 +7,7 @@ namespace LED { KDColor updateColorWithPlugAndCharge() { KDColor ledColor = getColor(); - if (ledColor != KDColorRed) { // If exam mode is on, we do not update the LED with the plugged/charging state + if (ledColor != KDColorRed && ledColor != KDColorYellow) { // If exam mode is on, we do not update the LED with the plugged/charging state if (USB::isPlugged()) { ledColor = Battery::isCharging() ? KDColorOrange : KDColorGreen; } else { From 425f0cb45900f9c9cee27dbeaad0651b1d41c4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Dec 2019 15:16:05 +0100 Subject: [PATCH 081/130] [apps] GlobalPreferences: remove useless assertion --- apps/global_preferences.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/global_preferences.cpp b/apps/global_preferences.cpp index 7a0763e49..e47965cc6 100644 --- a/apps/global_preferences.cpp +++ b/apps/global_preferences.cpp @@ -9,7 +9,6 @@ GlobalPreferences::ExamMode GlobalPreferences::examMode() const { if (m_examMode == ExamMode::Unknown) { m_examMode = (ExamMode)Ion::ExamMode::FetchExamMode(); } - assert((int)m_examMode >= 0 && (int)m_examMode <= 2); return m_examMode; } From 902cc64d32a32c4d3ffe4199f0025e2e8b3fda84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Dec 2019 15:18:03 +0100 Subject: [PATCH 082/130] [apps] GlobalPreferences: add an assertion to ensure the the fetched exam mode can be casted in GlobalPreferences::ExamMode --- apps/global_preferences.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/global_preferences.cpp b/apps/global_preferences.cpp index e47965cc6..c6644f5fd 100644 --- a/apps/global_preferences.cpp +++ b/apps/global_preferences.cpp @@ -7,7 +7,9 @@ GlobalPreferences * GlobalPreferences::sharedGlobalPreferences() { GlobalPreferences::ExamMode GlobalPreferences::examMode() const { if (m_examMode == ExamMode::Unknown) { - m_examMode = (ExamMode)Ion::ExamMode::FetchExamMode(); + uint8_t mode = Ion::ExamMode::FetchExamMode(); + assert(mode >= 0 && mode < 3); // mode can be cast in ExamMode (Off, Standard or Dutch) + m_examMode = (ExamMode)mode; } return m_examMode; } From 73673384aec58238e9a226359640da055f7ad75c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Dec 2019 15:26:42 +0100 Subject: [PATCH 083/130] [ion] Avoid unclear, over-optimized computation in modulo 3 --- ion/src/device/shared/drivers/exam_mode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion/src/device/shared/drivers/exam_mode.cpp b/ion/src/device/shared/drivers/exam_mode.cpp index 3ae01315c..99b412e78 100644 --- a/ion/src/device/shared/drivers/exam_mode.cpp +++ b/ion/src/device/shared/drivers/exam_mode.cpp @@ -75,7 +75,7 @@ uint8_t * SignificantExamModeAddress() { uint8_t FetchExamMode() { uint8_t * readingAddress = SignificantExamModeAddress(); // Count the number of 0[3] before reading address - uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)&_exam_mode_buffer_start) * 2) % 3; + uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)&_exam_mode_buffer_start) * numberOfBitsInByte) % 3; // Count the number of 0[3] at reading address size_t numberOfLeading0 = (numberOfBitsInByte - firstOneBitInByte(*readingAddress)) % 3; return (nbOfZerosBefore + numberOfLeading0) % 3; From 3454265d7e6f55420bd02b31ecbde7a8a8d68836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Dec 2019 15:31:34 +0100 Subject: [PATCH 084/130] [ion] ExamMode: change firstOneBitInByte name to numberOfBitsAfterLeadingZeroes and add comment --- ion/src/device/shared/drivers/exam_mode.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ion/src/device/shared/drivers/exam_mode.cpp b/ion/src/device/shared/drivers/exam_mode.cpp index 99b412e78..c61d6ca97 100644 --- a/ion/src/device/shared/drivers/exam_mode.cpp +++ b/ion/src/device/shared/drivers/exam_mode.cpp @@ -32,7 +32,8 @@ char ones[Config::ExamModeBufferSize] constexpr static size_t numberOfBitsInByte = 8; -size_t firstOneBitInByte(int i) { +// if i = 0b000011101, firstOneBitInByte(i) returns 5 +size_t numberOfBitsAfterLeadingZeroes(int i) { int minShift = 0; int maxShift = numberOfBitsInByte; while (maxShift > minShift+1) { @@ -77,7 +78,7 @@ uint8_t FetchExamMode() { // Count the number of 0[3] before reading address uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)&_exam_mode_buffer_start) * numberOfBitsInByte) % 3; // Count the number of 0[3] at reading address - size_t numberOfLeading0 = (numberOfBitsInByte - firstOneBitInByte(*readingAddress)) % 3; + size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*readingAddress)) % 3; return (nbOfZerosBefore + numberOfLeading0) % 3; } @@ -85,7 +86,7 @@ void IncrementExamMode(uint8_t delta) { assert(delta == 1 || delta == 2); uint8_t * writingAddress = SignificantExamModeAddress(); assert(*writingAddress != 0); - size_t nbOfTargetedOnes = firstOneBitInByte(*writingAddress); + size_t nbOfTargetedOnes = numberOfBitsAfterLeadingZeroes(*writingAddress); // Compute the new value with delta bits switched to 0. /* We write in 2 bytes instead of 1, in case there was only one bit From 0254266803627a88bbc4568ebc2da12e3b1af534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Dec 2019 15:35:57 +0100 Subject: [PATCH 085/130] [ion] ExamMode: add comment --- ion/src/device/shared/drivers/exam_mode.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ion/src/device/shared/drivers/exam_mode.cpp b/ion/src/device/shared/drivers/exam_mode.cpp index c61d6ca97..a4aa20143 100644 --- a/ion/src/device/shared/drivers/exam_mode.cpp +++ b/ion/src/device/shared/drivers/exam_mode.cpp @@ -107,8 +107,11 @@ void IncrementExamMode(uint8_t delta) { } // Write the value in flash - /* Avoid writing out of sector */ + /* As the number of changed bits is capped by 2, if *writingAddress has more + * than one remaining 1 bit, we know we toggle bits only in the first byte of + * newValue. We can settle for writing one byte instead of two. */ size_t writtenFlash = *writingAddress == 1 ? sizeof(uint16_t) : sizeof(uint8_t); + /* Avoid writing out of sector */ assert(writingAddress < (uint8_t *)&_exam_mode_buffer_end - 1 || (writingAddress == (uint8_t *)&_exam_mode_buffer_end - 1 && writtenFlash == 1)); Ion::Device::Flash::WriteMemory(writingAddress, newValue, writtenFlash); } From e13425d2318ad98c3aea67d3345f321dcc2aab0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 19 Dec 2019 15:41:40 +0100 Subject: [PATCH 086/130] [apps] Add comment about LED color in Dutch exam mode --- apps/apps_container.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 8d96b2b02..5656aecb9 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -327,6 +327,13 @@ void AppsContainer::redrawWindow() { void AppsContainer::activateExamMode(GlobalPreferences::ExamMode examMode) { assert(examMode == GlobalPreferences::ExamMode::Standard || examMode == GlobalPreferences::ExamMode::Dutch); reset(); + /* The Dutch exam mode LED is supposed to be orange but we can only make + * blink "pure" colors: with RGB leds on or off (as the PWM is used for + * blinking). The closest "pure" color is Yellow. Moreover, Orange LED is + * already used when the battery is charging. Using yellow, we can assert + * that the yellow LED only means that Dutch exam mode is on and avoid + * confusing states when the battery is charging and states when the Dutch + * exam mode is on. */ Ion::LED::setColor(examMode == GlobalPreferences::ExamMode::Dutch ? KDColorYellow : KDColorRed); Ion::LED::setBlinking(1000, 0.1f); } From fe11d6e3543a3c528e2787b97280f86e6b1232d4 Mon Sep 17 00:00:00 2001 From: Damien Nicolet Date: Thu, 19 Dec 2019 20:02:44 +0100 Subject: [PATCH 087/130] Block external files in exam mode --- apps/external/archive.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/external/archive.cpp b/apps/external/archive.cpp index aaa89373a..2818d4a51 100644 --- a/apps/external/archive.cpp +++ b/apps/external/archive.cpp @@ -1,5 +1,6 @@ #include "archive.h" #include "extapp_api.h" +#include "../global_preferences.h" #include #include @@ -34,12 +35,16 @@ bool isSane(const TarHeader* tar) { return !memcmp(tar->magic, "ustar ", 8) && tar->name[0] != '\x00' && tar->name[0] != '\xFF'; } +bool isExamModeAndFileNotExecutable(const TarHeader* tar) { + return GlobalPreferences::sharedGlobalPreferences()->examMode() && (tar->mode[4] & 0x01) == 0; +} + bool fileAtIndex(size_t index, File &entry) { const TarHeader* tar = reinterpret_cast(0x90200000); unsigned size = 0; // Sanity check. - if (!isSane(tar)) { + if (!isSane(tar) || isExamModeAndFileNotExecutable(tar)) { return false; } @@ -58,7 +63,7 @@ bool fileAtIndex(size_t index, File &entry) { tar = reinterpret_cast(reinterpret_cast(tar) + stride); // Sanity check. - if (!isSane(tar)) { + if (!isSane(tar) || isExamModeAndFileNotExecutable(tar)) { return false; } } From 2c7a26103b0af12e8f1290c575c03b4d1efb422f Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Thu, 19 Dec 2019 17:22:26 -0500 Subject: [PATCH 088/130] [ci] Use a recent ARM GCC toolchain --- .github/workflows/ci-workflow.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index d38794afc..7b53519b9 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -14,7 +14,8 @@ jobs: build-device-n0100: runs-on: ubuntu-latest steps: - - run: sudo apt-get install binutils-arm-none-eabi build-essential gcc-arm-none-eabi imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config + - run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config + - uses: numworks/setup-arm-toolchain@v1 - uses: actions/checkout@v1 - run: make -j2 MODEL=n0100 epsilon.dfu - run: make -j2 MODEL=n0100 epsilon.onboarding.dfu @@ -30,7 +31,8 @@ jobs: build-device-n0110: runs-on: ubuntu-latest steps: - - run: sudo apt-get install binutils-arm-none-eabi build-essential gcc-arm-none-eabi imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config + - run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config + - uses: numworks/setup-arm-toolchain@v1 - uses: actions/checkout@v1 - run: make -j2 epsilon.dfu - run: make -j2 epsilon.onboarding.dfu From ae8c111da5b52e84db291c6238ed41ba357dc047 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Mon, 16 Dec 2019 21:36:46 -0500 Subject: [PATCH 089/130] [ion] Prevent duplicating SFLAGS Using $(sort) in the Makefile has the side effect of removing duplicates --- ion/src/device/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ion/src/device/Makefile b/ion/src/device/Makefile index 5adb13861..d15012f4e 100644 --- a/ion/src/device/Makefile +++ b/ion/src/device/Makefile @@ -19,7 +19,7 @@ ion_src += $(addprefix ion/src/shared/, \ ION_DEVICE_SFLAGS = -Iion/src/device/$(MODEL) -Iion/src/device/shared -$(call object_for,$(ion_device_src) $(dfu_src) $(ion_target_device_flasher_light_src) $(ion_target_device_flasher_verbose_src) $(usb_src) $(ion_target_device_bench_src) $(ion_device_dfu_xip_src) $(ion_device_dfu_relocated_src) $(ion_console_uart_src)): SFLAGS += $(ION_DEVICE_SFLAGS) +$(call object_for,$(sort $(ion_device_src) $(dfu_src) $(ion_target_device_flasher_light_src) $(ion_target_device_flasher_verbose_src) $(usb_src) $(ion_target_device_bench_src) $(ion_device_dfu_xip_src) $(ion_device_dfu_relocated_src) $(ion_console_uart_src))): SFLAGS += $(ION_DEVICE_SFLAGS) ion_src += $(ion_device_src) # When using the register.h C++ file in production mode, we expect the compiler From d0660b6543aa5cafbb7a3981bb39b35717a72bed Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Mon, 16 Dec 2019 21:44:56 -0500 Subject: [PATCH 090/130] [ion/device] Force inlining compile-time bit ranges Most of the time register operations can be optimized to a single assembly instruction. That being said, aggressive -Os optimization can lead the compiler to think that factorizing calls to setBitRange is a good idea. But we really want register operations to be inlined (and therefore optimized as a single instruction), so we enforce inlining setBitRange and REGS_FIELD macros. --- ion/src/device/shared/regs/register.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ion/src/device/shared/regs/register.h b/ion/src/device/shared/regs/register.h index cac002a6b..12adc8a28 100644 --- a/ion/src/device/shared/regs/register.h +++ b/ion/src/device/shared/regs/register.h @@ -4,6 +4,8 @@ #include #include +#define always_inline __attribute__((always_inline)) + namespace Ion { namespace Device { namespace Regs { @@ -22,7 +24,7 @@ public: T get() volatile { return m_value; } - void setBitRange(uint8_t high, uint8_t low, T value) volatile { + always_inline void setBitRange(uint8_t high, uint8_t low, T value) volatile { m_value = bit_range_set_value(high, low, m_value, value); } T getBitRange(uint8_t high, uint8_t low) volatile { @@ -57,8 +59,8 @@ typedef Register Register64; } } -#define REGS_FIELD_R(name,type,high,low) type get##name() volatile { return (type)getBitRange(high,low); }; -#define REGS_FIELD_W(name,type,high,low) void set##name(type v) volatile { static_assert(sizeof(type) <= 4, "Invalid size"); setBitRange(high, low, static_cast(v)); }; +#define REGS_FIELD_R(name,type,high,low) always_inline type get##name() volatile { return (type)getBitRange(high,low); }; +#define REGS_FIELD_W(name,type,high,low) always_inline void set##name(type v) volatile { static_assert(sizeof(type) <= 4, "Invalid size"); setBitRange(high, low, static_cast(v)); }; #define REGS_FIELD(name,type,high,low) REGS_FIELD_R(name,type,high,low); REGS_FIELD_W(name,type,high,low); #define REGS_TYPE_FIELD(name,high,low) REGS_FIELD(name,name,high,low) #define REGS_BOOL_FIELD(name,bit) REGS_FIELD(name,bool,bit,bit) From 5b00192b6712f3891cced8b93589f4c3ff9d4e85 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Mon, 16 Dec 2019 21:45:42 -0500 Subject: [PATCH 091/130] [ion/device] Remove ad-hoc compiler optimizations Since we hand-specify which regs/regs.h functions shoudl be inlined, we don't need to depend on specific compiler optimization levels. --- ion/src/device/Makefile | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/ion/src/device/Makefile b/ion/src/device/Makefile index d15012f4e..161218a49 100644 --- a/ion/src/device/Makefile +++ b/ion/src/device/Makefile @@ -21,18 +21,3 @@ ION_DEVICE_SFLAGS = -Iion/src/device/$(MODEL) -Iion/src/device/shared $(call object_for,$(sort $(ion_device_src) $(dfu_src) $(ion_target_device_flasher_light_src) $(ion_target_device_flasher_verbose_src) $(usb_src) $(ion_target_device_bench_src) $(ion_device_dfu_xip_src) $(ion_device_dfu_relocated_src) $(ion_console_uart_src))): SFLAGS += $(ION_DEVICE_SFLAGS) ion_src += $(ion_device_src) - -# When using the register.h C++ file in production mode, we expect the compiler -# to completely inline all bit manipulations. For some reason, if we build using -# the -Os optimization flag, GCC doesn't inline everything and and ends up -# emitting calls to aeabi_llsl for 64-bits registers. This is very sub-optimal -# so we're enforcing -O3 for this specific file. - -ifneq ($(DEBUG),1) -ifneq ($(COMPILER),llvm) -$(BUILD_DIR)/ion/src/device/led.o: SFLAGS+=-O3 -$(BUILD_DIR)/ion/src/device/console.o: SFLAGS+=-O3 -$(BUILD_DIR)/ion/src/device/display.o: SFLAGS+=-O3 -$(BUILD_DIR)/ion/src/device/swd.o: SFLAGS+=-O3 -endif -endif From 0412a45cea77557235d2fc811ce33692970a8495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Dec 2019 15:36:57 +0100 Subject: [PATCH 092/130] [escher/responder] Inline some methods --- escher/include/escher/responder.h | 14 +++++++------- escher/src/responder.cpp | 24 ------------------------ 2 files changed, 7 insertions(+), 31 deletions(-) diff --git a/escher/include/escher/responder.h b/escher/include/escher/responder.h index cf84840bb..c8315c5bb 100644 --- a/escher/include/escher/responder.h +++ b/escher/include/escher/responder.h @@ -5,15 +5,15 @@ class Responder { public: - Responder(Responder * parentResponder); + Responder(Responder * parentResponder) : m_parentResponder(parentResponder) {} virtual bool handleEvent(Ion::Events::Event event) { return false; }; // Default implementation does nothing - virtual void didBecomeFirstResponder(); - virtual void willResignFirstResponder(); - virtual void didEnterResponderChain(Responder * previousFirstResponder); - virtual void willExitResponderChain(Responder * nextFirstResponder); - Responder * parentResponder() const; + virtual void didBecomeFirstResponder() {} + virtual void willResignFirstResponder() {} + virtual void didEnterResponderChain(Responder * previousFirstResponder) {} + virtual void willExitResponderChain(Responder * nextFirstResponder) {} + Responder * parentResponder() const { return m_parentResponder; } Responder * commonAncestorWith(Responder * responder); - void setParentResponder(Responder * responder); + void setParentResponder(Responder * responder) { m_parentResponder = responder; } private: Responder * m_parentResponder; }; diff --git a/escher/src/responder.cpp b/escher/src/responder.cpp index 34cbd96a0..ba0a120f4 100644 --- a/escher/src/responder.cpp +++ b/escher/src/responder.cpp @@ -2,30 +2,6 @@ #include #include -Responder::Responder(Responder * parentResponder) : - m_parentResponder(parentResponder) -{ -} - -Responder * Responder::parentResponder() const { - return m_parentResponder; -} - -void Responder::setParentResponder(Responder * responder) { - m_parentResponder = responder; -} - -void Responder::didBecomeFirstResponder() { -} - -void Responder::willResignFirstResponder() { -} - -void Responder::didEnterResponderChain(Responder * previousFirstResponder) { -} - -void Responder::willExitResponderChain(Responder * nextFirstResponder) { -} Responder * Responder::commonAncestorWith(Responder * responder) { if (responder == nullptr) { From 4e96a11a4c98b1ec7d4fd91e1636e7b128a6c6ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Thu, 19 Dec 2019 15:55:10 +0100 Subject: [PATCH 093/130] [escher/responder] Clean commonAncestor method --- escher/include/escher/responder.h | 1 + escher/src/responder.cpp | 47 +++++++++++++------------------ 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/escher/include/escher/responder.h b/escher/include/escher/responder.h index c8315c5bb..b0918b5fc 100644 --- a/escher/include/escher/responder.h +++ b/escher/include/escher/responder.h @@ -15,6 +15,7 @@ public: Responder * commonAncestorWith(Responder * responder); void setParentResponder(Responder * responder) { m_parentResponder = responder; } private: + bool hasAncestor(Responder * responder) const; Responder * m_parentResponder; }; diff --git a/escher/src/responder.cpp b/escher/src/responder.cpp index ba0a120f4..72f12c85e 100644 --- a/escher/src/responder.cpp +++ b/escher/src/responder.cpp @@ -7,33 +7,24 @@ Responder * Responder::commonAncestorWith(Responder * responder) { if (responder == nullptr) { return nullptr; } - if (this == responder) { - return this; + Responder * p = this; + while (p != nullptr) { + if (responder->hasAncestor(p)) { + return p; + } + p = p->parentResponder(); } - Responder * rootResponder = this; - while (rootResponder->parentResponder() != responder && rootResponder->parentResponder() != nullptr) { - rootResponder = rootResponder->parentResponder(); - } - if (rootResponder->parentResponder() == responder) { - return responder; - } - rootResponder = responder; - while (rootResponder->parentResponder() != this && rootResponder->parentResponder() != nullptr) { - rootResponder = rootResponder->parentResponder(); - } - if (rootResponder->parentResponder() == this) { - return this; - } - Responder * r = nullptr; - if (parentResponder()) { - r = parentResponder()->commonAncestorWith(responder); - } - Responder * s = nullptr; - if (responder->parentResponder()) { - s = commonAncestorWith(responder->parentResponder()); - } - if (r) { - return r; - } - return s; + return nullptr; +} + +bool Responder::hasAncestor(Responder * responder) const { + assert(responder != nullptr); + Responder * p = const_cast(this); + while (p != nullptr) { + if (p == responder) { + return true; + } + p = p->parentResponder(); + } + return false; } From 053fb935e321dc366292247acef06d6a5ee82bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 20 Dec 2019 14:02:08 +0100 Subject: [PATCH 094/130] [apps] Change color of LED in power on self test: blue is too easily confused with white --- apps/on_boarding/power_on_self_test.cpp | 2 +- kandinsky/include/kandinsky/color.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/on_boarding/power_on_self_test.cpp b/apps/on_boarding/power_on_self_test.cpp index dde93f04c..5bdeb1807 100644 --- a/apps/on_boarding/power_on_self_test.cpp +++ b/apps/on_boarding/power_on_self_test.cpp @@ -20,7 +20,7 @@ KDColor PowerOnSelfTest::Perform() { resultColor = KDColorRed; } } else { - resultColor = KDColorBlue; + resultColor = KDColorPurple; } Ion::LED::setColor(resultColor); return previousLEDColor; diff --git a/kandinsky/include/kandinsky/color.h b/kandinsky/include/kandinsky/color.h index a416bd2d7..9879e006b 100644 --- a/kandinsky/include/kandinsky/color.h +++ b/kandinsky/include/kandinsky/color.h @@ -45,5 +45,6 @@ constexpr KDColor KDColorGreen = KDColor::RGB24(0x00FF00); constexpr KDColor KDColorBlue = KDColor::RGB24(0x0000FF); constexpr KDColor KDColorYellow = KDColor::RGB24(0xFFFF00); constexpr KDColor KDColorOrange = KDColor::RGB24(0xFF9900); +constexpr KDColor KDColorPurple = KDColor::RGB24(0xFF00DD); #endif From e6e583d9671c180fa2d4404c53054ce40e76d44f Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Sat, 21 Dec 2019 15:08:24 +0100 Subject: [PATCH 095/130] Added OMEGA_THEME (#33). Added cleanall target --- Makefile | 12 +++ build/config.mak | 1 + escher/Makefile | 7 ++ escher/include/escher/palette.h | 139 -------------------------------- themes | 2 +- 5 files changed, 21 insertions(+), 140 deletions(-) delete mode 100644 escher/include/escher/palette.h diff --git a/Makefile b/Makefile index 8f8af5d51..6976f63d3 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,8 @@ info: @echo "EPSILON_VERSION = $(EPSILON_VERSION)" @echo "EPSILON_APPS = $(EPSILON_APPS)" @echo "EPSILON_I18N = $(EPSILON_I18N)" + @echo "OMEGA_THEME = $(OMEGA_THEME)" + @echo "BUILD_DIR = $(BUILD_DIR)" @echo "PLATFORM" = $(PLATFORM) @echo "DEBUG" = $(DEBUG) @echo "EPSILON_GETOPT" = $(EPSILON_GETOPT) @@ -103,6 +105,11 @@ include build/scenario/Makefile include quiz/Makefile # Quiz needs to be included at the end all_src = $(apps_all_src) $(escher_src) $(ion_all_src) $(kandinsky_src) $(liba_src) $(libaxx_src) $(poincare_src) $(python_src) $(epsilon_src) $(runner_src) $(ion_target_device_flasher_light_src) $(ion_target_device_flasher_verbose_src) $(ion_target_device_bench_src) $(tests_src) + +# Make palette.h a dep for every source-file. +# This ensures that the theming engine works correctly. +$(call object_for,$(all_app_src)): $(BUILD_DIR)/escher/palette.h + all_objs = $(call object_for,$(all_src)) .SECONDARY: $(all_objs) @@ -127,6 +134,11 @@ clean: @echo "CLEAN" $(Q) rm -rf $(BUILD_DIR) +.PHONY: cleanall +cleanall: + @echo "CLEANALL" + $(Q) rm -rf output + .PHONY: cowsay_% cowsay_%: @echo " -------" diff --git a/build/config.mak b/build/config.mak index a59637cc0..0d3568c60 100644 --- a/build/config.mak +++ b/build/config.mak @@ -11,6 +11,7 @@ EPSILON_APPS ?= calculation rpn graph code statistics probability solver atom se EPSILON_I18N ?= en fr es de pt EPSILON_GETOPT ?= 0 ESCHER_LOG_EVENTS_BINARY ?= 0 +OMEGA_THEME ?= omega_light include build/defaults.mak include build/platform.$(PLATFORM).mak diff --git a/escher/Makefile b/escher/Makefile index ee4f501d2..6e6453e89 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -95,6 +95,13 @@ $(eval $(call rule_for, \ $$(HOSTCC) -std=c99 `libpng-config --cflags` $$^ `libpng-config --ldflags` -o $$@ \ )) +$(eval $(call rule_for, \ + THEME, \ + escher/palette.h, \ + $(addprefix themes/themes/, $(addsuffix .json, $(OMEGA_THEME))), \ + $$(PYTHON) themes/themes_manager.py $(OMEGA_THEME) $$@ \ +)) + INLINER := $(BUILD_DIR)/escher/image/inliner .PRECIOUS: $(BUILD_DIR)/%.h $(BUILD_DIR)/%.cpp diff --git a/escher/include/escher/palette.h b/escher/include/escher/palette.h deleted file mode 100644 index f7d4c6284..000000000 --- a/escher/include/escher/palette.h +++ /dev/null @@ -1,139 +0,0 @@ -#ifndef ESCHER_PALETTE_H -#define ESCHER_PALETTE_H - -#include - -class Palette { -public: - constexpr static KDColor PrimaryText = KDColor::RGB24(0x000000); - constexpr static KDColor SecondaryText = KDColor::RGB24(0x6e6e6e); - constexpr static KDColor AccentText = KDColor::RGB24(0x00857f); - constexpr static KDColor ApproximateSignText = KDColor::RGB24(0x595959); - constexpr static KDColor ApproximateExpressionText = KDColor::RGB24(0x595959); - constexpr static KDColor BackgroundHard = KDColor::RGB24(0xffffff); - constexpr static KDColor BackgroundApps = KDColor::RGB24(0xfafafa); - constexpr static KDColor BackgroundAppsSecondary = KDColor::RGB24(0xf0f0f0); - constexpr static KDColor Toolbar = KDColor::RGB24(0xc03535); - constexpr static KDColor ToolbarText = KDColor::RGB24(0xffffff); - constexpr static KDColor ExpressionInputBackground = KDColor::RGB24(0xe0e0e0); - constexpr static KDColor ExpressionInputBorder = KDColor::RGB24(0xd9d9d9); - constexpr static KDColor GridPrimaryLine = KDColor::RGB24(0xd9d9d9); - constexpr static KDColor GridSecondaryLine = KDColor::RGB24(0xf5f5f5); - constexpr static KDColor Battery = KDColor::RGB24(0xffffff); - constexpr static KDColor BatteryInCharge = KDColor::RGB24(0x179e1f); - constexpr static KDColor BatteryLow = KDColor::RGB24(0x992321); - constexpr static KDColor ScrollBarForeground = KDColor::RGB24(0x4a4a4a); - constexpr static KDColor ScrollBarBackground = KDColor::RGB24(0xd9d9d9); - constexpr static KDColor Control = KDColor::RGB24(0x00857f); - constexpr static KDColor ControlEnabled = KDColor::RGB24(0x00b2b0); - constexpr static KDColor ControlDisabled = KDColor::RGB24(0x9e9e9e); - constexpr static KDColor CalculationBackgroundOdd = KDColor::RGB24(0xfafafa); - constexpr static KDColor CalculationBackgroundEven = KDColor::RGB24(0xffffff); - constexpr static KDColor CalculationEmptyBox = KDColor::RGB24(0xc4c4c4); - constexpr static KDColor CalculationEmptyBoxNeeded = KDColor::RGB24(0x00857f); - constexpr static KDColor CodeBackground = KDColor::RGB24(0xffffff); - constexpr static KDColor CodeBackgroundSelected = KDColor::RGB24(0xe0e0e0); - constexpr static KDColor CodeText = KDColor::RGB24(0x000000); - constexpr static KDColor CodeComment = KDColor::RGB24(0x999988); - constexpr static KDColor CodeNumber = KDColor::RGB24(0x009999); - constexpr static KDColor CodeKeyword = KDColor::RGB24(0xff000c); - constexpr static KDColor CodeOperator = KDColor::RGB24(0xd73a49); - constexpr static KDColor CodeString = KDColor::RGB24(0x032f62); - constexpr static KDColor ProbabilityCurve = KDColor::RGB24(0x00857f); - constexpr static KDColor ProbabilityCellBorder = KDColor::RGB24(0xececec); - constexpr static KDColor ProbabilityHistogramBar = KDColor::RGB24(0xd9d9d9); - constexpr static KDColor StatisticsBox = KDColor::RGB24(0x00857f); - constexpr static KDColor StatisticsBoxVerticalLine = KDColor::RGB24(0xd9d9d9); - constexpr static KDColor StatisticsSelected = KDColor::RGB24(0x00857f); - constexpr static KDColor StatisticsNotSelected = KDColor::RGB24(0xf5f5f5); - constexpr static KDColor GraphTangent = KDColor::RGB24(0x595959); - constexpr static KDColor SubMenuBackground = KDColor::RGB24(0xe0e0e0); - constexpr static KDColor SubMenuBorder = KDColor::RGB24(0xfafafa); - constexpr static KDColor SubMenuText = KDColor::RGB24(0x000000); - constexpr static KDColor ToolboxHeaderBackground = KDColor::RGB24(0x4a4a4a); - constexpr static KDColor ToolboxHeaderText = KDColor::RGB24(0xffffff); - constexpr static KDColor ToolboxHeaderBorder = KDColor::RGB24(0x4a4a4a); - constexpr static KDColor ToolboxBackground = KDColor::RGB24(0x000000); - constexpr static KDColor ListCellBackground = KDColor::RGB24(0xffffff); - constexpr static KDColor ListCellBackgroundSelected = KDColor::RGB24(0xe0e0e0); - constexpr static KDColor ListCellBorder = KDColor::RGB24(0xededef); - constexpr static KDColor ButtonBackground = KDColor::RGB24(0xe0e0e0); - constexpr static KDColor ButtonBackgroundSelected = KDColor::RGB24(0xd1d1d1); - constexpr static KDColor ButtonBackgroundSelectedHighContrast = KDColor::RGB24(0x00b2b0); - constexpr static KDColor ButtonBorder = KDColor::RGB24(0xadadad); - constexpr static KDColor ButtonRowBorder = KDColor::RGB24(0xd9d9d9); - constexpr static KDColor ButtonBorderOut = KDColor::RGB24(0xf5f5f5); - constexpr static KDColor ButtonShadow = KDColor::RGB24(0x003833); - constexpr static KDColor ButtonText = KDColor::RGB24(0x000000); - constexpr static KDColor TabBackground = KDColor::RGB24(0x4a4a4a); - constexpr static KDColor TabBackgroundSelected = KDColor::RGB24(0x757575); - constexpr static KDColor TabBackgroundActive = KDColor::RGB24(0xfafafa); - constexpr static KDColor TabBackgroundSelectedAndActive = KDColor::RGB24(0xe3e3e3); - constexpr static KDColor TabText = KDColor::RGB24(0xffffff); - constexpr static KDColor TabTextActive = KDColor::RGB24(0x000000); - constexpr static KDColor SubTabBackground = KDColor::RGB24(0xe0e0e0); - constexpr static KDColor SubTabBackgroundSelected = KDColor::RGB24(0xd1d1d1); - constexpr static KDColor SubTabText = KDColor::RGB24(0x000000); - constexpr static KDColor BannerFirstBackground = KDColor::RGB24(0x4a4a4a); - constexpr static KDColor BannerFirstBorder = KDColor::RGB24(0x4a4a4a); - constexpr static KDColor BannerFirstText = KDColor::RGB24(0xffffff); - constexpr static KDColor BannerFirstVariantBackground = KDColor::RGB24(0x4a4a4a); - constexpr static KDColor BannerFirstVariantBorder = KDColor::RGB24(0xfafafa); - constexpr static KDColor BannerFirstVariantText = KDColor::RGB24(0xffffff); - constexpr static KDColor BannerSecondBackground = KDColor::RGB24(0xe0e0e0); - constexpr static KDColor BannerSecondBorder = KDColor::RGB24(0xfafafa); - constexpr static KDColor BannerSecondText = KDColor::RGB24(0x000000); - constexpr static KDColor HomeBackground = KDColor::RGB24(0xffffff); - constexpr static KDColor HomeCellBackground = KDColor::RGB24(0xffffff); - constexpr static KDColor HomeCellBackgroundActive = KDColor::RGB24(0x4a4a4a); - constexpr static KDColor HomeCellText = KDColor::RGB24(0x000000); - constexpr static KDColor HomeCellTextActive = KDColor::RGB24(0xffffff); - constexpr static KDColor AtomUnknown = KDColor::RGB24(0xeeeeee); - constexpr static KDColor AtomText = KDColor::RGB24(0x000000); - constexpr static KDColor AtomAlkaliMetal = KDColor::RGB24(0xffaa00); - constexpr static KDColor AtomAlkaliEarthMetal = KDColor::RGB24(0xf6f200); - constexpr static KDColor AtomLanthanide = KDColor::RGB24(0xffaa8b); - constexpr static KDColor AtomActinide = KDColor::RGB24(0xdeaacd); - constexpr static KDColor AtomTransitionMetal = KDColor::RGB24(0xde999c); - constexpr static KDColor AtomPostTransitionMetal = KDColor::RGB24(0x9cbaac); - constexpr static KDColor AtomMetalloid = KDColor::RGB24(0x52ce8b); - constexpr static KDColor AtomHalogen = KDColor::RGB24(0x00debd); - constexpr static KDColor AtomReactiveNonmetal = KDColor::RGB24(0x00ee00); - constexpr static KDColor AtomNobleGas = KDColor::RGB24(0x8baaff); - constexpr static KDColor AtomTableLines = KDColor::RGB24(0x323532); - constexpr static KDColor YellowDark = KDColor::RGB24(0xffb734); - constexpr static KDColor YellowLight = KDColor::RGB24(0xffcc7b); - constexpr static KDColor PurpleBright = KDColor::RGB24(0x656975); - constexpr static KDColor PurpleDark = KDColor::RGB24(0x414147); - constexpr static KDColor GreyWhite = KDColor::RGB24(0xf5f5f5); - constexpr static KDColor GreyBright = KDColor::RGB24(0xececec); - constexpr static KDColor GreyMiddle = KDColor::RGB24(0xd9d9d9); - constexpr static KDColor GreyDark = KDColor::RGB24(0xa7a7a7); - constexpr static KDColor GreyVeryDark = KDColor::RGB24(0x8c8c8c); - constexpr static KDColor Select = KDColor::RGB24(0xd4d7e0); - constexpr static KDColor SelectDark = KDColor::RGB24(0xb0b8d8); - constexpr static KDColor WallScreen = KDColor::RGB24(0xf7f9fa); - constexpr static KDColor WallScreenDark = KDColor::RGB24(0xe0e6ed); - constexpr static KDColor SubTab = KDColor::RGB24(0xb8bbc5); - constexpr static KDColor LowBattery = KDColor::RGB24(0xf30211); - constexpr static KDColor Red = KDColor::RGB24(0xff000c); - constexpr static KDColor RedLight = KDColor::RGB24(0xfe6363); - constexpr static KDColor Magenta = KDColor::RGB24(0xff0588); - constexpr static KDColor Turquoise = KDColor::RGB24(0x60c1ec); - constexpr static KDColor Pink = KDColor::RGB24(0xffabb6); - constexpr static KDColor Blue = KDColor::RGB24(0x5075f2); - constexpr static KDColor BlueLight = KDColor::RGB24(0x718fee); - constexpr static KDColor Orange = KDColor::RGB24(0xfe871f); - constexpr static KDColor Green = KDColor::RGB24(0x50c102); - constexpr static KDColor GreenLight = KDColor::RGB24(0x52db8f); - constexpr static KDColor Brown = KDColor::RGB24(0x8d7350); - constexpr static KDColor Purple = KDColor::RGB24(0x6e2d79); - constexpr static KDColor DataColor[] = {Red, Blue, Green, YellowDark, Magenta, Turquoise, Pink, Orange}; - constexpr static KDColor DataColorLight[] = {RedLight, BlueLight, GreenLight, YellowLight}; - constexpr static KDColor AtomColor[] = { - AtomUnknown, AtomAlkaliMetal, AtomAlkaliEarthMetal, AtomLanthanide, AtomActinide, AtomTransitionMetal, - AtomPostTransitionMetal, AtomMetalloid, AtomHalogen, AtomReactiveNonmetal, AtomNobleGas - }; -}; - -#endif diff --git a/themes b/themes index 57312b33a..775ae1ceb 160000 --- a/themes +++ b/themes @@ -1 +1 @@ -Subproject commit 57312b33acc18d4a93210046c59940f8552ef533 +Subproject commit 775ae1cebdd9f2bdc4d6afc6a15418327490799a From d53676068b047afa50ec05993032f1756a71f335 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Sat, 21 Dec 2019 15:20:35 +0100 Subject: [PATCH 096/130] Added target run for simulator --- build/targets.simulator.mak | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/targets.simulator.mak b/build/targets.simulator.mak index 1d6573daf..d3732c05c 100644 --- a/build/targets.simulator.mak +++ b/build/targets.simulator.mak @@ -7,4 +7,8 @@ $(BUILD_DIR)/test.headless.$(EXE): $(call object_for,$(test_runner_headless_src) HANDY_TARGETS += epsilon.headless test.headless +run: $(BUILD_DIR)/epsilon.$(EXE) + @echo RUN + @$(Q) $(BUILD_DIR)/epsilon.$(EXE) -s + -include build/targets.simulator.$(TARGET).mak From c903e674d3d036b7fdb3c2806a61751732a4f874 Mon Sep 17 00:00:00 2001 From: redgl0w <43498612+RedGl0w@users.noreply.github.com> Date: Sun, 22 Dec 2019 11:14:56 +0100 Subject: [PATCH 097/130] Remove % Removed % and put again the remove glyph --- escher/src/text_area.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/escher/src/text_area.cpp b/escher/src/text_area.cpp index 0b61fa3cf..aec2f1621 100644 --- a/escher/src/text_area.cpp +++ b/escher/src/text_area.cpp @@ -112,8 +112,6 @@ bool TextArea::handleEvent(Ion::Events::Event event) { contentView()->moveCursorGeo(INT_MAX/2, 0); } else if (event == Ion::Events::Backspace) { return removePreviousGlyph(); - } else if (event.hasText()) { - return handleEventWithText(event.text()); } else if (event == Ion::Events::EXE) { return handleEventWithText("\n"); } else if (event == Ion::Events::Clear) { @@ -122,6 +120,10 @@ bool TextArea::handleEvent(Ion::Events::Event event) { } } else if (event == Ion::Events::Paste) { return handleEventWithText(Clipboard::sharedClipboard()->storedText()); + } else if (!(preferences->isPercentOnKeyboard()) && event == Ion::Events::Percent) { + return removePreviousGlyph(); + } else if (event.hasText()) { + return handleEventWithText(event.text()); } else { return false; } From eb28aabd75b53361475187ba5d464567a1d49b92 Mon Sep 17 00:00:00 2001 From: redgl0w Date: Sun, 22 Dec 2019 11:18:52 +0100 Subject: [PATCH 098/130] Removed experiment --- escher/src/text_area.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/escher/src/text_area.cpp b/escher/src/text_area.cpp index aec2f1621..b2060929a 100644 --- a/escher/src/text_area.cpp +++ b/escher/src/text_area.cpp @@ -120,7 +120,7 @@ bool TextArea::handleEvent(Ion::Events::Event event) { } } else if (event == Ion::Events::Paste) { return handleEventWithText(Clipboard::sharedClipboard()->storedText()); - } else if (!(preferences->isPercentOnKeyboard()) && event == Ion::Events::Percent) { + } else if (event == Ion::Events::Percent) { return removePreviousGlyph(); } else if (event.hasText()) { return handleEventWithText(event.text()); From 45d7aee71351d74da8181c2f7ff3075e0941f996 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Sun, 22 Dec 2019 14:01:34 +0100 Subject: [PATCH 099/130] [build] Icon theming! --- escher/Makefile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/escher/Makefile b/escher/Makefile index 6e6453e89..91c2147c0 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -102,13 +102,20 @@ $(eval $(call rule_for, \ $$(PYTHON) themes/themes_manager.py $(OMEGA_THEME) $$@ \ )) +$(eval $(call rule_for, \ + THEME, \ + %.png, \ + $(addprefix themes/themes/, $(addsuffix .json, $(OMEGA_THEME))), \ + $$(PYTHON) themes/themes_manager.py -i $(OMEGA_THEME) $$@ $(BUILD_DIR)/ \ +)) + INLINER := $(BUILD_DIR)/escher/image/inliner .PRECIOUS: $(BUILD_DIR)/%.h $(BUILD_DIR)/%.cpp $(eval $(call rule_for, \ INLINER, \ %.h %.cpp, \ - %.png $$(INLINER), \ + $$(addprefix $$(BUILD_DIR)/,%.png) $$(INLINER), \ $$(INLINER) $$< $$(basename $$@).h $$(basename $$@).cpp \ )) From 53c7dfee8a20707d22c4a084d222b1e4d70b85a3 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Sun, 22 Dec 2019 17:13:28 +0100 Subject: [PATCH 100/130] [build] added print-*, made it work --- Makefile | 5 +++++ apps/Makefile | 12 ++++++++++++ escher/Makefile | 10 ++-------- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 6976f63d3..0a3541650 100644 --- a/Makefile +++ b/Makefile @@ -68,6 +68,11 @@ help: @echo " make PLATFORM=simulator TARGET=web" @echo " make PLATFORM=simulator TARGET=windows" +.PHONY: print-% +print-%: + @echo $* = $($*) + @echo $*\'s origin is $(origin $*) + # Since we're building out-of-tree, we need to make sure the output directories # are created, otherwise the receipes will fail (e.g. gcc will fail to create # "output/foo/bar.o" because the directory "output/foo" doesn't exist). diff --git a/apps/Makefile b/apps/Makefile index 43cf2c95a..7fc4cd594 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -79,6 +79,8 @@ $(eval $(call rule_for, \ $$(PYTHON) apps/i18n.py --header $$(subst .cpp,.h,$$@) --implementation $$@ --locales $$(EPSILON_I18N) --files $$^ \ )) + + $(BUILD_DIR)/apps/i18n.h: $(BUILD_DIR)/apps/i18n.cpp # Handle PNG files @@ -92,6 +94,16 @@ $(call object_for,$(all_app_src)): $(BUILD_DIR)/python/port/genhdr/qstrdefs.gene apps_tests_src = $(app_calculation_test_src) $(app_probability_test_src) $(app_regression_test_src) $(app_sequence_test_src) $(app_shared_test_src) $(app_statistics_test_src) $(app_solver_test_src) + + +$(foreach img,$(image_list), $(eval $(call rule_for, \ + ICON, \ + $(img), \ + $(addprefix themes/themes/, $(addsuffix .json, $(OMEGA_THEME))), \ + $$(PYTHON) themes/themes_manager.py -i $(OMEGA_THEME) $$@ $(BUILD_DIR)/ \ +))) + + # Configure variants apps_all_src = $(app_src) apps_all_src += $(apps_launch_default_src) $(apps_launch_on_boarding_src diff --git a/escher/Makefile b/escher/Makefile index 91c2147c0..6263321ba 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -102,20 +102,13 @@ $(eval $(call rule_for, \ $$(PYTHON) themes/themes_manager.py $(OMEGA_THEME) $$@ \ )) -$(eval $(call rule_for, \ - THEME, \ - %.png, \ - $(addprefix themes/themes/, $(addsuffix .json, $(OMEGA_THEME))), \ - $$(PYTHON) themes/themes_manager.py -i $(OMEGA_THEME) $$@ $(BUILD_DIR)/ \ -)) - INLINER := $(BUILD_DIR)/escher/image/inliner .PRECIOUS: $(BUILD_DIR)/%.h $(BUILD_DIR)/%.cpp $(eval $(call rule_for, \ INLINER, \ %.h %.cpp, \ - $$(addprefix $$(BUILD_DIR)/,%.png) $$(INLINER), \ + $(BUILD_DIR)/%.png $$(INLINER), \ $$(INLINER) $$< $$(basename $$@).h $$(basename $$@).cpp \ )) @@ -129,4 +122,5 @@ define depends_on_image $(call object_for,$(1)): $(call object_for,$(2)) $(call object_for,$(1)): SFLAGS += $(foreach d,$(sort $(dir $(call object_for,$(1)))),-I$(d)) escher_src += $(2) +image_list += $(2) endef From c2f86e080629261e4a4710c9c7b7b6aca56bc85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Dec 2019 10:58:50 +0100 Subject: [PATCH 101/130] [poincare] Add tests on lcm and gcd approximations --- poincare/test/approximation.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/poincare/test/approximation.cpp b/poincare/test/approximation.cpp index bf8ff4a3e..d6573c8d7 100644 --- a/poincare/test/approximation.cpp +++ b/poincare/test/approximation.cpp @@ -269,12 +269,18 @@ QUIZ_CASE(poincare_approximation_function) { assert_expression_approximates_to("gcd(234,394)", "2"); assert_expression_approximates_to("gcd(234,394)", "2"); + assert_expression_approximates_to("gcd(-234,394)", "2"); + assert_expression_approximates_to("gcd(234,-394)", "2"); + assert_expression_approximates_to("gcd(-234,-394)", "2"); assert_expression_approximates_to("im(2+3𝐢)", "3"); assert_expression_approximates_to("im(2+3𝐢)", "3"); assert_expression_approximates_to("lcm(234,394)", "46098"); assert_expression_approximates_to("lcm(234,394)", "46098"); + assert_expression_approximates_to("lcm(-234,394)", "46098"); + assert_expression_approximates_to("lcm(234,-394)", "46098"); + assert_expression_approximates_to("lcm(-234,-394)", "46098"); assert_expression_approximates_to("int(x,x, 1, 2)", "1.5"); assert_expression_approximates_to("int(x,x, 1, 2)", "1.5"); From 07ecc119ab9da5a8afa9b97d75f40a7761976988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 13 Dec 2019 10:59:20 +0100 Subject: [PATCH 102/130] [poincare] Fix gcd and lcm approximations --- .../include/poincare/approximation_helper.h | 1 + poincare/src/approximation_helper.cpp | 14 +++++++++++++ poincare/src/great_common_divisor.cpp | 19 ++++++++--------- poincare/src/least_common_multiple.cpp | 21 +++++++++---------- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/poincare/include/poincare/approximation_helper.h b/poincare/include/poincare/approximation_helper.h index b079d6a62..6634e7646 100644 --- a/poincare/include/poincare/approximation_helper.h +++ b/poincare/include/poincare/approximation_helper.h @@ -9,6 +9,7 @@ namespace Poincare { namespace ApproximationHelper { + template int IntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); template std::complex TruncateRealOrImaginaryPartAccordingToArgument(std::complex c); template using ComplexCompute = Complex(*)(const std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); diff --git a/poincare/src/approximation_helper.cpp b/poincare/src/approximation_helper.cpp index 2d7eafc39..2cc0b81a5 100644 --- a/poincare/src/approximation_helper.cpp +++ b/poincare/src/approximation_helper.cpp @@ -15,6 +15,18 @@ template T absMod(T a, T b) { return result > b/2 ? b-result : result; } +static inline int absInt(int x) { return x < 0 ? -x : x; } + +template int ApproximationHelper::IntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { + Evaluation evaluation = expression->approximate(T(), context, complexFormat, angleUnit); + T scalar = evaluation.toScalar(); + if (std::isnan(scalar) || scalar != (int)scalar) { + *isUndefined = true; + return 0; + } + return absInt((int)scalar); +} + template std::complex ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex c) { T arg = std::arg(c); T precision = 10*Expression::Epsilon(); @@ -92,6 +104,8 @@ template MatrixComplex ApproximationHelper::ElementWiseOnComplexM return matrix; } +template int Poincare::ApproximationHelper::IntegerApproximationIfPossible(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); +template int Poincare::ApproximationHelper::IntegerApproximationIfPossible(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); template std::complex Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex); template std::complex Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex); template Poincare::Evaluation Poincare::ApproximationHelper::Map(const Poincare::ExpressionNode * expression, Poincare::Context * context, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexCompute compute); diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 51afde0c1..a66d3525e 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -27,22 +28,20 @@ Expression GreatCommonDivisorNode::shallowReduce(ReductionContext reductionConte template Evaluation GreatCommonDivisorNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - Evaluation f1Input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); - Evaluation f2Input = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); - T f1 = f1Input.toScalar(); - T f2 = f2Input.toScalar(); - if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { + bool isUndefined = false; + int a = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit); + int b = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit); + if (isUndefined) { return Complex::Undefined(); } - int a = (int)f2; - int b = (int)f1; - if (f1 > f2) { + if (b > a) { + int temp = b; b = a; - a = (int)f1; + a = temp; } int r = 0; while((int)b!=0){ - r = a - ((int)(a/b))*b; + r = a - (a/b)*b; a = b; b = r; } diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index c94547809..c6a104fed 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -27,26 +28,24 @@ Expression LeastCommonMultipleNode::shallowReduce(ReductionContext reductionCont template Evaluation LeastCommonMultipleNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { - Evaluation f1Input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit); - Evaluation f2Input = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit); - T f1 = f1Input.toScalar(); - T f2 = f2Input.toScalar(); - if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { + bool isUndefined = false; + int a = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit); + int b = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit); + if (isUndefined) { return Complex::Undefined(); } - if (f1 == 0.0f || f2 == 0.0f) { + if (a == 0 || b == 0) { return Complex::Builder(0.0); } - int a = (int)f2; - int b = (int)f1; - if (f1 > f2) { + if (b > a) { + int temp = b; b = a; - a = (int)f1; + a = temp; } int product = a*b; int r = 0; while((int)b!=0){ - r = a - ((int)(a/b))*b; + r = a - (a/b)*b; a = b; b = r; } From 934e2c8aeb5626f74cecb97ab386edd1f6496c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Fri, 20 Dec 2019 11:30:22 +0100 Subject: [PATCH 103/130] [poincare] Change name IntegerApproximationIfPossible --> PositiveIntegerApproximationIfPossible --- poincare/include/poincare/approximation_helper.h | 2 +- poincare/src/approximation_helper.cpp | 6 +++--- poincare/src/great_common_divisor.cpp | 4 ++-- poincare/src/least_common_multiple.cpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/poincare/include/poincare/approximation_helper.h b/poincare/include/poincare/approximation_helper.h index 6634e7646..169143faf 100644 --- a/poincare/include/poincare/approximation_helper.h +++ b/poincare/include/poincare/approximation_helper.h @@ -9,7 +9,7 @@ namespace Poincare { namespace ApproximationHelper { - template int IntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); + template int PositiveIntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); template std::complex TruncateRealOrImaginaryPartAccordingToArgument(std::complex c); template using ComplexCompute = Complex(*)(const std::complex, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit); diff --git a/poincare/src/approximation_helper.cpp b/poincare/src/approximation_helper.cpp index 2cc0b81a5..32f1f88ad 100644 --- a/poincare/src/approximation_helper.cpp +++ b/poincare/src/approximation_helper.cpp @@ -17,7 +17,7 @@ template T absMod(T a, T b) { static inline int absInt(int x) { return x < 0 ? -x : x; } -template int ApproximationHelper::IntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { +template int ApproximationHelper::PositiveIntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) { Evaluation evaluation = expression->approximate(T(), context, complexFormat, angleUnit); T scalar = evaluation.toScalar(); if (std::isnan(scalar) || scalar != (int)scalar) { @@ -104,8 +104,8 @@ template MatrixComplex ApproximationHelper::ElementWiseOnComplexM return matrix; } -template int Poincare::ApproximationHelper::IntegerApproximationIfPossible(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); -template int Poincare::ApproximationHelper::IntegerApproximationIfPossible(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); +template int Poincare::ApproximationHelper::PositiveIntegerApproximationIfPossible(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); +template int Poincare::ApproximationHelper::PositiveIntegerApproximationIfPossible(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit); template std::complex Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex); template std::complex Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex); template Poincare::Evaluation Poincare::ApproximationHelper::Map(const Poincare::ExpressionNode * expression, Poincare::Context * context, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexCompute compute); diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index a66d3525e..d9e9faec0 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -29,8 +29,8 @@ Expression GreatCommonDivisorNode::shallowReduce(ReductionContext reductionConte template Evaluation GreatCommonDivisorNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { bool isUndefined = false; - int a = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit); - int b = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit); + int a = ApproximationHelper::PositiveIntegerApproximationIfPossible(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit); + int b = ApproximationHelper::PositiveIntegerApproximationIfPossible(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit); if (isUndefined) { return Complex::Undefined(); } diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index c6a104fed..cb356e338 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -29,8 +29,8 @@ Expression LeastCommonMultipleNode::shallowReduce(ReductionContext reductionCont template Evaluation LeastCommonMultipleNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { bool isUndefined = false; - int a = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit); - int b = ApproximationHelper::IntegerApproximationIfPossible(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit); + int a = ApproximationHelper::PositiveIntegerApproximationIfPossible(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit); + int b = ApproximationHelper::PositiveIntegerApproximationIfPossible(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit); if (isUndefined) { return Complex::Undefined(); } From 7b7447b1107dee52d0be0d6ad0705c57a67c9126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 18 Dec 2019 11:47:05 +0100 Subject: [PATCH 104/130] [ion] N0110 cache: clean isb/dsb calls --- ion/src/device/n0110/drivers/cache.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ion/src/device/n0110/drivers/cache.cpp b/ion/src/device/n0110/drivers/cache.cpp index 87b1a36f2..0d16f5261 100644 --- a/ion/src/device/n0110/drivers/cache.cpp +++ b/ion/src/device/n0110/drivers/cache.cpp @@ -65,7 +65,7 @@ void cleanDCache() { void enableDCache() { invalidateDCache(); - CORTEX.CCR()->setDC(true); + CORTEX.CCR()->setDC(true); // Enable D-cache dsb(); isb(); } @@ -77,14 +77,14 @@ void disableDCache() { void invalidateICache() { dsb(); isb(); - CORTEX.ICIALLU()->set(0); + CORTEX.ICIALLU()->set(0); // Invalidate I-cache dsb(); isb(); } void enableICache() { invalidateICache(); - CORTEX.CCR()->setIC(true); + CORTEX.CCR()->setIC(true); // Enable I-cache dsb(); isb(); } @@ -92,8 +92,10 @@ void enableICache() { void disableICache() { dsb(); isb(); - CORTEX.CCR()->setIC(false); - invalidateICache(); + CORTEX.CCR()->setIC(false); // Disable I-cache + CORTEX.ICIALLU()->set(0); // Invalidate I-cache + dsb(); + isb(); } From 9fca8e8b8b8a9fe45e7fa1b9f4c51e2867d089ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 18 Dec 2019 11:47:30 +0100 Subject: [PATCH 105/130] [ion] Reset: factorize cache disabling --- ion/src/device/shared/drivers/reset.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ion/src/device/shared/drivers/reset.cpp b/ion/src/device/shared/drivers/reset.cpp index d69b2e102..21f93eed1 100644 --- a/ion/src/device/shared/drivers/reset.cpp +++ b/ion/src/device/shared/drivers/reset.cpp @@ -41,8 +41,7 @@ void __attribute__((noinline)) internalFlashJump(uint32_t jumpIsrVectorAddress) void jump(uint32_t jumpIsrVectorAddress) { // Disable cache before reset - Ion::Device::Cache::disableDCache(); - Ion::Device::Cache::disableICache(); + Ion::Device::Cache::disable(); /* Shutdown all clocks and periherals to mimic a hardware reset. */ Board::shutdownPeripherals(); From 588c05f6b4fb9d3ae7eff8ea592b6a381437f7d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 18 Dec 2019 11:48:00 +0100 Subject: [PATCH 106/130] [ion] Reset: Add memory barriers before/after calling for a core reset: --- ion/src/device/shared/drivers/reset.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ion/src/device/shared/drivers/reset.cpp b/ion/src/device/shared/drivers/reset.cpp index 21f93eed1..ef6053570 100644 --- a/ion/src/device/shared/drivers/reset.cpp +++ b/ion/src/device/shared/drivers/reset.cpp @@ -12,7 +12,13 @@ using namespace Regs; void core() { // Perform a full core reset + Ion::Device::Cache::dsb(); // Complete all memory accesses CORTEX.AIRCR()->requestReset(); + Ion::Device::Cache::dsb(); + // Wait until reset + while (true) { + asm("nop"); + } } /* We isolate the jump code that needs to be executed from the internal From 004551d6b75c9b76c884758901f62c23437d0d69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Tue, 24 Dec 2019 01:20:28 +0100 Subject: [PATCH 107/130] [EXPERIMENTAL] Upstream merged with Omega --- apps/calculation/calculation_store.cpp | 2 +- apps/settings/main_controller_prompt_beta.cpp | 2 +- apps/settings/main_controller_prompt_none.cpp | 2 +- apps/settings/main_controller_prompt_update.cpp | 2 +- apps/settings/sub_menu/exam_mode_controller.cpp | 14 +++++++------- apps/settings/sub_menu/exam_mode_controller.h | 3 --- apps/title_bar_view.cpp | 2 +- 7 files changed, 12 insertions(+), 15 deletions(-) diff --git a/apps/calculation/calculation_store.cpp b/apps/calculation/calculation_store.cpp index b493ccf91..c8f1b25ef 100644 --- a/apps/calculation/calculation_store.cpp +++ b/apps/calculation/calculation_store.cpp @@ -92,7 +92,7 @@ ExpiringPointer CalculationStore::push(const char * text, Context * // Compute and serialize the outputs { Expression outputs[] = {Expression(), Expression()}; - PoincareHelpers::ParseAndSimplifyAndApproximate(inputSerialization, &(outputs[0]), &(outputs[1]), context, GlobalPreferences::sharedGlobalPreferences()->examMode() ? Preferences::sharedPreferences()->isExamSymbolic() : true); // Symbolic computation + PoincareHelpers::ParseAndSimplifyAndApproximate(inputSerialization, &(outputs[0]), &(outputs[1]), context, GlobalPreferences::sharedGlobalPreferences()->isInExamMode() ? Preferences::sharedPreferences()->isExamSymbolic() : true); // Symbolic computation for (int i = 0; i < 2; i++) { if (!serializeExpression(outputs[i], nextSerializationLocation, &newCalculationsLocation)) { /* If the exat/approximate output does not fit in the store (event if the diff --git a/apps/settings/main_controller_prompt_beta.cpp b/apps/settings/main_controller_prompt_beta.cpp index 57c4ed980..d3528fafa 100644 --- a/apps/settings/main_controller_prompt_beta.cpp +++ b/apps/settings/main_controller_prompt_beta.cpp @@ -14,7 +14,7 @@ constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::M //sub-menus constexpr SettingsMessageTree s_modelMathOptionsChildren[5] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren, 4)}; -constexpr SettingsMessageTree s_modelExamChildren[3] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[4] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; #ifdef USERNAME constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 5)}; diff --git a/apps/settings/main_controller_prompt_none.cpp b/apps/settings/main_controller_prompt_none.cpp index 3289d680f..f9f4c2431 100644 --- a/apps/settings/main_controller_prompt_none.cpp +++ b/apps/settings/main_controller_prompt_none.cpp @@ -15,7 +15,7 @@ constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::M //sub-menus constexpr SettingsMessageTree s_modelMathOptionsChildren[5] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren, 4)}; -constexpr SettingsMessageTree s_modelExamChildren[3] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[4] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; #ifdef USERNAME constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 5)}; diff --git a/apps/settings/main_controller_prompt_update.cpp b/apps/settings/main_controller_prompt_update.cpp index 784dcd4cc..a929483b2 100644 --- a/apps/settings/main_controller_prompt_update.cpp +++ b/apps/settings/main_controller_prompt_update.cpp @@ -14,7 +14,7 @@ constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::M //sub-menus constexpr SettingsMessageTree s_modelMathOptionsChildren[5] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren, 4)}; -constexpr SettingsMessageTree s_modelExamChildren[3] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[4] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; #ifdef USERNAME constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 5)}; diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index 1d6e98a9a..e05056066 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -17,8 +17,8 @@ ExamModeController::ExamModeController(Responder * parentResponder) : m_preferencesController(this), m_examModeCell(I18n::Message::Default, KDFont::LargeFont), m_ledCell(KDFont::LargeFont, KDFont::SmallFont), - m_symbolicCell(I18n::Message::SymbolicEnabled, KDFont::LargeFont) - m_cell{MessageTableCell(I18n::Message::ExamModeActive, KDFont::LargeFont), MessageTableCell(I18n::Message::ActivateDutchExamMode, KDFont::LargeFont)} + m_symbolicCell(I18n::Message::SymbolicEnabled, KDFont::LargeFont), + m_cell{ MessageTableCell(I18n::Message::ExamModeActive, KDFont::LargeFont), MessageTableCell(I18n::Message::ActivateDutchExamMode, KDFont::LargeFont) } { } @@ -37,18 +37,18 @@ bool ExamModeController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) { if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { // If the exam mode is already on, this re-activate the same exam mode - mode = GlobalPreferences::sharedGlobalPreferences()->examMode(); + GlobalPreferences::ExamMode mode = GlobalPreferences::sharedGlobalPreferences()->examMode(); if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive) - AppsContainer::sharedAppsContainer()->displayExamModePopUp(true); + AppsContainer::sharedAppsContainer()->displayExamModePopUp(mode); return true; } else if (childLabel == I18n::Message::ActivateDutchExamMode) { - mode = GlobalPreferences::ExamMode::Dutch + GlobalPreferences::ExamMode mode = GlobalPreferences::ExamMode::Dutch; if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive) - AppsContainer::sharedAppsContainer()->displayExamModePopUp(true); + AppsContainer::sharedAppsContainer()->displayExamModePopUp(mode); return true; } if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive) { - AppsContainer::sharedAppsContainer()->displayExamModePopUp(true); + AppsContainer::sharedAppsContainer()->displayExamModePopUp(GlobalPreferences::sharedGlobalPreferences()->examMode()); return true; } if (childLabel == I18n::Message::LEDColor) { diff --git a/apps/settings/sub_menu/exam_mode_controller.h b/apps/settings/sub_menu/exam_mode_controller.h index 3177bf437..149799207 100644 --- a/apps/settings/sub_menu/exam_mode_controller.h +++ b/apps/settings/sub_menu/exam_mode_controller.h @@ -16,16 +16,13 @@ public: void willDisplayCellForIndex(HighlightCell * cell, int index) override; int typeAtLocation(int i, int j) override; private: -<<<<<<< HEAD MessageTableCell m_examModeCell; MessageTableCellWithChevronAndMessage m_ledCell; PreferencesController m_preferencesController; MessageTableCellWithSwitch m_symbolicCell; -======= int initialSelectedRow() const override; static constexpr int k_maxNumberOfCells = 2; MessageTableCell m_cell[k_maxNumberOfCells]; ->>>>>>> upstream/master }; } diff --git a/apps/title_bar_view.cpp b/apps/title_bar_view.cpp index 6c71ea337..f37e4f4ba 100644 --- a/apps/title_bar_view.cpp +++ b/apps/title_bar_view.cpp @@ -85,7 +85,7 @@ void TitleBarView::refreshPreferences() { char buffer[bufferSize]; int numberOfChar = 0; Preferences * preferences = Preferences::sharedPreferences(); - if (GlobalPreferences::sharedGlobalPreferences()->examMode() && Preferences::sharedPreferences()->isExamSymbolic()) { + if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode() && Preferences::sharedPreferences()->isExamSymbolic()) { // Display "cas" if in exam mode with symbolic computation enabled numberOfChar += strlcpy(buffer+numberOfChar, I18n::translate(I18n::Message::Sym), bufferSize - numberOfChar); assert(numberOfChar < bufferSize-1); From a680bb5aa2f6a1d1f7010340c1e7436ab7408942 Mon Sep 17 00:00:00 2001 From: redgl0w <43498612+RedGl0w@users.noreply.github.com> Date: Tue, 24 Dec 2019 09:19:12 +0100 Subject: [PATCH 108/130] Update layout_field.cpp --- escher/src/layout_field.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/escher/src/layout_field.cpp b/escher/src/layout_field.cpp index 9d04cef04..df0c1a3f8 100644 --- a/escher/src/layout_field.cpp +++ b/escher/src/layout_field.cpp @@ -234,7 +234,11 @@ bool LayoutField::privateHandleEvent(Ion::Events::Event event) { setEditing(true); } if (event.hasText()) { - handleEventWithText(event.text()); + if(event.text() == "%" && Ion::Events::isLockActive() ){ + m_contentView.cursor()->performBackspace(); + } else { + handleEventWithText(event.text()); + } } else if (event == Ion::Events::Paste) { handleEventWithText(Clipboard::sharedClipboard()->storedText(), false, true); } else { From bb83ec9b762f8f9ed80f4b53c69ca0f00dee9894 Mon Sep 17 00:00:00 2001 From: redgl0w <43498612+RedGl0w@users.noreply.github.com> Date: Tue, 24 Dec 2019 09:20:33 +0100 Subject: [PATCH 109/130] Update text_area.cpp --- escher/src/text_area.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/escher/src/text_area.cpp b/escher/src/text_area.cpp index b2060929a..10dfe6c91 100644 --- a/escher/src/text_area.cpp +++ b/escher/src/text_area.cpp @@ -123,7 +123,11 @@ bool TextArea::handleEvent(Ion::Events::Event event) { } else if (event == Ion::Events::Percent) { return removePreviousGlyph(); } else if (event.hasText()) { - return handleEventWithText(event.text()); + if(event.text() == "%" && Ion::Events::isLockActive()){ + return removePreviousGlyph(); + } else { + return handleEventWithText(event.text()); + } } else { return false; } From f838d31ec1c1519cd8678605c68a78cd410fe022 Mon Sep 17 00:00:00 2001 From: redgl0w <43498612+RedGl0w@users.noreply.github.com> Date: Tue, 24 Dec 2019 09:21:14 +0100 Subject: [PATCH 110/130] Update events_modifier.cpp --- ion/src/shared/events_modifier.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ion/src/shared/events_modifier.cpp b/ion/src/shared/events_modifier.cpp index 959350c8b..ddfdb4c10 100644 --- a/ion/src/shared/events_modifier.cpp +++ b/ion/src/shared/events_modifier.cpp @@ -18,6 +18,10 @@ bool isAlphaActive() { return sShiftAlphaStatus == ShiftAlphaStatus::Alpha || sShiftAlphaStatus == ShiftAlphaStatus::ShiftAlpha || sShiftAlphaStatus == ShiftAlphaStatus::AlphaLock || sShiftAlphaStatus == ShiftAlphaStatus::ShiftAlphaLock; ; } + +bool isLockActive() { + return sShiftAlphaStatus == ShiftAlphaStatus::AlphaLock || sShiftAlphaStatus == ShiftAlphaStatus::ShiftAlphaLock; +} void setShiftAlphaStatus(ShiftAlphaStatus s) { sShiftAlphaStatus = s; From 3e91ba0f80895afa5ba19f32f4eafdcc0fdf6703 Mon Sep 17 00:00:00 2001 From: redgl0w <43498612+RedGl0w@users.noreply.github.com> Date: Tue, 24 Dec 2019 09:22:27 +0100 Subject: [PATCH 111/130] Update layout_events.h --- .../ion/keyboard/layout_B2/layout_events.h | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ion/include/ion/keyboard/layout_B2/layout_events.h b/ion/include/ion/keyboard/layout_B2/layout_events.h index a0d877cd5..7282f289c 100644 --- a/ion/include/ion/keyboard/layout_B2/layout_events.h +++ b/ion/include/ion/keyboard/layout_B2/layout_events.h @@ -25,10 +25,10 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + T("17"), T("18"), T("19"), T("20"), T("21"), U(), + T("14"), T("15"), T("16"), T("factor(\x11)"), T("%"), U(), + T("11"), T("12"), T("13"), T("normal(\x11)"), T("\\"), U(), + T("10"), T("11"), T("12"), T("20"), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), @@ -38,17 +38,17 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { T("m"), T("n"), T("o"), T("p"), T("q"), U(), T("r"), T("s"), T("t"), T("u"), T("v"), U(), T("w"), T("x"), T("y"), T("z"), T(" "), U(), - T("?"), T("!"), U(), U(), U(), U(), + T("?"), T("!"), U(), TL(), U(), U(), // Shift+Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), U(), T("'"), T("%"), T("A"), T("B"), T("C"), T("D"), T("E"), T("F"), T("G"), T("H"), T("I"), T("J"), T("K"), T("L"), T("M"), T("N"), T("O"), T("P"), T("Q"), U(), T("R"), T("S"), T("T"), T("U"), T("V"), U(), T("W"), T("X"), T("Y"), T("Z"), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), TL(), U(), U(), }; #if DEBUG @@ -70,9 +70,9 @@ static constexpr const char * s_nameForEvent[255] = { nullptr, "AlphaLock", "Cut", "Copy", "Paste", "Clear", "LeftBracket", "RightBracket", "LeftBrace", "RightBrace", "Underscore", "Sto", "Arcsine", "Arccosine", "Arctangent", "Equal", "Lower", "Greater", + nullptr, nullptr, nullptr, nullptr, "DoubleParenthesis", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, "BrightnessPlus", "BrightnessMinus", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //Alpha, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, @@ -87,7 +87,7 @@ static constexpr const char * s_nameForEvent[255] = { //Shift+Alpha, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, "Percent", "UpperA", "UpperB", "UpperC", "UpperD", "UpperE", "UpperF", "UpperG", "UpperH", "UpperI", "UpperJ", "UpperK", "UpperL", "UpperM", "UpperN", "UpperO", "UpperP", "UpperQ", nullptr, From 39241210088c4fdcd6ae13308a51edb66163e091 Mon Sep 17 00:00:00 2001 From: redgl0w <43498612+RedGl0w@users.noreply.github.com> Date: Tue, 24 Dec 2019 09:22:57 +0100 Subject: [PATCH 112/130] Update layout_events.h --- ion/include/ion/keyboard/layout_B3/layout_events.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ion/include/ion/keyboard/layout_B3/layout_events.h b/ion/include/ion/keyboard/layout_B3/layout_events.h index 1783ff7a3..f7072bd60 100644 --- a/ion/include/ion/keyboard/layout_B3/layout_events.h +++ b/ion/include/ion/keyboard/layout_B3/layout_events.h @@ -25,10 +25,10 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + T("17"), T("18"), T("19"), T("20"), T("21"), U(), + T("14"), T("15"), T("16"), T("factor(\x11)"), T("%"), U(), + T("11"), T("12"), T("13"), T("normal(\x11)"), T("\\"), U(), + T("10"), T("11"), T("12"), T("20"), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), @@ -42,7 +42,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { // Shift+Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), U(), T("'"), T("%"), T("A"), T("B"), T("C"), T("D"), T("E"), T("F"), T("G"), T("H"), T("I"), T("J"), T("K"), T("L"), T("M"), T("N"), T("O"), T("P"), T("Q"), U(), @@ -72,7 +72,7 @@ static constexpr const char * s_nameForEvent[255] = { "Arcsine", "Arccosine", "Arctangent", "Equal", "Lower", "Greater", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, "BrightnessPlus", "BrightnessMinus", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, //Alpha, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, @@ -87,7 +87,7 @@ static constexpr const char * s_nameForEvent[255] = { //Shift+Alpha, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, "Percent", "UpperA", "UpperB", "UpperC", "UpperD", "UpperE", "UpperF", "UpperG", "UpperH", "UpperI", "UpperJ", "UpperK", "UpperL", "UpperM", "UpperN", "UpperO", "UpperP", "UpperQ", nullptr, From 9a813b8dfbf44ada6b0c007a9850c8b2d82eee03 Mon Sep 17 00:00:00 2001 From: redgl0w <43498612+RedGl0w@users.noreply.github.com> Date: Tue, 24 Dec 2019 09:23:28 +0100 Subject: [PATCH 113/130] Update events.h --- ion/include/ion/events.h | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/ion/include/ion/events.h b/ion/include/ion/events.h index 1ce72c76d..1caffaeb7 100644 --- a/ion/include/ion/events.h +++ b/ion/include/ion/events.h @@ -55,6 +55,7 @@ ShiftAlphaStatus shiftAlphaStatus(); void setShiftAlphaStatus(ShiftAlphaStatus s); bool isShiftActive(); bool isAlphaActive(); +bool isLockActive(); void updateModifiersFromEvent(Event e); // Plain @@ -138,6 +139,30 @@ constexpr Event Arctangent = Event::ShiftKey(Keyboard::Key::Tangent); constexpr Event Equal = Event::ShiftKey(Keyboard::Key::Pi); constexpr Event Lower = Event::ShiftKey(Keyboard::Key::Sqrt); constexpr Event Greater = Event::ShiftKey(Keyboard::Key::Square); +constexpr Event shiftans = Event::ShiftKey(Keyboard::Key::Ans); +constexpr Event shiftplus = Event::ShiftKey(Keyboard::Key::Plus); +constexpr Event shiftfois = Event::ShiftKey(Keyboard::Key::Multiplication); +constexpr Event shiftdiv = Event::ShiftKey(Keyboard::Key::Division); +constexpr Event shiftminus = Event::ShiftKey(Keyboard::Key::Minus); +constexpr Event shift1 = Event::ShiftKey(Keyboard::Key::One); +constexpr Event shift2 = Event::ShiftKey(Keyboard::Key::Two); +constexpr Event shift3 = Event::ShiftKey(Keyboard::Key::Three); +constexpr Event shift4 = Event::ShiftKey(Keyboard::Key::Four); +constexpr Event shift5 = Event::ShiftKey(Keyboard::Key::Five); +constexpr Event shift6 = Event::ShiftKey(Keyboard::Key::Six); +constexpr Event shift7 = Event::ShiftKey(Keyboard::Key::Seven); +constexpr Event shift8 = Event::ShiftKey(Keyboard::Key::Eight); +constexpr Event shift9 = Event::ShiftKey(Keyboard::Key::Nine); +constexpr Event shift0 = Event::ShiftKey(Keyboard::Key::Zero); +constexpr Event shiftdot = Event::ShiftKey(Keyboard::Key::Dot); +constexpr Event shiftee = Event::ShiftKey(Keyboard::Key::EE); +constexpr Event shiftlp = Event::ShiftKey(Keyboard::Key::LeftParenthesis); +constexpr Event shiftrp = Event::ShiftKey(Keyboard::Key::RightParenthesis); + +constexpr Event BrightnessPlus = Event::ShiftKey(Keyboard::Key::Plus); +constexpr Event BrightnessMinus = Event::ShiftKey(Keyboard::Key::Minus); + +constexpr Event DoubleParenthesis = Event::ShiftKey(Keyboard::Key::LeftParenthesis); constexpr Event ShiftSeven = Event::ShiftKey(Keyboard::Key::Seven); constexpr Event ShiftEight = Event::ShiftKey(Keyboard::Key::Eight); @@ -156,7 +181,7 @@ constexpr Event ShiftThree = Event::ShiftKey(Keyboard::Key::Three); constexpr Event Colon = Event::AlphaKey(Keyboard::Key::XNT); constexpr Event SemiColon = Event::AlphaKey(Keyboard::Key::Var); constexpr Event DoubleQuotes = Event::AlphaKey(Keyboard::Key::Toolbox); -constexpr Event Percent = Event::AlphaKey(Keyboard::Key::Backspace); +constexpr Event Percent = Event::AlphaKey(Keyboard::Key::Back); constexpr Event LowerA = Event::AlphaKey(Keyboard::Key::Exp); constexpr Event LowerB = Event::AlphaKey(Keyboard::Key::Ln); @@ -192,8 +217,10 @@ constexpr Event Space = Event::AlphaKey(Keyboard::Key::Minus); constexpr Event Question = Event::AlphaKey(Keyboard::Key::Zero); constexpr Event Exclamation = Event::AlphaKey(Keyboard::Key::Dot); +constexpr Event alphaans = Event::AlphaKey(Keyboard::Key::Ans); // Shift + Alpha +constexpr Event SimpleQuote = Event::ShiftAlphaKey(Keyboard::Key::Toolbox); constexpr Event UpperA = Event::ShiftAlphaKey(Keyboard::Key::Exp); constexpr Event UpperB = Event::ShiftAlphaKey(Keyboard::Key::Ln); @@ -226,6 +253,7 @@ constexpr Event UpperX = Event::ShiftAlphaKey(Keyboard::Key::Two); constexpr Event UpperY = Event::ShiftAlphaKey(Keyboard::Key::Three); constexpr Event UpperZ = Event::ShiftAlphaKey(Keyboard::Key::Plus); +constexpr Event shiftalphaans = Event::ShiftAlphaKey(Keyboard::Key::Ans); // Special constexpr Event None = Event::Special(0); From eff2ba92a49c4ed03db9619fa8811aeae75b2c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Tue, 24 Dec 2019 10:57:56 +0100 Subject: [PATCH 114/130] Ignore MacOS files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6d58dfa02..5019cb014 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ build/device/**/*.pyc epsilon.elf .vscode +.DS_Store \ No newline at end of file From 26dcc7c546777eefd36d67e99d3a949d15b08243 Mon Sep 17 00:00:00 2001 From: Damien Nicolet Date: Tue, 24 Dec 2019 11:43:30 +0100 Subject: [PATCH 115/130] Disable "External" in Dutch exam mode --- apps/home/controller.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index 3062e6485..2cd40bf8f 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -59,7 +59,8 @@ bool Controller::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::EXE) { AppsContainer * container = AppsContainer::sharedAppsContainer(); ::App::Snapshot * selectedSnapshot = container->appSnapshotAtIndex(selectionDataSource()->selectedRow()*k_numberOfColumns+selectionDataSource()->selectedColumn()+1); - if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Dutch && selectedSnapshot->descriptor()->name() == I18n::Message::CodeApp) { + if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Dutch && + (selectedSnapshot->descriptor()->name() == I18n::Message::CodeApp || selectedSnapshot->descriptor()->name() == I18n::Message::ExternalApp)) { App::app()->displayWarning(I18n::Message::ForbidenAppInExamMode1, I18n::Message::ForbidenAppInExamMode2); } else { bool switched = container->switchTo(selectedSnapshot); From 0ffe82fd171fbf560eb783dd7b15f33f32353d20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Tue, 24 Dec 2019 16:56:55 +0100 Subject: [PATCH 116/130] Update themes --- themes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes b/themes index 1ff3eed1d..775ae1ceb 160000 --- a/themes +++ b/themes @@ -1 +1 @@ -Subproject commit 1ff3eed1d70cf1fae0ea6404ccd10614bcc0ff90 +Subproject commit 775ae1cebdd9f2bdc4d6afc6a15418327490799a From be8085eaf8396b3c9182bbb73b428bcad0e8799a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Tue, 24 Dec 2019 17:23:55 +0100 Subject: [PATCH 117/130] Updated submodules --- apps/atom | 2 +- apps/rpn | 2 +- themes | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/atom b/apps/atom index c2f563017..e47da6820 160000 --- a/apps/atom +++ b/apps/atom @@ -1 +1 @@ -Subproject commit c2f5630178b34529da27414a51663573001d5cbe +Subproject commit e47da6820d488fa5eecddeabbf2297a2e5639a5e diff --git a/apps/rpn b/apps/rpn index 9149fd110..141b17c91 160000 --- a/apps/rpn +++ b/apps/rpn @@ -1 +1 @@ -Subproject commit 9149fd11077ea7c8b36589775e5b5fec5295a4a6 +Subproject commit 141b17c91cd76affaf3ecef18fe69f6de1ce9722 diff --git a/themes b/themes index 775ae1ceb..53aac1350 160000 --- a/themes +++ b/themes @@ -1 +1 @@ -Subproject commit 775ae1cebdd9f2bdc4d6afc6a15418327490799a +Subproject commit 53aac135045ca4b52ac5118f67e11741d2109513 From 57f2b41c3f84871cdfd7bdc46b43c45f486ff714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Wed, 25 Dec 2019 14:37:08 +0100 Subject: [PATCH 118/130] Fix: OMEGA not displayed on the home screen --- apps/home/base.de.i18n | 1 - apps/home/base.en.i18n | 1 - apps/home/base.es.i18n | 1 - apps/home/base.fr.i18n | 1 - apps/home/base.pt.i18n | 1 - 5 files changed, 5 deletions(-) diff --git a/apps/home/base.de.i18n b/apps/home/base.de.i18n index e3ac17694..352d41520 100644 --- a/apps/home/base.de.i18n +++ b/apps/home/base.de.i18n @@ -1,5 +1,4 @@ Apps = "Anwendungen" AppsCapital = "OMEGA" -AppsCapital = "ANWENDUNGEN" ForbidenAppInExamMode1 = "This application is" ForbidenAppInExamMode2 = "forbidden in exam mode" diff --git a/apps/home/base.en.i18n b/apps/home/base.en.i18n index 45c8bb6cd..dde4e2129 100644 --- a/apps/home/base.en.i18n +++ b/apps/home/base.en.i18n @@ -1,5 +1,4 @@ Apps = "Applications" AppsCapital = "OMEGA" -AppsCapital = "APPLICATIONS" ForbidenAppInExamMode1 = "This application is" ForbidenAppInExamMode2 = "forbidden in exam mode" diff --git a/apps/home/base.es.i18n b/apps/home/base.es.i18n index 921b3b308..9d3258766 100644 --- a/apps/home/base.es.i18n +++ b/apps/home/base.es.i18n @@ -1,5 +1,4 @@ Apps = "Aplicaciones" AppsCapital = "OMEGA" -AppsCapital = "APLICACIONES" ForbidenAppInExamMode1 = "This application is" ForbidenAppInExamMode2 = "forbidden in exam mode" diff --git a/apps/home/base.fr.i18n b/apps/home/base.fr.i18n index 45c8bb6cd..dde4e2129 100644 --- a/apps/home/base.fr.i18n +++ b/apps/home/base.fr.i18n @@ -1,5 +1,4 @@ Apps = "Applications" AppsCapital = "OMEGA" -AppsCapital = "APPLICATIONS" ForbidenAppInExamMode1 = "This application is" ForbidenAppInExamMode2 = "forbidden in exam mode" diff --git a/apps/home/base.pt.i18n b/apps/home/base.pt.i18n index 12bc7a302..5e84c0ba1 100644 --- a/apps/home/base.pt.i18n +++ b/apps/home/base.pt.i18n @@ -1,5 +1,4 @@ Apps = "Aplicações" AppsCapital = "OMEGA" -AppsCapital = "APLICAÇÕES" ForbidenAppInExamMode1 = "This application is" ForbidenAppInExamMode2 = "forbidden in exam mode" From 160adf6bab58fc68eb2b05d8a0b874a88268e136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Wed, 25 Dec 2019 14:40:57 +0100 Subject: [PATCH 119/130] Fix compilation errors on n0110 --- apps/external/archive.cpp | 2 +- ion/src/device/n0110/drivers/led.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/external/archive.cpp b/apps/external/archive.cpp index 2818d4a51..3472aabe5 100644 --- a/apps/external/archive.cpp +++ b/apps/external/archive.cpp @@ -36,7 +36,7 @@ bool isSane(const TarHeader* tar) { } bool isExamModeAndFileNotExecutable(const TarHeader* tar) { - return GlobalPreferences::sharedGlobalPreferences()->examMode() && (tar->mode[4] & 0x01) == 0; + return GlobalPreferences::sharedGlobalPreferences()->isInExamMode() && (tar->mode[4] & 0x01) == 0; } bool fileAtIndex(size_t index, File &entry) { diff --git a/ion/src/device/n0110/drivers/led.cpp b/ion/src/device/n0110/drivers/led.cpp index a63b35189..9990bdc41 100644 --- a/ion/src/device/n0110/drivers/led.cpp +++ b/ion/src/device/n0110/drivers/led.cpp @@ -9,7 +9,7 @@ namespace LED { KDColor updateColorWithPlugAndCharge() { KDColor ledColor = getColor(); - if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode() { // If exam mode is on, we do not update the LED with the plugged/charging state + if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { // If exam mode is on, we do not update the LED with the plugged/charging state if (USB::isPlugged()) { ledColor = Battery::isCharging() ? KDColorOrange : KDColorGreen; } else { From b7fe5b51c8dd2b5edd11252611c3af061755a7d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quentin=20Guid=C3=A9e?= Date: Wed, 25 Dec 2019 19:24:33 +0100 Subject: [PATCH 120/130] Fixed alpha + % --- ion/include/ion/keyboard/layout_B2/layout_events.h | 2 +- ion/include/ion/keyboard/layout_B3/layout_events.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ion/include/ion/keyboard/layout_B2/layout_events.h b/ion/include/ion/keyboard/layout_B2/layout_events.h index 8c8c46f07..7282f289c 100644 --- a/ion/include/ion/keyboard/layout_B2/layout_events.h +++ b/ion/include/ion/keyboard/layout_B2/layout_events.h @@ -32,7 +32,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), T(":"), T(";"), T("\""), U(), + U(), U(), T(":"), T(";"), T("\""), T("%"), T("a"), T("b"), T("c"), T("d"), T("e"), T("f"), T("g"), T("h"), T("i"), T("j"), T("k"), T("l"), T("m"), T("n"), T("o"), T("p"), T("q"), U(), diff --git a/ion/include/ion/keyboard/layout_B3/layout_events.h b/ion/include/ion/keyboard/layout_B3/layout_events.h index 9e1fde2af..f7072bd60 100644 --- a/ion/include/ion/keyboard/layout_B3/layout_events.h +++ b/ion/include/ion/keyboard/layout_B3/layout_events.h @@ -32,7 +32,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), T(":"), T(";"), T("\""), U(), + U(), U(), T(":"), T(";"), T("\""), T("%"), T("a"), T("b"), T("c"), T("d"), T("e"), T("f"), T("g"), T("h"), T("i"), T("j"), T("k"), T("l"), T("m"), T("n"), T("o"), T("p"), T("q"), U(), From 9a9ae068efec302bbae54b460af1c2839fe84418 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Fri, 27 Dec 2019 16:48:45 +0100 Subject: [PATCH 121/130] Reworked exam mode, fixed #106 --- apps/apps_container.cpp | 2 +- apps/calculation/calculation_store.cpp | 2 +- apps/exam_pop_up_controller.cpp | 2 +- apps/global_preferences.cpp | 13 ++- apps/global_preferences.h | 8 +- apps/settings/base.de.i18n | 6 +- apps/settings/base.en.i18n | 6 +- apps/settings/base.es.i18n | 6 +- apps/settings/base.fr.i18n | 6 +- apps/settings/base.pt.i18n | 6 +- apps/settings/main_controller_prompt_beta.cpp | 5 +- apps/settings/main_controller_prompt_none.cpp | 5 +- .../main_controller_prompt_update.cpp | 3 +- .../sub_menu/exam_mode_controller.cpp | 98 +++++-------------- apps/settings/sub_menu/exam_mode_controller.h | 7 +- .../sub_menu/preferences_controller.cpp | 20 ++++ apps/title_bar_view.cpp | 2 +- ion/src/device/n0110/drivers/led.cpp | 2 +- ion/src/device/shared/drivers/exam_mode.cpp | 13 +-- poincare/include/poincare/preferences.h | 3 - poincare/src/preferences.cpp | 3 +- 21 files changed, 102 insertions(+), 116 deletions(-) diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index c4a77a547..f08efd05b 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -363,7 +363,7 @@ void AppsContainer::redrawWindow(bool force) { } void AppsContainer::activateExamMode(GlobalPreferences::ExamMode examMode) { - assert(examMode == GlobalPreferences::ExamMode::Standard || examMode == GlobalPreferences::ExamMode::Dutch); + assert(examMode == GlobalPreferences::ExamMode::Standard || examMode == GlobalPreferences::ExamMode::Dutch || examMode == GlobalPreferences::ExamMode::NoSym); reset(); Preferences * preferences = Preferences::sharedPreferences(); switch ((int)preferences->colorOfLED()) { diff --git a/apps/calculation/calculation_store.cpp b/apps/calculation/calculation_store.cpp index c8f1b25ef..10505479a 100644 --- a/apps/calculation/calculation_store.cpp +++ b/apps/calculation/calculation_store.cpp @@ -92,7 +92,7 @@ ExpiringPointer CalculationStore::push(const char * text, Context * // Compute and serialize the outputs { Expression outputs[] = {Expression(), Expression()}; - PoincareHelpers::ParseAndSimplifyAndApproximate(inputSerialization, &(outputs[0]), &(outputs[1]), context, GlobalPreferences::sharedGlobalPreferences()->isInExamMode() ? Preferences::sharedPreferences()->isExamSymbolic() : true); // Symbolic computation + PoincareHelpers::ParseAndSimplifyAndApproximate(inputSerialization, &(outputs[0]), &(outputs[1]), context, GlobalPreferences::sharedGlobalPreferences()->isInExamModeSymbolic()); // Symbolic computation for (int i = 0; i < 2; i++) { if (!serializeExpression(outputs[i], nextSerializationLocation, &newCalculationsLocation)) { /* If the exat/approximate output does not fit in the store (event if the diff --git a/apps/exam_pop_up_controller.cpp b/apps/exam_pop_up_controller.cpp index f35afe420..27451be80 100644 --- a/apps/exam_pop_up_controller.cpp +++ b/apps/exam_pop_up_controller.cpp @@ -96,7 +96,7 @@ void ExamPopUpController::ContentView::setMessagesForExamMode(GlobalPreferences: m_messageTextView1.setMessage(I18n::Message::ExitExamMode1); m_messageTextView2.setMessage(I18n::Message::ExitExamMode2); m_messageTextView3.setMessage(I18n::Message::Default); - } else if (mode == GlobalPreferences::ExamMode::Standard) { + } else if (mode == GlobalPreferences::ExamMode::Standard || mode == GlobalPreferences::ExamMode::NoSym) { m_messageTextView1.setMessage(I18n::Message::ActiveExamModeMessage1); m_messageTextView2.setMessage(I18n::Message::ActiveExamModeMessage2); m_messageTextView3.setMessage(I18n::Message::ActiveExamModeMessage3); diff --git a/apps/global_preferences.cpp b/apps/global_preferences.cpp index c6644f5fd..d05127172 100644 --- a/apps/global_preferences.cpp +++ b/apps/global_preferences.cpp @@ -8,12 +8,17 @@ GlobalPreferences * GlobalPreferences::sharedGlobalPreferences() { GlobalPreferences::ExamMode GlobalPreferences::examMode() const { if (m_examMode == ExamMode::Unknown) { uint8_t mode = Ion::ExamMode::FetchExamMode(); - assert(mode >= 0 && mode < 3); // mode can be cast in ExamMode (Off, Standard or Dutch) + assert(mode >= 0 && mode < 4); // mode can be cast in ExamMode (Off, Standard, NoSym or Dutch) m_examMode = (ExamMode)mode; } return m_examMode; } +GlobalPreferences::ExamMode GlobalPreferences::tempExamMode() const { + return m_tempExamMode; +} + + void GlobalPreferences::setExamMode(ExamMode mode) { ExamMode currentMode = examMode(); if (currentMode == mode) { @@ -21,12 +26,16 @@ void GlobalPreferences::setExamMode(ExamMode mode) { } assert(mode != ExamMode::Unknown); int8_t deltaMode = (int8_t)mode - (int8_t)currentMode; - deltaMode = deltaMode < 0 ? deltaMode + 3 : deltaMode; + deltaMode = deltaMode < 0 ? deltaMode + 4 : deltaMode; assert(deltaMode > 0); Ion::ExamMode::IncrementExamMode(deltaMode); m_examMode = mode; } +void GlobalPreferences::setTempExamMode(ExamMode mode) { + m_tempExamMode = mode; +} + void GlobalPreferences::setBrightnessLevel(int brightnessLevel) { if (m_brightnessLevel != brightnessLevel) { brightnessLevel = brightnessLevel < 0 ? 0 : brightnessLevel; diff --git a/apps/global_preferences.h b/apps/global_preferences.h index 4e266c63b..adf5e27fd 100644 --- a/apps/global_preferences.h +++ b/apps/global_preferences.h @@ -9,14 +9,18 @@ public: Unknown = -1, Off = 0, Standard = 1, - Dutch = 2 + NoSym = 2, + Dutch = 3, }; static GlobalPreferences * sharedGlobalPreferences(); I18n::Language language() const { return m_language; } void setLanguage(I18n::Language language) { m_language = language; } bool isInExamMode() const { return (int8_t)examMode() > 0; } + bool isInExamModeSymbolic() const { return !((int8_t)examMode() > 1); } ExamMode examMode() const; + ExamMode tempExamMode() const; void setExamMode(ExamMode examMode); + void setTempExamMode(ExamMode examMode); bool showPopUp() const { return m_showPopUp; } void setShowPopUp(bool showPopUp) { m_showPopUp = showPopUp; } int brightnessLevel() const { return m_brightnessLevel; } @@ -26,12 +30,14 @@ private: GlobalPreferences() : m_language(I18n::Language::EN), m_examMode(ExamMode::Unknown), + m_tempExamMode(ExamMode::Standard), m_showPopUp(true), m_brightnessLevel(Ion::Backlight::MaxBrightness) {} I18n::Language m_language; static_assert((int8_t)GlobalPreferences::ExamMode::Off == 0, "GlobalPreferences::isInExamMode() is not right"); static_assert((int8_t)GlobalPreferences::ExamMode::Unknown < 0, "GlobalPreferences::isInExamMode() is not right"); mutable ExamMode m_examMode; + mutable ExamMode m_tempExamMode; bool m_showPopUp; int m_brightnessLevel; }; diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 048f88912..f52613c5e 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -9,7 +9,6 @@ ComplexFormat = "Komplex" ExamMode = "Testmodus" ActivateExamMode = "Starten Testmodus" ExamModeActive = "Wieder starten Testmodus" -ActivateDutchExamMode = "Activate Dutch exam mode" About = "Über" Degrees = "Grad " Gradians = "Gone " @@ -30,6 +29,10 @@ SerialNumber = "Seriennummer" UpdatePopUp = "Erinnerung: Update" BetaPopUp = "Beta pop-up" LEDColor = "LEDs farbe" +ExamModeMode = "Modus" +ExamModeModeStandard = "Standard " +ExamModeModeNoSym = "Ohne symbolisch " +ExamModeModeDutch = "Niederländisch " ColorWhite = "Weiss " ColorBlue = "Blau " ColorGreen = "Grün " @@ -48,4 +51,3 @@ SymbolMultiplicationCross = "Kreuz" SymbolMultiplicationMiddleDot = "Mittelpunkt" SymbolMultiplicationStar = "Stern" SymbolMultiplicationAutoSymbol = "automatisch" -SymbolicEnabled = "Symbolische Berechnung" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index b9c411b26..94dd552f5 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -9,7 +9,6 @@ ComplexFormat = "Complex format" ExamMode = "Exam mode" ActivateExamMode = "Activate exam mode" ExamModeActive = "Reactivate exam mode" -ActivateDutchExamMode = "Activate Dutch exam mode" About = "About" Degrees = "Degrees " Gradians = "Gradians " @@ -30,6 +29,10 @@ SerialNumber = "Serial number" UpdatePopUp = "Update pop-up" BetaPopUp = "Beta pop-up" LEDColor = "LED color" +ExamModeMode = "Mode" +ExamModeModeStandard = "Standard " +ExamModeModeNoSym = "No sym " +ExamModeModeDutch = "Dutch " ColorWhite = "White " ColorBlue = "Blue " ColorGreen = "Green " @@ -48,4 +51,3 @@ SymbolMultiplicationCross = "Cross " SymbolMultiplicationMiddleDot = "Dot " SymbolMultiplicationStar = "Star " SymbolMultiplicationAutoSymbol = "Auto " -SymbolicEnabled = "Symbolic calculation" \ No newline at end of file diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index bd100e830..2391a98e1 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -9,7 +9,6 @@ ComplexFormat = "Forma compleja" ExamMode = "Modo examen" ActivateExamMode = "Activar el modo examen" ExamModeActive = "Reactivar el modo examen" -ActivateDutchExamMode = "Activate Dutch exam mode" About = "Acerca" Degrees = "Grados " Gradians = "Gradianes " @@ -30,6 +29,10 @@ SerialNumber = "Número serie" UpdatePopUp = "Pop-up de actualización" BetaPopUp = "Beta pop-up" LEDColor = "Color del LED" +ExamModeMode = "Modo" +ExamModeModeStandard = "Estándar " +ExamModeModeNoSym = "Sin simbólico " +ExamModeModeDutch = "Holandés " ColorWhite = "Blanco " ColorBlue = "Azul " ColorGreen = "Verde " @@ -48,4 +51,3 @@ SymbolMultiplicationCross = "Contrariar " SymbolMultiplicationMiddleDot = "Punto " SymbolMultiplicationStar = "Estrella " SymbolMultiplicationAutoSymbol = "Auto " -SymbolicEnabled = "Cálculo simbólico" \ No newline at end of file diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 3e87a529c..775786ed3 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -9,7 +9,6 @@ ComplexFormat = "Forme complexe" ExamMode = "Mode examen" ActivateExamMode = "Activer le mode examen" ExamModeActive = "Réactiver le mode examen" -ActivateDutchExamMode = "Activate Dutch exam mode" About = "À propos" Degrees = "Degrés " Gradians = "Grades " @@ -30,6 +29,10 @@ SerialNumber = "Numéro série" UpdatePopUp = "Rappel mise à jour" BetaPopUp = "Rappel version bêta" LEDColor = "Couleur LED" +ExamModeMode = "Mode" +ExamModeModeStandard = "Standard " +ExamModeModeNoSym = "Sans symbolique " +ExamModeModeDutch = "Néerlandais " ColorWhite = "Blanc " ColorBlue = "Bleu " ColorGreen = "Vert " @@ -48,4 +51,3 @@ SymbolMultiplicationCross = "Croix" SymbolMultiplicationMiddleDot = "Point" SymbolMultiplicationStar = "Etoile" SymbolMultiplicationAutoSymbol = "Automatique" -SymbolicEnabled = "Calcul symbolique" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index cfff892d8..c7f1f6419 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -9,7 +9,6 @@ ComplexFormat = "Complexos" ExamMode = "Modo de exame" ActivateExamMode = "Ativar o modo de exame" ExamModeActive = "Reativar o modo de exame" -ActivateDutchExamMode = "Activate Dutch exam mode" About = "Acerca" Degrees = "Graus " Gradians = "Grados " @@ -30,6 +29,10 @@ SerialNumber = "Número serie" UpdatePopUp = "Alertas de atualização" BetaPopUp = "Beta pop-up" LEDColor = "Cor LED" +ExamModeMode = "Modo" +ExamModeModeStandard = "Padrão " +ExamModeModeNoSym = "Sem simbólico " +ExamModeModeDutch = "Holandês " ColorWhite = "Branco " ColorBlue = "Azul " ColorGreen = "Verde " @@ -48,4 +51,3 @@ SymbolMultiplicationCross = "crómio" SymbolMultiplicationMiddleDot = "ponto médio" SymbolMultiplicationStar = "estrela" SymbolMultiplicationAutoSymbol = "automático" -SymbolicEnabled = "Cálculo simbólico" diff --git a/apps/settings/main_controller_prompt_beta.cpp b/apps/settings/main_controller_prompt_beta.cpp index d3528fafa..a0cd43ae2 100644 --- a/apps/settings/main_controller_prompt_beta.cpp +++ b/apps/settings/main_controller_prompt_beta.cpp @@ -5,16 +5,17 @@ namespace Settings { //sub-sub-menus constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; +constexpr SettingsMessageTree s_examModeMode[3] = {SettingsMessageTree(I18n::Message::ExamModeModeStandard), SettingsMessageTree(I18n::Message::ExamModeModeNoSym), SettingsMessageTree(I18n::Message::ExamModeModeDutch)}; constexpr SettingsMessageTree s_contributorsChildren[5] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::MaximeFriess)}; constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18n::Message::Degrees), SettingsMessageTree(I18n::Message::Radian), SettingsMessageTree(I18n::Message::Gradians)}; constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)}; constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::Engineering), SettingsMessageTree(I18n::Message::SignificantFigures)}; constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessageTree(I18n::Message::Real), SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)}; -constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::Message::SymbolMultiplicationCross), SettingsMessageTree(I18n::Message::SymbolMultiplicationMiddleDot), SettingsMessageTree(I18n::Message::SymbolMultiplicationStar), SettingsMessageTree(I18n::Message::SymbolMultiplicationAutoSymbol)}; +constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::Message::SymbolMultiplicationCross),SettingsMessageTree(I18n::Message::SymbolMultiplicationMiddleDot),SettingsMessageTree(I18n::Message::SymbolMultiplicationStar),SettingsMessageTree(I18n::Message::SymbolMultiplicationAutoSymbol)}; //sub-menus constexpr SettingsMessageTree s_modelMathOptionsChildren[5] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren, 4)}; -constexpr SettingsMessageTree s_modelExamChildren[4] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[3] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::ExamModeMode, s_examModeMode, 3), SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; #ifdef USERNAME constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 5)}; diff --git a/apps/settings/main_controller_prompt_none.cpp b/apps/settings/main_controller_prompt_none.cpp index f9f4c2431..4c37fbf39 100644 --- a/apps/settings/main_controller_prompt_none.cpp +++ b/apps/settings/main_controller_prompt_none.cpp @@ -6,6 +6,7 @@ namespace Settings { // TODO: factorize most parts of the final models with main_controller_prompt_beta and main_controller_prompt_update //sub-sub-menus constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; +constexpr SettingsMessageTree s_examModeMode[3] = {SettingsMessageTree(I18n::Message::ExamModeModeStandard), SettingsMessageTree(I18n::Message::ExamModeModeNoSym), SettingsMessageTree(I18n::Message::ExamModeModeDutch)}; constexpr SettingsMessageTree s_contributorsChildren[5] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::MaximeFriess)}; constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18n::Message::Degrees), SettingsMessageTree(I18n::Message::Radian), SettingsMessageTree(I18n::Message::Gradians)}; constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)}; @@ -15,7 +16,7 @@ constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::M //sub-menus constexpr SettingsMessageTree s_modelMathOptionsChildren[5] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren, 4)}; -constexpr SettingsMessageTree s_modelExamChildren[4] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[3] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::ExamModeMode, s_examModeMode, 3), SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; #ifdef USERNAME constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 5)}; @@ -27,7 +28,7 @@ constexpr SettingsMessageTree s_modelMenu[] = {SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren, 5), SettingsMessageTree(I18n::Message::Brightness), SettingsMessageTree(I18n::Message::Language), - SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 4), + SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 3), SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6), #ifdef USERNAME SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 7)}; diff --git a/apps/settings/main_controller_prompt_update.cpp b/apps/settings/main_controller_prompt_update.cpp index a929483b2..3e70547ff 100644 --- a/apps/settings/main_controller_prompt_update.cpp +++ b/apps/settings/main_controller_prompt_update.cpp @@ -5,6 +5,7 @@ namespace Settings { //sub-sub-menus constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; +constexpr SettingsMessageTree s_examModeMode[3] = {SettingsMessageTree(I18n::Message::ExamModeModeStandard), SettingsMessageTree(I18n::Message::ExamModeModeNoSym), SettingsMessageTree(I18n::Message::ExamModeModeDutch)}; constexpr SettingsMessageTree s_contributorsChildren[5] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::MaximeFriess)}; constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18n::Message::Degrees), SettingsMessageTree(I18n::Message::Radian), SettingsMessageTree(I18n::Message::Gradians)}; constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)}; @@ -14,7 +15,7 @@ constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::M //sub-menus constexpr SettingsMessageTree s_modelMathOptionsChildren[5] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren, 3), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren, 4), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren, 2), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren, 3), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren, 4)}; -constexpr SettingsMessageTree s_modelExamChildren[4] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; +constexpr SettingsMessageTree s_modelExamChildren[3] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::ExamModeMode, s_examModeMode, 3), SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; #ifdef USERNAME constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 5)}; diff --git a/apps/settings/sub_menu/exam_mode_controller.cpp b/apps/settings/sub_menu/exam_mode_controller.cpp index e05056066..0909bc6f6 100644 --- a/apps/settings/sub_menu/exam_mode_controller.cpp +++ b/apps/settings/sub_menu/exam_mode_controller.cpp @@ -17,23 +17,12 @@ ExamModeController::ExamModeController(Responder * parentResponder) : m_preferencesController(this), m_examModeCell(I18n::Message::Default, KDFont::LargeFont), m_ledCell(KDFont::LargeFont, KDFont::SmallFont), - m_symbolicCell(I18n::Message::SymbolicEnabled, KDFont::LargeFont), - m_cell{ MessageTableCell(I18n::Message::ExamModeActive, KDFont::LargeFont), MessageTableCell(I18n::Message::ActivateDutchExamMode, KDFont::LargeFont) } + m_modeCell(KDFont::LargeFont, KDFont::SmallFont) { } -int ExamModeController::initialSelectedRow() const { - int row = selectedRow(); - if (row >= numberOfRows()) { - return numberOfRows()-1; - } else if (row < 0) { - return 0; - } - return row; -} - bool ExamModeController::handleEvent(Ion::Events::Event event) { - I18n::Message childLabel = m_messageTreeModel->children(selectedRow())->label(); +I18n::Message childLabel = m_messageTreeModel->children(selectedRow())->label(); if (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) { if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { // If the exam mode is already on, this re-activate the same exam mode @@ -41,72 +30,43 @@ bool ExamModeController::handleEvent(Ion::Events::Event event) { if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive) AppsContainer::sharedAppsContainer()->displayExamModePopUp(mode); return true; - } else if (childLabel == I18n::Message::ActivateDutchExamMode) { - GlobalPreferences::ExamMode mode = GlobalPreferences::ExamMode::Dutch; - if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive) - AppsContainer::sharedAppsContainer()->displayExamModePopUp(mode); - return true; } + if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive) { - AppsContainer::sharedAppsContainer()->displayExamModePopUp(GlobalPreferences::sharedGlobalPreferences()->examMode()); + GlobalPreferences::ExamMode mode = GlobalPreferences::ExamMode::Standard; + AppsContainer::sharedAppsContainer()->displayExamModePopUp(GlobalPreferences::sharedGlobalPreferences()->tempExamMode()); return true; } - if (childLabel == I18n::Message::LEDColor) { + if (childLabel == I18n::Message::LEDColor || childLabel == I18n::Message::ExamModeMode) { GenericSubController * subController = &m_preferencesController; subController->setMessageTreeModel(m_messageTreeModel->children(selectedRow())); StackViewController * stack = stackController(); stack->push(subController); return true; } - if (childLabel == I18n::Message::SymbolicEnabled) { - Preferences * preferences = Preferences::sharedPreferences(); - preferences->setExamSymbolic(!preferences->isExamSymbolic()); - m_selectableTableView.reloadData(); - return true; - } } return GenericSubController::handleEvent(event); } -int ExamModeController::numberOfRows() const { - if (GlobalPreferences::sharedGlobalPreferences()->language() != I18n::Language::EN || GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { - return 1; - } - return GenericSubController::numberOfRows(); -} - HighlightCell * ExamModeController::reusableCell(int index, int type) { - assert(index == 0); - if (type == 0) { - return &m_ledCell; + assert(type == 0); + assert(index >= 0 && index < 3); + + switch(index) { + case 0: + return &m_ledCell; + case 1: + return &m_modeCell; + case 2: + return &m_examModeCell; } - if (type == 1) { - return &m_symbolicCell; - } - return &m_examModeCell; } int ExamModeController::reusableCellCount(int type) { - switch (type) { - case 0: - return 1; - case 1: - return 1; - case 2: - return 1; - default: - assert(false); - return 0; - } - /*assert(type == 0); - assert(index >= 0 && index < k_maxNumberOfCells); - return &m_cell[index];*/ + assert(type == 0); + return 3; } -/*int ExamModeController::reusableCellCount(int type) { - return k_maxNumberOfCells; -}*/ - void ExamModeController::willDisplayCellForIndex(HighlightCell * cell, int index) { Preferences * preferences = Preferences::sharedPreferences(); GenericSubController::willDisplayCellForIndex(cell, index); @@ -121,24 +81,10 @@ void ExamModeController::willDisplayCellForIndex(HighlightCell * cell, int index I18n::Message message = (I18n::Message) m_messageTreeModel->children(index)->children((int)preferences->colorOfLED())->label(); myTextCell->setSubtitle(message); } - if (thisLabel == I18n::Message::SymbolicEnabled) { - MessageTableCellWithSwitch * mySwitchCell = (MessageTableCellWithSwitch *)cell; - SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); - mySwitch->setState(preferences->isExamSymbolic()); - } -} - -int ExamModeController::typeAtLocation(int i, int j) { - switch (j) { - case 0: - return 0; - case 1: - return 1; - case 2: - return 2; - default: - assert(false); - return 0; + if (thisLabel == I18n::Message::ExamModeMode) { + MessageTableCellWithChevronAndMessage * myTextCell = (MessageTableCellWithChevronAndMessage *)cell; + I18n::Message message = (I18n::Message) m_messageTreeModel->children(index)->children((uint8_t)GlobalPreferences::sharedGlobalPreferences()->tempExamMode() - 1)->label(); + myTextCell->setSubtitle(message); } } diff --git a/apps/settings/sub_menu/exam_mode_controller.h b/apps/settings/sub_menu/exam_mode_controller.h index 149799207..e2e7bb505 100644 --- a/apps/settings/sub_menu/exam_mode_controller.h +++ b/apps/settings/sub_menu/exam_mode_controller.h @@ -10,19 +10,14 @@ class ExamModeController : public GenericSubController { public: ExamModeController(Responder * parentResponder); bool handleEvent(Ion::Events::Event event) override; - int numberOfRows() const override; HighlightCell * reusableCell(int index, int type) override; int reusableCellCount(int type) override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; - int typeAtLocation(int i, int j) override; private: MessageTableCell m_examModeCell; MessageTableCellWithChevronAndMessage m_ledCell; + MessageTableCellWithChevronAndMessage m_modeCell; PreferencesController m_preferencesController; - MessageTableCellWithSwitch m_symbolicCell; - int initialSelectedRow() const override; - static constexpr int k_maxNumberOfCells = 2; - MessageTableCell m_cell[k_maxNumberOfCells]; }; } diff --git a/apps/settings/sub_menu/preferences_controller.cpp b/apps/settings/sub_menu/preferences_controller.cpp index 11e6364c8..62921e49a 100644 --- a/apps/settings/sub_menu/preferences_controller.cpp +++ b/apps/settings/sub_menu/preferences_controller.cpp @@ -128,6 +128,24 @@ Layout PreferencesController::layoutForPreferences(I18n::Message message) { const char * text = " "; return LayoutHelper::String(text, strlen(text), k_layoutFont); } + + // Exam mode modes + case I18n::Message::ExamModeModeStandard: + { + const char * text = " "; + return LayoutHelper::String(text, strlen(text), k_layoutFont); + } + case I18n::Message::ExamModeModeNoSym: + { + const char * text = " "; + return LayoutHelper::String(text, strlen(text), k_layoutFont); + } + case I18n::Message::ExamModeModeDutch: + { + const char * text = " "; + return LayoutHelper::String(text, strlen(text), k_layoutFont); + } + // Symbol controller case I18n::Message::SymbolMultiplicationCross: // × and · aren't single characters, so they cannot be constructed into codepoints..? @@ -182,6 +200,8 @@ void PreferencesController::setPreferenceWithValueIndex(I18n::Message message, i preferences->setComplexFormat((Preferences::ComplexFormat)valueIndex); } else if (message == I18n::Message::LEDColor) { preferences->setColorOfLED((Preferences::LEDColor)valueIndex); + } else if (message == I18n::Message::ExamModeMode) { + GlobalPreferences::sharedGlobalPreferences()->setTempExamMode((GlobalPreferences::ExamMode)((uint8_t)valueIndex + 1)); } else if (message == I18n::Message::SymbolMultiplication) { preferences->setSymbolMultiplication((Preferences::SymbolMultiplication)valueIndex); } diff --git a/apps/title_bar_view.cpp b/apps/title_bar_view.cpp index f37e4f4ba..b818db873 100644 --- a/apps/title_bar_view.cpp +++ b/apps/title_bar_view.cpp @@ -85,7 +85,7 @@ void TitleBarView::refreshPreferences() { char buffer[bufferSize]; int numberOfChar = 0; Preferences * preferences = Preferences::sharedPreferences(); - if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode() && Preferences::sharedPreferences()->isExamSymbolic()) { + if (GlobalPreferences::sharedGlobalPreferences()->isInExamModeSymbolic()) { // Display "cas" if in exam mode with symbolic computation enabled numberOfChar += strlcpy(buffer+numberOfChar, I18n::translate(I18n::Message::Sym), bufferSize - numberOfChar); assert(numberOfChar < bufferSize-1); diff --git a/ion/src/device/n0110/drivers/led.cpp b/ion/src/device/n0110/drivers/led.cpp index 9990bdc41..28d425096 100644 --- a/ion/src/device/n0110/drivers/led.cpp +++ b/ion/src/device/n0110/drivers/led.cpp @@ -9,7 +9,7 @@ namespace LED { KDColor updateColorWithPlugAndCharge() { KDColor ledColor = getColor(); - if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { // If exam mode is on, we do not update the LED with the plugged/charging state + if (!GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) { // If exam mode is on, we do not update the LED with the plugged/charging state if (USB::isPlugged()) { ledColor = Battery::isCharging() ? KDColorOrange : KDColorGreen; } else { diff --git a/ion/src/device/shared/drivers/exam_mode.cpp b/ion/src/device/shared/drivers/exam_mode.cpp index a4aa20143..326480d5e 100644 --- a/ion/src/device/shared/drivers/exam_mode.cpp +++ b/ion/src/device/shared/drivers/exam_mode.cpp @@ -18,12 +18,13 @@ char ones[Config::ExamModeBufferSize] /* The exam mode is written in flash so that it is resilient to resets. * We erase the dedicated flash sector (all bits written to 1) and, upon - * deactivating or activating standard or Dutch exam mode we write one or two + * deactivating or activating standard, nosym or Dutch exam mode we write one, two or tree * bits to 0. To determine in which exam mode we are, we count the number of * leading 0 bits. If it is equal to: * - 0[3]: the exam mode is off; * - 1[3]: the standard exam mode is activated; - * - 2[3]: the Dutch exam mode is activated. */ + * - 2[3]: the NoSym exam mode is activated. + * - 3[3]: the Dutch exam mode is activated. */ /* significantExamModeAddress returns the first uint32_t * in the exam mode * flash sector that does not point to 0. If this flash sector has only 0s or @@ -76,14 +77,14 @@ uint8_t * SignificantExamModeAddress() { uint8_t FetchExamMode() { uint8_t * readingAddress = SignificantExamModeAddress(); // Count the number of 0[3] before reading address - uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)&_exam_mode_buffer_start) * numberOfBitsInByte) % 3; + uint32_t nbOfZerosBefore = ((readingAddress - (uint8_t *)&_exam_mode_buffer_start) * numberOfBitsInByte) % 4; // Count the number of 0[3] at reading address - size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*readingAddress)) % 3; - return (nbOfZerosBefore + numberOfLeading0) % 3; + size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*readingAddress)) % 4; + return (nbOfZerosBefore + numberOfLeading0) % 4; } void IncrementExamMode(uint8_t delta) { - assert(delta == 1 || delta == 2); + assert(delta == 1 || delta == 2 || delta == 3); uint8_t * writingAddress = SignificantExamModeAddress(); assert(*writingAddress != 0); size_t nbOfTargetedOnes = numberOfBitsAfterLeadingZeroes(*writingAddress); diff --git a/poincare/include/poincare/preferences.h b/poincare/include/poincare/preferences.h index 32e60041d..95505cf55 100644 --- a/poincare/include/poincare/preferences.h +++ b/poincare/include/poincare/preferences.h @@ -64,8 +64,6 @@ public: void setColorOfLED(LEDColor color) { m_colorOfLED = color; } SymbolMultiplication symbolofMultiplication() const {return m_symbolMultiplication;} void setSymbolMultiplication(SymbolMultiplication symbolofMultiplication) {m_symbolMultiplication = symbolofMultiplication;} - bool isExamSymbolic() const {return m_examSymbolic;} - void setExamSymbolic(bool examSymbolic) {m_examSymbolic = examSymbolic;} private: AngleUnit m_angleUnit; PrintFloatMode m_displayMode; @@ -74,7 +72,6 @@ private: uint8_t m_numberOfSignificantDigits; LEDColor m_colorOfLED; SymbolMultiplication m_symbolMultiplication; - bool m_examSymbolic; }; } diff --git a/poincare/src/preferences.cpp b/poincare/src/preferences.cpp index 03ced1ee6..4cdb0613f 100644 --- a/poincare/src/preferences.cpp +++ b/poincare/src/preferences.cpp @@ -14,8 +14,7 @@ Preferences::Preferences() : m_complexFormat(Preferences::ComplexFormat::Real), m_numberOfSignificantDigits(PrintFloat::k_numberOfPrintedSignificantDigits), m_colorOfLED(Preferences::LEDColor::White), - m_symbolMultiplication(Preferences::SymbolMultiplication::Auto), - m_examSymbolic(true) + m_symbolMultiplication(Preferences::SymbolMultiplication::Auto) {} Preferences * Preferences::sharedPreferences() { From c91227bc2e12ef60399ca71e1ebae2084d0772dd Mon Sep 17 00:00:00 2001 From: redgl0w <43498612+RedGl0w@users.noreply.github.com> Date: Fri, 27 Dec 2019 19:33:06 +0100 Subject: [PATCH 122/130] Update Makefile --- Makefile | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Makefile b/Makefile index 8f8af5d51..d3d2545b5 100644 --- a/Makefile +++ b/Makefile @@ -141,3 +141,23 @@ cowsay_%: .PHONY: clena clena: cowsay_CLENA clean +.PHONY: compile +compile: output/$(BUILD_TYPE)/simulator/$(HOST)/epsilon.$(EXE) + +.PHONY: cleanandcompile +cleanandcompile: + ${MAKE} cleanall + ${MAKE} compile + +.PHONY: start +start: + @echo "INFO Starting output/$(BUILD_TYPE)/simulator/$(HOST)/epsilon.$(EXE)" + @$(Q) output/$(BUILD_TYPE)/simulator/$(HOST)/epsilon.$(EXE) + +.PHONY: clean_run +clean_run: cleanandcompile + ${MAKE} start + +.PHONY: run +run: compile + ${MAKE} start From 765e648d2b2e86df18bfc512beb20b4253d2c489 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Fri, 27 Dec 2019 19:44:48 +0100 Subject: [PATCH 123/130] Added missing names, added usernames, closes #89 --- apps/settings/main_controller_prompt_beta.cpp | 2 +- apps/settings/main_controller_prompt_none.cpp | 4 ++-- apps/settings/main_controller_prompt_update.cpp | 2 +- apps/settings/sub_menu/contributors_controller.cpp | 12 ++++++++++++ apps/settings/sub_menu/contributors_controller.h | 2 +- apps/shared.universal.i18n | 11 ++++++++++- 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/apps/settings/main_controller_prompt_beta.cpp b/apps/settings/main_controller_prompt_beta.cpp index d3528fafa..88ed5f249 100644 --- a/apps/settings/main_controller_prompt_beta.cpp +++ b/apps/settings/main_controller_prompt_beta.cpp @@ -5,7 +5,7 @@ namespace Settings { //sub-sub-menus constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; -constexpr SettingsMessageTree s_contributorsChildren[5] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::MaximeFriess)}; +constexpr SettingsMessageTree s_contributorsChildren[7] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::MaximeFriess), SettingsMessageTree(I18n::Message::David),SettingsMessageTree(I18n::Message::DamienNicolet)}; constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18n::Message::Degrees), SettingsMessageTree(I18n::Message::Radian), SettingsMessageTree(I18n::Message::Gradians)}; constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)}; constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::Engineering), SettingsMessageTree(I18n::Message::SignificantFigures)}; diff --git a/apps/settings/main_controller_prompt_none.cpp b/apps/settings/main_controller_prompt_none.cpp index f9f4c2431..9cd127a84 100644 --- a/apps/settings/main_controller_prompt_none.cpp +++ b/apps/settings/main_controller_prompt_none.cpp @@ -6,7 +6,7 @@ namespace Settings { // TODO: factorize most parts of the final models with main_controller_prompt_beta and main_controller_prompt_update //sub-sub-menus constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; -constexpr SettingsMessageTree s_contributorsChildren[5] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::MaximeFriess)}; +constexpr SettingsMessageTree s_contributorsChildren[7] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::MaximeFriess), SettingsMessageTree(I18n::Message::David),SettingsMessageTree(I18n::Message::DamienNicolet)}; constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18n::Message::Degrees), SettingsMessageTree(I18n::Message::Radian), SettingsMessageTree(I18n::Message::Gradians)}; constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)}; constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::Engineering), SettingsMessageTree(I18n::Message::SignificantFigures)}; @@ -18,7 +18,7 @@ constexpr SettingsMessageTree s_modelMathOptionsChildren[5] = {SettingsMessageTr constexpr SettingsMessageTree s_modelExamChildren[4] = {SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), SettingsMessageTree(I18n::Message::SymbolicEnabled), SettingsMessageTree(I18n::Message::ActivateExamMode), SettingsMessageTree(I18n::Message::ActivateDutchExamMode)}; constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; #ifdef USERNAME -constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 5)}; +constexpr SettingsMessageTree s_modelAboutChildren[7] = {SettingsMessageTree(I18n::Message::Username), SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 7)}; #else constexpr SettingsMessageTree s_modelAboutChildren[6] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::MicroPythonVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 5)}; #endif diff --git a/apps/settings/main_controller_prompt_update.cpp b/apps/settings/main_controller_prompt_update.cpp index a929483b2..8b65733f3 100644 --- a/apps/settings/main_controller_prompt_update.cpp +++ b/apps/settings/main_controller_prompt_update.cpp @@ -5,7 +5,7 @@ namespace Settings { //sub-sub-menus constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; -constexpr SettingsMessageTree s_contributorsChildren[5] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::MaximeFriess)}; +constexpr SettingsMessageTree s_contributorsChildren[7] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric), SettingsMessageTree(I18n::Message::MaximeFriess), SettingsMessageTree(I18n::Message::David),SettingsMessageTree(I18n::Message::DamienNicolet)}; constexpr SettingsMessageTree s_modelAngleChildren[3] = {SettingsMessageTree(I18n::Message::Degrees), SettingsMessageTree(I18n::Message::Radian), SettingsMessageTree(I18n::Message::Gradians)}; constexpr SettingsMessageTree s_modelEditionModeChildren[2] = {SettingsMessageTree(I18n::Message::Edition2D), SettingsMessageTree(I18n::Message::EditionLinear)}; constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMessageTree(I18n::Message::Decimal), SettingsMessageTree(I18n::Message::Scientific), SettingsMessageTree(I18n::Message::Engineering), SettingsMessageTree(I18n::Message::SignificantFigures)}; diff --git a/apps/settings/sub_menu/contributors_controller.cpp b/apps/settings/sub_menu/contributors_controller.cpp index 50364cd62..e70db01bd 100644 --- a/apps/settings/sub_menu/contributors_controller.cpp +++ b/apps/settings/sub_menu/contributors_controller.cpp @@ -28,7 +28,19 @@ int ContributorsController::reusableCellCount(int type) { return k_totalNumberOfCell; } +constexpr static I18n::Message s_contributorsUsernames[7] = { + I18n::Message::PQuentinGuidee, + I18n::Message::PDannySimmons, + I18n::Message::PJoachimLeFournis, + I18n::Message::PJeanBaptisteBoric, + I18n::Message::PMaximeFriess, + I18n::Message::PDavid, + I18n::Message::PDamienNicolet +}; + void ContributorsController::willDisplayCellForIndex(HighlightCell * cell, int index) { + MessageTableCellWithBuffer * myTextCell = (MessageTableCellWithBuffer *)cell; + myTextCell->setAccessoryText(I18n::translate(s_contributorsUsernames[index])); GenericSubController::willDisplayCellForIndex(cell, index); } diff --git a/apps/settings/sub_menu/contributors_controller.h b/apps/settings/sub_menu/contributors_controller.h index deac2515e..71674836c 100644 --- a/apps/settings/sub_menu/contributors_controller.h +++ b/apps/settings/sub_menu/contributors_controller.h @@ -14,7 +14,7 @@ public: int reusableCellCount(int type) override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; private: - constexpr static int k_totalNumberOfCell = 5; + constexpr static int k_totalNumberOfCell = 7; MessageTableCellWithBuffer m_cells[k_totalNumberOfCell]; }; diff --git a/apps/shared.universal.i18n b/apps/shared.universal.i18n index 9b88d865d..4676d5d5c 100644 --- a/apps/shared.universal.i18n +++ b/apps/shared.universal.i18n @@ -210,11 +210,20 @@ ElementTsMass = "294" ElementOgMass = "294" ElementUueMass = "295" ElementUbnMass = "297" -QuentinGuidee = "Quentin Guidee " +QuentinGuidee = "Quentin Guidée " +PQuentinGuidee = "@quentinguidee" DannySimmons = "Danny Simmons " +PDannySimmons = "@MixedMatched" JoachimLeFournis = "Joachim Le Fournis " +PJoachimLeFournis = "@RedGl0w" JeanBaptisteBoric = "Jean-Baptiste Boric " +PJeanBaptisteBoric = "@boricj" MaximeFriess = "Maxime Friess " +PMaximeFriess = "@M4x1m3" +David = "David " +PDavid = "@0b101" +DamienNicolet = "Damien Nicolet " +PDamienNicolet = "@zardam" SpeedOfLight = "2.998·10^8" YearLight = "9.461·10^12" Boltzmann = "1.38064852·10^-23" From e1d907f7c253cc90810e76ba93ccf0412d03ae9c Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Fri, 27 Dec 2019 20:17:38 +0100 Subject: [PATCH 124/130] [ion/keyboard] Fixed layout. Added shift + ( --- ion/include/ion/keyboard/layout_B2/layout_events.h | 8 ++++---- ion/include/ion/keyboard/layout_B3/layout_events.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ion/include/ion/keyboard/layout_B2/layout_events.h b/ion/include/ion/keyboard/layout_B2/layout_events.h index 7282f289c..b047ae30e 100644 --- a/ion/include/ion/keyboard/layout_B2/layout_events.h +++ b/ion/include/ion/keyboard/layout_B2/layout_events.h @@ -25,10 +25,10 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - T("17"), T("18"), T("19"), T("20"), T("21"), U(), - T("14"), T("15"), T("16"), T("factor(\x11)"), T("%"), U(), - T("11"), T("12"), T("13"), T("normal(\x11)"), T("\\"), U(), - T("10"), T("11"), T("12"), T("20"), U(), U(), + TL(), TL(), TL(), T("()"), U(), U(), + TL(), TL(), TL(), TL(), T("%"), U(), + TL(), TL(), TL(), TL(), T("\\"), U(), + TL(), TL(), TL(), TL(), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), diff --git a/ion/include/ion/keyboard/layout_B3/layout_events.h b/ion/include/ion/keyboard/layout_B3/layout_events.h index f7072bd60..3312e05c2 100644 --- a/ion/include/ion/keyboard/layout_B3/layout_events.h +++ b/ion/include/ion/keyboard/layout_B3/layout_events.h @@ -25,10 +25,10 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - T("17"), T("18"), T("19"), T("20"), T("21"), U(), - T("14"), T("15"), T("16"), T("factor(\x11)"), T("%"), U(), - T("11"), T("12"), T("13"), T("normal(\x11)"), T("\\"), U(), - T("10"), T("11"), T("12"), T("20"), U(), U(), + TL(), TL(), TL(), T("()"), U(), U(), + TL(), TL(), TL(), TL(), T("%"), U(), + TL(), TL(), TL(), TL(), T("\\"), U(), + TL(), TL(), TL(), TL(), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), From 3a4ffa9fb97689997444e0cbc1f155333204fe8e Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Fri, 27 Dec 2019 20:31:41 +0100 Subject: [PATCH 125/130] [settings/about] MicroPython version from mpconfig.h --- apps/settings/sub_menu/about_controller.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/settings/sub_menu/about_controller.cpp b/apps/settings/sub_menu/about_controller.cpp index 8ad0bbb74..fd5d92e6d 100644 --- a/apps/settings/sub_menu/about_controller.cpp +++ b/apps/settings/sub_menu/about_controller.cpp @@ -4,6 +4,9 @@ #include #include +#define MP_STRINGIFY_HELPER(x) #x +#define MP_STRINGIFY(x) MP_STRINGIFY_HELPER(x) + namespace Settings { AboutController::AboutController(Responder * parentResponder) : @@ -94,8 +97,7 @@ void AboutController::willDisplayCellForIndex(HighlightCell * cell, int index) { } else { MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)cell; - // TODO: Use MICROPY_VERSION_STRING from "mpconfig" - static const char * mpVersion = "1.11.0"; + static const char * mpVersion = MICROPY_VERSION_STRING; static const char * messages[] = { #ifdef USERNAME Ion::username(), From 76a6678a299f95f2fd14c691fcc36925bd63cd0a Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Fri, 27 Dec 2019 20:36:59 +0100 Subject: [PATCH 126/130] =?UTF-8?q?[settings/about]=20MicroPython=20->=20?= =?UTF-8?q?=C2=B5Python,=20fixes=20offset=20of=20the=20version.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/settings/base.de.i18n | 2 +- apps/settings/base.en.i18n | 4 ++-- apps/settings/base.es.i18n | 4 ++-- apps/settings/base.fr.i18n | 2 +- apps/settings/base.pt.i18n | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 048f88912..1d86d9af5 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -25,7 +25,7 @@ Brightness = "Helligkeit" SoftwareVersion = "Epsilon version" CustomSoftwareVersion = "Omega version" Username = "Name" -MicroPythonVersion = "MicroPythonversion" +MicroPythonVersion = "µPythonversion" SerialNumber = "Seriennummer" UpdatePopUp = "Erinnerung: Update" BetaPopUp = "Beta pop-up" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index b9c411b26..a356a0c37 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -25,7 +25,7 @@ Brightness = "Brightness" SoftwareVersion = "Epsilon version" CustomSoftwareVersion = "Omega version" Username = "Name" -MicroPythonVersion = "MicroPython version" +MicroPythonVersion = "µPython version" SerialNumber = "Serial number" UpdatePopUp = "Update pop-up" BetaPopUp = "Beta pop-up" @@ -48,4 +48,4 @@ SymbolMultiplicationCross = "Cross " SymbolMultiplicationMiddleDot = "Dot " SymbolMultiplicationStar = "Star " SymbolMultiplicationAutoSymbol = "Auto " -SymbolicEnabled = "Symbolic calculation" \ No newline at end of file +SymbolicEnabled = "Symbolic calculation" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index bd100e830..e73bb0c58 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -25,7 +25,7 @@ Brightness = "Brillo" SoftwareVersion = "Versión de Epsilon" CustomSoftwareVersion = "Versión de Omega" Username = "Apellido" -MicroPythonVersion = "Version de MicroPython" +MicroPythonVersion = "Version de µPython" SerialNumber = "Número serie" UpdatePopUp = "Pop-up de actualización" BetaPopUp = "Beta pop-up" @@ -48,4 +48,4 @@ SymbolMultiplicationCross = "Contrariar " SymbolMultiplicationMiddleDot = "Punto " SymbolMultiplicationStar = "Estrella " SymbolMultiplicationAutoSymbol = "Auto " -SymbolicEnabled = "Cálculo simbólico" \ No newline at end of file +SymbolicEnabled = "Cálculo simbólico" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 3e87a529c..395772e3b 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -25,7 +25,7 @@ Brightness = "Luminosité" SoftwareVersion = "Version d'Epsilon" CustomSoftwareVersion = "Version d'Omega" Username = "Nom" -MicroPythonVersion = "Version de MicroPython" +MicroPythonVersion = "Version de µPython" SerialNumber = "Numéro série" UpdatePopUp = "Rappel mise à jour" BetaPopUp = "Rappel version bêta" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index cfff892d8..0e3a9d55b 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -25,7 +25,7 @@ Brightness = "Brilho" SoftwareVersion = "Versão do Epsilon" CustomSoftwareVersion = "Versão do Omega" Username = "Nome" -MicroPythonVersion = "Versao do MicroPython" +MicroPythonVersion = "Versao do µPython" SerialNumber = "Número serie" UpdatePopUp = "Alertas de atualização" BetaPopUp = "Beta pop-up" From b8ae0f625da731dc50bb56b1b8081bdf4b73261f Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Fri, 27 Dec 2019 20:54:50 +0100 Subject: [PATCH 127/130] [settings/math] Changed from "Multiply symbol" to "Multiply", fixed #109. --- apps/settings/base.de.i18n | 10 +++++----- apps/settings/base.en.i18n | 4 ++-- apps/settings/base.es.i18n | 4 ++-- apps/settings/base.fr.i18n | 10 +++++----- apps/settings/base.pt.i18n | 10 +++++----- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 048f88912..152ea3f96 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -43,9 +43,9 @@ AccessibilityGammaRed = "Rotes Gamma" AccessibilityGammaGreen = "Grünes Gamma" AccessibilityGammaBlue = "Blaues Gamma" MathOptions = "Mathe-optionen" -SymbolMultiplication = "Multiplikationszeichen" -SymbolMultiplicationCross = "Kreuz" -SymbolMultiplicationMiddleDot = "Mittelpunkt" -SymbolMultiplicationStar = "Stern" -SymbolMultiplicationAutoSymbol = "automatisch" +SymbolMultiplication = "Multiplikation" +SymbolMultiplicationCross = "Kreuz " +SymbolMultiplicationMiddleDot = "Mittelpunkt " +SymbolMultiplicationStar = "Stern " +SymbolMultiplicationAutoSymbol = "automatisch " SymbolicEnabled = "Symbolische Berechnung" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index b9c411b26..6d689494f 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -43,9 +43,9 @@ AccessibilityGammaRed = "Red gamma" AccessibilityGammaGreen = "Green gamma" AccessibilityGammaBlue = "Blue gamma" MathOptions = "Math options" -SymbolMultiplication = "Multiply sign" +SymbolMultiplication = "Multiply" SymbolMultiplicationCross = "Cross " SymbolMultiplicationMiddleDot = "Dot " SymbolMultiplicationStar = "Star " SymbolMultiplicationAutoSymbol = "Auto " -SymbolicEnabled = "Symbolic calculation" \ No newline at end of file +SymbolicEnabled = "Symbolic calculation" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index bd100e830..ddff88f5b 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -43,9 +43,9 @@ AccessibilityGammaRed = "Gamma roja" AccessibilityGammaGreen = "Gamma verde" AccessibilityGammaBlue = "Gamma azul" MathOptions = "Matemáticas" -SymbolMultiplication = "Signo de multiplicación" +SymbolMultiplication = "Multiplicación" SymbolMultiplicationCross = "Contrariar " SymbolMultiplicationMiddleDot = "Punto " SymbolMultiplicationStar = "Estrella " SymbolMultiplicationAutoSymbol = "Auto " -SymbolicEnabled = "Cálculo simbólico" \ No newline at end of file +SymbolicEnabled = "Cálculo simbólico" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index 3e87a529c..1d3a4da41 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -43,9 +43,9 @@ AccessibilityGammaRed = "Gamma rouge" AccessibilityGammaGreen = "Gamma vert" AccessibilityGammaBlue = "Gamma bleu" MathOptions = "Math" -SymbolMultiplication = "Signe de multiplication" -SymbolMultiplicationCross = "Croix" -SymbolMultiplicationMiddleDot = "Point" -SymbolMultiplicationStar = "Etoile" -SymbolMultiplicationAutoSymbol = "Automatique" +SymbolMultiplication = "Multiplication" +SymbolMultiplicationCross = "Croix " +SymbolMultiplicationMiddleDot = "Point " +SymbolMultiplicationStar = "Etoile " +SymbolMultiplicationAutoSymbol = "Automatique " SymbolicEnabled = "Calcul symbolique" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index cfff892d8..6a8d724cb 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -43,9 +43,9 @@ AccessibilityGammaRed = "Gama vermelha" AccessibilityGammaGreen = "Gama verde" AccessibilityGammaBlue = "Gama azul" MathOptions = "Matemática" -SymbolMultiplication = "Sinal de multiplicação" -SymbolMultiplicationCross = "crómio" -SymbolMultiplicationMiddleDot = "ponto médio" -SymbolMultiplicationStar = "estrela" -SymbolMultiplicationAutoSymbol = "automático" +SymbolMultiplication = "Multiplicação" +SymbolMultiplicationCross = "crómio " +SymbolMultiplicationMiddleDot = "ponto médio " +SymbolMultiplicationStar = "estrela " +SymbolMultiplicationAutoSymbol = "automático " SymbolicEnabled = "Cálculo simbólico" From 0d183cedf290728492df30bbc88e1e66cf4d0ff1 Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Fri, 27 Dec 2019 21:32:15 +0100 Subject: [PATCH 128/130] [build] Added target doc, using doxygen. --- Makefile | 6 + build/doc/Doxyfile | 2546 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2552 insertions(+) create mode 100644 build/doc/Doxyfile diff --git a/Makefile b/Makefile index 0a3541650..7297ac63a 100644 --- a/Makefile +++ b/Makefile @@ -68,6 +68,12 @@ help: @echo " make PLATFORM=simulator TARGET=web" @echo " make PLATFORM=simulator TARGET=windows" +.PHONY: doc +doc: + @echo "DOXYGEN" + @mkdir -p output/doc/ + $(Q) doxygen build/doc/Doxyfile + .PHONY: print-% print-%: @echo $* = $($*) diff --git a/build/doc/Doxyfile b/build/doc/Doxyfile new file mode 100644 index 000000000..6bc017f8d --- /dev/null +++ b/build/doc/Doxyfile @@ -0,0 +1,2546 @@ +# Doxyfile 1.8.16 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = Omega + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = apps/on_boarding/logo_icon.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = output/doc + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# (including Cygwin) ands Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = NO + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = NO + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = NO + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = apps \ + ion/src \ + escher/src \ + ion/include \ + escher/include \ + kandinsky/src \ + kandinsky/include \ + poincare/src \ + poincare/include + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /