mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
Resolved conflicts
This commit is contained in:
6
.github/workflows/ci-workflow.yml
vendored
6
.github/workflows/ci-workflow.yml
vendored
@@ -14,7 +14,8 @@ jobs:
|
|||||||
build-device-n0100:
|
build-device-n0100:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
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
|
- uses: actions/checkout@v1
|
||||||
- run: make -j2 MODEL=n0100 epsilon.dfu
|
- run: make -j2 MODEL=n0100 epsilon.dfu
|
||||||
- run: make -j2 MODEL=n0100 epsilon.onboarding.dfu
|
- run: make -j2 MODEL=n0100 epsilon.onboarding.dfu
|
||||||
@@ -30,7 +31,8 @@ jobs:
|
|||||||
build-device-n0110:
|
build-device-n0110:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
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
|
- uses: actions/checkout@v1
|
||||||
- run: make -j2 epsilon.dfu
|
- run: make -j2 epsilon.dfu
|
||||||
- run: make -j2 epsilon.onboarding.dfu
|
- run: make -j2 epsilon.onboarding.dfu
|
||||||
|
|||||||
@@ -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 = $(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
|
# Configure variants
|
||||||
apps_all_src = $(app_src)
|
apps_all_src = $(app_src)
|
||||||
apps_all_src += $(apps_launch_default_src) $(apps_launch_on_boarding_src
|
apps_all_src += $(apps_launch_default_src) $(apps_launch_on_boarding_src
|
||||||
|
|||||||
@@ -201,8 +201,8 @@ bool AppsContainer::processEvent(Ion::Events::Event event) {
|
|||||||
// Warning: if the window is dirtied, you need to call window()->redraw()
|
// Warning: if the window is dirtied, you need to call window()->redraw()
|
||||||
if (event == Ion::Events::USBPlug) {
|
if (event == Ion::Events::USBPlug) {
|
||||||
if (Ion::USB::isPlugged()) {
|
if (Ion::USB::isPlugged()) {
|
||||||
if (GlobalPreferences::sharedGlobalPreferences()->examMode()) {
|
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
||||||
displayExamModePopUp(false);
|
displayExamModePopUp(GlobalPreferences::ExamMode::Off);
|
||||||
window()->redraw();
|
window()->redraw();
|
||||||
} else {
|
} else {
|
||||||
Ion::USB::enable();
|
Ion::USB::enable();
|
||||||
@@ -251,8 +251,8 @@ void AppsContainer::run() {
|
|||||||
* and it is visible when reflashing a N0100 (there is some noise on the
|
* and it is visible when reflashing a N0100 (there is some noise on the
|
||||||
* screen before the logo appears). */
|
* screen before the logo appears). */
|
||||||
Ion::Display::pushRectUniform(screenRect, KDColorWhite);
|
Ion::Display::pushRectUniform(screenRect, KDColorWhite);
|
||||||
if (GlobalPreferences::sharedGlobalPreferences()->examMode()) {
|
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
||||||
activateExamMode();
|
activateExamMode(GlobalPreferences::sharedGlobalPreferences()->examMode());
|
||||||
}
|
}
|
||||||
refreshPreferences();
|
refreshPreferences();
|
||||||
|
|
||||||
@@ -313,8 +313,8 @@ void AppsContainer::reloadTitleBarView() {
|
|||||||
m_window.reloadTitleBarView();
|
m_window.reloadTitleBarView();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppsContainer::displayExamModePopUp(bool activate) {
|
void AppsContainer::displayExamModePopUp(GlobalPreferences::ExamMode mode) {
|
||||||
m_examPopUpController.setActivatingExamMode(activate);
|
m_examPopUpController.setTargetExamMode(mode);
|
||||||
s_activeApp->displayModalViewController(&m_examPopUpController, 0.f, 0.f, Metric::ExamPopUpTopMargin, Metric::PopUpRightMargin, Metric::ExamPopUpBottomMargin, Metric::PopUpLeftMargin);
|
s_activeApp->displayModalViewController(&m_examPopUpController, 0.f, 0.f, Metric::ExamPopUpTopMargin, Metric::PopUpRightMargin, Metric::ExamPopUpBottomMargin, Metric::PopUpLeftMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +329,7 @@ void AppsContainer::shutdownDueToLowBattery() {
|
|||||||
}
|
}
|
||||||
while (Ion::Battery::level() == Ion::Battery::Charge::EMPTY) {
|
while (Ion::Battery::level() == Ion::Battery::Charge::EMPTY) {
|
||||||
Ion::Backlight::setBrightness(0);
|
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
|
/* 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
|
* low battery event happened during the Power-On Self-Test, a LED might
|
||||||
* have stayed lit up. */
|
* have stayed lit up. */
|
||||||
@@ -362,7 +362,8 @@ void AppsContainer::redrawWindow(bool force) {
|
|||||||
m_window.redraw(force);
|
m_window.redraw(force);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppsContainer::activateExamMode() {
|
void AppsContainer::activateExamMode(GlobalPreferences::ExamMode examMode) {
|
||||||
|
assert(examMode == GlobalPreferences::ExamMode::Standard || examMode == GlobalPreferences::ExamMode::Dutch);
|
||||||
reset();
|
reset();
|
||||||
Preferences * preferences = Preferences::sharedPreferences();
|
Preferences * preferences = Preferences::sharedPreferences();
|
||||||
switch ((int)preferences->colorOfLED()) {
|
switch ((int)preferences->colorOfLED()) {
|
||||||
@@ -379,6 +380,14 @@ void AppsContainer::activateExamMode() {
|
|||||||
Ion::LED::setColor(KDColorYellow);
|
Ion::LED::setColor(KDColorYellow);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* 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);
|
Ion::LED::setBlinking(1000, 0.1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "exam_pop_up_controller_delegate.h"
|
#include "exam_pop_up_controller_delegate.h"
|
||||||
#include "battery_timer.h"
|
#include "battery_timer.h"
|
||||||
#include "suspend_timer.h"
|
#include "suspend_timer.h"
|
||||||
|
#include "global_preferences.h"
|
||||||
#include "backlight_dimming_timer.h"
|
#include "backlight_dimming_timer.h"
|
||||||
#include "shared/global_context.h"
|
#include "shared/global_context.h"
|
||||||
#include "on_boarding/pop_up_controller.h"
|
#include "on_boarding/pop_up_controller.h"
|
||||||
@@ -41,12 +42,12 @@ public:
|
|||||||
bool updateBatteryState();
|
bool updateBatteryState();
|
||||||
void refreshPreferences();
|
void refreshPreferences();
|
||||||
void reloadTitleBarView();
|
void reloadTitleBarView();
|
||||||
void displayExamModePopUp(bool activate);
|
void displayExamModePopUp(GlobalPreferences::ExamMode mode);
|
||||||
void shutdownDueToLowBattery();
|
void shutdownDueToLowBattery();
|
||||||
void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus);
|
void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus);
|
||||||
OnBoarding::PopUpController * promptController();
|
OnBoarding::PopUpController * promptController();
|
||||||
void redrawWindow(bool force = false);
|
void redrawWindow(bool force = false);
|
||||||
void activateExamMode();
|
void activateExamMode(GlobalPreferences::ExamMode examMode);
|
||||||
// Exam pop-up controller delegate
|
// Exam pop-up controller delegate
|
||||||
void examDeactivatingPopUpIsDismissed() override;
|
void examDeactivatingPopUpIsDismissed() override;
|
||||||
// Ion::StorageDelegate
|
// Ion::StorageDelegate
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "calculation.h"
|
#include "calculation.h"
|
||||||
#include "../shared/poincare_helpers.h"
|
#include "../shared/poincare_helpers.h"
|
||||||
|
#include "../global_preferences.h"
|
||||||
#include <poincare/exception_checkpoint.h>
|
#include <poincare/exception_checkpoint.h>
|
||||||
#include <poincare/undefined.h>
|
#include <poincare/undefined.h>
|
||||||
#include <poincare/unreal.h>
|
#include <poincare/unreal.h>
|
||||||
@@ -123,7 +124,9 @@ Calculation::DisplayOutput Calculation::displayOutput(Context * context) {
|
|||||||
}
|
}
|
||||||
if (shouldOnlyDisplayExactOutput()) {
|
if (shouldOnlyDisplayExactOutput()) {
|
||||||
m_displayOutput = DisplayOutput::ExactOnly;
|
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) {
|
[](const Expression e, Context * c) {
|
||||||
constexpr int approximateOnlyTypesCount = 9;
|
constexpr int approximateOnlyTypesCount = 9;
|
||||||
/* If the input contains the following types, we only display the
|
/* If the input contains the following types, we only display the
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ using namespace Poincare;
|
|||||||
ExamPopUpController::ExamPopUpController(ExamPopUpControllerDelegate * delegate) :
|
ExamPopUpController::ExamPopUpController(ExamPopUpControllerDelegate * delegate) :
|
||||||
ViewController(nullptr),
|
ViewController(nullptr),
|
||||||
m_contentView(this),
|
m_contentView(this),
|
||||||
m_isActivatingExamMode(false),
|
m_targetExamMode(GlobalPreferences::ExamMode::Unknown),
|
||||||
m_delegate(delegate)
|
m_delegate(delegate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExamPopUpController::setActivatingExamMode(bool activatingExamMode) {
|
void ExamPopUpController::setTargetExamMode(GlobalPreferences::ExamMode mode) {
|
||||||
m_isActivatingExamMode = activatingExamMode;
|
m_targetExamMode = mode;
|
||||||
m_contentView.setMessages(activatingExamMode);
|
m_contentView.setMessagesForExamMode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
View * ExamPopUpController::view() {
|
View * ExamPopUpController::view() {
|
||||||
@@ -25,7 +25,7 @@ View * ExamPopUpController::view() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ExamPopUpController::viewDidDisappear() {
|
void ExamPopUpController::viewDidDisappear() {
|
||||||
if (m_isActivatingExamMode == false) {
|
if (m_targetExamMode == GlobalPreferences::ExamMode::Off) {
|
||||||
m_delegate->examDeactivatingPopUpIsDismissed();
|
m_delegate->examDeactivatingPopUpIsDismissed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,13 +53,15 @@ ExamPopUpController::ContentView::ContentView(Responder * parentResponder) :
|
|||||||
}, parentResponder), KDFont::SmallFont),
|
}, parentResponder), KDFont::SmallFont),
|
||||||
m_okButton(parentResponder, I18n::Message::Ok, Invocation([](void * context, void * sender) {
|
m_okButton(parentResponder, I18n::Message::Ok, Invocation([](void * context, void * sender) {
|
||||||
ExamPopUpController * controller = (ExamPopUpController *)context;
|
ExamPopUpController * controller = (ExamPopUpController *)context;
|
||||||
GlobalPreferences::sharedGlobalPreferences()->setExamMode(controller->isActivatingExamMode());
|
GlobalPreferences::ExamMode mode = controller->targetExamMode();
|
||||||
|
assert(mode != GlobalPreferences::ExamMode::Unknown);
|
||||||
|
GlobalPreferences::sharedGlobalPreferences()->setExamMode(mode);
|
||||||
AppsContainer * container = AppsContainer::sharedAppsContainer();
|
AppsContainer * container = AppsContainer::sharedAppsContainer();
|
||||||
if (controller->isActivatingExamMode()) {
|
if (mode == GlobalPreferences::ExamMode::Off) {
|
||||||
container->activateExamMode();
|
|
||||||
} else {
|
|
||||||
Ion::LED::setColor(KDColorBlack);
|
Ion::LED::setColor(KDColorBlack);
|
||||||
Ion::LED::updateColorWithPlugAndCharge();
|
Ion::LED::updateColorWithPlugAndCharge();
|
||||||
|
} else {
|
||||||
|
container->activateExamMode(mode);
|
||||||
}
|
}
|
||||||
container->refreshPreferences();
|
container->refreshPreferences();
|
||||||
Container::activeApp()->dismissModalViewController();
|
Container::activeApp()->dismissModalViewController();
|
||||||
@@ -89,15 +91,20 @@ int ExamPopUpController::ContentView::selectedButton() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExamPopUpController::ContentView::setMessages(bool activingExamMode) {
|
void ExamPopUpController::ContentView::setMessagesForExamMode(GlobalPreferences::ExamMode mode) {
|
||||||
if (activingExamMode) {
|
if (mode == GlobalPreferences::ExamMode::Off) {
|
||||||
|
m_messageTextView1.setMessage(I18n::Message::ExitExamMode1);
|
||||||
|
m_messageTextView2.setMessage(I18n::Message::ExitExamMode2);
|
||||||
|
m_messageTextView3.setMessage(I18n::Message::Default);
|
||||||
|
} else if (mode == GlobalPreferences::ExamMode::Standard) {
|
||||||
m_messageTextView1.setMessage(I18n::Message::ActiveExamModeMessage1);
|
m_messageTextView1.setMessage(I18n::Message::ActiveExamModeMessage1);
|
||||||
m_messageTextView2.setMessage(I18n::Message::ActiveExamModeMessage2);
|
m_messageTextView2.setMessage(I18n::Message::ActiveExamModeMessage2);
|
||||||
m_messageTextView3.setMessage(I18n::Message::ActiveExamModeMessage3);
|
m_messageTextView3.setMessage(I18n::Message::ActiveExamModeMessage3);
|
||||||
} else {
|
} else {
|
||||||
m_messageTextView1.setMessage(I18n::Message::ExitExamMode1);
|
assert(mode == GlobalPreferences::ExamMode::Dutch);
|
||||||
m_messageTextView2.setMessage(I18n::Message::ExitExamMode2);
|
m_messageTextView1.setMessage(I18n::Message::ActiveDutchExamModeMessage1);
|
||||||
m_messageTextView3.setMessage(I18n::Message::Default);
|
m_messageTextView2.setMessage(I18n::Message::ActiveDutchExamModeMessage2);
|
||||||
|
m_messageTextView3.setMessage(I18n::Message::ActiveDutchExamModeMessage3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <escher.h>
|
#include <escher.h>
|
||||||
#include "exam_pop_up_controller_delegate.h"
|
#include "exam_pop_up_controller_delegate.h"
|
||||||
|
#include "global_preferences.h"
|
||||||
|
|
||||||
class HighContrastButton : public Button {
|
class HighContrastButton : public Button {
|
||||||
public:
|
public:
|
||||||
@@ -13,8 +14,8 @@ public:
|
|||||||
class ExamPopUpController : public ViewController {
|
class ExamPopUpController : public ViewController {
|
||||||
public:
|
public:
|
||||||
ExamPopUpController(ExamPopUpControllerDelegate * delegate);
|
ExamPopUpController(ExamPopUpControllerDelegate * delegate);
|
||||||
void setActivatingExamMode(bool activingExamMode);
|
void setTargetExamMode(GlobalPreferences::ExamMode mode);
|
||||||
bool isActivatingExamMode() const { return m_isActivatingExamMode; }
|
GlobalPreferences::ExamMode targetExamMode() const { return m_targetExamMode; }
|
||||||
// View Controller
|
// View Controller
|
||||||
View * view() override;
|
View * view() override;
|
||||||
void viewDidDisappear() override;
|
void viewDidDisappear() override;
|
||||||
@@ -28,7 +29,7 @@ private:
|
|||||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||||
void setSelectedButton(int selectedButton);
|
void setSelectedButton(int selectedButton);
|
||||||
int selectedButton();
|
int selectedButton();
|
||||||
void setMessages(bool activingExamMode);
|
void setMessagesForExamMode(GlobalPreferences::ExamMode mode);
|
||||||
private:
|
private:
|
||||||
constexpr static KDCoordinate k_buttonMargin = 10;
|
constexpr static KDCoordinate k_buttonMargin = 10;
|
||||||
constexpr static KDCoordinate k_buttonHeight = 20;
|
constexpr static KDCoordinate k_buttonHeight = 20;
|
||||||
@@ -45,7 +46,7 @@ private:
|
|||||||
MessageTextView m_messageTextView3;
|
MessageTextView m_messageTextView3;
|
||||||
};
|
};
|
||||||
ContentView m_contentView;
|
ContentView m_contentView;
|
||||||
bool m_isActivatingExamMode;
|
GlobalPreferences::ExamMode m_targetExamMode;
|
||||||
ExamPopUpControllerDelegate * m_delegate;
|
ExamPopUpControllerDelegate * m_delegate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,20 +5,26 @@ GlobalPreferences * GlobalPreferences::sharedGlobalPreferences() {
|
|||||||
return &globalPreferences;
|
return &globalPreferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GlobalPreferences::examMode() const {
|
GlobalPreferences::ExamMode GlobalPreferences::examMode() const {
|
||||||
if (m_examMode == ExamMode::Unknown) {
|
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;
|
||||||
}
|
}
|
||||||
assert((int)m_examMode == 0 || (int)m_examMode == 1);
|
return m_examMode;
|
||||||
return (bool)m_examMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalPreferences::setExamMode(bool activateExamMode) {
|
void GlobalPreferences::setExamMode(ExamMode mode) {
|
||||||
if (((bool)examMode()) == activateExamMode) {
|
ExamMode currentMode = examMode();
|
||||||
|
if (currentMode == mode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Ion::ExamMode::ToggleExamMode();
|
assert(mode != ExamMode::Unknown);
|
||||||
m_examMode = (ExamMode)activateExamMode;
|
int8_t deltaMode = (int8_t)mode - (int8_t)currentMode;
|
||||||
|
deltaMode = deltaMode < 0 ? deltaMode + 3 : deltaMode;
|
||||||
|
assert(deltaMode > 0);
|
||||||
|
Ion::ExamMode::IncrementExamMode(deltaMode);
|
||||||
|
m_examMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalPreferences::setBrightnessLevel(int brightnessLevel) {
|
void GlobalPreferences::setBrightnessLevel(int brightnessLevel) {
|
||||||
|
|||||||
@@ -5,11 +5,18 @@
|
|||||||
|
|
||||||
class GlobalPreferences {
|
class GlobalPreferences {
|
||||||
public:
|
public:
|
||||||
|
enum class ExamMode : int8_t {
|
||||||
|
Unknown = -1,
|
||||||
|
Off = 0,
|
||||||
|
Standard = 1,
|
||||||
|
Dutch = 2
|
||||||
|
};
|
||||||
static GlobalPreferences * sharedGlobalPreferences();
|
static GlobalPreferences * sharedGlobalPreferences();
|
||||||
I18n::Language language() const { return m_language; }
|
I18n::Language language() const { return m_language; }
|
||||||
void setLanguage(I18n::Language language) { m_language = language; }
|
void setLanguage(I18n::Language language) { m_language = language; }
|
||||||
bool examMode() const;
|
bool isInExamMode() const { return (int8_t)examMode() > 0; }
|
||||||
void setExamMode(bool activateExamMode);
|
ExamMode examMode() const;
|
||||||
|
void setExamMode(ExamMode examMode);
|
||||||
bool showPopUp() const { return m_showPopUp; }
|
bool showPopUp() const { return m_showPopUp; }
|
||||||
void setShowPopUp(bool showPopUp) { m_showPopUp = showPopUp; }
|
void setShowPopUp(bool showPopUp) { m_showPopUp = showPopUp; }
|
||||||
int brightnessLevel() const { return m_brightnessLevel; }
|
int brightnessLevel() const { return m_brightnessLevel; }
|
||||||
@@ -22,13 +29,8 @@ private:
|
|||||||
m_showPopUp(true),
|
m_showPopUp(true),
|
||||||
m_brightnessLevel(Ion::Backlight::MaxBrightness) {}
|
m_brightnessLevel(Ion::Backlight::MaxBrightness) {}
|
||||||
I18n::Language m_language;
|
I18n::Language m_language;
|
||||||
enum class ExamMode : uint8_t {
|
static_assert((int8_t)GlobalPreferences::ExamMode::Off == 0, "GlobalPreferences::isInExamMode() is not right");
|
||||||
Deactivate = 0,
|
static_assert((int8_t)GlobalPreferences::ExamMode::Unknown < 0, "GlobalPreferences::isInExamMode() is not right");
|
||||||
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;
|
mutable ExamMode m_examMode;
|
||||||
bool m_showPopUp;
|
bool m_showPopUp;
|
||||||
int m_brightnessLevel;
|
int m_brightnessLevel;
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
Apps = "Anwendungen"
|
Apps = "Anwendungen"
|
||||||
AppsCapital = "OMEGA"
|
AppsCapital = "OMEGA"
|
||||||
|
AppsCapital = "ANWENDUNGEN"
|
||||||
|
ForbidenAppInExamMode1 = "This application is"
|
||||||
|
ForbidenAppInExamMode2 = "forbidden in exam mode"
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
Apps = "Applications"
|
Apps = "Applications"
|
||||||
AppsCapital = "OMEGA"
|
AppsCapital = "OMEGA"
|
||||||
|
AppsCapital = "APPLICATIONS"
|
||||||
|
ForbidenAppInExamMode1 = "This application is"
|
||||||
|
ForbidenAppInExamMode2 = "forbidden in exam mode"
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
Apps = "Aplicaciones"
|
Apps = "Aplicaciones"
|
||||||
AppsCapital = "OMEGA"
|
AppsCapital = "OMEGA"
|
||||||
|
AppsCapital = "APLICACIONES"
|
||||||
|
ForbidenAppInExamMode1 = "This application is"
|
||||||
|
ForbidenAppInExamMode2 = "forbidden in exam mode"
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
Apps = "Applications"
|
Apps = "Applications"
|
||||||
AppsCapital = "OMEGA"
|
AppsCapital = "OMEGA"
|
||||||
|
AppsCapital = "APPLICATIONS"
|
||||||
|
ForbidenAppInExamMode1 = "This application is"
|
||||||
|
ForbidenAppInExamMode2 = "forbidden in exam mode"
|
||||||
|
|||||||
@@ -1,2 +1,5 @@
|
|||||||
Apps = "Aplicações"
|
Apps = "Aplicações"
|
||||||
AppsCapital = "OMEGA"
|
AppsCapital = "OMEGA"
|
||||||
|
AppsCapital = "APLICAÇÕES"
|
||||||
|
ForbidenAppInExamMode1 = "This application is"
|
||||||
|
ForbidenAppInExamMode2 = "forbidden in exam mode"
|
||||||
|
|||||||
@@ -58,9 +58,14 @@ Controller::Controller(Responder * parentResponder, SelectableTableViewDataSourc
|
|||||||
bool Controller::handleEvent(Ion::Events::Event event) {
|
bool Controller::handleEvent(Ion::Events::Event event) {
|
||||||
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
|
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
|
||||||
AppsContainer * container = AppsContainer::sharedAppsContainer();
|
AppsContainer * container = AppsContainer::sharedAppsContainer();
|
||||||
bool switched = container->switchTo(container->appSnapshotAtIndex(selectionDataSource()->selectedRow()*k_numberOfColumns+selectionDataSource()->selectedColumn()+1));
|
::App::Snapshot * selectedSnapshot = container->appSnapshotAtIndex(selectionDataSource()->selectedRow()*k_numberOfColumns+selectionDataSource()->selectedColumn()+1);
|
||||||
assert(switched);
|
if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Dutch && selectedSnapshot->descriptor()->name() == I18n::Message::CodeApp) {
|
||||||
(void) switched; // Silence compilation warning about unused variable.
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ void LogoController::viewDidDisappear() {
|
|||||||
Ion::LED::setColor(m_previousLEDColor);
|
Ion::LED::setColor(m_previousLEDColor);
|
||||||
/* TODO: instead of setting again the exam mode, put the previous led color
|
/* TODO: instead of setting again the exam mode, put the previous led color
|
||||||
* AND BLINKING.*/
|
* AND BLINKING.*/
|
||||||
if (GlobalPreferences::sharedGlobalPreferences()->examMode()) {
|
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
||||||
AppsContainer::sharedAppsContainer()->activateExamMode();
|
AppsContainer::sharedAppsContainer()->activateExamMode(GlobalPreferences::sharedGlobalPreferences()->examMode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ViewController::viewDidDisappear();
|
ViewController::viewDidDisappear();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ KDColor PowerOnSelfTest::Perform() {
|
|||||||
resultColor = KDColorRed;
|
resultColor = KDColorRed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
resultColor = KDColorBlue;
|
resultColor = KDColorPurple;
|
||||||
}
|
}
|
||||||
Ion::LED::setColor(resultColor);
|
Ion::LED::setColor(resultColor);
|
||||||
return previousLEDColor;
|
return previousLEDColor;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ ComplexFormat = "Komplex"
|
|||||||
ExamMode = "Testmodus"
|
ExamMode = "Testmodus"
|
||||||
ActivateExamMode = "Starten Testmodus"
|
ActivateExamMode = "Starten Testmodus"
|
||||||
ExamModeActive = "Wieder starten Testmodus"
|
ExamModeActive = "Wieder starten Testmodus"
|
||||||
|
ActivateDutchExamMode = "Activate Dutch exam mode"
|
||||||
About = "Über"
|
About = "Über"
|
||||||
Degrees = "Grad "
|
Degrees = "Grad "
|
||||||
Gradians = "Gone "
|
Gradians = "Gone "
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ ComplexFormat = "Complex format"
|
|||||||
ExamMode = "Exam mode"
|
ExamMode = "Exam mode"
|
||||||
ActivateExamMode = "Activate exam mode"
|
ActivateExamMode = "Activate exam mode"
|
||||||
ExamModeActive = "Reactivate exam mode"
|
ExamModeActive = "Reactivate exam mode"
|
||||||
|
ActivateDutchExamMode = "Activate Dutch exam mode"
|
||||||
About = "About"
|
About = "About"
|
||||||
Degrees = "Degrees "
|
Degrees = "Degrees "
|
||||||
Gradians = "Gradians "
|
Gradians = "Gradians "
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ ComplexFormat = "Forma compleja"
|
|||||||
ExamMode = "Modo examen"
|
ExamMode = "Modo examen"
|
||||||
ActivateExamMode = "Activar el modo examen"
|
ActivateExamMode = "Activar el modo examen"
|
||||||
ExamModeActive = "Reactivar el modo examen"
|
ExamModeActive = "Reactivar el modo examen"
|
||||||
|
ActivateDutchExamMode = "Activate Dutch exam mode"
|
||||||
About = "Acerca"
|
About = "Acerca"
|
||||||
Degrees = "Grados "
|
Degrees = "Grados "
|
||||||
Gradians = "Gradianes "
|
Gradians = "Gradianes "
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ ComplexFormat = "Forme complexe"
|
|||||||
ExamMode = "Mode examen"
|
ExamMode = "Mode examen"
|
||||||
ActivateExamMode = "Activer le mode examen"
|
ActivateExamMode = "Activer le mode examen"
|
||||||
ExamModeActive = "Réactiver le mode examen"
|
ExamModeActive = "Réactiver le mode examen"
|
||||||
|
ActivateDutchExamMode = "Activate Dutch exam mode"
|
||||||
About = "À propos"
|
About = "À propos"
|
||||||
Degrees = "Degrés "
|
Degrees = "Degrés "
|
||||||
Gradians = "Grades "
|
Gradians = "Grades "
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ ComplexFormat = "Complexos"
|
|||||||
ExamMode = "Modo de exame"
|
ExamMode = "Modo de exame"
|
||||||
ActivateExamMode = "Ativar o modo de exame"
|
ActivateExamMode = "Ativar o modo de exame"
|
||||||
ExamModeActive = "Reativar o modo de exame"
|
ExamModeActive = "Reativar o modo de exame"
|
||||||
|
ActivateDutchExamMode = "Activate Dutch exam mode"
|
||||||
About = "Acerca"
|
About = "Acerca"
|
||||||
Degrees = "Graus "
|
Degrees = "Graus "
|
||||||
Gradians = "Grados "
|
Gradians = "Grados "
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::M
|
|||||||
|
|
||||||
//sub-menus
|
//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_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)};
|
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_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)};
|
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
|
#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, 5)};
|
||||||
@@ -26,7 +26,7 @@ constexpr SettingsMessageTree s_modelMenu[] =
|
|||||||
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren, 5),
|
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren, 5),
|
||||||
SettingsMessageTree(I18n::Message::Brightness),
|
SettingsMessageTree(I18n::Message::Brightness),
|
||||||
SettingsMessageTree(I18n::Message::Language),
|
SettingsMessageTree(I18n::Message::Language),
|
||||||
SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 3),
|
SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 4),
|
||||||
SettingsMessageTree(I18n::Message::BetaPopUp),
|
SettingsMessageTree(I18n::Message::BetaPopUp),
|
||||||
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6),
|
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6),
|
||||||
#ifdef USERNAME
|
#ifdef USERNAME
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::M
|
|||||||
|
|
||||||
//sub-menus
|
//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_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)};
|
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_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)};
|
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
|
#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, 5)};
|
||||||
@@ -27,7 +27,7 @@ constexpr SettingsMessageTree s_modelMenu[] =
|
|||||||
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren, 5),
|
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren, 5),
|
||||||
SettingsMessageTree(I18n::Message::Brightness),
|
SettingsMessageTree(I18n::Message::Brightness),
|
||||||
SettingsMessageTree(I18n::Message::Language),
|
SettingsMessageTree(I18n::Message::Language),
|
||||||
SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 3),
|
SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 4),
|
||||||
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6),
|
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6),
|
||||||
#ifdef USERNAME
|
#ifdef USERNAME
|
||||||
SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 7)};
|
SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 7)};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::M
|
|||||||
|
|
||||||
//sub-menus
|
//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_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)};
|
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_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)};
|
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
|
#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, 5)};
|
||||||
@@ -26,7 +26,7 @@ constexpr SettingsMessageTree s_modelMenu[] =
|
|||||||
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren, 5),
|
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren, 5),
|
||||||
SettingsMessageTree(I18n::Message::Brightness),
|
SettingsMessageTree(I18n::Message::Brightness),
|
||||||
SettingsMessageTree(I18n::Message::Language),
|
SettingsMessageTree(I18n::Message::Language),
|
||||||
SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 3),
|
SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 4),
|
||||||
SettingsMessageTree(I18n::Message::UpdatePopUp),
|
SettingsMessageTree(I18n::Message::UpdatePopUp),
|
||||||
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6),
|
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6),
|
||||||
#ifdef USERNAME
|
#ifdef USERNAME
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "exam_mode_controller.h"
|
#include "exam_mode_controller.h"
|
||||||
#include "../../global_preferences.h"
|
#include "../../global_preferences.h"
|
||||||
#include "../../apps_container.h"
|
#include "../../apps_container.h"
|
||||||
|
#include <apps/i18n.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <poincare/preferences.h>
|
#include <poincare/preferences.h>
|
||||||
@@ -17,17 +18,31 @@ ExamModeController::ExamModeController(Responder * parentResponder) :
|
|||||||
m_examModeCell(I18n::Message::Default, KDFont::LargeFont),
|
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)
|
m_symbolicCell(I18n::Message::SymbolicEnabled, KDFont::LargeFont)
|
||||||
|
m_cell{MessageTableCell(I18n::Message::ExamModeActive, KDFont::LargeFont), MessageTableCell(I18n::Message::ActivateDutchExamMode, KDFont::LargeFont)}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExamModeController::didEnterResponderChain(Responder * previousFirstResponder) {
|
int ExamModeController::initialSelectedRow() const {
|
||||||
m_selectableTableView.reloadData();
|
int row = selectedRow();
|
||||||
|
if (row >= numberOfRows()) {
|
||||||
|
return numberOfRows()-1;
|
||||||
|
} else if (row < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExamModeController::handleEvent(Ion::Events::Event event) {
|
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 (event == Ion::Events::OK || event == Ion::Events::EXE || event == Ion::Events::Right) {
|
||||||
if (GlobalPreferences::sharedGlobalPreferences()->examMode()) {
|
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
||||||
|
// If the exam mode is already on, this re-activate the same exam mode
|
||||||
|
mode = GlobalPreferences::sharedGlobalPreferences()->examMode();
|
||||||
|
if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive)
|
||||||
|
AppsContainer::sharedAppsContainer()->displayExamModePopUp(true);
|
||||||
|
return true;
|
||||||
|
} else if (childLabel == I18n::Message::ActivateDutchExamMode) {
|
||||||
|
mode = GlobalPreferences::ExamMode::Dutch
|
||||||
if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive)
|
if (childLabel == I18n::Message::ActivateExamMode || childLabel == I18n::Message::ExamModeActive)
|
||||||
AppsContainer::sharedAppsContainer()->displayExamModePopUp(true);
|
AppsContainer::sharedAppsContainer()->displayExamModePopUp(true);
|
||||||
return true;
|
return true;
|
||||||
@@ -53,6 +68,13 @@ bool ExamModeController::handleEvent(Ion::Events::Event event) {
|
|||||||
return GenericSubController::handleEvent(event);
|
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) {
|
HighlightCell * ExamModeController::reusableCell(int index, int type) {
|
||||||
assert(index == 0);
|
assert(index == 0);
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
@@ -76,14 +98,21 @@ int ExamModeController::reusableCellCount(int type) {
|
|||||||
assert(false);
|
assert(false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/*assert(type == 0);
|
||||||
|
assert(index >= 0 && index < k_maxNumberOfCells);
|
||||||
|
return &m_cell[index];*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*int ExamModeController::reusableCellCount(int type) {
|
||||||
|
return k_maxNumberOfCells;
|
||||||
|
}*/
|
||||||
|
|
||||||
void ExamModeController::willDisplayCellForIndex(HighlightCell * cell, int index) {
|
void ExamModeController::willDisplayCellForIndex(HighlightCell * cell, int index) {
|
||||||
Preferences * preferences = Preferences::sharedPreferences();
|
Preferences * preferences = Preferences::sharedPreferences();
|
||||||
GenericSubController::willDisplayCellForIndex(cell, index);
|
GenericSubController::willDisplayCellForIndex(cell, index);
|
||||||
I18n::Message thisLabel = m_messageTreeModel->children(index)->label();
|
I18n::Message thisLabel = m_messageTreeModel->children(index)->label();
|
||||||
|
|
||||||
if (GlobalPreferences::sharedGlobalPreferences()->examMode() && (thisLabel == I18n::Message::ActivateExamMode || thisLabel == I18n::Message::ExamModeActive)) {
|
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode() && (thisLabel == I18n::Message::ActivateExamMode || thisLabel == I18n::Message::ExamModeActive)) {
|
||||||
MessageTableCell * myCell = (MessageTableCell *)cell;
|
MessageTableCell * myCell = (MessageTableCell *)cell;
|
||||||
myCell->setMessage(I18n::Message::ExamModeActive);
|
myCell->setMessage(I18n::Message::ExamModeActive);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,17 +9,23 @@ namespace Settings {
|
|||||||
class ExamModeController : public GenericSubController {
|
class ExamModeController : public GenericSubController {
|
||||||
public:
|
public:
|
||||||
ExamModeController(Responder * parentResponder);
|
ExamModeController(Responder * parentResponder);
|
||||||
void didEnterResponderChain(Responder * previousFirstResponder) override;
|
|
||||||
bool handleEvent(Ion::Events::Event event) override;
|
bool handleEvent(Ion::Events::Event event) override;
|
||||||
|
int numberOfRows() const override;
|
||||||
HighlightCell * reusableCell(int index, int type) override;
|
HighlightCell * reusableCell(int index, int type) override;
|
||||||
int reusableCellCount(int type) override;
|
int reusableCellCount(int type) override;
|
||||||
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
||||||
int typeAtLocation(int i, int j) override;
|
int typeAtLocation(int i, int j) override;
|
||||||
private:
|
private:
|
||||||
|
<<<<<<< HEAD
|
||||||
MessageTableCell m_examModeCell;
|
MessageTableCell m_examModeCell;
|
||||||
MessageTableCellWithChevronAndMessage m_ledCell;
|
MessageTableCellWithChevronAndMessage m_ledCell;
|
||||||
PreferencesController m_preferencesController;
|
PreferencesController m_preferencesController;
|
||||||
MessageTableCellWithSwitch m_symbolicCell;
|
MessageTableCellWithSwitch m_symbolicCell;
|
||||||
|
=======
|
||||||
|
int initialSelectedRow() const override;
|
||||||
|
static constexpr int k_maxNumberOfCells = 2;
|
||||||
|
MessageTableCell m_cell[k_maxNumberOfCells];
|
||||||
|
>>>>>>> upstream/master
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,12 @@ View * GenericSubController::view() {
|
|||||||
return &m_selectableTableView;
|
return &m_selectableTableView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenericSubController::didEnterResponderChain(Responder * previousFirstResponder) {
|
||||||
|
selectCellAtLocation(0, initialSelectedRow());
|
||||||
|
m_selectableTableView.reloadData();
|
||||||
|
}
|
||||||
|
|
||||||
void GenericSubController::didBecomeFirstResponder() {
|
void GenericSubController::didBecomeFirstResponder() {
|
||||||
selectCellAtLocation(0, 0);
|
|
||||||
Container::activeApp()->setFirstResponder(&m_selectableTableView);
|
Container::activeApp()->setFirstResponder(&m_selectableTableView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,10 +79,6 @@ void GenericSubController::setMessageTreeModel(const MessageTree * messageTreeMo
|
|||||||
m_messageTreeModel = (MessageTree *)messageTreeModel;
|
m_messageTreeModel = (MessageTree *)messageTreeModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericSubController::viewWillAppear() {
|
|
||||||
m_selectableTableView.reloadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GenericSubController::viewDidDisappear() {
|
void GenericSubController::viewDidDisappear() {
|
||||||
m_selectableTableView.deselectTable();
|
m_selectableTableView.deselectTable();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public:
|
|||||||
GenericSubController(Responder * parentResponder);
|
GenericSubController(Responder * parentResponder);
|
||||||
const char * title() override;
|
const char * title() override;
|
||||||
View * view() override;
|
View * view() override;
|
||||||
|
void didEnterResponderChain(Responder * previousFirstResponder) override;
|
||||||
void didBecomeFirstResponder() override;
|
void didBecomeFirstResponder() override;
|
||||||
bool handleEvent(Ion::Events::Event event) override;
|
bool handleEvent(Ion::Events::Event event) override;
|
||||||
int numberOfRows() const override;
|
int numberOfRows() const override;
|
||||||
@@ -20,10 +21,10 @@ public:
|
|||||||
virtual int typeAtLocation(int i, int j) override;
|
virtual int typeAtLocation(int i, int j) override;
|
||||||
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
||||||
void setMessageTreeModel(const MessageTree * messageTreeModel);
|
void setMessageTreeModel(const MessageTree * messageTreeModel);
|
||||||
void viewWillAppear() override;
|
|
||||||
void viewDidDisappear() override;
|
void viewDidDisappear() override;
|
||||||
protected:
|
protected:
|
||||||
StackViewController * stackController() const;
|
StackViewController * stackController() const;
|
||||||
|
virtual int initialSelectedRow() const { return 0; }
|
||||||
constexpr static KDCoordinate k_topBottomMargin = 13;
|
constexpr static KDCoordinate k_topBottomMargin = 13;
|
||||||
SelectableTableView m_selectableTableView;
|
SelectableTableView m_selectableTableView;
|
||||||
MessageTree * m_messageTreeModel;
|
MessageTree * m_messageTreeModel;
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ PreferencesController::PreferencesController(Responder * parentResponder) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PreferencesController::didBecomeFirstResponder() {
|
void PreferencesController::didBecomeFirstResponder() {
|
||||||
selectCellAtLocation(0, valueIndexForPreference(m_messageTreeModel->label()));
|
|
||||||
Container::activeApp()->setFirstResponder(&m_selectableTableView);
|
Container::activeApp()->setFirstResponder(&m_selectableTableView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +187,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();
|
Preferences * preferences = Preferences::sharedPreferences();
|
||||||
if (message == I18n::Message::AngleUnit) {
|
if (message == I18n::Message::AngleUnit) {
|
||||||
return (int)preferences->angleUnit();
|
return (int)preferences->angleUnit();
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ protected:
|
|||||||
constexpr static int k_totalNumberOfCell = 4;
|
constexpr static int k_totalNumberOfCell = 4;
|
||||||
private:
|
private:
|
||||||
constexpr static const KDFont * k_layoutFont = KDFont::SmallFont;
|
constexpr static const KDFont * k_layoutFont = KDFont::SmallFont;
|
||||||
|
int initialSelectedRow() const override { return valueIndexForPreference(m_messageTreeModel->label()); }
|
||||||
Poincare::Layout layoutForPreferences(I18n::Message message);
|
Poincare::Layout layoutForPreferences(I18n::Message message);
|
||||||
void setPreferenceWithValueIndex(I18n::Message message, int valueIndex);
|
void setPreferenceWithValueIndex(I18n::Message message, int valueIndex);
|
||||||
int valueIndexForPreference(I18n::Message message);
|
int valueIndexForPreference(I18n::Message message) const;
|
||||||
MessageTableCellWithExpression m_cells[k_totalNumberOfCell];
|
MessageTableCellWithExpression m_cells[k_totalNumberOfCell];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ ActivateDeactivate = "Aktivieren/Deaktivieren"
|
|||||||
ActiveExamModeMessage1 = "Alle Ihre Daten werden "
|
ActiveExamModeMessage1 = "Alle Ihre Daten werden "
|
||||||
ActiveExamModeMessage2 = "gelöscht, wenn Sie den "
|
ActiveExamModeMessage2 = "gelöscht, wenn Sie den "
|
||||||
ActiveExamModeMessage3 = "Testmodus einschalten."
|
ActiveExamModeMessage3 = "Testmodus einschalten."
|
||||||
|
ActiveDutchExamModeMessage1 = "All your data will be deleted when"
|
||||||
|
ActiveDutchExamModeMessage2 = "you activate the exam mode. Python"
|
||||||
|
ActiveDutchExamModeMessage3 = "application will be unavailable."
|
||||||
Axis = "Achsen"
|
Axis = "Achsen"
|
||||||
Cancel = "Abbrechen"
|
Cancel = "Abbrechen"
|
||||||
ClearColumn = "Spalte löschen"
|
ClearColumn = "Spalte löschen"
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ ActivateDeactivate = "Turn on/off"
|
|||||||
ActiveExamModeMessage1 = "All your data will be "
|
ActiveExamModeMessage1 = "All your data will be "
|
||||||
ActiveExamModeMessage2 = "deleted when you activate "
|
ActiveExamModeMessage2 = "deleted when you activate "
|
||||||
ActiveExamModeMessage3 = "the exam mode."
|
ActiveExamModeMessage3 = "the exam mode."
|
||||||
|
ActiveDutchExamModeMessage1 = "All your data will be deleted when"
|
||||||
|
ActiveDutchExamModeMessage2 = "you activate the exam mode. Python"
|
||||||
|
ActiveDutchExamModeMessage3 = "application will be unavailable."
|
||||||
Axis = "Axes"
|
Axis = "Axes"
|
||||||
Cancel = "Cancel"
|
Cancel = "Cancel"
|
||||||
ClearColumn = "Clear column"
|
ClearColumn = "Clear column"
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ ActivateDeactivate = "Activar/Desactivar"
|
|||||||
ActiveExamModeMessage1 = "Todos sus datos se "
|
ActiveExamModeMessage1 = "Todos sus datos se "
|
||||||
ActiveExamModeMessage2 = "eliminaran al activar "
|
ActiveExamModeMessage2 = "eliminaran al activar "
|
||||||
ActiveExamModeMessage3 = "el modo examen."
|
ActiveExamModeMessage3 = "el modo examen."
|
||||||
|
ActiveDutchExamModeMessage1 = "All your data will be deleted when"
|
||||||
|
ActiveDutchExamModeMessage2 = "you activate the exam mode. Python"
|
||||||
|
ActiveDutchExamModeMessage3 = "application will be unavailable."
|
||||||
Axis = "Ejes"
|
Axis = "Ejes"
|
||||||
Cancel = "Cancelar"
|
Cancel = "Cancelar"
|
||||||
ClearColumn = "Borrar la columna"
|
ClearColumn = "Borrar la columna"
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ ActivateDeactivate = "Activer/Désactiver"
|
|||||||
ActiveExamModeMessage1 = "Toutes vos données seront "
|
ActiveExamModeMessage1 = "Toutes vos données seront "
|
||||||
ActiveExamModeMessage2 = "supprimées si vous activez "
|
ActiveExamModeMessage2 = "supprimées si vous activez "
|
||||||
ActiveExamModeMessage3 = "le mode examen."
|
ActiveExamModeMessage3 = "le mode examen."
|
||||||
|
ActiveDutchExamModeMessage1 = "All your data will be deleted when"
|
||||||
|
ActiveDutchExamModeMessage2 = "you activate the exam mode. Python"
|
||||||
|
ActiveDutchExamModeMessage3 = "application will be unavailable."
|
||||||
Axis = "Axes"
|
Axis = "Axes"
|
||||||
Cancel = "Annuler"
|
Cancel = "Annuler"
|
||||||
ClearColumn = "Effacer la colonne"
|
ClearColumn = "Effacer la colonne"
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ ActivateDeactivate = "Activar/Desactivar"
|
|||||||
ActiveExamModeMessage1 = "Todos os seus dados serão "
|
ActiveExamModeMessage1 = "Todos os seus dados serão "
|
||||||
ActiveExamModeMessage2 = "apagados se você ligar "
|
ActiveExamModeMessage2 = "apagados se você ligar "
|
||||||
ActiveExamModeMessage3 = "o modo de exame."
|
ActiveExamModeMessage3 = "o modo de exame."
|
||||||
|
ActiveDutchExamModeMessage1 = "All your data will be deleted when"
|
||||||
|
ActiveDutchExamModeMessage2 = "you activate the exam mode. Python"
|
||||||
|
ActiveDutchExamModeMessage3 = "application will be unavailable."
|
||||||
Axis = "Eixos"
|
Axis = "Eixos"
|
||||||
Cancel = "Cancelar"
|
Cancel = "Cancelar"
|
||||||
ClearColumn = "Excluir coluna"
|
ClearColumn = "Excluir coluna"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "equation_store.h"
|
#include "equation_store.h"
|
||||||
#include "../constant.h"
|
#include "../constant.h"
|
||||||
#include "../shared/poincare_helpers.h"
|
#include "../shared/poincare_helpers.h"
|
||||||
|
#include "../global_preferences.h"
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#include <poincare/constant.h>
|
#include <poincare/constant.h>
|
||||||
@@ -193,6 +194,8 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Create the results' layouts
|
// Create the results' layouts
|
||||||
|
// In Dutch exam mode, display only approximate solutions
|
||||||
|
bool forbidExactSolutions = GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Dutch;
|
||||||
int solutionIndex = 0;
|
int solutionIndex = 0;
|
||||||
int initialNumberOfSolutions = m_numberOfSolutions <= k_maxNumberOfExactSolutions ? m_numberOfSolutions : -1;
|
int initialNumberOfSolutions = m_numberOfSolutions <= k_maxNumberOfExactSolutions ? m_numberOfSolutions : -1;
|
||||||
// We iterate through the solutions and the potential delta
|
// We iterate through the solutions and the potential delta
|
||||||
@@ -211,7 +214,9 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
|
|||||||
char approximateBuffer[::Constant::MaxSerializedExpressionSize];
|
char approximateBuffer[::Constant::MaxSerializedExpressionSize];
|
||||||
m_exactSolutionExactLayouts[solutionIndex].serializeForParsing(exactBuffer, ::Constant::MaxSerializedExpressionSize);
|
m_exactSolutionExactLayouts[solutionIndex].serializeForParsing(exactBuffer, ::Constant::MaxSerializedExpressionSize);
|
||||||
m_exactSolutionApproximateLayouts[solutionIndex].serializeForParsing(approximateBuffer, ::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]) {
|
if (!m_exactSolutionIdentity[solutionIndex]) {
|
||||||
char buffer[::Constant::MaxSerializedExpressionSize];
|
char buffer[::Constant::MaxSerializedExpressionSize];
|
||||||
m_exactSolutionEquality[solutionIndex] = exactSolutions[i].isEqualToItsApproximationLayout(exactSolutionsApproximations[i], buffer, ::Constant::MaxSerializedExpressionSize, preferences->complexFormat(), preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), context);
|
m_exactSolutionEquality[solutionIndex] = exactSolutions[i].isEqualToItsApproximationLayout(exactSolutionsApproximations[i], buffer, ::Constant::MaxSerializedExpressionSize, preferences->complexFormat(), preferences->angleUnit(), preferences->displayMode(), preferences->numberOfSignificantDigits(), context);
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ void TitleBarView::layoutSubviews() {
|
|||||||
m_preferenceView.setFrame(KDRect(Metric::TitleBarExternHorizontalMargin, 0, m_preferenceView.minimalSizeForOptimalDisplay().width(), bounds().height()));
|
m_preferenceView.setFrame(KDRect(Metric::TitleBarExternHorizontalMargin, 0, m_preferenceView.minimalSizeForOptimalDisplay().width(), bounds().height()));
|
||||||
KDSize batterySize = m_batteryView.minimalSizeForOptimalDisplay();
|
KDSize batterySize = m_batteryView.minimalSizeForOptimalDisplay();
|
||||||
m_batteryView.setFrame(KDRect(bounds().width() - batterySize.width() - Metric::TitleBarExternHorizontalMargin, (bounds().height()- batterySize.height())/2, batterySize));
|
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));
|
m_examModeIconView.setFrame(KDRect(k_examIconMargin, (bounds().height() - k_examIconHeight)/2, k_examIconWidth, k_examIconHeight));
|
||||||
} else {
|
} else {
|
||||||
m_examModeIconView.setFrame(KDRectZero);
|
m_examModeIconView.setFrame(KDRectZero);
|
||||||
|
|||||||
@@ -60,22 +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)
|
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.ram.$(EXE): $(call object_for,$(bench_src))
|
||||||
$(BUILD_DIR)/bench.flash.$(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 -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
|
|
||||||
$(Q) printf "\xFF\xFF\xFF\xFF" >> $(basename $<).internal.bin
|
|
||||||
|
|
||||||
.PHONY: binpack
|
|
||||||
binpack: $(BUILD_DIR)/flasher.light.bin $(BUILD_DIR)/epsilon.onboarding.two_binaries
|
|
||||||
rm -rf $(BUILD_DIR)/binpack
|
|
||||||
mkdir -p $(BUILD_DIR)/binpack
|
|
||||||
cp $(BUILD_DIR)/flasher.light.bin $(BUILD_DIR)/binpack
|
|
||||||
cp $(BUILD_DIR)/epsilon.onboarding.internal.bin $(BUILD_DIR)/epsilon.onboarding.external.bin $(BUILD_DIR)/binpack
|
|
||||||
cd $(BUILD_DIR) && for binary in flasher.light.bin epsilon.onboarding.internal.bin epsilon.onboarding.external.bin; do shasum -a 256 -b binpack/$${binary} > binpack/$${binary}.sha256;done
|
|
||||||
cd $(BUILD_DIR) && tar cvfz binpack-$(MODEL)-`git rev-parse HEAD | head -c 7`.tgz binpack/*
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,3 +19,31 @@ $(BUILD_DIR)/test.external_flash.write.$(EXE): $(BUILD_DIR)/quiz/src/test_ion_ex
|
|||||||
sleep 2; \
|
sleep 2; \
|
||||||
fi
|
fi
|
||||||
$(Q) $(PYTHON) build/device/dfu.py -u $(word 1,$^)
|
$(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
|
||||||
|
|||||||
@@ -5,16 +5,17 @@
|
|||||||
|
|
||||||
class Responder {
|
class Responder {
|
||||||
public:
|
public:
|
||||||
Responder(Responder * parentResponder);
|
Responder(Responder * parentResponder) : m_parentResponder(parentResponder) {}
|
||||||
virtual bool handleEvent(Ion::Events::Event event) { return false; }; // Default implementation does nothing
|
virtual bool handleEvent(Ion::Events::Event event) { return false; }; // Default implementation does nothing
|
||||||
virtual void didBecomeFirstResponder();
|
virtual void didBecomeFirstResponder() {}
|
||||||
virtual void willResignFirstResponder();
|
virtual void willResignFirstResponder() {}
|
||||||
virtual void didEnterResponderChain(Responder * previousFirstResponder);
|
virtual void didEnterResponderChain(Responder * previousFirstResponder) {}
|
||||||
virtual void willExitResponderChain(Responder * nextFirstResponder);
|
virtual void willExitResponderChain(Responder * nextFirstResponder) {}
|
||||||
Responder * parentResponder() const;
|
Responder * parentResponder() const { return m_parentResponder; }
|
||||||
Responder * commonAncestorWith(Responder * responder);
|
Responder * commonAncestorWith(Responder * responder);
|
||||||
void setParentResponder(Responder * responder);
|
void setParentResponder(Responder * responder) { m_parentResponder = responder; }
|
||||||
private:
|
private:
|
||||||
|
bool hasAncestor(Responder * responder) const;
|
||||||
Responder * m_parentResponder;
|
Responder * m_parentResponder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,62 +2,29 @@
|
|||||||
#include <escher/container.h>
|
#include <escher/container.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
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) {
|
Responder * Responder::commonAncestorWith(Responder * responder) {
|
||||||
if (responder == nullptr) {
|
if (responder == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (this == responder) {
|
Responder * p = this;
|
||||||
return this;
|
while (p != nullptr) {
|
||||||
|
if (responder->hasAncestor(p)) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
p = p->parentResponder();
|
||||||
}
|
}
|
||||||
Responder * rootResponder = this;
|
return nullptr;
|
||||||
while (rootResponder->parentResponder() != responder && rootResponder->parentResponder() != nullptr) {
|
}
|
||||||
rootResponder = rootResponder->parentResponder();
|
|
||||||
}
|
bool Responder::hasAncestor(Responder * responder) const {
|
||||||
if (rootResponder->parentResponder() == responder) {
|
assert(responder != nullptr);
|
||||||
return responder;
|
Responder * p = const_cast<Responder *>(this);
|
||||||
}
|
while (p != nullptr) {
|
||||||
rootResponder = responder;
|
if (p == responder) {
|
||||||
while (rootResponder->parentResponder() != this && rootResponder->parentResponder() != nullptr) {
|
return true;
|
||||||
rootResponder = rootResponder->parentResponder();
|
}
|
||||||
}
|
p = p->parentResponder();
|
||||||
if (rootResponder->parentResponder() == this) {
|
}
|
||||||
return this;
|
return false;
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
#ifndef ION_EXAM_MODE_H
|
#ifndef ION_EXAM_MODE_H
|
||||||
#define ION_EXAM_MODE_H
|
#define ION_EXAM_MODE_H
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <stdint.h>
|
||||||
|
}
|
||||||
|
|
||||||
namespace Ion {
|
namespace Ion {
|
||||||
namespace ExamMode {
|
namespace ExamMode {
|
||||||
|
|
||||||
bool FetchExamMode();
|
uint8_t FetchExamMode();
|
||||||
void ToggleExamMode();
|
void IncrementExamMode(uint8_t delta);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,20 +19,5 @@ ion_src += $(addprefix ion/src/shared/, \
|
|||||||
|
|
||||||
ION_DEVICE_SFLAGS = -Iion/src/device/$(MODEL) -Iion/src/device/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)
|
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
|
|
||||||
|
|||||||
@@ -22,7 +22,10 @@ using namespace Regs;
|
|||||||
|
|
||||||
constexpr static uint32_t StartAddress = 0xFFFFFFFF;
|
constexpr static uint32_t StartAddress = 0xFFFFFFFF;
|
||||||
constexpr static uint32_t EndAddress = 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[] = {};
|
constexpr static AFGPIOPin Pins[] = {};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,43 +7,39 @@ namespace Cache {
|
|||||||
using namespace Regs;
|
using namespace Regs;
|
||||||
|
|
||||||
void privateCleanInvalidateDisableDCache(bool clean, bool invalidate, bool disable) {
|
void privateCleanInvalidateDisableDCache(bool clean, bool invalidate, bool disable) {
|
||||||
|
// Select Level 1 data cache
|
||||||
CORTEX.CSSELR()->set(0);
|
CORTEX.CSSELR()->set(0);
|
||||||
dsb();
|
dsb();
|
||||||
|
|
||||||
// Associativity = 6
|
// Disable D-Cache
|
||||||
|
|
||||||
uint32_t sets = CORTEX.CCSIDR()->getNUMSETS();
|
|
||||||
uint32_t ways = CORTEX.CCSIDR()->getASSOCIATIVITY();
|
|
||||||
|
|
||||||
if (disable) {
|
if (disable) {
|
||||||
CORTEX.CCR()->setDC(false);
|
CORTEX.CCR()->setDC(false);
|
||||||
dsb();
|
dsb();
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
// Pick the right DC??SW register according to invalidate/disable parameters
|
||||||
uint32_t w = ways;
|
volatile CORTEX::DCSW * target = nullptr;
|
||||||
do {
|
if (clean && invalidate) {
|
||||||
if (clean) {
|
target = CORTEX.DCCISW();
|
||||||
if (invalidate) {
|
} else if (clean) {
|
||||||
class CORTEX::DCCISW dccisw;
|
target = CORTEX.DCCSW();
|
||||||
dccisw.setSET(sets);
|
} else {
|
||||||
dccisw.setWAY(w);
|
assert(invalidate);
|
||||||
CORTEX.DCCISW()->set(dccisw);
|
target = CORTEX.DCISW();
|
||||||
} else {
|
}
|
||||||
class CORTEX::DCCSW dccsw;
|
|
||||||
dccsw.setSET(sets);
|
class CORTEX::CCSIDR ccsidr = CORTEX.CCSIDR()->get();
|
||||||
dccsw.setWAY(w);
|
uint32_t sets = ccsidr.getNUMSETS();
|
||||||
CORTEX.DCCSW()->set(dccsw);
|
uint32_t ways = ccsidr.getASSOCIATIVITY();
|
||||||
}
|
|
||||||
} else if (invalidate) {
|
for (int set = sets; set >= 0; set--) {
|
||||||
class CORTEX::DCISW dcisw;
|
for (int way = ways; way >= 0; way--) {
|
||||||
dcisw.setSET(sets);
|
class CORTEX::DCSW dcsw;
|
||||||
dcisw.setWAY(w);
|
dcsw.setSET(set);
|
||||||
CORTEX.DCISW()->set(dcisw);
|
dcsw.setWAY(way);
|
||||||
}
|
target->set(dcsw);
|
||||||
__asm volatile("nop");
|
}
|
||||||
} while (w-- != 0);
|
}
|
||||||
} while (sets-- != 0);
|
|
||||||
|
|
||||||
dsb();
|
dsb();
|
||||||
isb();
|
isb();
|
||||||
@@ -69,7 +65,7 @@ void cleanDCache() {
|
|||||||
|
|
||||||
void enableDCache() {
|
void enableDCache() {
|
||||||
invalidateDCache();
|
invalidateDCache();
|
||||||
CORTEX.CCR()->setDC(true);
|
CORTEX.CCR()->setDC(true); // Enable D-cache
|
||||||
dsb();
|
dsb();
|
||||||
isb();
|
isb();
|
||||||
}
|
}
|
||||||
@@ -81,14 +77,14 @@ void disableDCache() {
|
|||||||
void invalidateICache() {
|
void invalidateICache() {
|
||||||
dsb();
|
dsb();
|
||||||
isb();
|
isb();
|
||||||
CORTEX.ICIALLU()->set(0);
|
CORTEX.ICIALLU()->set(0); // Invalidate I-cache
|
||||||
dsb();
|
dsb();
|
||||||
isb();
|
isb();
|
||||||
}
|
}
|
||||||
|
|
||||||
void enableICache() {
|
void enableICache() {
|
||||||
invalidateICache();
|
invalidateICache();
|
||||||
CORTEX.CCR()->setIC(true);
|
CORTEX.CCR()->setIC(true); // Enable I-cache
|
||||||
dsb();
|
dsb();
|
||||||
isb();
|
isb();
|
||||||
}
|
}
|
||||||
@@ -96,8 +92,10 @@ void enableICache() {
|
|||||||
void disableICache() {
|
void disableICache() {
|
||||||
dsb();
|
dsb();
|
||||||
isb();
|
isb();
|
||||||
CORTEX.CCR()->setIC(false);
|
CORTEX.CCR()->setIC(false); // Disable I-cache
|
||||||
invalidateICache();
|
CORTEX.ICIALLU()->set(0); // Invalidate I-cache
|
||||||
|
dsb();
|
||||||
|
isb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,12 @@ using namespace Regs;
|
|||||||
|
|
||||||
constexpr static uint32_t StartAddress = 0x90000000;
|
constexpr static uint32_t StartAddress = 0x90000000;
|
||||||
constexpr static uint32_t EndAddress = 0x90800000;
|
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[] = {
|
constexpr static AFGPIOPin Pins[] = {
|
||||||
AFGPIOPin(GPIOB, 2, GPIO::AFR::AlternateFunction::AF9, GPIO::PUPDR::Pull::None, GPIO::OSPEEDR::OutputSpeed::Fast),
|
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),
|
AFGPIOPin(GPIOB, 6, GPIO::AFR::AlternateFunction::AF10, GPIO::PUPDR::Pull::None, GPIO::OSPEEDR::OutputSpeed::Fast),
|
||||||
|
|||||||
@@ -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 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 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";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace LED {
|
|||||||
|
|
||||||
KDColor updateColorWithPlugAndCharge() {
|
KDColor updateColorWithPlugAndCharge() {
|
||||||
KDColor ledColor = getColor();
|
KDColor ledColor = getColor();
|
||||||
if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { // 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()) {
|
if (USB::isPlugged()) {
|
||||||
ledColor = Battery::isCharging() ? KDColorOrange : KDColorGreen;
|
ledColor = Battery::isCharging() ? KDColorOrange : KDColorGreen;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
namespace Ion {
|
|
||||||
namespace ExamMode {
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
extern char _exam_mode_buffer_start;
|
extern char _exam_mode_buffer_start;
|
||||||
extern char _exam_mode_buffer_end;
|
extern char _exam_mode_buffer_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Ion {
|
||||||
|
namespace ExamMode {
|
||||||
|
|
||||||
char ones[Config::ExamModeBufferSize]
|
char ones[Config::ExamModeBufferSize]
|
||||||
__attribute__((section(".exam_mode_buffer")))
|
__attribute__((section(".exam_mode_buffer")))
|
||||||
__attribute__((used))
|
__attribute__((used))
|
||||||
@@ -18,33 +18,24 @@ char ones[Config::ExamModeBufferSize]
|
|||||||
|
|
||||||
/* The exam mode is written in flash so that it is resilient to resets.
|
/* 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
|
* 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
|
* deactivating or activating standard or Dutch exam mode we write one or two
|
||||||
* if we are in exam mode, we count the number of leading 0 bits. If it is even,
|
* bits to 0. To determine in which exam mode we are, we count the number of
|
||||||
* the exam mode is deactivated, if it is odd, the exam mode is activated. */
|
* 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
|
/* 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
|
* flash sector that does not point to 0. If this flash sector has only 0s or
|
||||||
* is erased (to 1) and significantExamModeAddress returns the start of the
|
* if it has only one 1, it is erased (to 1) and significantExamModeAddress
|
||||||
* sector. */
|
* returns the start of the sector. */
|
||||||
|
|
||||||
uint32_t * SignificantExamModeAddress() {
|
constexpr static size_t numberOfBitsInByte = 8;
|
||||||
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_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t firstOneBit(int i, size_t size) {
|
// if i = 0b000011101, firstOneBitInByte(i) returns 5
|
||||||
|
size_t numberOfBitsAfterLeadingZeroes(int i) {
|
||||||
int minShift = 0;
|
int minShift = 0;
|
||||||
int maxShift = size;
|
int maxShift = numberOfBitsInByte;
|
||||||
while (maxShift > minShift+1) {
|
while (maxShift > minShift+1) {
|
||||||
int shift = (minShift + maxShift)/2;
|
int shift = (minShift + maxShift)/2;
|
||||||
int shifted = i >> shift;
|
int shifted = i >> shift;
|
||||||
@@ -57,23 +48,72 @@ size_t firstOneBit(int i, size_t size) {
|
|||||||
return maxShift;
|
return maxShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FetchExamMode() {
|
uint8_t * SignificantExamModeAddress() {
|
||||||
uint32_t * readingAddress = SignificantExamModeAddress();
|
uint32_t * persitence_start_32 = (uint32_t *)&_exam_mode_buffer_start;
|
||||||
size_t numberOfLeading0 = 32 - firstOneBit(*readingAddress, 32);
|
uint32_t * persitence_end_32 = (uint32_t *)&_exam_mode_buffer_end;
|
||||||
return numberOfLeading0 % 2 == 1;
|
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++;
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToggleExamMode() {
|
uint8_t FetchExamMode() {
|
||||||
uint32_t * writingAddress = SignificantExamModeAddress();
|
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;
|
||||||
|
// Count the number of 0[3] at reading address
|
||||||
|
size_t numberOfLeading0 = (numberOfBitsInByte - numberOfBitsAfterLeadingZeroes(*readingAddress)) % 3;
|
||||||
|
return (nbOfZerosBefore + numberOfLeading0) % 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IncrementExamMode(uint8_t delta) {
|
||||||
|
assert(delta == 1 || delta == 2);
|
||||||
|
uint8_t * writingAddress = SignificantExamModeAddress();
|
||||||
assert(*writingAddress != 0);
|
assert(*writingAddress != 0);
|
||||||
// Compute the new value with one bit switched
|
size_t nbOfTargetedOnes = numberOfBitsAfterLeadingZeroes(*writingAddress);
|
||||||
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
|
// Compute the new value with delta bits switched to 0.
|
||||||
* the fifth bit in a byte, we can thus write "11110111". */
|
/* We write in 2 bytes instead of 1, in case there was only one bit
|
||||||
uint32_t newValue = ~(1 << (31 - numberOfLeadingZeroes));
|
* left to 1 in writingAddress. */
|
||||||
|
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
|
// Write the value in flash
|
||||||
Ion::Device::Flash::WriteMemory((uint8_t *)writingAddress, (uint8_t *)&newValue, sizeof(uint32_t));
|
/* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ enum class Command : uint8_t {
|
|||||||
Reset = 0x99,
|
Reset = 0x99,
|
||||||
// Erase the whole chip or a 64-Kbyte block as being "1"
|
// Erase the whole chip or a 64-Kbyte block as being "1"
|
||||||
ChipErase = 0xC7,
|
ChipErase = 0xC7,
|
||||||
|
Erase4KbyteBlock = 0x20,
|
||||||
|
Erase32KbyteBlock = 0x52,
|
||||||
Erase64KbyteBlock = 0xD8,
|
Erase64KbyteBlock = 0xD8,
|
||||||
SetReadParameters = 0xC0,
|
SetReadParameters = 0xC0,
|
||||||
DeepPowerDown = 0xB9,
|
DeepPowerDown = 0xB9,
|
||||||
@@ -79,6 +81,8 @@ enum class Command : uint8_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static constexpr uint8_t NumberOfAddressBitsIn64KbyteBlock = 16;
|
static constexpr uint8_t NumberOfAddressBitsIn64KbyteBlock = 16;
|
||||||
|
static constexpr uint8_t NumberOfAddressBitsIn32KbyteBlock = 15;
|
||||||
|
static constexpr uint8_t NumberOfAddressBitsIn4KbyteBlock = 12;
|
||||||
|
|
||||||
class ExternalFlashStatusRegister {
|
class ExternalFlashStatusRegister {
|
||||||
public:
|
public:
|
||||||
@@ -367,10 +371,23 @@ void shutdown() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int SectorAtAddress(uint32_t address) {
|
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;
|
int i = address >> NumberOfAddressBitsIn64KbyteBlock;
|
||||||
if (i >= Config::NumberOfSectors) {
|
if (i > Config::NumberOf64KSectors) {
|
||||||
return -1;
|
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;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,7 +425,22 @@ void __attribute__((noinline)) EraseSector(int i) {
|
|||||||
unlockFlash();
|
unlockFlash();
|
||||||
send_command(Command::WriteEnable);
|
send_command(Command::WriteEnable);
|
||||||
wait();
|
wait();
|
||||||
send_write_command(Command::Erase64KbyteBlock, reinterpret_cast<uint8_t *>(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<uint8_t *>(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<uint8_t *>((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<uint8_t *>((i - Config::NumberOf4KSectors - Config::NumberOf32KSectors + 1) << NumberOfAddressBitsIn64KbyteBlock), nullptr, 0);
|
||||||
|
}
|
||||||
wait();
|
wait();
|
||||||
set_as_memory_mapped();
|
set_as_memory_mapped();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,12 @@
|
|||||||
* 2^7 64KiB blocks 0x..0000 - 0x..FFFF
|
* 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 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 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 Ion {
|
||||||
namespace Device {
|
namespace Device {
|
||||||
|
|||||||
@@ -12,7 +12,13 @@ using namespace Regs;
|
|||||||
|
|
||||||
void core() {
|
void core() {
|
||||||
// Perform a full core reset
|
// Perform a full core reset
|
||||||
|
Ion::Device::Cache::dsb(); // Complete all memory accesses
|
||||||
CORTEX.AIRCR()->requestReset();
|
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
|
/* We isolate the jump code that needs to be executed from the internal
|
||||||
@@ -41,8 +47,7 @@ void __attribute__((noinline)) internalFlashJump(uint32_t jumpIsrVectorAddress)
|
|||||||
|
|
||||||
void jump(uint32_t jumpIsrVectorAddress) {
|
void jump(uint32_t jumpIsrVectorAddress) {
|
||||||
// Disable cache before reset
|
// Disable cache before reset
|
||||||
Ion::Device::Cache::disableDCache();
|
Ion::Device::Cache::disable();
|
||||||
Ion::Device::Cache::disableICache();
|
|
||||||
|
|
||||||
/* Shutdown all clocks and periherals to mimic a hardware reset. */
|
/* Shutdown all clocks and periherals to mimic a hardware reset. */
|
||||||
Board::shutdownPeripherals();
|
Board::shutdownPeripherals();
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ public:
|
|||||||
#if REGS_CORTEX_CONFIG_CACHE
|
#if REGS_CORTEX_CONFIG_CACHE
|
||||||
class CCSIDR : public Register32 {
|
class CCSIDR : public Register32 {
|
||||||
public:
|
public:
|
||||||
|
using Register32::Register32;
|
||||||
REGS_FIELD(ASSOCIATIVITY, uint16_t, 12, 3);
|
REGS_FIELD(ASSOCIATIVITY, uint16_t, 12, 3);
|
||||||
REGS_FIELD(NUMSETS, uint16_t, 27, 13);
|
REGS_FIELD(NUMSETS, uint16_t, 27, 13);
|
||||||
};
|
};
|
||||||
@@ -100,25 +101,20 @@ public:
|
|||||||
using Register32::Register32;
|
using Register32::Register32;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DCISW : public Register32 {
|
class DCSW : public Register32 {
|
||||||
public:
|
public:
|
||||||
DCISW() : Register32(0) {}
|
DCSW() : Register32(0) {}
|
||||||
REGS_FIELD(SET, uint16_t, 13, 5);
|
REGS_FIELD(SET, uint16_t, 13, 5);
|
||||||
REGS_FIELD(WAY, uint8_t, 31, 30);
|
REGS_FIELD(WAY, uint8_t, 31, 30);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DCCSW : public Register32 {
|
class DCISW : public DCSW {
|
||||||
public:
|
|
||||||
DCCSW() : Register32(0) {}
|
|
||||||
REGS_FIELD(SET, uint16_t, 13, 5);
|
|
||||||
REGS_FIELD(WAY, uint8_t, 31, 30);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DCCISW : public Register32 {
|
class DCCSW : public DCSW {
|
||||||
public:
|
};
|
||||||
DCCISW() : Register32(0) {}
|
|
||||||
REGS_FIELD(SET, uint16_t, 13, 5);
|
class DCCISW : public DCSW {
|
||||||
REGS_FIELD(WAY, uint8_t, 31, 30);
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define always_inline __attribute__((always_inline))
|
||||||
|
|
||||||
namespace Ion {
|
namespace Ion {
|
||||||
namespace Device {
|
namespace Device {
|
||||||
namespace Regs {
|
namespace Regs {
|
||||||
@@ -22,7 +24,7 @@ public:
|
|||||||
T get() volatile {
|
T get() volatile {
|
||||||
return m_value;
|
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);
|
m_value = bit_range_set_value(high, low, m_value, value);
|
||||||
}
|
}
|
||||||
T getBitRange(uint8_t high, uint8_t low) volatile {
|
T getBitRange(uint8_t high, uint8_t low) volatile {
|
||||||
@@ -57,8 +59,8 @@ typedef Register<uint64_t> Register64;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define REGS_FIELD_R(name,type,high,low) type get##name() volatile { return (type)getBitRange(high,low); };
|
#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) void set##name(type v) volatile { static_assert(sizeof(type) <= 4, "Invalid size"); setBitRange(high, low, static_cast<uint32_t>(v)); };
|
#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<uint32_t>(v)); };
|
||||||
#define REGS_FIELD(name,type,high,low) REGS_FIELD_R(name,type,high,low); REGS_FIELD_W(name,type,high,low);
|
#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_TYPE_FIELD(name,high,low) REGS_FIELD(name,name,high,low)
|
||||||
#define REGS_BOOL_FIELD(name,bit) REGS_FIELD(name,bool,bit,bit)
|
#define REGS_BOOL_FIELD(name,bit) REGS_FIELD(name,bool,bit,bit)
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
namespace Ion {
|
namespace Ion {
|
||||||
namespace ExamMode {
|
namespace ExamMode {
|
||||||
|
|
||||||
bool FetchExamMode() {
|
uint8_t FetchExamMode() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToggleExamMode() {
|
void IncrementExamMode(uint8_t delta) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,5 +46,6 @@ constexpr KDColor KDColorGreen = KDColor::RGB24(0x00FF00);
|
|||||||
constexpr KDColor KDColorBlue = KDColor::RGB24(0x0000FF);
|
constexpr KDColor KDColorBlue = KDColor::RGB24(0x0000FF);
|
||||||
constexpr KDColor KDColorYellow = KDColor::RGB24(0xFFFF00);
|
constexpr KDColor KDColorYellow = KDColor::RGB24(0xFFFF00);
|
||||||
constexpr KDColor KDColorOrange = KDColor::RGB24(0xFF9900);
|
constexpr KDColor KDColorOrange = KDColor::RGB24(0xFF9900);
|
||||||
|
constexpr KDColor KDColorPurple = KDColor::RGB24(0xFF00DD);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
namespace Poincare {
|
namespace Poincare {
|
||||||
|
|
||||||
namespace ApproximationHelper {
|
namespace ApproximationHelper {
|
||||||
|
template <typename T> int PositiveIntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit);
|
||||||
template <typename T> std::complex<T> TruncateRealOrImaginaryPartAccordingToArgument(std::complex<T> c);
|
template <typename T> std::complex<T> TruncateRealOrImaginaryPartAccordingToArgument(std::complex<T> c);
|
||||||
|
|
||||||
template <typename T> using ComplexCompute = Complex<T>(*)(const std::complex<T>, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit);
|
template <typename T> using ComplexCompute = Complex<T>(*)(const std::complex<T>, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit);
|
||||||
|
|||||||
@@ -15,6 +15,18 @@ template <typename T> T absMod(T a, T b) {
|
|||||||
return result > b/2 ? b-result : result;
|
return result > b/2 ? b-result : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int absInt(int x) { return x < 0 ? -x : x; }
|
||||||
|
|
||||||
|
template <typename T> int ApproximationHelper::PositiveIntegerApproximationIfPossible(const ExpressionNode * expression, bool * isUndefined, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) {
|
||||||
|
Evaluation<T> 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 <typename T> std::complex<T> ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex<T> c) {
|
template <typename T> std::complex<T> ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument(std::complex<T> c) {
|
||||||
T arg = std::arg(c);
|
T arg = std::arg(c);
|
||||||
T precision = 10*Expression::Epsilon<T>();
|
T precision = 10*Expression::Epsilon<T>();
|
||||||
@@ -92,6 +104,8 @@ template<typename T> MatrixComplex<T> ApproximationHelper::ElementWiseOnComplexM
|
|||||||
return matrix;
|
return matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template int Poincare::ApproximationHelper::PositiveIntegerApproximationIfPossible<float>(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit);
|
||||||
|
template int Poincare::ApproximationHelper::PositiveIntegerApproximationIfPossible<double>(Poincare::ExpressionNode const*, bool*, Poincare::Context*, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit);
|
||||||
template std::complex<float> Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument<float>(std::complex<float>);
|
template std::complex<float> Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument<float>(std::complex<float>);
|
||||||
template std::complex<double> Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument<double>(std::complex<double>);
|
template std::complex<double> Poincare::ApproximationHelper::TruncateRealOrImaginaryPartAccordingToArgument<double>(std::complex<double>);
|
||||||
template Poincare::Evaluation<float> Poincare::ApproximationHelper::Map(const Poincare::ExpressionNode * expression, Poincare::Context * context, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexCompute<float> compute);
|
template Poincare::Evaluation<float> Poincare::ApproximationHelper::Map(const Poincare::ExpressionNode * expression, Poincare::Context * context, Poincare::Preferences::ComplexFormat, Poincare::Preferences::AngleUnit angleUnit, Poincare::ApproximationHelper::ComplexCompute<float> compute);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <poincare/great_common_divisor.h>
|
#include <poincare/great_common_divisor.h>
|
||||||
|
|
||||||
|
#include <poincare/approximation_helper.h>
|
||||||
#include <poincare/arithmetic.h>
|
#include <poincare/arithmetic.h>
|
||||||
#include <poincare/layout_helper.h>
|
#include <poincare/layout_helper.h>
|
||||||
#include <poincare/rational.h>
|
#include <poincare/rational.h>
|
||||||
@@ -27,22 +28,20 @@ Expression GreatCommonDivisorNode::shallowReduce(ReductionContext reductionConte
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Evaluation<T> GreatCommonDivisorNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
|
Evaluation<T> GreatCommonDivisorNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
|
||||||
Evaluation<T> f1Input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit);
|
bool isUndefined = false;
|
||||||
Evaluation<T> f2Input = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit);
|
int a = ApproximationHelper::PositiveIntegerApproximationIfPossible<T>(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit);
|
||||||
T f1 = f1Input.toScalar();
|
int b = ApproximationHelper::PositiveIntegerApproximationIfPossible<T>(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit);
|
||||||
T f2 = f2Input.toScalar();
|
if (isUndefined) {
|
||||||
if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) {
|
|
||||||
return Complex<T>::Undefined();
|
return Complex<T>::Undefined();
|
||||||
}
|
}
|
||||||
int a = (int)f2;
|
if (b > a) {
|
||||||
int b = (int)f1;
|
int temp = b;
|
||||||
if (f1 > f2) {
|
|
||||||
b = a;
|
b = a;
|
||||||
a = (int)f1;
|
a = temp;
|
||||||
}
|
}
|
||||||
int r = 0;
|
int r = 0;
|
||||||
while((int)b!=0){
|
while((int)b!=0){
|
||||||
r = a - ((int)(a/b))*b;
|
r = a - (a/b)*b;
|
||||||
a = b;
|
a = b;
|
||||||
b = r;
|
b = r;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <poincare/least_common_multiple.h>
|
#include <poincare/least_common_multiple.h>
|
||||||
|
#include <poincare/approximation_helper.h>
|
||||||
#include <poincare/rational.h>
|
#include <poincare/rational.h>
|
||||||
#include <poincare/undefined.h>
|
#include <poincare/undefined.h>
|
||||||
#include <poincare/arithmetic.h>
|
#include <poincare/arithmetic.h>
|
||||||
@@ -27,26 +28,24 @@ Expression LeastCommonMultipleNode::shallowReduce(ReductionContext reductionCont
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Evaluation<T> LeastCommonMultipleNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
|
Evaluation<T> LeastCommonMultipleNode::templatedApproximate(Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const {
|
||||||
Evaluation<T> f1Input = childAtIndex(0)->approximate(T(), context, complexFormat, angleUnit);
|
bool isUndefined = false;
|
||||||
Evaluation<T> f2Input = childAtIndex(1)->approximate(T(), context, complexFormat, angleUnit);
|
int a = ApproximationHelper::PositiveIntegerApproximationIfPossible<T>(childAtIndex(0), &isUndefined, context, complexFormat, angleUnit);
|
||||||
T f1 = f1Input.toScalar();
|
int b = ApproximationHelper::PositiveIntegerApproximationIfPossible<T>(childAtIndex(1), &isUndefined, context, complexFormat, angleUnit);
|
||||||
T f2 = f2Input.toScalar();
|
if (isUndefined) {
|
||||||
if (std::isnan(f1) || std::isnan(f2) || f1 != (int)f1 || f2 != (int)f2) {
|
|
||||||
return Complex<T>::Undefined();
|
return Complex<T>::Undefined();
|
||||||
}
|
}
|
||||||
if (f1 == 0.0f || f2 == 0.0f) {
|
if (a == 0 || b == 0) {
|
||||||
return Complex<T>::Builder(0.0);
|
return Complex<T>::Builder(0.0);
|
||||||
}
|
}
|
||||||
int a = (int)f2;
|
if (b > a) {
|
||||||
int b = (int)f1;
|
int temp = b;
|
||||||
if (f1 > f2) {
|
|
||||||
b = a;
|
b = a;
|
||||||
a = (int)f1;
|
a = temp;
|
||||||
}
|
}
|
||||||
int product = a*b;
|
int product = a*b;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
while((int)b!=0){
|
while((int)b!=0){
|
||||||
r = a - ((int)(a/b))*b;
|
r = a - (a/b)*b;
|
||||||
a = b;
|
a = b;
|
||||||
b = r;
|
b = r;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,12 +269,18 @@ QUIZ_CASE(poincare_approximation_function) {
|
|||||||
|
|
||||||
assert_expression_approximates_to<float>("gcd(234,394)", "2");
|
assert_expression_approximates_to<float>("gcd(234,394)", "2");
|
||||||
assert_expression_approximates_to<double>("gcd(234,394)", "2");
|
assert_expression_approximates_to<double>("gcd(234,394)", "2");
|
||||||
|
assert_expression_approximates_to<float>("gcd(-234,394)", "2");
|
||||||
|
assert_expression_approximates_to<double>("gcd(234,-394)", "2");
|
||||||
|
assert_expression_approximates_to<float>("gcd(-234,-394)", "2");
|
||||||
|
|
||||||
assert_expression_approximates_to<float>("im(2+3𝐢)", "3");
|
assert_expression_approximates_to<float>("im(2+3𝐢)", "3");
|
||||||
assert_expression_approximates_to<double>("im(2+3𝐢)", "3");
|
assert_expression_approximates_to<double>("im(2+3𝐢)", "3");
|
||||||
|
|
||||||
assert_expression_approximates_to<float>("lcm(234,394)", "46098");
|
assert_expression_approximates_to<float>("lcm(234,394)", "46098");
|
||||||
assert_expression_approximates_to<double>("lcm(234,394)", "46098");
|
assert_expression_approximates_to<double>("lcm(234,394)", "46098");
|
||||||
|
assert_expression_approximates_to<float>("lcm(-234,394)", "46098");
|
||||||
|
assert_expression_approximates_to<double>("lcm(234,-394)", "46098");
|
||||||
|
assert_expression_approximates_to<float>("lcm(-234,-394)", "46098");
|
||||||
|
|
||||||
assert_expression_approximates_to<float>("int(x,x, 1, 2)", "1.5");
|
assert_expression_approximates_to<float>("int(x,x, 1, 2)", "1.5");
|
||||||
assert_expression_approximates_to<double>("int(x,x, 1, 2)", "1.5");
|
assert_expression_approximates_to<double>("int(x,x, 1, 2)", "1.5");
|
||||||
|
|||||||
Reference in New Issue
Block a user