[Fix] Conflicts

This commit is contained in:
Quentin
2020-04-08 15:05:17 +02:00
211 changed files with 4896 additions and 2103 deletions

View File

@@ -2,7 +2,7 @@ name: Continuous integration
on: [pull_request, push]
jobs:
build-simulator-android:
android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
@@ -11,9 +11,9 @@ jobs:
- run: make -j2 PLATFORM=simulator TARGET=android
- uses: actions/upload-artifact@master
with:
name: epsilon-simulator-android.apk
path: output/release/simulator/android/app/outputs/apk/release/android-release-unsigned.apk
build-device-n0100:
name: epsilon-android.apk
path: output/release/simulator/android/epsilon.apk
n0100:
runs-on: ubuntu-latest
steps:
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
@@ -29,10 +29,9 @@ jobs:
- run: make -j2 MODEL=n0100 flasher.verbose.dfu
- uses: actions/upload-artifact@master
with:
name: epsilon-device-n0100.dfu
name: epsilon-n0100.dfu
path: output/release/device/n0100/epsilon.dfu
- run: make -j2 MODEL=n0100 test.elf
build-device-n0110:
n0110:
runs-on: ubuntu-latest
steps:
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
@@ -50,10 +49,9 @@ jobs:
- run: make -j2 bench.flash.dfu
- uses: actions/upload-artifact@master
with:
name: epsilon-device-n0110.dfu
name: epsilon-n0110.dfu
path: output/release/device/n0110/epsilon.dfu
- run: make -j2 test.elf
build-simulator-web:
web:
runs-on: ubuntu-latest
steps:
- uses: numworks/setup-emscripten@v1
@@ -65,10 +63,9 @@ jobs:
- run: make -j2 PLATFORM=simulator TARGET=web
- uses: actions/upload-artifact@master
with:
name: epsilon-simulator-web.zip
name: epsilon-web.zip
path: output/release/simulator/web/epsilon.zip
- run: make -j2 PLATFORM=simulator TARGET=web test.headless.js
build-simulator-linux:
linux:
runs-on: ubuntu-latest
steps:
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
@@ -78,6 +75,6 @@ jobs:
- run: make -j2 PLATFORM=simulator
- uses: actions/upload-artifact@master
with:
name: epsilon-simulator-linux.bin
name: epsilon-linux.bin
path: output/release/simulator/linux/epsilon.bin
- run: make -j2 PLATFORM=simulator test.headless.bin
- run: make -j2 PLATFORM=simulator test.headless.bin

View File

@@ -1,5 +1,16 @@
# Disable default Make rules
.SUFFIXES:
# Define the default recipe
default:
include build/config.mak
include build/pimp.mak
include build/defaults.mak
include build/platform.$(PLATFORM).mak
include build/toolchain.$(TOOLCHAIN).mak
include build/variants.mak
include build/helpers.mk
ifeq (${MODEL}, n0110)
apps_list = ${EPSILON_APPS}
@@ -11,36 +22,6 @@ ifdef FORCE_EXTERNAL
apps_list = ${EPSILON_APPS}
endif
# Disable default Make rules
.SUFFIXES:
object_for = $(addprefix $(BUILD_DIR)/,$(addsuffix .o,$(basename $(1))))
# Define the default recipe
default:
# Define a standard rule helper
# If passed a last parameter value of with_local_version, we also define an
# extra rule that can build source files within the $(BUILD_DIR). This is useful
# for rules that can be applied for intermediate objects (for example, when
# going .png -> .cpp -> .o).
define rule_label
@ echo "$(shell printf "%-8s" $(strip $(1)))$(@:$(BUILD_DIR)/%=%)"
endef
define rule_for
ifeq ($(strip $(5)),with_local_version)
$(addprefix $$(BUILD_DIR)/,$(strip $(2))): $(addprefix $$(BUILD_DIR)/,$(strip $(3))) | $(if $(findstring official,${MAKECMDGOALS}),official_authorization)
@ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(BUILD_DIR)/%=%)"
$(Q) $(4)
endif
$(addprefix $$(BUILD_DIR)/,$(strip $(2))): $(strip $(3)) | $$$$(@D)/. $(if $(findstring official,${MAKECMDGOALS}),official_authorization)
@ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(BUILD_DIR)/%=%)"
$(Q) $(4)
endef
.PHONY: info
info:
@echo "EPSILON_VERSION = $(EPSILON_VERSION)"
@@ -108,7 +89,9 @@ $(BUILD_DIR)%/.:
# Each sub-Makefile can either add sources to $(%_src) variables or define a
# new executable target. The $(%_src) variables list the sources that can be
# built and linked to executables being generated.
ifndef USE_LIBA
$(error platform.mak should define USE_LIBA)
endif
ifeq ($(USE_LIBA),0)
include liba/Makefile.bridge
else
@@ -127,10 +110,10 @@ include build/struct_layout/Makefile
include build/scenario/Makefile
include quiz/Makefile # Quiz needs to be included at the end
all_src = $(apps_all_src) $(escher_src) $(ion_all_src) $(kandinsky_src) $(liba_src) $(libaxx_src) $(poincare_src) $(python_src) $(runner_src) $(ion_target_device_flasher_light_src) $(ion_target_device_flasher_verbose_src) $(ion_target_device_bench_src) $(tests_src)
all_src = $(apps_src) $(escher_src) $(ion_src) $(kandinsky_src) $(liba_src) $(libaxx_src) $(poincare_src) $(python_src) $(runner_src) $(ion_device_flasher_src) $(ion_device_bench_src) $(tests_src)
# Make palette.h a dep for every source-file.
# This ensures that the theming engine works correctly.
$(call object_for,$(all_app_src)): $(BUILD_DIR)/escher/palette.h
$(call object_for,$(all_src)): $(BUILD_DIR)/escher/palette.h
all_objs = $(call object_for,$(all_src))
.SECONDARY: $(all_objs)
@@ -145,8 +128,7 @@ all_objs = $(call object_for,$(all_src))
include build/targets.mak
# Fill in the default recipe
DEFAULT ?= $(BUILD_DIR)/epsilon.$(EXE)
default: $(DEFAULT)
default: $(firstword $(HANDY_TARGETS)).$(firstword $(HANDY_TARGETS_EXTENSIONS))
# Load standard build rules
include build/rules.mk

View File

@@ -10,8 +10,14 @@ apps =
# (path to the apps header).
$(foreach i,${apps_list},${eval include apps/$(i)/Makefile})
app_src += $(addprefix apps/,\
apps_src += $(addprefix apps/,\
apps_container.cpp \
apps_container_launch_default.cpp:-onboarding \
apps_container_launch_on_boarding.cpp:+onboarding \
apps_container_prompt_beta.cpp:+beta \
apps_container_prompt_none.cpp:-beta \
apps_container_prompt_none.cpp:-update \
apps_container_prompt_update.cpp:+update \
apps_container_storage.cpp \
apps_window.cpp \
backlight_dimming_timer.cpp \
@@ -19,6 +25,8 @@ app_src += $(addprefix apps/,\
battery_view.cpp \
empty_battery_window.cpp \
exam_pop_up_controller.cpp \
exam_mode_configuration_official.cpp:+official \
exam_mode_configuration_non_official.cpp:-official \
global_preferences.cpp \
i18n.py \
lock_view.cpp \
@@ -32,14 +40,6 @@ app_src += $(addprefix apps/,\
)
tests_src += apps/exam_mode_configuration_non_official.cpp
apps_official += apps/exam_mode_configuration_non_official.cpp
apps_non_official += apps/exam_mode_configuration_non_official.cpp
apps_launch_on_boarding_src += apps/apps_container_launch_on_boarding.cpp
apps_launch_default_src += apps/apps_container_launch_default.cpp
apps_prompt_none_src += apps/apps_container_prompt_none.cpp
apps_prompt_beta_src += apps/apps_container_prompt_beta.cpp
apps_prompt_update_src += apps/apps_container_prompt_update.cpp
snapshots_declaration = $(foreach i,$(apps),$(i)::Snapshot m_snapshot$(subst :,,$(i))Snapshot;)
apps_declaration = $(foreach i,$(apps),$(i) m_$(subst :,,$(i));)
@@ -83,7 +83,8 @@ $(eval $(call rule_for, \
I18N, \
apps/i18n.cpp, \
$(i18n_files), \
$$(PYTHON) apps/i18n.py --header $$(subst .cpp,.h,$$@) --implementation $$@ --locales $$(EPSILON_I18N) --files $$^ \
$$(PYTHON) apps/i18n.py --codepoints $(code_points) --header $$(subst .cpp,.h,$$@) --implementation $$@ --locales $$(EPSILON_I18N) --files $$^, \
global \
))
@@ -94,36 +95,19 @@ $(BUILD_DIR)/apps/i18n.h: $(BUILD_DIR)/apps/i18n.cpp
$(eval $(call depends_on_image,apps/title_bar_view.cpp,apps/exam_icon.png))
all_app_src = $(app_src)(apps_launch_on_boarding_src) $(apps_launch_default_src) $(apps_prompt_none_src) $(apps_prompt_update_src) $(apps_prompt_beta_src) $(apps_official) $(apps_non_official) $(tests_src)
$(call object_for,$(apps_src) $(tests_src)): $(BUILD_DIR)/apps/i18n.h
$(call object_for,$(apps_src) $(tests_src)): $(BUILD_DIR)/python/port/genhdr/qstrdefs.generated.h
$(call object_for,$(all_app_src)): $(BUILD_DIR)/apps/i18n.h
$(call object_for,$(all_app_src)): $(BUILD_DIR)/python/port/genhdr/qstrdefs.generated.h
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_settings_test_src) $(app_solver_test_src)
apps_tests_src = $(app_calculation_test_src) $(app_code_test_src) $(app_probability_test_src) $(app_regression_test_src) $(app_sequence_test_src) $(app_shared_test_src) $(app_statistics_test_src) $(app_settings_test_src) $(app_solver_test_src)
apps_tests_src += $(addprefix apps/,\
global_preferences.cpp \
)
$(foreach img,$(image_list), $(eval $(call rule_for, \
ICON, \
$(img), \
$(addprefix themes/themes/, $(addsuffix .json, $(OMEGA_THEME))), \
$$(PYTHON) themes/themes_manager.py -i $(OMEGA_THEME) $$@ $(BUILD_DIR)/ \
$$(PYTHON) themes/themes_manager.py -i $(OMEGA_THEME) $$@ $(BUILD_DIR)/, \
global \
)))
# Configure variants
apps_all_src = $(app_src)
apps_all_src += $(apps_official) $(apps_non_official)
apps_all_src += $(apps_launch_default_src) $(apps_launch_on_boarding_src)
apps_all_src += $(apps_prompt_none_src) $(apps_prompt_update_src) $(apps_prompt_beta_src)
apps_default_src = $(app_src) $(apps_non_official) $(apps_launch_default_src) $(apps_prompt_none_src)
apps_official_default_src = $(app_src) $(apps_official) $(apps_launch_default_src) $(apps_prompt_none_src)
apps_onboarding_src = $(app_src) $(apps_non_official) $(apps_launch_on_boarding_src) $(apps_prompt_none_src)
apps_official_onboarding_src = $(app_src) $(apps_official) $(apps_launch_on_boarding_src) $(apps_prompt_none_src)
apps_onboarding_update_src = $(app_src) $(apps_non_official) $(apps_launch_on_boarding_src) $(apps_prompt_update_src)
apps_official_onboarding_update_src = $(app_src) $(apps_official) $(apps_launch_on_boarding_src) $(apps_prompt_update_src)
apps_onboarding_beta_src = $(app_src) $(apps_non_official) $(apps_launch_on_boarding_src) $(apps_prompt_beta_src)
apps_official_onboarding_beta_src = $(app_src) $(apps_official) $(apps_launch_on_boarding_src) $(apps_prompt_beta_src)

View File

@@ -30,7 +30,7 @@ app_calculation_src = $(addprefix apps/calculation/,\
)
app_calculation_src += $(app_calculation_test_src)
app_src += $(app_calculation_src)
apps_src += $(app_calculation_src)
i18n_files += $(addprefix apps/calculation/,\
base.de.i18n\

View File

@@ -71,7 +71,7 @@ void ComplexGraphView::drawRect(KDContext * ctx, KDRect rect) const {
// 're(z)' label
drawLabel(ctx, rect, real, 0.0f, "re(z)", Palette::Red, CurveView::RelativePosition::None, imag >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After);
// 'im(z)' label
drawLabel(ctx, rect, 0.0f, imag, "im(θ)", Palette::Red, real >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After, CurveView::RelativePosition::None);
drawLabel(ctx, rect, 0.0f, imag, "im(z)", Palette::Red, real >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After, CurveView::RelativePosition::None);
// '|z|' label, the relative horizontal position of this label depends on the quadrant
CurveView::RelativePosition verticalPosition = real*imag < 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After;
if (real == 0.0f) {

View File

@@ -30,6 +30,7 @@ void HistoryViewCellDataSource::setSelectedSubviewType(SubviewType subviewType,
if (selectedCell) {
selectedCell->reloadSubviewHighlight();
selectedCell->cellDidSelectSubview(subviewType, previousSubviewType);
Container::activeApp()->setFirstResponder(selectedCell);
}
if (previouslySelectedCell) {
previouslySelectedCell->cellDidSelectSubview(SubviewType::Input);

View File

@@ -12,12 +12,12 @@ CalculationSelectableTableView::CalculationSelectableTableView(Responder * paren
}
void CalculationSelectableTableView::scrollToCell(int i, int j) {
::SelectableTableView::scrollToCell(i, j);
if (m_contentView.bounds().height() < bounds().height()) {
setTopMargin(bounds().height() - m_contentView.bounds().height());
} else {
setTopMargin(0);
}
::SelectableTableView::scrollToCell(i, j);
ScrollView::layoutSubviews();
if (m_contentView.bounds().height() - contentOffset().y() < bounds().height()) {
KDCoordinate contentOffsetX = contentOffset().x();

View File

@@ -1,6 +1,10 @@
apps += Code::App
app_headers += apps/code/app.h
app_code_test_src = $(addprefix apps/code/,\
script_template.cpp \
)
app_code_src = $(addprefix apps/code/,\
app.cpp \
console_controller.cpp \
@@ -19,11 +23,11 @@ app_code_src = $(addprefix apps/code/,\
script_node_cell.cpp \
script_parameter_controller.cpp \
script_store.cpp \
script_template.cpp \
variable_box_controller.cpp \
)
app_src += $(app_code_src)
app_code_src += $(app_code_test_src)
apps_src += $(app_code_src)
i18n_files += $(addprefix apps/code/,\
base.de.i18n\

View File

@@ -139,10 +139,10 @@ PythonRadians = "Convert x from degrees to radians"
PythonRandint = "Random integer in [a,b]"
PythonRandom = "Floating point number in [0,1["
PythonRandomFunction = "random module function prefix"
PythonRandrange = "Random number in range(start, stop)"
PythonRandrange = "Random number in range(start,stop)"
PythonRangeStartStop = "List from start to stop-1"
PythonRangeStop = "List from 0 to stop-1"
PythonRect = "z in cartesian coordinates"
PythonRect = "Convert to cartesian coordinates"
PythonRemove = "Remove the first occurrence of x"
PythonReverse = "Reverse the elements of the list"
PythonRound = "Round to n digits"

View File

@@ -139,10 +139,10 @@ PythonRadians = "Convert x from degrees to radians"
PythonRandint = "Random integer in [a,b]"
PythonRandom = "Floating point number in [0,1["
PythonRandomFunction = "random module function prefix"
PythonRandrange = "Random number in range(start, stop)"
PythonRandrange = "Random number in range(start,stop)"
PythonRangeStartStop = "List from start to stop-1"
PythonRangeStop = "List from 0 to stop-1"
PythonRect = "z in cartesian coordinates"
PythonRect = "Convert to cartesian coordinates"
PythonRemove = "Remove the first occurrence of x"
PythonReverse = "Reverse the elements of the list"
PythonRound = "Round to n digits"

View File

@@ -139,10 +139,10 @@ PythonRadians = "Convert x from degrees to radians"
PythonRandint = "Random integer in [a,b]"
PythonRandom = "Floating point number in [0,1["
PythonRandomFunction = "random module function prefix"
PythonRandrange = "Random number in range(start, stop)"
PythonRandrange = "Random number in range(start,stop)"
PythonRangeStartStop = "List from start to stop-1"
PythonRangeStop = "List from 0 to stop-1"
PythonRect = "z in cartesian coordinates"
PythonRect = "Convert to cartesian coordinates"
PythonRemove = "Remove the first occurrence of x"
PythonReverse = "Reverse the elements of the list"
PythonRound = "Round to n digits"

View File

@@ -139,7 +139,7 @@ PythonRadians = "Conversion de degrés en radians"
PythonRandint = "Entier aléatoire dans [a,b]"
PythonRandom = "Nombre décimal dans [0,1["
PythonRandomFunction = "Préfixe fonction du module random"
PythonRandrange = "Nombre dans range(start, stop)"
PythonRandrange = "Nombre dans range(start,stop)"
PythonRangeStartStop = "Liste de start à stop-1"
PythonRangeStop = "Liste de 0 à stop-1"
PythonRect = "Conversion en algébrique"

View File

@@ -139,10 +139,10 @@ PythonRadians = "Convert x from degrees to radians"
PythonRandint = "Random integer in [a,b]"
PythonRandom = "Floating point number in [0,1["
PythonRandomFunction = "random module function prefix"
PythonRandrange = "Random number in range(start, stop)"
PythonRandrange = "Random number in range(start,stop)"
PythonRangeStartStop = "List from start to stop-1"
PythonRangeStop = "List from 0 to stop-1"
PythonRect = "z in cartesian coordinates"
PythonRect = "Convert to cartesian coordinates"
PythonRemove = "Remove the first occurrence of x"
PythonReverse = "Reverse the elements of the list"
PythonRound = "Round to n digits"

View File

@@ -165,17 +165,17 @@ PythonCommandRandint = "randint(a,b)"
PythonCommandRandom = "random()"
PythonCommandRandomFunction = "random.function"
PythonCommandRandomFunctionWithoutArg = "random.\x11"
PythonCommandRandrange = "randrange(start, stop)"
PythonCommandRangeStartStop = "range(start, stop)"
PythonCommandRandrange = "randrange(start,stop)"
PythonCommandRangeStartStop = "range(start,stop)"
PythonCommandRangeStop = "range(stop)"
PythonCommandReal = "z.real"
PythonCommandRealWithoutArg = ".real"
PythonCommandRect = "rect(r, arg)"
PythonCommandRect = "rect(r,arg)"
PythonCommandRemove = "list.remove(x)"
PythonCommandRemoveWithoutArg = ".remove(\x11)"
PythonCommandReverse = "list.reverse()"
PythonCommandReverseWithoutArg = ".reverse()"
PythonCommandRound = "round(x, n)"
PythonCommandRound = "round(x,n)"
PythonCommandScatter = "scatter(x,y)"
PythonCommandSeed = "seed(x)"
PythonCommandSetPixel = "set_pixel(x,y,color)"
@@ -227,7 +227,7 @@ PythonTurtleCommandRed = "'red'"
PythonTurtleCommandReset = "reset()"
PythonTurtleCommandRight = "right(a)"
PythonTurtleCommandSetheading = "setheading(a)"
PythonTurtleCommandSetposition = "setposition(x, [y])"
PythonTurtleCommandSetposition = "setposition(x,[y])"
PythonTurtleCommandShowturtle = "showturtle()"
PythonTurtleCommandSpeed = "speed(x)"
PythonTurtleCommandWhite = "'white'"

View File

@@ -36,6 +36,12 @@ bool ScriptStore::isFull() {
void ScriptStore::scanScriptsForFunctionsAndVariables(void * context, ScanCallback storeFunction, ScanCallback storeVariable) {
for (int scriptIndex = 0; scriptIndex < numberOfScripts(); scriptIndex++) {
//Don't scan not loaded script
if (!scriptAtIndex(scriptIndex).importationStatus()){
continue;
}
// Handle lexer or parser errors with nlr.
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {

View File

@@ -1,5 +1,4 @@
#include "empty_battery_window.h"
#include "global_preferences.h"
#include <apps/i18n.h>
extern "C" {
#include <assert.h>
@@ -12,7 +11,7 @@ EmptyBatteryWindow::EmptyBatteryWindow() :
void EmptyBatteryWindow::drawRect(KDContext * ctx, KDRect rect) const {
ctx->fillRect(bounds(), KDColorWhite);
const char * warningMessage = I18n::translate(I18n::Message::LowBattery, GlobalPreferences::sharedGlobalPreferences()->language());
const char * warningMessage = I18n::translate(I18n::Message::LowBattery);
KDSize warningSize = KDFont::LargeFont->stringSize(warningMessage);
ctx->drawString(warningMessage, KDPoint((Ion::Display::Width - warningSize.width())/2, (Ion::Display::Height - warningSize.height())/2), KDFont::LargeFont);
}

View File

@@ -18,7 +18,7 @@ else
include $(EXTAPP_PATH)/sources.mak
endif
app_src += $(app_external_src)
apps_src += $(app_external_src)
i18n_files += $(addprefix apps/external/,\
base.de.i18n\

View File

@@ -269,7 +269,7 @@ int extapp_getKey(bool allowSuspend, bool *alphaWasActive) {
continue;
}
if (event.isKeyboardEvent()) {
key = event.id();
key = static_cast<uint8_t>(event);
if (key == 17 || key == 4 || key == 5 || key == 52) {
extapp_resetKeyboard();
}

View File

@@ -30,8 +30,9 @@ public:
void setFont(const KDFont * font) { m_font = font; }
constexpr static int NumberOfBrightnessStates = 15;
private:
static_assert(I18n::NumberOfLanguages > 0, "I18n::NumberOfLanguages is not superior to 0"); // There should already have be an error when processing an empty EPSILON_I18N flag
GlobalPreferences() :
m_language(I18n::Language::EN),
m_language((I18n::Language)0),
m_examMode(ExamMode::Unknown),
m_tempExamMode(ExamMode::Standard),
m_showPopUp(true),

View File

@@ -31,7 +31,7 @@ app_graph_src = $(addprefix apps/graph/,\
values/values_controller.cpp \
)
app_src += $(app_graph_src)
apps_src += $(app_graph_src)
i18n_files += $(addprefix apps/graph/,\
base.de.i18n\

View File

@@ -20,8 +20,8 @@ Zeros = "Nullstellen"
Tangent = "Tangente"
Intersection = "Schnittmenge"
Preimage = "Urbild"
SelectLowerBound = "Untere Integrationsgrenze"
SelectUpperBound = "Obere Integrationsgrenze"
SelectLowerBound = "Untere Integrationsgrenze "
SelectUpperBound = "Obere Integrationsgrenze "
NoMaximumFound = "Kein Maximalwert gefunden"
NoMinimumFound = "Kein Mindestwert gefunden"
NoZeroFound = "Keine Nullstelle gefunden"
@@ -29,5 +29,5 @@ NoIntersectionFound = "Kein Schnittpunkt gefunden"
NoPreimageFound = "Kein Urbild gefunden"
DerivativeFunctionColumn = "Spalte der Ableitungsfunktion"
HideDerivativeColumn = "Ableitungsfunktion ausblenden"
AllowedCharactersAZaz09 = "Erlaubte Zeichen: A-Z, a-z, 0-9, _"
AllowedCharactersAZaz09 = "Erlaubte Zeichen: A..Z, a..z, 0..9, _"
ReservedName = "Reserviertes Wort"

View File

@@ -20,8 +20,8 @@ Zeros = "Zeros"
Tangent = "Tangent"
Intersection = "Intersection"
Preimage = "Inverse image"
SelectLowerBound = "Select lower bound"
SelectUpperBound = "Select upper bound"
SelectLowerBound = "Select lower bound "
SelectUpperBound = "Select upper bound "
NoMaximumFound = "No maximum found"
NoMinimumFound = "No minimum found"
NoZeroFound = "No zero found"
@@ -29,5 +29,5 @@ NoIntersectionFound = "No intersection found"
NoPreimageFound = "No inverse image found"
DerivativeFunctionColumn = "Derivative function column"
HideDerivativeColumn = "Hide the derivative function"
AllowedCharactersAZaz09 = "Allowed characters: A-Z, a-z, 0-9, _"
AllowedCharactersAZaz09 = "Allowed characters: A.Z, a..z, 0..9, _"
ReservedName = "Reserved name"

View File

@@ -20,8 +20,8 @@ Zeros = "Raíces"
Tangent = "Tangente"
Intersection = "Intersección"
Preimage = "Imagen inversa"
SelectLowerBound = "Seleccionar el límite inferior"
SelectUpperBound = "Seleccionar el límite superior"
SelectLowerBound = "Seleccionar el límite inferior "
SelectUpperBound = "Seleccionar el límite superior "
NoMaximumFound = "Níngun máximo encontrado"
NoMinimumFound = "Níngun mínimo encontrado"
NoZeroFound = "Ninguna raíz encontrada"
@@ -29,5 +29,5 @@ NoIntersectionFound = "Ninguna intersección encontrada"
NoPreimageFound = "Ninguna imagen inversa encontrada"
DerivativeFunctionColumn = "Columna de la derivada"
HideDerivativeColumn = "Ocultar la derivada"
AllowedCharactersAZaz09 = "Caracteres permitidos : A-Z, a-z, 0-9, _"
AllowedCharactersAZaz09 = "Caracteres permitidos : A..Z, a..z, 0..9, _"
ReservedName = "Nombre reservado"

View File

@@ -4,7 +4,7 @@ FunctionTab = "Fonctions"
AddFunction = "Ajouter une fonction"
DeleteFunction = "Supprimer la fonction"
CurveType = "Type de courbe"
CartesianType = "Cartésien "
CartesianType = "Cartésienne "
PolarType = "Polaire "
ParametricType = "Paramétrique "
IntervalT = "Intervalle t"
@@ -16,18 +16,18 @@ NoFunction = "Aucune fonction"
NoActivatedFunction = "Aucune fonction activée"
PlotOptions = "Options de la courbe"
Compute = "Calculer"
Zeros = "Zéros"
Zeros = "Racines"
Tangent = "Tangente"
Intersection = "Intersection"
Preimage = "Antécédent"
SelectLowerBound = "Sélectionner la borne inférieure"
SelectUpperBound = "Sélectionner la borne supérieure"
SelectLowerBound = "Sélectionner la borne inférieure "
SelectUpperBound = "Sélectionner la borne supérieure "
NoMaximumFound = "Aucun maximum trouvé"
NoMinimumFound = "Aucun minimum trouvé"
NoZeroFound = "Aucun zéro trouvé"
NoZeroFound = "Aucune racine trouvée"
NoIntersectionFound = "Aucune intersection trouvée"
NoPreimageFound = "Aucun antécédent trouvé"
DerivativeFunctionColumn = "Colonne de la fonction dérivée"
HideDerivativeColumn = "Masquer la fonction dérivée"
AllowedCharactersAZaz09 = "Caractères autorisés : A-Z, a-z, 0-9, _"
AllowedCharactersAZaz09 = "Caractères autorisés : A..Z, a..z, 0..9, _"
ReservedName = "Nom réservé"

View File

@@ -20,8 +20,8 @@ Zeros = "Raízes"
Tangent = "Tangente"
Intersection = "Intersecção"
Preimage = "Imagem inversa"
SelectLowerBound = "Selecionar limite superior"
SelectUpperBound = "Selecionar limite inferior"
SelectLowerBound = "Selecionar limite superior "
SelectUpperBound = "Selecionar limite inferior "
NoMaximumFound = "Nenhum máximo encontrado"
NoMinimumFound = "Nenhum mínimo encontrado"
NoZeroFound = "Nenhuma raiz encontrada"
@@ -29,5 +29,5 @@ NoIntersectionFound = "Nenhuma intersecção encontrada"
NoPreimageFound = "Nenhuma imagem inversa encontrada"
DerivativeFunctionColumn = "Coluna da função derivada"
HideDerivativeColumn = "Esconder função derivada"
AllowedCharactersAZaz09 = "Caracteres permitidos : A-Z, a-z, 0-9, _"
AllowedCharactersAZaz09 = "Caracteres permitidos : A..Z, a..z, 0..9, _"
ReservedName = "Nome reservado"

View File

@@ -16,4 +16,4 @@ app_hardware_test_src = $(addprefix apps/hardware_test/,\
vblank_test_controller.cpp \
)
app_src += $(app_hardware_test_src)
apps_src += $(app_hardware_test_src)

View File

@@ -4,7 +4,7 @@ app_home_src = $(addprefix apps/home/,\
controller.cpp \
)
app_src += $(app_home_src)
apps_src += $(app_home_src)
i18n_files += $(addprefix apps/home/,\
base.de.i18n \

View File

@@ -1,4 +1,4 @@
Apps = "Applications"
AppsCapital = "STAY HOME(GA)"
ForbidenAppInExamMode1 = "This application is"
ForbidenAppInExamMode2 = "forbidden in exam mode"
ForbidenAppInExamMode1 = "Cette application n'est"
ForbidenAppInExamMode2 = "pas autorisée en mode examen."

View File

@@ -12,6 +12,19 @@ import unicodedata
import argparse
import io
parser = argparse.ArgumentParser(description="Process some i18n files.")
parser.add_argument('--header', help='the .h file to generate')
parser.add_argument('--implementation', help='the .cpp file to generate')
parser.add_argument('--locales', nargs='+', help='locale to actually generate')
parser.add_argument('--codepoints', help='the code_points.h file')
parser.add_argument('--files', nargs='+', help='an i18n file')
args = parser.parse_args()
def has_glyph(glyph):
return glyph in codepoints
def source_definition(i18n_string):
s = unicodedata.normalize("NFKD", i18n_string)
result = u"\""
@@ -29,6 +42,9 @@ def source_definition(i18n_string):
# Remove the uppercase characters with combining chars
checkForCombining = s[i].isupper()
result = result + s[i]
if not has_glyph(s[i]):
sys.stderr.write(s[i] + " (" + str(hex(ord(s[i]))) + ") is not a character present in " + args.codepoints + " . Exiting !\n")
sys.exit(-1)
i = i+1
result = result + u"\""
return result.encode("utf-8")
@@ -73,6 +89,27 @@ def parse_files(files):
data[locale][name] = definition
return {"messages": sorted(messages), "universal_messages": sorted(universal_messages), "data": data}
def parse_codepoints(file):
codepoints = []
with io.open(file, "r", encoding='utf-8') as file:
IsCodePoint = False
for line in file:
if "};" in line:
IsCodePoint = False
if IsCodePoint:
start = line.find('0x')
stop = line.find(',')
if not (start == -1 or stop == -1):
hexstring = line[start:stop]
value = int(hexstring, 16)
char = chr(value)
codepoints.append(char)
if "CodePoints[]" in line:
IsCodePoint = True
return codepoints
codepoints = parse_codepoints(args.codepoints)
def print_header(data, path, locales):
f = open(path, "w")
f.write("#ifndef APPS_I18N_H\n")
@@ -95,9 +132,10 @@ def print_header(data, path, locales):
# Languages enumeration
f.write("enum class Language : uint16_t {\n")
f.write(" Default = 0,\n")
index = 0
for locale in locales:
f.write(" " + locale.upper() + ",\n")
f.write(" " + locale.upper() + (" = 0" if (index < 1) else "") +",\n")
index = index + 1
f.write("};\n\n")
# Language names
@@ -159,32 +197,21 @@ def print_implementation(data, path, locales):
# Write the translate method
f.write("const char * translate(Message m, Language l) {\n")
f.write("const char * translate(Message m) {\n")
f.write(" assert(m != Message::LocalizedMessageMarker);\n")
f.write(" int localizedMessageOffset = (int)Message::LocalizedMessageMarker+1;\n")
f.write(" if ((int)m < localizedMessageOffset) {\n")
f.write(" assert(universalMessages[(int)m] != nullptr);\n")
f.write(" return universalMessages[(int)m];\n")
f.write(" }\n")
f.write(" int languageIndex = (int)l;\n")
f.write(" if (l == Language::Default) {\n")
f.write(" languageIndex = (int) GlobalPreferences::sharedGlobalPreferences()->language();\n")
f.write(" }\n")
f.write(" assert(languageIndex > 0);\n")
f.write(" int languageIndex = (int)GlobalPreferences::sharedGlobalPreferences()->language();\n")
f.write(" int messageIndex = (int)m - localizedMessageOffset;\n")
f.write(" assert((messageIndex*NumberOfLanguages+languageIndex-1)*sizeof(char *) < sizeof(messages));\n")
f.write(" return messages[messageIndex][languageIndex-1];\n")
f.write(" assert((messageIndex*NumberOfLanguages+languageIndex)*sizeof(char *) < sizeof(messages));\n")
f.write(" return messages[messageIndex][languageIndex];\n")
f.write("}\n\n")
f.write("}\n")
f.close()
parser = argparse.ArgumentParser(description="Process some i18n files.")
parser.add_argument('--header', help='the .h file to generate')
parser.add_argument('--implementation', help='the .cpp file to generate')
parser.add_argument('--locales', nargs='+', help='locale to actually generate')
parser.add_argument('--files', nargs='+', help='an i18n file')
args = parser.parse_args()
data = parse_files(args.files)
if args.header:
print_header(data, args.header, args.locales)

View File

@@ -1,7 +1,7 @@
apps += Omega::App
app_headers += apps/omega/app.h
app_src += $(addprefix apps/omega/,\
apps_src += $(addprefix apps/omega/,\
app.cpp \
omega_controller.cpp \
omega_view.cpp \

View File

@@ -7,7 +7,7 @@ app_on_boarding_src = $(addprefix apps/on_boarding/,\
power_on_self_test.cpp \
)
app_src += $(app_on_boarding_src)
apps_src += $(app_on_boarding_src)
i18n_files += $(addprefix apps/on_boarding/,\
base.de.i18n\

View File

@@ -38,7 +38,7 @@ app_probability_src = $(addprefix apps/probability/,\
)
app_probability_src += $(app_probability_test_src)
app_src += $(app_probability_src)
apps_src += $(app_probability_src)
i18n_files += $(addprefix apps/probability/,\
base.de.i18n\

View File

@@ -10,13 +10,13 @@ UniformDistribution = "Loi uniforme"
ExponentialDistribution = "Loi exponentielle"
GeometricDistribution = "Loi géométrique"
PoissonDistribution = "Loi de Poisson"
ChiSquaredDistribution = "Loi du chi2"
ChiSquaredDistribution = "Loi du Khi-2"
StudentDistribution = "Loi de Student"
FisherDistribution = "Loi de Fisher"
ChooseParameters = "Choisir les paramètres"
RepetitionNumber = "n : Nombre de répétitions"
SuccessProbability = "p : Probabilité de succès"
IntervalDefinition = "[a,b] : Intervalle"
IntervalDefinition = "[a;b] : Intervalle"
LambdaExponentialDefinition = "λ : Paramètre"
MeanDefinition = "μ : Espérance ou moyenne"
DeviationDefinition = "σ : Écart type"

View File

@@ -23,5 +23,5 @@ DeviationDefinition = "σ: szórás"
LambdaPoissonDefinition = "λ: Paraméter"
DegreesOfFreedomDefinition = "k: Szabadságfokok"
D1FisherDefinition = "d1: A számláló szabadsági foka"
D2FisherDefinition = "d2: A nevező szabadsági foka"
D2FisherDefinition = "d2: A nevezó szabadsági foka"
ComputeProbability = "Számítsa ki a valószínüségeket"

View File

@@ -37,7 +37,7 @@ app_regression_src = $(addprefix apps/regression/,\
)
app_regression_src += $(app_regression_test_src)
app_src += $(app_regression_src)
apps_src += $(app_regression_src)
i18n_files += $(addprefix apps/regression/,\
base.de.i18n\

View File

@@ -351,7 +351,7 @@ uint32_t GraphController::modelVersion() {
return m_store->storeChecksum();
}
uint32_t GraphController::modelVersionAtIndex(size_t i) {
uint32_t GraphController::modelVersionAtIndex(int i) {
assert(i < numberOfMemoizedVersions());
return *(m_store->seriesChecksum() + i);
}

View File

@@ -43,7 +43,7 @@ private:
// InteractiveCurveViewController
void initCursorParameters() override;
uint32_t modelVersion() override;
uint32_t modelVersionAtIndex(size_t i) override;
uint32_t modelVersionAtIndex(int i) override;
uint32_t rangeVersion() override;
size_t numberOfMemoizedVersions() const override { return Store::k_numberOfSeries; }
int selectedCurveIndex() const override { return *m_selectedSeriesIndex; }

View File

@@ -26,7 +26,7 @@ app_sequence_src = $(addprefix apps/sequence/,\
)
app_sequence_src += $(app_sequence_test_src)
app_src += $(app_sequence_src)
apps_src += $(app_sequence_src)
i18n_files += $(addprefix apps/sequence/,\
base.de.i18n\

View File

@@ -5,8 +5,16 @@ app_settings_src = $(addprefix apps/settings/,\
app.cpp \
cell_with_separator.cpp \
main_controller.cpp \
main_controller_prompt_beta.cpp:+beta \
main_controller_prompt_none.cpp:-beta \
main_controller_prompt_none.cpp:-update \
main_controller_prompt_update.cpp:+update \
sub_menu/about_controller.cpp \
sub_menu/accessibility_controller.cpp \
sub_menu/about_controller_official.cpp:+official \
sub_menu/about_controller_non_official.cpp:-official \
sub_menu/exam_mode_controller_official.cpp:+official \
sub_menu/exam_mode_controller_non_official.cpp:-official \
sub_menu/display_mode_controller.cpp \
sub_menu/exam_mode_controller.cpp \
sub_menu/generic_sub_controller.cpp \
@@ -18,24 +26,7 @@ app_settings_src = $(addprefix apps/settings/,\
)
app_settings_src += $(app_settings_test_src)
app_src += $(app_settings_src)
apps_prompt_none_src += apps/settings/main_controller_prompt_none.cpp
apps_prompt_beta_src += apps/settings/main_controller_prompt_beta.cpp
apps_prompt_update_src += apps/settings/main_controller_prompt_update.cpp
apps_settings_official += $(addprefix apps/settings/,\
sub_menu/about_controller_official.cpp \
sub_menu/exam_mode_controller_official.cpp \
)
apps_settings_non_official += $(addprefix apps/settings/,\
sub_menu/about_controller_non_official.cpp \
sub_menu/exam_mode_controller_non_official.cpp \
)
apps_official += $(apps_settings_official)
apps_non_official += $(apps_settings_non_official)
apps_src += $(app_settings_src)
i18n_files += $(addprefix apps/settings/,\
base.de.i18n\

View File

@@ -6,9 +6,9 @@ EditionMode = "Eingabe"
EditionLinear = "Linear "
Edition2D = "Natürlich "
ComplexFormat = "Komplex"
ExamMode = "Testmodus"
ExamModeActive = "Testmodus neustarten"
ToDeactivateExamMode1 = "Um den Testmodus auszuschalten,"
ExamMode = "Prüfungsmodus"
ExamModeActive = "Wieder starten Modus"
ToDeactivateExamMode1 = "Um den Prüfungsmodus auszuschalten,"
ToDeactivateExamMode2 = "schließen Sie den Rechner an einen"
ToDeactivateExamMode3 = "Computer oder eine Steckdose an."
# --------------------- Please do not edit these messages ---------------------
@@ -22,13 +22,13 @@ AboutWarning4 = "for any resulting damage."
# -----------------------------------------------------------------------------
About = "Über"
Degrees = "Grad "
Gradians = "Gone "
Gradians = "Gon "
Radian = "Bogenmaß "
Decimal = "Dezimal "
Engineering = "Technisch "
Scientific = "Wissenschaftlich "
SignificantFigures = "Signifikante Stellen "
Real = "Reel "
Real = "Reell "
Cartesian = "Algebraische "
Polar = "Polar "
Brightness = "Helligkeit"

View File

@@ -42,9 +42,9 @@ CompactResult = "Compact "
FontSizes = "Police Python"
LargeFont = "Grand "
SmallFont = "Petit "
SerialNumber = "Numéro série"
UpdatePopUp = "Rappel mise à jour"
BetaPopUp = "Rappel version bêta"
SerialNumber = "Numéro de série"
UpdatePopUp = "Rappel de mise à jour"
BetaPopUp = "Rappel de version bêta"
Contributors = "Contributeurs"
Accessibility = "Accessibilité"
AccessibilityInvertColors = "Inverser couleurs"

View File

@@ -183,7 +183,7 @@ void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) {
MessageTableCell * myCell = (MessageTableCell *)cell;
myCell->setMessage(title);
if (model()->children(index)->label() == I18n::Message::Language) {
int index = (int)globalPreferences->language()-1;
int index = (int)(globalPreferences->language());
static_cast<MessageTableCellWithChevronAndMessage *>(cell)->setSubtitle(I18n::LanguageNames[index]);
return;
}

View File

@@ -1,9 +1,9 @@
ActivateDeactivate = "Aktivieren/Deaktivieren"
ActivateDutchExamMode = "Activate Dutch exam mode"
ActivateExamMode = "Starten Testmodus"
ActivateExamMode = "Starten Prüfungsmodus"
ActiveExamModeMessage1 = "Alle Ihre Daten werden "
ActiveExamModeMessage2 = "gelöscht, wenn Sie den "
ActiveExamModeMessage3 = "Testmodus einschalten."
ActiveExamModeMessage3 = "Prüfungsmodus einschalten."
ActiveDutchExamModeMessage1 = "All your data will be deleted when"
ActiveDutchExamModeMessage2 = "you activate the exam mode. Python"
ActiveDutchExamModeMessage3 = "application will be unavailable."
@@ -20,8 +20,8 @@ Deviation = "Varianz"
DisplayValues = "Werte anzeigen"
Empty = "Leer"
Eng = "tech"
ExitExamMode1 = "Möchten Sie den Testmodus "
ExitExamMode2 = "verlassen?"
ExitExamMode1 = "Möchten Sie den"
ExitExamMode2 = "Prüfungsmodus verlassen?"
Exponential = "Exponentielle"
FillWithFormula = "Mit einer Formel füllen"
ForbiddenValue = "Verbotener Wert"

View File

@@ -84,4 +84,4 @@ app_shared_src = $(addprefix apps/shared/,\
)
app_shared_src += $(app_shared_test_src)
app_src += $(app_shared_src)
apps_src += $(app_shared_src)

View File

@@ -472,6 +472,10 @@ void CurveView::drawArrow(KDContext * ctx, KDRect rect, float x, float y, float
*
**/
assert(angle >= 0.0f);
if (std::fabs(dx) < FLT_EPSILON && std::fabs(dy) < FLT_EPSILON) {
// We can't draw an arrow without any orientation
return;
}
/* We compute the arrow segments in pixels in order to correctly size the
* arrow without depending on the displayed range.
* Warning: the computed values are relative so we need to add/subtract the

View File

@@ -34,7 +34,7 @@ void ExpressionModel::text(const Storage::Record * record, char * buffer, size_t
e = e.replaceSymbolWithExpression(Symbol::Builder(UCodePointUnknown), Symbol::Builder(symbol));
}
int serializedSize = e.serialize(buffer, bufferSize);
if (serializedSize >= bufferSize - 1) {
if (serializedSize >= (int)bufferSize - 1) {
// It is very likely that the buffer is overflowed
buffer[0] = 0;
}

View File

@@ -183,7 +183,7 @@ uint32_t FunctionGraphController::modelVersion() {
return functionStore()->storeChecksum();
}
uint32_t FunctionGraphController::modelVersionAtIndex(size_t i) {
uint32_t FunctionGraphController::modelVersionAtIndex(int i) {
return functionStore()->storeChecksumAtIndex(i);
}

View File

@@ -50,7 +50,7 @@ private:
// InteractiveCurveViewController
bool moveCursorVertically(int direction) override;
uint32_t modelVersion() override;
uint32_t modelVersionAtIndex(size_t i) override;
uint32_t modelVersionAtIndex(int i) override;
uint32_t rangeVersion() override;
size_t numberOfMemoizedVersions() const override { return sNumberOfMemoizedModelVersions; }

View File

@@ -6,7 +6,7 @@ uint32_t FunctionStore::storeChecksum() {
return Ion::Storage::sharedStorage()->checksum();
}
uint32_t FunctionStore::storeChecksumAtIndex(size_t i) {
uint32_t FunctionStore::storeChecksumAtIndex(int i) {
if (numberOfActiveFunctions() <= i) {
return 0;
}

View File

@@ -13,7 +13,7 @@ class FunctionStore : public ExpressionModelStore {
public:
FunctionStore() : ExpressionModelStore() {}
uint32_t storeChecksum();
uint32_t storeChecksumAtIndex(size_t i);
uint32_t storeChecksumAtIndex(int i);
int numberOfActiveFunctions() const {
return numberOfModelsSatisfyingTest(&isFunctionActive, nullptr);
}

View File

@@ -41,7 +41,7 @@ protected:
virtual void initCursorParameters() = 0;
virtual bool moveCursorVertically(int direction) = 0;
virtual uint32_t modelVersion() = 0;
virtual uint32_t modelVersionAtIndex(size_t i) = 0;
virtual uint32_t modelVersionAtIndex(int i) = 0;
virtual uint32_t rangeVersion() = 0;
bool isCursorVisible();

View File

@@ -18,8 +18,7 @@ LanguageController::LanguageController(Responder * parentResponder, KDCoordinate
void LanguageController::resetSelection() {
m_selectableTableView.deselectTable();
int index = (int)GlobalPreferences::sharedGlobalPreferences()->language()-1;
selectCellAtLocation(0, index);
selectCellAtLocation(0, (int)(GlobalPreferences::sharedGlobalPreferences()->language()));
}
const char * LanguageController::title() {
@@ -41,7 +40,7 @@ void LanguageController::viewWillAppear() {
bool LanguageController::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
GlobalPreferences::sharedGlobalPreferences()->setLanguage((I18n::Language)(selectedRow()+1));
GlobalPreferences::sharedGlobalPreferences()->setLanguage((I18n::Language)selectedRow());
/* We need to reload the whole title bar in order to translate both the
* "Settings" title and the degree preference. */
AppsContainer::sharedAppsContainer()->reloadTitleBarView();

View File

@@ -2,10 +2,9 @@
namespace Shared {
static KDColor s_cursorWorkingBuffer[Dots::LargeDotDiameter*Dots::LargeDotDiameter];
void RoundCursorView::drawRect(KDContext * ctx, KDRect rect) const {
KDRect r = bounds();
KDColor cursorWorkingBuffer[Dots::LargeDotDiameter*Dots::LargeDotDiameter];
#ifdef GRAPH_CURSOR_SPEEDUP
/* Beware that only the pixels of the intersection of rect with KDContext's
* clipping rect are pulled. All other pixels are left unaltered. Indeed
@@ -15,7 +14,7 @@ void RoundCursorView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->getPixels(r, m_underneathPixelBuffer);
m_underneathPixelBufferLoaded = true;
#endif
ctx->blendRectWithMask(r, m_color, (const uint8_t *)Dots::LargeDotMask, s_cursorWorkingBuffer);
ctx->blendRectWithMask(r, m_color, (const uint8_t *)Dots::LargeDotMask, cursorWorkingBuffer);
}
KDSize RoundCursorView::minimalSizeForOptimalDisplay() const {
@@ -67,10 +66,11 @@ bool RoundCursorView::eraseCursorIfPossible() {
return false;
}
// Erase the cursor
KDColor cursorWorkingBuffer[Dots::LargeDotDiameter*Dots::LargeDotDiameter];
KDContext * ctx = KDIonContext::sharedContext();
ctx->setOrigin(currentFrame.origin());
ctx->setClippingRect(currentFrame);
ctx->fillRectWithPixels(KDRect(0,0,k_cursorSize, k_cursorSize), m_underneathPixelBuffer, s_cursorWorkingBuffer);
ctx->fillRectWithPixels(KDRect(0,0,k_cursorSize, k_cursorSize), m_underneathPixelBuffer, cursorWorkingBuffer);
// TODO Restore the context to previous values?
return true;
}

View File

@@ -168,7 +168,10 @@ void AbstractScrollableMultipleExpressionsView::setLayouts(Poincare::Layout left
}
if (updateLeftLayout || updateCenterLayout || updateRightLayout) {
contentCell()->reloadTextColor();
// Reload expressions layouts
contentCell()->layoutSubviews();
// Reload the scroll content view layout (the content size might have changed)
layoutSubviews();
// Do no reload scroll here as 'setLayouts' is called every time the table is re-layout (when scrolling for instance)
}
}

View File

@@ -16,7 +16,7 @@ app_solver_src = $(addprefix apps/solver/,\
)
app_solver_src += $(app_solver_test_src)
app_src += $(app_solver_src)
apps_src += $(app_solver_src)
i18n_files += $(addprefix apps/solver/,\
base.de.i18n\

View File

@@ -165,6 +165,15 @@ QUIZ_CASE(equation_solve) {
const char * solutions22[] = {"\u0012\u0012-π-20\u0013/\u00128\u0013\u0013", "\u0012\u0012π+20\u0013/\u00128\u0013\u0013", "\u0012\u0012π\u0013/\u00124\u0013\u0013", "3", "-8", "5"}; // (-π-20)/8, (π+20)/8, π/4, 3, 5, -8
assert_equation_system_exact_solve_to(equations22, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesxyzabc, solutions22, 6);
/* This test case needs the user defined variable. Indeed, in the equation
* store, m_variables is just before m_userVariables, so bad fetching in
* m_variables might fetch into m_userVariables and create problems. */
assert_simplify("0→x");
const char * variablesbDeyzt[] = {"b", "D", "e", "y", "z", "t"};
const char * equations23[] = {"b=0", "D=0", "e=0", "", "x+y+z+t=0", 0};
assert_equation_system_exact_solve_to(equations23, EquationStore::Error::NoError, EquationStore::Type::LinearSystem, (const char **)variablesbDeyzt, nullptr, INT_MAX);
Ion::Storage::sharedStorage()->recordNamed("x.exp").destroy();
// Monovariable non-polynomial equation
double solutions15[] = {-90.0, 90.0};
assert_equation_approximate_solve_to("cos(x)=0", -100.0, 100.0, "x", solutions15, 2, false);

View File

@@ -27,7 +27,7 @@ app_statistics_src = $(addprefix apps/statistics/,\
)
app_statistics_src += $(app_statistics_test_src)
app_src += $(app_statistics_src)
apps_src += $(app_statistics_src)
i18n_files += $(addprefix apps/statistics/,\
base.de.i18n\

View File

@@ -24,7 +24,7 @@ UnitDistanceInch = "Hüvelyk"
UnitDistanceFoot = "Láb"
UnitDistanceYard = "Yard"
UnitDistanceMile = "Mérföld"
UnitDistanceAstronomicalUnit = "Csillagászati egység"
UnitDistanceAstronomicalUnit = "Csillagászati egység"
UnitDistanceLightYear = "Fény év"
UnitDistanceParsec = "Parsec"
UnitMassImperialMenu = "Angolszász mértékegységek"

View File

@@ -3,7 +3,7 @@ app_usb_src = $(addprefix apps/usb/,\
usb_connected_controller.cpp \
)
app_src += $(app_usb_src)
apps_src += $(app_usb_src)
i18n_files += $(addprefix apps/usb/,\
base.de.i18n\

View File

@@ -2,6 +2,6 @@ USBConnected = "LA CALCULATRICE EST CONNECTÉE"
ConnectedMessage1 = "Pour transférer des données, connectez-"
ConnectedMessage2 = "vous depuis votre ordinateur sur le site"
ConnectedMessage3 = "workshop.numworks.com"
ConnectedMessage4 = "Appuyez sur la touche RETOUR de la"
ConnectedMessage5 = "calculatrice ou débranchez-la pour la"
ConnectedMessage6 = "déconnecter."
ConnectedMessage4 = "Appuyez sur la touche RETOUR"
ConnectedMessage5 = "de la calculatrice ou débranchez-la"
ConnectedMessage6 = "pour la déconnecter."

59
build/all.mak Normal file
View File

@@ -0,0 +1,59 @@
# This is a standalone Makefile
# Invoke using "make -f build/all.mak"
ANDROID_GRADLE_KEYSTORE ?= ~/.gradle/google-play-upload.keystore
ANDROID_GRADLE_PROPERTIES ?= ~/.gradle/gradle.properties
IOS_MOBILE_PROVISION ?= build/artifacts/NumWorks_Graphing_Calculator_Distribution.mobileprovision
EMCC ?= emcc
define file_check
@ if test ! -f $(1); \
then \
echo "Missing file: $(1)"; \
exit 1; \
fi
endef
define command_check
@ if ! command -v $(1) > /dev/null; \
then \
echo "Missing command: $(1), did you forget to source?"; \
exit 1; \
fi
endef
.PHONY: all
all:
$(call file_check,$(ANDROID_GRADLE_KEYSTORE))
$(call file_check,$(ANDROID_GRADLE_PROPERTIES))
$(call file_check,$(IOS_MOBILE_PROVISION))
$(call command_check,$(EMCC))
@ rm -rf output/all_official
@ mkdir -p output/all_official
@ echo "BUILD_FIRMWARE DEVICE N0110"
@ $(MAKE) clean
@ $(MAKE) epsilon.official.onboarding.dfu
@ cp output/release/device/n0110/epsilon.official.onboarding.dfu output/all_official/epsilon.device.n0110.dfu
@ echo "BUILD_FIRMWARE DEVICE N0100"
@ $(MAKE) MODEL=n0100 clean
@ $(MAKE) MODEL=n0100 epsilon.official.onboarding.dfu
@ cp output/release/device/n0100/epsilon.official.onboarding.dfu output/all_official/epsilon.device.n0100.dfu
@ echo "BUILD_FIRMWARE SIMULATOR WEB ZIP"
@ $(MAKE) PLATFORM=simulator TARGET=web clean
@ $(MAKE) PLATFORM=simulator TARGET=web epsilon.official.zip
@ cp output/release/simulator/web/epsilon.official.zip output/all_official/simulator.web.zip
@ echo "BUILD_FIRMWARE SIMULATOR WEB JS"
@ $(MAKE) PLATFORM=simulator TARGET=web epsilon.official.js
@ cp output/release/simulator/web/epsilon.official.js output/all_official/epsilon.js
@ echo "BUILD_FIRMWARE SIMULATOR WEB PYTHON JS"
@ $(MAKE) PLATFORM=simulator TARGET=web clean
@ $(MAKE) PLATFORM=simulator TARGET=web EPSILON_GETOPT=1 EPSILON_APPS=code epsilon.official.js
@ cp output/release/simulator/web/epsilon.official.js output/all_official/epsilon.python.js
@ echo "BUILD_FIRMWARE SIMULATOR ANDROID"
@ $(MAKE) PLATFORM=simulator TARGET=android clean
@ $(MAKE) PLATFORM=simulator TARGET=android epsilon.official.apk
@ cp output/release/simulator/android/epsilon.official.apk output/all_official/epsilon.official.apk
@ echo "BUILD_FIRMWARE SIMULATOR IOS"
@ $(MAKE) PLATFORM=simulator TARGET=ios clean
@ $(MAKE) PLATFORM=simulator TARGET=ios IOS_PROVISIONNING_PROFILE=$(IOS_MOBILE_PROVISION) epsilon.official.ipa
@ cp output/release/simulator/ios/epsilon.official.ipa output/all_official/epsilon.ipa

View File

@@ -2,10 +2,6 @@
PLATFORM ?= device
DEBUG ?= 0
LEDS_CHOICE ?= 0
include build/defaults.mak
include build/platform.$(PLATFORM).mak
EPSILON_VERSION ?= 13.1.0
OMEGA_VERSION ?= 1.20.0
@@ -17,17 +13,4 @@ EPSILON_GETOPT ?= 0
EPSILON_TELEMETRY ?= 0
ESCHER_LOG_EVENTS_BINARY ?= 0
OMEGA_THEME ?= omega_light
ifndef USE_LIBA
$(error platform.mak should define USE_LIBA)
endif
include build/toolchain.$(TOOLCHAIN).mak
SFLAGS += -DDEBUG=$(DEBUG)
SFLAGS += -DLEDS_CHOICE=$(LEDS_CHOICE)
ifdef USERNAME
SFLAGS += -DUSERNAME="$(USERNAME)"
endif
SFLAGS += -DEPSILON_GETOPT=$(EPSILON_GETOPT)
SFLAGS += -DEPSILON_TELEMETRY=$(EPSILON_TELEMETRY)
SFLAGS += -DESCHER_LOG_EVENTS_BINARY=$(ESCHER_LOG_EVENTS_BINARY)
LEDS_CHOICE ?= 0

View File

@@ -2,6 +2,15 @@ HOSTCC = gcc
HOSTCXX = g++
PYTHON = python3
SFLAGS += -DDEBUG=$(DEBUG)
SFLAGS += -DLEDS_CHOICE=$(LEDS_CHOICE)
ifdef USERNAME
SFLAGS += -DUSERNAME="$(USERNAME)"
endif
SFLAGS += -DEPSILON_GETOPT=$(EPSILON_GETOPT)
SFLAGS += -DEPSILON_TELEMETRY=$(EPSILON_TELEMETRY)
SFLAGS += -DESCHER_LOG_EVENTS_BINARY=$(ESCHER_LOG_EVENTS_BINARY)
# Language-specific flags
CFLAGS = -std=c99
CXXFLAGS = -std=c++11 -fno-exceptions -fno-rtti -fno-threadsafe-statics

View File

@@ -4,86 +4,61 @@ import re
import subprocess
import sys
import matplotlib.pyplot as plt
import random
from matplotlib.ticker import FormatStrFormatter
def filter_set(data, pred):
result = {}
for k,v in data.items():
if (pred(v)):
result[k] = v
return result
readelf_line_regex = re.compile("[0-9]+:\s+([0-9a-f]+)\s+([0-9]+)\s+[A-Z]+")
def parse_line(line):
hex_start, dec_size = re.findall(readelf_line_regex, line)[0]
return (int(hex_start, 16), int(dec_size))
def pred_ram(symbol):
return (symbol[0] >= 0x20000000) and (symbol[0] <= 0x20040000)
readelf_output = subprocess.check_output([
"arm-none-eabi-readelf",
"-W", # Don't limit line lenght
"-s", # Sizes
sys.argv[1]
]).decode('utf-8')
def pred_size(symbol):
return (symbol[1] >= 64)
for line in readelf_output.splitlines():
words = line.split()
if not words:
continue
symbol = words[-1]
if symbol == "_ZN3Ion17staticStorageAreaE":
storage = parse_line(line)
if symbol == "_ZZN13AppsContainer19sharedAppsContainerEvE20appsContainerStorage":
container = parse_line(line)
if symbol == "_stack_start":
stack_start, _ = parse_line(line)
if symbol == "_stack_end":
stack_end, _ = parse_line(line)
if symbol == "_heap_start":
heap_start, _ = parse_line(line)
if symbol == "_heap_end":
heap_end, _ = parse_line(line)
def load_symbols(filename):
nm_output = subprocess.check_output([
"arm-none-eabi-nm",
"--print-size",
filename
]).decode('utf-8').splitlines()
nm_symbol_regex = re.compile("^([0-9A-Fa-f]+) ([0-9A-Fa-f]+) (.) (.+)$")
nm_sizeless_regex = re.compile("^([0-9a-z]+) (.) (.+)$")
symbol_results = [ re.match(nm_symbol_regex, line).groups() for line in nm_output if re.match(nm_symbol_regex, line) ]
sizeless_results = [ re.match(nm_sizeless_regex, line).groups() for line in nm_output if re.match(nm_sizeless_regex, line) ]
results = {}
for result in symbol_results:
results[result[3]] = ((int(result[0],16),int(result[1],16),result[2],result[3]))
for result in sizeless_results:
results[result[2]] = ((int(result[0],16),0,result[1],result[2]))
# Fixup stack and heap
for i in (("_stack_start", "_stack_end", "_stack"), ("_heap_start", "_heap_end", "_heap")):
if i[0] in results and i[1] in results:
start = results[i[0]]
end = results[i[1]]
results[i[2]] = (min(start[0], end[0]), abs(end[0]-start[0]), start[2], i[2])
del results[i[0]]
del results[i[1]]
return results
def demangle_symbols(symbols):
symbol_names = []
for name in symbols.keys():
symbol_names.append(name)
symbols_encoded = "\n".join(symbol_names).encode('utf-8')
demangled_output = subprocess.check_output(["c++filt"], input=symbols_encoded).decode('utf-8').splitlines()
demangled_symbols = {}
cpt=0
for symbol in symbols.values():
demangled_symbols[demangled_output[cpt]] = (symbol[0], symbol[1], symbol[2], demangled_output[cpt])
cpt += 1
return demangled_symbols
stack_size = stack_start - stack_end # Stack grows downwards
stack = (stack_end, stack_size)
heap_size = heap_end - heap_start
heap = (heap_start, heap_size)
def format_kb(i):
return ("%.3f KiB" % (i/1024))
return ("%d KB" % (i/1024))
def plot_symbols(symbols, range_start, range_end):
fig,ax = plt.subplots()
cpt = 0
for symbol in symbols.values():
symbol_name = symbol[3].lstrip("_")
symbol_color=(random.uniform(0,1),random.uniform(0,1),random.uniform(0,1))
ax.broken_barh([(symbol[0], symbol[1])], (0, 1), color=symbol_color, label=symbol_name + " - " + format_kb(symbol[1]))
cpt += 1
ax.set_yticks([])
ax.set_xticks(list(range(range_start, range_end+1, int((range_end-range_start)/16))))
xlabels = map(lambda t: '0x%08X' % int(t), ax.get_xticks())
ax.set_xticklabels(xlabels);
ax.legend()
fig.set_size_inches(20, 2)
return fig
fig,ax = plt.subplots()
data=load_symbols(sys.argv[1])
data=demangle_symbols(data)
data = filter_set(data, pred_ram)
data = filter_set(data, pred_size)
def plot(value, name, c):
ax.broken_barh([value], (0, 1), color=c, label=name + " - " + format_kb(value[1]))
fig=plot_symbols(data,0x20000000,0x20040000)
plot(container, "Container", "blue")
plot(storage, "Storage", "red")
plot(heap, "Heap", "pink")
plot(stack, "Stack", "green")
fig.show()
input()
ax.set_yticks([])
ax.set_xticks(list(range(0x20000000,0x20040001,0x10000)))
xlabels = map(lambda t: '0x%08X' % int(t), ax.get_xticks())
ax.set_xticklabels(xlabels);
ax.legend()
fig.set_size_inches(20, 2)
fig.savefig(sys.argv[2])

60
build/helpers.mk Normal file
View File

@@ -0,0 +1,60 @@
# Define a standard rule helper
# If passed a last parameter value of with_local_version, we also define an
# extra rule that can build source files within the $(BUILD_DIR). This is useful
# for rules that can be applied for intermediate objects (for example, when
# going .png -> .cpp -> .o).
define rule_label
@ echo "$(shell printf "%-8s" $(strip $(1)))$(@:$(BUILD_DIR)/%=%)"
endef
# rule_for can define both global and local rules
# - use local if the source can be an intermediate file
# - use global if the source can be in the main tree
define rule_for
ifneq ($(filter global,$(5)),)
$(addprefix $$(BUILD_DIR)/,$(strip $(2))): $(strip $(3)) | $$$$(@D)/.
@ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(BUILD_DIR)/%=%)"
$(Q) $(4)
endif
ifneq ($(filter local,$(5)),)
$(addprefix $$(BUILD_DIR)/,$(strip $(2))): $(addprefix $$(BUILD_DIR)/,$(strip $(3)))
@ echo "$(shell printf "%-8s" $(strip $(1)))$$(@:$$(BUILD_DIR)/%=%)"
$(Q) $(4)
endif
endef
# Helper functions to work with variants
define direct_object_for
$(addprefix $(BUILD_DIR)/,$(addsuffix .o,$(basename $(1))))
endef
# Objects for source files in $(1) matching flavor $(2). A flavor is a dot
# separated list of variants (e.g. large.speed).
define flavored_object_for
$(call direct_object_for,$(call filter_variants,$(1),$(sort $(subst ., ,$(2)))))
endef
define object_for
$(call direct_object_for,$(call any_variant,$(1)))
endef
# Multi-arch helpers
ifdef ARCHS
ifndef ARCH
# This rule allow us to build any executable (%) for a specified ARCH ($1)
# We depend on a phony target to make sure this rule is always executed
.PHONY: force_remake
define rule_for_arch_executable
.PRECIOUS: $$(BUILD_DIR)/$(1)/%.$$(EXE)
$$(BUILD_DIR)/$(1)/%.$$(EXE): force_remake
$(Q) echo "MAKE ARCH=$(1)"
$(Q) $$(MAKE) ARCH=$(1) $$*.$$(EXE)
endef
$(foreach ARCH,$(ARCHS),$(eval $(call rule_for_arch_executable,$(ARCH))))
endif
endif

View File

@@ -0,0 +1,140 @@
#!/usr/bin/env python3
import argparse
import os
import re
import subprocess
import urllib.parse
# ELF analysis
def loadable_sections(elf_file, address_prefix = ""):
objdump_section_headers_pattern = re.compile("^\s+\d+\s+(\.[\w\.]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+("+address_prefix+"[0-9a-f]+)\s+([0-9a-f]+).*LOAD", flags=re.MULTILINE)
objdump_output = subprocess.check_output(["arm-none-eabi-objdump", "-h", "-w", elf_file]).decode('utf-8')
sections = []
for (name, size, vma, lma, offset) in re.findall(objdump_section_headers_pattern, objdump_output):
int_size = int(size,16)
if (int_size > 0):
sections.append({'name': name, 'size': int_size, 'vma': int(vma,16), 'lma': int(lma,16), 'offset':int(offset,16)})
return sections
# Data filtering
def biggest_sections(sections, n):
sorted_sections = sorted(sections, key=lambda s: s['size'], reverse=True)
return sorted_sections[:n]
def total_size(sections):
return sum(map(lambda s: s['size'], sections))
def row_for_elf(elf, columns):
sections = loadable_sections(elf)
result = {}
for s in biggest_sections(sections, columns):
result[s['name']] = s['size']
result['Total'] = total_size(sections)
return result
# String formatting
def iso_separate(string):
space = ' ' # We may want to use a thin non-breaking space as thousands separator
return string.replace('_',space).replace('+','+'+space).replace('-','-'+space)
def format_bytes(value, force_sign=False):
if value is None:
return ''
number_format = '{:'
if force_sign:
number_format += '+'
number_format += '_} bytes'
return iso_separate(number_format.format(value))
def format_percentage(value):
if value is None:
return ''
return iso_separate("{:+.1f} %".format(100*value))
# Markdown
def emphasize(string):
if string:
return '_' + string + '_'
else:
return ''
def strong(string):
if string:
return '**' + string + '**'
else:
return ''
# Deltas
def absolute_delta(x,y):
if x is None or y is None:
return None
return x-y
def ratio_delta(x,y):
if x is None or y is None:
return None
return (x-y)/y
# Table formatting
def format_row(row, header=False):
result = '|'
if header:
result += strong(header)
result += '|'
for v in row:
result += v
result += '|'
result += '\n'
return result
def format_table(table):
base = table[0]['values']
listed_sections = base.keys()
result = ''
result += format_row(listed_sections)
result += '|-|' + '-:|'*len(listed_sections) + '\n'
for i,row in enumerate(table):
v = row['values']
result += format_row((format_bytes(v.get(s)) for s in listed_sections), header=row['label'])
if i != 0:
result += format_row(emphasize(format_bytes(absolute_delta(v.get(s), base.get(s)), force_sign=True)) for s in listed_sections)
result += format_row(emphasize(format_percentage(ratio_delta(v.get(s), base.get(s)))) for s in listed_sections)
return result
# Argument parsing
parser = argparse.ArgumentParser(description='Compute binary size metrics')
parser.add_argument('files', type=str, nargs='+', help='an ELF file')
parser.add_argument('--labels', type=str, nargs='+', help='label for ELF file')
parser.add_argument('--number-of-sections', type=int, default=2, help='Number of detailed sections')
parser.add_argument('--escape', action='store_true', help='Escape the output')
args = parser.parse_args()
# Execution
table = []
for i,filename in enumerate(args.files):
label = os.path.basename(filename)
if args.labels and i < len(args.labels):
label = args.labels[i]
table.append({'label': label, 'values': row_for_elf(filename, args.number_of_sections)})
formatted_table = format_table(table)
if args.escape:
print(urllib.parse.quote(formatted_table, safe='| :*+'))
else:
print(formatted_table)

View File

@@ -1,10 +1,12 @@
TOOLCHAIN = android
EXE = so
EPSILON_TELEMETRY ?= 1
ARCHS = armeabi-v7a arm64-v8a x86 x86_64
ifdef ARCH
EXE = so
BUILD_DIR := $(BUILD_DIR)/$(ARCH)
else
HANDY_TARGETS_EXTENSIONS = apk
endif

View File

@@ -6,7 +6,7 @@ APPLE_PLATFORM_MIN_VERSION = 8.0
EPSILON_TELEMETRY ?= 1
ifeq ($(APPLE_PLATFORM),ios)
ARCHS ?= arm64 armv7
ARCHS = arm64 armv7
UI_REQUIRED_CAPABILITIES += armv7
else ifeq ($(APPLE_PLATFORM),ios-simulator)
ARCHS = x86_64
@@ -16,4 +16,6 @@ BUILD_DIR := $(subst $(TARGET),$(APPLE_PLATFORM),$(BUILD_DIR))
ifdef ARCH
BUILD_DIR := $(BUILD_DIR)/$(ARCH)
else
HANDY_TARGETS_EXTENSIONS = ipa app
endif

View File

@@ -10,4 +10,6 @@ EPSILON_SIMULATOR_HAS_LIBPNG = 1
ifdef ARCH
BUILD_DIR := $(BUILD_DIR)/$(ARCH)
else
HANDY_TARGETS_EXTENSIONS = app
endif

View File

@@ -1,2 +1,4 @@
TOOLCHAIN = emscripten
EXE = js
HANDY_TARGETS_EXTENSIONS += zip

View File

@@ -1,46 +1,63 @@
# Define standard compilation rules
.PHONY: official_authorization
ifeq ($(ACCEPT_OFFICIAL_TOS),1)
official_authorization:
else
official_authorization:
@echo "CAUTION: You are trying to build an official NumWorks firmware."
@echo "Distribution of such firmware by a third party is prohibited."
@echo "Please set the ACCEPT_OFFICIAL_TOS environment variable to proceed."
@exit -1
endif
$(eval $(call rule_for, \
AS, %.o, %.s, \
$$(CC) $$(SFLAGS) -c $$< -o $$@ \
$$(CC) $$(SFLAGS) -c $$< -o $$@, \
global \
))
$(eval $(call rule_for, \
CC, %.o, %.c, \
$$(CC) $$(CFLAGS) $$(SFLAGS) -c $$< -o $$@, \
with_local_version \
global local \
))
$(eval $(call rule_for, \
CPP, %, %.inc, \
$$(CPP) -P $$< $$@, \
global \
))
$(eval $(call rule_for, \
CXX, %.o, %.cpp, \
$$(CXX) $$(CXXFLAGS) $$(SFLAGS) -c $$< -o $$@, \
with_local_version \
global local \
))
$(eval $(call rule_for, \
DFUSE, %.dfu, %.elf, \
$$(PYTHON) build/device/elf2dfu.py $$< $$@, \
local \
))
$(eval $(call rule_for, \
OBJCOPY, %.hex, %.elf, \
$$(OBJCOPY) -O ihex $$< $$@, \
local \
))
$(eval $(call rule_for, \
OBJCOPY, %.bin, %.elf, \
$$(OBJCOPY) -O binary $$< $$@, \
local \
))
$(eval $(call rule_for, \
OCC, %.o, %.m, \
$$(CC) $$(CFLAGS) $$(SFLAGS) -c $$< -o $$@ \
$$(CC) $$(CFLAGS) $$(SFLAGS) -c $$< -o $$@, \
global \
))
$(eval $(call rule_for, \
OCC, %.o, %.mm, \
$$(CXX) $$(CXXFLAGS) $$(SFLAGS) -c $$< -o $$@ \
$$(CXX) $$(CXXFLAGS) $$(SFLAGS) -c $$< -o $$@, \
global \
))
$(eval $(call rule_for, \
CPP, %, %.inc, \
$$(CPP) -P $$< $$@ \
WINDRES, %.o, %.rc, \
$$(WINDRES) $$< -O coff -o $$@, \
global \
))
ifdef EXE
@@ -52,17 +69,14 @@ ifeq ($(OS),Windows_NT)
# the linker to read its arguments from this file.
$(eval $(call rule_for, \
LD, %.$$(EXE), , \
echo $$^ > $$@.objs && $$(LD) @$$@.objs $$(LDFLAGS) -o $$@ && rm $$@.objs \
echo $$^ > $$@.objs && $$(LD) @$$@.objs $$(LDFLAGS) -o $$@ && rm $$@.objs, \
global \
))
else
$(eval $(call rule_for, \
LD, %.$$(EXE), , \
$$(LD) $$^ $$(LDFLAGS) -o $$@ \
$$(LD) $$^ $$(LDFLAGS) -o $$@, \
global \
))
endif
endif
$(eval $(call rule_for, \
WINDRES, %.o, %.rc, \
$$(WINDRES) $$< -O coff -o $$@ \
))

View File

@@ -1,60 +0,0 @@
ANDROID_GRADLE_KEYSTORE ?= ~/.gradle/google-play-upload.keystore
ANDROID_GRADLE_PROPERTIES ?= ~/.gradle/gradle.properties
IOS_MOBILE_PROVISION ?= build/artifacts/NumWorks_Graphing_Calculator_Distribution.mobileprovision
EMCC ?= emcc
define source_emsdk
source ~/emsdk/emsdk_env.sh > /dev/null
endef
define file_check
@ if test ! -f $(1); \
then \
echo "Missing file: $(1)"; \
exit 1; \
fi
endef
define command_check
@ if ! command -v $(1) > /dev/null; \
then \
echo "Missing command: $(1), did you forget to source?"; \
exit 1; \
fi
endef
.PHONY: all_official
all_official:
$(call file_check,$(ANDROID_GRADLE_KEYSTORE))
$(call file_check,$(ANDROID_GRADLE_PROPERTIES))
$(call file_check,$(IOS_MOBILE_PROVISION))
$(call command_check,$(EMCC))
$(Q) rm -rf output/all_official
$(Q) mkdir -p output/all_official
$(Q) echo "BUILD_FIRMWARE DEVICE N0110"
$(Q) $(MAKE) clean
$(Q) $(MAKE) epsilon.official.onboarding.dfu
$(Q) cp output/release/device/n0110/epsilon.official.onboarding.dfu output/all_official/epsilon.device.n0110.dfu
$(Q) echo "BUILD_FIRMWARE DEVICE N0100"
$(Q) $(MAKE) MODEL=n0100 clean
$(Q) $(MAKE) MODEL=n0100 epsilon.official.onboarding.dfu
$(Q) cp output/release/device/n0100/epsilon.official.onboarding.dfu output/all_official/epsilon.device.n0100.dfu
$(Q) echo "BUILD_FIRMWARE SIMULATOR WEB ZIP"
$(Q) $(MAKE) PLATFORM=simulator TARGET=web clean
$(Q) $(call source_emsdk); $(MAKE) PLATFORM=simulator TARGET=web epsilon.official.zip
$(Q) cp output/release/simulator/web/epsilon.official.zip output/all_official/simulator.web.zip
$(Q) echo "BUILD_FIRMWARE SIMULATOR WEB JS"
$(Q) $(call source_emsdk); $(MAKE) PLATFORM=simulator TARGET=web epsilon.official.js
$(Q) cp output/release/simulator/web/epsilon.official.js output/all_official/epsilon.js
$(Q) echo "BUILD_FIRMWARE SIMULATOR WEB PYTHON JS"
$(Q) $(MAKE) PLATFORM=simulator TARGET=web clean
$(Q) $(call source_emsdk); $(MAKE) PLATFORM=simulator TARGET=web EPSILON_GETOPT=1 EPSILON_APPS=code epsilon.official.js
$(Q) cp output/release/simulator/web/epsilon.official.js output/all_official/epsilon.python.js
$(Q) echo "BUILD_FIRMWARE SIMULATOR ANDROID"
$(Q) $(MAKE) PLATFORM=simulator TARGET=android clean
$(Q) $(MAKE) PLATFORM=simulator TARGET=android epsilon.official.signed.apk
$(Q) cp output/release/simulator/android/app/outputs/apk/codesigned/android-codesigned.apk output/all_official/epsilon.official.apk
$(Q) echo "BUILD_FIRMWARE SIMULATOR IOS"
$(Q) $(MAKE) PLATFORM=simulator TARGET=ios clean
$(Q) $(MAKE) PLATFORM=simulator TARGET=ios IOS_PROVISIONNING_PROFILE=$(IOS_MOBILE_PROVISION) output/release/simulator/ios/app/epsilon.official.ipa
$(Q) cp output/release/simulator/ios/app/epsilon.official.ipa output/all_official/epsilon.ipa

View File

@@ -3,25 +3,14 @@ include build/targets.device.$(MODEL).mak
HANDY_TARGETS += flasher.light flasher.verbose bench.ram bench.flash
HANDY_TARGETS_EXTENSIONS += dfu hex bin
$(eval $(call rule_for, \
DFUSE, %.dfu, %.$$(EXE), \
$$(PYTHON) build/device/elf2dfu.py $$< $$@, \
with_local_version \
))
$(eval $(call rule_for, \
OBJCOPY, %.hex, %.$$(EXE), \
$$(OBJCOPY) -O ihex $$< $$@ \
))
$(eval $(call rule_for, \
OBJCOPY, %.bin, %.$$(EXE), \
$$(OBJCOPY) -O binary $$< $$@, \
with_local_version \
))
%_ram_map: %.$(EXE)
$(PYTHON) build/device/ram_map.py $(BUILD_DIR)/$<
$(eval $(call rule_for, \
RAMSIZE, %_ram_map.png, %.elf, \
$$(PYTHON) build/device/ram_map.py $$< $$@, \
local \
))
.PHONY: %_size
%_size: $(BUILD_DIR)/%.$(EXE)
@@ -50,19 +39,19 @@ openocd:
# The flasher target is defined here because otherwise $(%_src) has not been
# fully filled
flasher_src = $(ion_src) $(ion_device_flasher_src) $(liba_src) $(kandinsky_src)
$(BUILD_DIR)/flasher.light.$(EXE): $(call flavored_object_for,$(flasher_src),light usbxip)
$(BUILD_DIR)/flasher.verbose.$(EXE): $(call flavored_object_for,$(flasher_src),usbxip)
$(BUILD_DIR)/flasher.%.$(EXE): LDFLAGS += -Lion/src/$(PLATFORM)/flasher
$(BUILD_DIR)/flasher.%.$(EXE): LDSCRIPT = ion/src/$(PLATFORM)/shared/ram.ld
flasher_base_src = $(ion_xip_src) $(liba_src) $(kandinsky_src)
$(BUILD_DIR)/flasher.light.$(EXE): $(call object_for,$(flasher_base_src) $(ion_target_device_flasher_light_src))
$(BUILD_DIR)/flasher.verbose.$(EXE): $(call object_for,$(flasher_base_src) $(ion_target_device_flasher_verbose_src))
#TODO Do not build all apps... Put elsewhere?
bench_src = $(ion_src) $(liba_src) $(kandinsky_src) $(poincare_src) $(libaxx_src) $(app_shared_src) $(ion_device_bench_src)
$(BUILD_DIR)/bench.ram.$(EXE): $(call flavored_object_for,$(bench_src),consoleuart usbxip)
$(BUILD_DIR)/bench.ram.$(EXE): LDFLAGS += -Lion/src/$(PLATFORM)/bench
$(BUILD_DIR)/bench.ram.$(EXE): LDSCRIPT = ion/src/$(PLATFORM)/shared/ram.ld
$(BUILD_DIR)/bench.flash.$(EXE): $(call flavored_object_for,$(bench_src),consoleuart usbxip)
$(BUILD_DIR)/bench.flash.$(EXE): LDSCRIPT = ion/src/$(PLATFORM)/$(MODEL)/internal_flash.ld
bench_src = $(ion_xip_src) $(liba_src) $(kandinsky_src) $(poincare_src) $(libaxx_src) $(app_shared_src) $(ion_target_device_bench_src)
$(BUILD_DIR)/bench.ram.$(EXE): $(call object_for,$(bench_src))
$(BUILD_DIR)/bench.flash.$(EXE): $(call object_for,$(bench_src))
.PHONY: %.two_binaries
%.two_binaries: %.elf

View File

@@ -1,28 +1,78 @@
# Define standard Epsilon targets
base_src = $(liba_src) $(kandinsky_src) $(escher_src) $(libaxx_src) $(poincare_src) $(python_src)
epsilon_src = $(base_src) $(ion_default_src) $(apps_default_src)
epsilon_official_src = $(base_src) $(ion_default_src) $(apps_official_default_src)
$(BUILD_DIR)/epsilon.$(EXE): $(call object_for,$(epsilon_src))
$(BUILD_DIR)/epsilon.official.$(EXE): $(call object_for,$(epsilon_official_src))
$(BUILD_DIR)/epsilon.onboarding.$(EXE): $(call object_for, $(base_src) $(ion_default_src) $(apps_onboarding_src))
$(BUILD_DIR)/epsilon.official.onboarding.$(EXE): $(call object_for,$(base_src) $(ion_default_src) $(apps_official_onboarding_src))
$(BUILD_DIR)/epsilon.onboarding.update.$(EXE): $(call object_for, $(base_src) $(ion_default_src) $(apps_onboarding_update_src))
$(BUILD_DIR)/epsilon.official.onboarding.update.$(EXE): $(call object_for,$(base_src) $(ion_default_src) $(apps_official_onboarding_update_src))
$(BUILD_DIR)/epsilon.onboarding.beta.$(EXE): $(call object_for, $(base_src) $(ion_default_src) $(apps_onboarding_beta_src))
$(BUILD_DIR)/epsilon.official.onboarding.beta.$(EXE): $(call object_for,$(base_src) $(ion_default_src) $(apps_official_onboarding_beta_src))
test_base_src = $(base_src) $(apps_tests_src) $(runner_src) $(tests_src)
test_runner_src = $(test_base_src) $(ion_console_on_screen_src)
$(BUILD_DIR)/test.$(EXE): $(call object_for,$(test_runner_src))
# Define handy targets
# Those can be built easily by simply invoking "make target.ext". The named file
# will be built in $(BUILD_DIR).
HANDY_TARGETS += epsilon epsilon.official epsilon.onboarding epsilon.official.onboarding epsilon.onboarding.update epsilon.official.onboarding.update epsilon.onboarding.beta epsilon.official.onboarding.beta test
HANDY_TARGETS ?=
HANDY_TARGETS_EXTENSIONS ?=
# Epsilon base target
base_src = $(ion_src) $(liba_src) $(kandinsky_src) $(escher_src) $(libaxx_src) $(poincare_src) $(python_src)
epsilon_src = $(base_src) $(apps_src)
$(BUILD_DIR)/epsilon.$(EXE): $(call flavored_object_for,$(epsilon_src))
HANDY_TARGETS += epsilon
# Epsilon flavored targets
epsilon_flavors = \
onboarding \
onboarding.update \
onboarding.beta
define rule_for_epsilon_flavor
$$(BUILD_DIR)/epsilon.$(1).$$(EXE): $$(call flavored_object_for,$$(epsilon_src),$(1))
endef
$(foreach flavor,$(epsilon_flavors),$(eval $(call rule_for_epsilon_flavor,$(flavor))))
HANDY_TARGETS += $(foreach flavor,$(epsilon_flavors),epsilon.$(flavor))
# Epsilon official targets
epsilon_official_flavors = \
official \
official.onboarding \
official.onboarding.update \
official.onboarding.beta
define rule_for_unconfirmed_official_flavor
$$(BUILD_DIR)/epsilon.$(1).$$(EXE):
@echo "CAUTION: You are trying to build an official NumWorks firmware."
@echo "Distribution of such firmware by a third party is prohibited."
@echo "Please set the ACCEPT_OFFICIAL_TOS environment variable to proceed."
@exit -1
endef
ifeq ($(ACCEPT_OFFICIAL_TOS),1)
rule_for_official_epsilon_flavor = rule_for_epsilon_flavor
else
rule_for_official_epsilon_flavor = rule_for_unconfirmed_official_flavor
endif
$(foreach flavor,$(epsilon_official_flavors),$(eval $(call $(rule_for_official_epsilon_flavor),$(flavor))))
HANDY_TARGETS += $(foreach flavor,$(epsilon_official_flavors),epsilon.$(flavor))
# Test
test_runner_src = $(base_src) $(apps_tests_src) $(runner_src) $(tests_src)
$(BUILD_DIR)/test.$(EXE): $(call flavored_object_for,$(test_runner_src),consoledisplay)
HANDY_TARGETS += test
# Load platform-specific targets
# We include them before the standard ones to give them precedence.
-include build/targets.$(PLATFORM).mak
# Generate handy targets rules
# Define handy targets
# Those can be built easily by simply invoking "make target.ext". The named file
# will be built in $(BUILD_DIR).
HANDY_TARGETS_EXTENSIONS += $(EXE)
define handy_target_rule
@@ -30,10 +80,4 @@ define handy_target_rule
$(1).$(2): $$(BUILD_DIR)/$(1).$(2)
endef
# Load platform-specific targets
# We include them before the standard ones to give them precedence.
-include build/targets.$(PLATFORM).mak
$(foreach extension,$(HANDY_TARGETS_EXTENSIONS),$(foreach executable,$(HANDY_TARGETS),$(eval $(call handy_target_rule,$(executable),$(extension)))))
include build/targets.all.mak

View File

@@ -1,3 +1,4 @@
ifndef ARCH
HANDY_TARGETS_EXTENSIONS += apk
endif
.PHONY: %_run
%_run: $(BUILD_DIR)/%.apk
$(call rule_label,ADB)
$(Q) adb install $<

View File

@@ -0,0 +1,6 @@
ifeq ($(APPLE_PLATFORM),ios-simulator)
.PHONY: %_run
%_run: $(BUILD_DIR)/%.app
$(call rule_label,XCRUN)
$(Q) xcrun simctl install booted $^
endif

View File

@@ -1,10 +1,8 @@
# Headless targets
epsilon_headless_src = $(base_src) $(ion_headless_src) $(apps_default_src)
$(BUILD_DIR)/epsilon.headless.$(EXE): $(call object_for,$(epsilon_headless_src))
$(eval $(call rule_for_epsilon_flavor,headless))
HANDY_TARGETS += epsilon.headless
test_runner_headless_src = $(test_base_src) $(ion_headless_src)
$(BUILD_DIR)/test.headless.$(EXE): $(call object_for,$(test_runner_headless_src))
HANDY_TARGETS += epsilon.headless test.headless
$(BUILD_DIR)/test.headless.$(EXE): $(call flavored_object_for,$(test_runner_src),headless)
HANDY_TARGETS += test.headless
-include build/targets.simulator.$(TARGET).mak

View File

@@ -1,3 +1 @@
HANDY_TARGETS_EXTENSIONS += zip
$(BUILD_DIR)/test.headless.js: EMSCRIPTEN_MODULARIZE = 0

63
build/variants.mak Normal file
View File

@@ -0,0 +1,63 @@
# Helper functions to work with variants
# Make variants_test for an example
define available_variants_in
$(sort $(patsubst +%,%,$(filter +%,$(subst :, ,$(1)))))
endef
define without_any_variant_specifier
$(filter-out $(foreach variant,$(call available_variants_in,$(1)),%:-$(variant) %:+$(variant)),$(1))
endef
define with_variant_specifier_matching
$(foreach variant,$(3),$(patsubst %:$(1)$(variant),%,$(filter %:$(1)$(variant),$(2))))
endef
define without_any_variant_specifier_matching
$(filter-out \
$(call with_variant_specifier_matching,$(1),$(2),$(3)), \
$(foreach variant,$(call available_variants_in,$(2)),$(call with_variant_specifier_matching,$(1),$(2),$(variant))) \
)
endef
# Return files in $(1) that match the variant $(2)
define filter_variants
$(sort \
$(call without_any_variant_specifier,$(1)) \
$(call with_variant_specifier_matching,+,$(1),$(2)) \
$(call without_any_variant_specifier_matching,-,$(1),$(2)) \
)
endef
# Return all files in $(1) no matter their variant
define any_variant
$(sort $(filter-out -%,$(filter-out +%,$(subst :, ,$(1)))))
endef
# Examples
variants_test_src = base.cpp
variants_test_src += color/green.cpp:+green
variants_test_src += color/red.cpp:+red
variants_test_src += color/blue.cpp:-red
variants_test_src += color/blue.cpp:-green
variants_test_src += engine/fast.cpp:+nitro
variants_test_src += engine/slow.cpp:-nitro
.PHONY: variants_test
variants_test:
$(info AVAILABLE_VARIANTS_IN)
$(info --result: $(call available_variants_in,$(variants_test_src),))
$(info --expected: green nitro red)
$(info FILTER_VARIANTS)
$(info --result: $(call filter_variants,$(variants_test_src),))
$(info --expected: base.cpp color/blue.cpp engine/slow.cpp)
$(info FILTER_VARIANTS red)
$(info --result: $(call filter_variants,$(variants_test_src),red))
$(info --expected: base.cpp color/red.cpp engine/slow.cpp)
$(info FILTER_VARIANTS green speed)
$(info --result: $(call filter_variants,$(variants_test_src),green nitro))
$(info --expected: base.cpp color/green.cpp engine/fast.cpp)
$(info ANY_VARIANT)
$(info --result: $(call any_variant,$(variants_test_src)))
$(info --expected: base.cpp color/blue.cpp color/green.cpp color/red.cpp engine/fast.cpp engine/slow.cpp)

View File

@@ -1,5 +1,13 @@
SFLAGS += -Iescher/include
$(eval $(call rule_for, \
THEME, \
escher/palette.h, \
$(addprefix themes/themes/, $(addsuffix .json, $(OMEGA_THEME))), \
$$(PYTHON) themes/themes_manager.py $(OMEGA_THEME) $$@, \
global \
))
escher_src += $(addprefix escher/src/,\
alternate_empty_view_controller.cpp \
app.cpp \
@@ -94,14 +102,8 @@ $(eval $(call rule_for, \
HOSTCC, \
escher/image/inliner, \
escher/image/inliner.c $(addprefix ion/src/external/lz4/, lz4.c lz4hc.c), \
$$(HOSTCC) -std=c99 `libpng-config --cflags` $$^ `libpng-config --ldflags` -o $$@ \
))
$(eval $(call rule_for, \
THEME, \
escher/palette.h, \
$(addprefix themes/themes/, $(addsuffix .json, $(OMEGA_THEME))), \
$$(PYTHON) themes/themes_manager.py $(OMEGA_THEME) $$@ \
$$(HOSTCC) -std=c99 `libpng-config --cflags` $$^ `libpng-config --ldflags` -o $$@, \
global \
))
INLINER := $(BUILD_DIR)/escher/image/inliner
@@ -111,7 +113,8 @@ $(eval $(call rule_for, \
INLINER, \
%.h %.cpp, \
$(BUILD_DIR)/%.png $$(INLINER), \
$$(INLINER) $$< $$(basename $$@).h $$(basename $$@).cpp \
$$(INLINER) $$< $$(basename $$@).h $$(basename $$@).cpp, \
global \
))
# Mark a .cpp file as depending on a .png one

View File

@@ -6,7 +6,7 @@
namespace I18n {
enum class Message : uint16_t;
enum class Language : uint16_t;
const char * translate(Message m, Language l = (Language)0);
const char * translate(Message m);
int numberOfLanguages();
}

View File

@@ -508,15 +508,46 @@ bool LayoutField::privateHandleEvent(Ion::Events::Event event) {
return false;
}
static inline bool IsSimpleMoveEvent(Ion::Events::Event event) {
return event == Ion::Events::Left
|| event == Ion::Events::Right
|| event == Ion::Events::Up
|| event == Ion::Events::Down;
#define static_assert_immediately_follows(a, b) static_assert( \
static_cast<uint8_t>(a) + 1 == static_cast<uint8_t>(b), \
"Ordering error" \
)
#define static_assert_sequential(a, b, c, d) \
static_assert_immediately_follows(a, b); \
static_assert_immediately_follows(b, c); \
static_assert_immediately_follows(c, d);
static_assert_sequential(
LayoutCursor::Direction::Left,
LayoutCursor::Direction::Up,
LayoutCursor::Direction::Down,
LayoutCursor::Direction::Right
);
static_assert_sequential(
Ion::Events::Left,
Ion::Events::Up,
Ion::Events::Down,
Ion::Events::Right
);
static inline bool IsMoveEvent(Ion::Events::Event event) {
return
static_cast<uint8_t>(event) >= static_cast<uint8_t>(Ion::Events::Left) &&
static_cast<uint8_t>(event) <= static_cast<uint8_t>(Ion::Events::Right);
}
static inline LayoutCursor::Direction DirectionForMoveEvent(Ion::Events::Event event) {
assert(IsMoveEvent(event));
return static_cast<LayoutCursor::Direction>(
static_cast<uint8_t>(LayoutCursor::Direction::Left) +
static_cast<uint8_t>(event) - static_cast<uint8_t>(Ion::Events::Left)
);
}
bool LayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) {
if (!IsSimpleMoveEvent(event)) {
if (!IsMoveEvent(event)) {
return false;
}
if (resetSelection()) {
@@ -524,16 +555,7 @@ bool LayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * should
return true;
}
LayoutCursor result;
if (event == Ion::Events::Left) {
result = m_contentView.cursor()->cursorAtDirection(LayoutCursor::Direction::Left, shouldRecomputeLayout);
} else if (event == Ion::Events::Right) {
result = m_contentView.cursor()->cursorAtDirection(LayoutCursor::Direction::Right, shouldRecomputeLayout);
} else if (event == Ion::Events::Up) {
result = m_contentView.cursor()->cursorAtDirection(LayoutCursor::Direction::Up, shouldRecomputeLayout);
} else {
assert(event == Ion::Events::Down);
result = m_contentView.cursor()->cursorAtDirection(LayoutCursor::Direction::Down, shouldRecomputeLayout);
}
result = m_contentView.cursor()->cursorAtDirection(DirectionForMoveEvent(event), shouldRecomputeLayout);
if (result.isDefined()) {
m_contentView.setCursor(result);
return true;
@@ -541,20 +563,37 @@ bool LayoutField::privateHandleMoveEvent(Ion::Events::Event event, bool * should
return false;
}
bool eventIsSelection(Ion::Events::Event event) {
return event == Ion::Events::ShiftLeft || event == Ion::Events::ShiftRight || event == Ion::Events::ShiftUp || event == Ion::Events::ShiftDown;
static_assert_sequential(
Ion::Events::ShiftLeft,
Ion::Events::ShiftUp,
Ion::Events::ShiftDown,
Ion::Events::ShiftRight
);
static inline bool IsSelectionEvent(Ion::Events::Event event) {
return
static_cast<uint8_t>(event) >= static_cast<uint8_t>(Ion::Events::ShiftLeft) &&
static_cast<uint8_t>(event) <= static_cast<uint8_t>(Ion::Events::ShiftRight);
}
static inline LayoutCursor::Direction DirectionForSelectionEvent(Ion::Events::Event event) {
assert(IsSelectionEvent(event));
return static_cast<LayoutCursor::Direction>(
static_cast<uint8_t>(LayoutCursor::Direction::Left) +
static_cast<uint8_t>(event) - static_cast<uint8_t>(Ion::Events::ShiftLeft)
);
}
bool LayoutField::privateHandleSelectionEvent(Ion::Events::Event event, bool * shouldRecomputeLayout) {
if (!eventIsSelection(event)) {
if (!IsSelectionEvent(event)) {
return false;
}
Layout addedSelection;
LayoutCursor::Direction direction = event == Ion::Events::ShiftLeft ? LayoutCursor::Direction::Left :
(event == Ion::Events::ShiftRight ? LayoutCursor::Direction::Right :
(event == Ion::Events::ShiftUp ? LayoutCursor::Direction::Up :
LayoutCursor::Direction::Down));
LayoutCursor result = m_contentView.cursor()->selectAtDirection(direction, shouldRecomputeLayout, &addedSelection);
LayoutCursor result = m_contentView.cursor()->selectAtDirection(
DirectionForSelectionEvent(event),
shouldRecomputeLayout,
&addedSelection
);
if (addedSelection.isUninitialized()) {
return false;
}

View File

@@ -53,7 +53,7 @@ bool RunLoop::step() {
}
#if ESCHER_LOG_EVENTS_BINARY
Ion::Console::writeChar((char)event.id());
Ion::Console::writeChar(static_cast<uint8_t>(event));
#endif
#if ESCHER_LOG_EVENTS_NAME
const char * name = event.name();

View File

@@ -15,8 +15,6 @@ include ion/src/$(PLATFORM)/Makefile
-include ion/test/$(PLATFORM)/Makefile
include ion/src/shared/tools/Makefile
ion_console_display_src += ion/src/shared/console_display.cpp
# We need to work around a GCC bug (concerning versions < 5.1). It is valid in
# C++11 to initialize a character array by providing a string litteral (e.g.
# char test[4]= "ab"; is valid and should initialize test to 'a','b',0,0).
@@ -25,10 +23,13 @@ initializer_list = $(shell echo $(1) | sed "s/\(.\)/'\1',/g")0
$(call object_for,ion/src/shared/platform_info.cpp): SFLAGS += -DPATCH_LEVEL="$(call initializer_list,$(PATCH_LEVEL))" -DEPSILON_VERSION="$(call initializer_list,$(EPSILON_VERSION))" -DOMEGA_VERSION="$(call initializer_list,$(OMEGA_VERSION))" -DUSERNAME="$(call initializer_list,$(USERNAME))"
ion_src += $(addprefix ion/src/shared/, \
console_display.cpp:+consoledisplay \
console_line.cpp \
crc32_eat_byte.cpp \
decompress.cpp \
events.cpp \
events_keyboard.cpp \
events_modifier.cpp \
platform_info.cpp \
storage.cpp \
unicode/utf8_decoder.cpp\
@@ -49,14 +50,3 @@ tests_src += $(addprefix ion/test/,\
ifdef ION_STORAGE_LOG
SFLAGS += -DION_STORAGE_LOG=1
endif
# Configure variants
ion_all_src = $(ion_src)
ion_all_src += $(ion_simulator_sdl_src) $(ion_simulator_headless_src)
ion_all_src += $(ion_device_dfu_relocated_src) $(ion_device_dfu_xip_src)
ion_all_src += $(ion_console_display_src) $(ion_console_stdio_src) $(ion_console_uart_src)
ion_default_src = $(ion_src) $(ion_simulator_sdl_src) $(ion_device_dfu_relocated_src) $(ion_console_stdio_src)
ion_console_on_screen_src = $(ion_src) $(ion_simulator_sdl_src) $(ion_device_dfu_relocated_src) $(ion_console_display_src)
ion_xip_src = $(ion_src) $(ion_simulator_sdl_src) $(ion_device_dfu_xip_src) $(ion_console_uart_src)
ion_headless_src = $(ion_src) $(ion_simulator_headless_src) $(ion_device_dfu_relocated_src) $(ion_console_stdio_src)

View File

@@ -17,7 +17,7 @@ public:
constexpr Event() : m_id(4*PageSize){} // Return Ion::Event::None by default
constexpr Event(int i) : m_id(i){} // TODO: Assert here that i>=0 && i<255
uint8_t id() const { return m_id; }
constexpr explicit operator uint8_t() const { return m_id; }
#if DEBUG
const char * name() const;
#endif

View File

@@ -11,7 +11,7 @@ void msleep(uint32_t ms);
/* millis is the number of milliseconds ellapsed since a random epoch.
* On the device, epoch is the boot time. */
volatile uint64_t millis();
uint64_t millis();
}
}

View File

@@ -6,22 +6,12 @@ include ion/src/device/$(MODEL)/Makefile
$(call object_for,ion/src/shared/platform_info.cpp): SFLAGS += -DHEADER_SECTION="__attribute__((section(\".header\")))"
ion_src += $(addprefix ion/src/shared/, \
console_line.cpp \
events_keyboard.cpp \
events_modifier.cpp \
)
ifeq ($(EPSILON_TELEMETRY),1)
ion_src += ion/src/shared/telemetry_console.cpp
endif
# If you need to benchmark execution, you can replace events_keyboard with
# events_benchmark.
# If you need to profile execution, you can replace events_keyboard with
# events_replay.o and dummy/events_modifier.o
ION_DEVICE_SFLAGS = -Iion/src/device/$(MODEL) -Iion/src/device/shared
$(call object_for,$(sort $(ion_device_src) $(dfu_src) $(ion_target_device_flasher_light_src) $(ion_target_device_flasher_verbose_src) $(usb_src) $(ion_target_device_bench_src) $(ion_device_dfu_xip_src) $(ion_device_dfu_relocated_src) $(ion_console_uart_src))): SFLAGS += $(ION_DEVICE_SFLAGS)
$(call object_for,$(ion_device_src) $(ion_device_flasher_src) $(ion_device_bench_src)): SFLAGS += $(ION_DEVICE_SFLAGS)
ion_src += $(ion_device_src)

View File

@@ -1,11 +1,11 @@
ion_target_device_bench_src += $(addprefix ion/src/device/bench/, \
ion_device_bench_src += $(addprefix ion/src/device/bench/, \
bench.cpp \
command_handler.cpp \
command_list.cpp \
runner.cpp \
)
ion_target_device_bench_src += $(addprefix ion/src/device/bench/command/, \
ion_device_bench_src += $(addprefix ion/src/device/bench/command/, \
adc.cpp \
backlight.cpp \
charge.cpp \

View File

@@ -1,9 +1,5 @@
ion_target_device_flasher_light_src = $(addprefix ion/src/device/flasher/, \
ion_device_flasher_src = $(addprefix ion/src/device/flasher/, \
main.cpp \
display_light.cpp \
)
ion_target_device_flasher_verbose_src = $(addprefix ion/src/device/flasher/, \
main.cpp \
display_verbose.cpp \
display_light.cpp:+light \
display_verbose.cpp:-light \
)

View File

@@ -119,5 +119,7 @@ void __attribute__((noinline)) start() {
}
void __attribute__((interrupt, noinline)) isr_systick() {
Ion::Device::Timing::MillisElapsed++;
auto t = Ion::Device::Timing::MillisElapsed;
t++;
Ion::Device::Timing::MillisElapsed = t;
}

View File

@@ -3,6 +3,8 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \
battery.cpp \
base64.cpp \
board.cpp \
console_uart.cpp:+consoleuart \
console_dummy.cpp:-consoleuart \
crc32.cpp \
display.cpp \
events_keyboard_platform.cpp \
@@ -21,7 +23,3 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \
usb.cpp \
wakeup.cpp \
)
ion_console_uart_src = ion/src/device/shared/drivers/console.cpp
ion_console_stdio_src += ion/src/device/shared/drivers/console_dummy.cpp
ion_console_display_src += ion/src/device/shared/drivers/console_dummy.cpp

View File

@@ -29,7 +29,7 @@ void usleep(uint32_t us) {
}
}
volatile uint64_t millis() {
uint64_t millis() {
return MillisElapsed;
}

View File

@@ -1,9 +1,11 @@
usb_src += $(addprefix ion/src/device/shared/usb/, \
# USB code
ion_device_usb_src += $(addprefix ion/src/device/shared/usb/, \
calculator.cpp \
dfu_interface.cpp\
)
usb_src += $(addprefix ion/src/device/shared/usb/stack/, \
ion_device_usb_src += $(addprefix ion/src/device/shared/usb/stack/, \
device.cpp\
endpoint0.cpp \
interface.cpp\
@@ -12,7 +14,7 @@ usb_src += $(addprefix ion/src/device/shared/usb/stack/, \
streamable.cpp\
)
usb_src += $(addprefix ion/src/device/shared/usb/stack/descriptor/, \
ion_device_usb_src += $(addprefix ion/src/device/shared/usb/stack/descriptor/, \
bos_descriptor.cpp\
configuration_descriptor.cpp \
descriptor.cpp\
@@ -29,27 +31,24 @@ usb_src += $(addprefix ion/src/device/shared/usb/stack/descriptor/, \
webusb_platform_descriptor.cpp\
)
# Sources required to execute DFU in place
ion_device_dfu_xip_src += ion/src/device/shared/usb/dfu_xip.cpp
ion_device_dfu_xip_src += $(usb_src)
# DFU code
# Sources required to execute DFU in RAM
dfu_src += liba/src/assert.c
dfu_src += liba/src/strlen.c
dfu_src += liba/src/strlcpy.c
dfu_src += liba/src/memset.c
dfu_src += liba/src/memcpy.c
dfu_src += libaxx/src/cxxabi/pure_virtual.cpp
dfu_src += ion/src/device/shared/usb/boot.cpp
dfu_src += ion/src/device/$(MODEL)/drivers/board.cpp
dfu_src += ion/src/device/$(MODEL)/drivers/cache.cpp
dfu_src += ion/src/device/$(MODEL)/drivers/reset.cpp
dfu_src += $(addprefix ion/src/device/shared/drivers/, \
ion_device_dfu_src += liba/src/assert.c
ion_device_dfu_src += liba/src/strlen.c
ion_device_dfu_src += liba/src/strlcpy.c
ion_device_dfu_src += liba/src/memset.c
ion_device_dfu_src += liba/src/memcpy.c
ion_device_dfu_src += libaxx/src/cxxabi/pure_virtual.cpp
ion_device_dfu_src += ion/src/device/shared/usb/boot.cpp
ion_device_dfu_src += ion/src/device/$(MODEL)/drivers/board.cpp
ion_device_dfu_src += ion/src/device/$(MODEL)/drivers/cache.cpp
ion_device_dfu_src += ion/src/device/$(MODEL)/drivers/reset.cpp
ion_device_dfu_src += $(addprefix ion/src/device/shared/drivers/, \
backlight.cpp \
battery.cpp \
base64.cpp \
board.cpp \
console.cpp \
console_uart.cpp \
crc32.cpp \
display.cpp \
events_keyboard_platform.cpp \
@@ -68,8 +67,14 @@ dfu_src += $(addprefix ion/src/device/shared/drivers/, \
wakeup.cpp \
)
# Sources required to execute DFU in place
ion_device_src += ion/src/device/shared/usb/dfu_xip.cpp:+usbxip
ion_device_src += $(addsuffix :+usbxip,$(ion_device_usb_src))
# Sources required to execute DFU in RAM
$(BUILD_DIR)/ion/src/device/shared/usb/dfu.elf: LDSCRIPT = ion/src/device/shared/usb/dfu.ld
$(BUILD_DIR)/ion/src/device/shared/usb/dfu.elf: $(call object_for,$(usb_src) $(dfu_src))
$(BUILD_DIR)/ion/src/device/shared/usb/dfu.elf: $(call object_for,$(ion_device_usb_src) $(ion_device_dfu_src))
# In order to link the dfu bootloader inside the epsilon firmware, we need to
# turn the dfu binary (dfu.bin) into an elf object.
@@ -83,5 +88,5 @@ $(BUILD_DIR)/ion/src/device/shared/usb/dfu.o: $(BUILD_DIR)/ion/src/device/shared
$(call rule_label,OBJCOPY)
$(Q) cd $(dir $<) ; $(OBJCOPY) -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata.dfu_bootloader --redefine-sym _binary_dfu_bin_start=_dfu_bootloader_flash_start --redefine-sym _binary_dfu_bin_end=_dfu_bootloader_flash_end $(notdir $<) $(notdir $@)
ion_device_dfu_relocated_src += ion/src/device/shared/usb/dfu.cpp
ion_device_dfu_relocated_src += ion/src/device/shared/usb/dfu_relocated.cpp
ion_device_src += ion/src/device/shared/usb/dfu.cpp:-usbxip
ion_device_src += ion/src/device/shared/usb/dfu_relocated.cpp:-usbxip

View File

@@ -3,7 +3,7 @@
static auto start = std::chrono::steady_clock::now();
volatile uint64_t Ion::Timing::millis() {
uint64_t Ion::Timing::millis() {
auto elapsed = std::chrono::steady_clock::now() - start;
return std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
}

View File

@@ -1,9 +1,5 @@
# TODO
ion_src += $(addprefix ion/src/shared/, \
crc32.cpp \
events.cpp \
events_keyboard.cpp \
events_modifier.cpp \
power.cpp \
random.cpp \
timing.cpp \
@@ -18,24 +14,19 @@ ion_src += $(addprefix ion/src/shared/, \
dummy/usb.cpp \
)
ion_simulator_sdl_src += $(addprefix ion/src/simulator/shared/, \
display.cpp \
events_keyboard.cpp \
ion_src += $(addprefix ion/src/simulator/shared/, \
console_stdio.cpp:-consoledisplay \
display.cpp:-headless \
events_keyboard.cpp:-headless \
events_stdin.cpp:+headless \
framebuffer_base.cpp \
keyboard_sdl.cpp \
main_sdl.cpp \
layout.cpp \
framebuffer_png.cpp:+headless \
keyboard_dummy.cpp:+headless \
keyboard_sdl.cpp:-headless \
layout.cpp:-headless \
main_headless.cpp:+headless \
main_sdl.cpp:-headless \
)
ion_simulator_headless_src += $(addprefix ion/src/simulator/shared/, \
events_stdin.cpp \
framebuffer_base.cpp \
framebuffer_png.cpp \
keyboard_dummy.cpp \
main_headless.cpp \
)
ion_console_stdio_src = ion/src/simulator/shared/console_stdio.cpp
include ion/src/simulator/$(TARGET)/Makefile
include ion/src/simulator/external/Makefile

View File

@@ -11,7 +11,6 @@ $(call object_for,ion/src/simulator/shared/main.cpp) : SFLAGS += -DEPSILON_SDL_F
LDFLAGS += -ljnigraphics -llog
# If ARCH is not defined, we will re-trigger a build for each avaialble ARCH.
# This is used to build APKs, which needs to embbed a binary for each ARCH.
@@ -33,17 +32,6 @@ $(BUILD_DIR)/app/res/%.xml: ion/src/simulator/android/src/res/%.xml | $$(@D)/.
$(call rule_label,COPY)
$(Q) cp $< $@
# This rule allow us to build any executable (%) for a specified ARCH ($1)
# We depend on a phony target to make sure this rule is always executed
.PHONY: force_remake
define rule_for_arch_executable
.PRECIOUS: $$(BUILD_DIR)/$(1)/%.so
$$(BUILD_DIR)/$(1)/%.so: force_remake
$(Q) echo "MAKE ARCH=$(1) $$*.so"
$(Q) $$(MAKE) ARCH=$(1) --silent $$*.so
endef
# We need to put the .so files somewhere Gradle can pick them up.
# We decided to use the location "app/libs/$EXECUTABLE/$ARCH/libepsilon.so"
# This way it's easy to import the shared object from Java code (it's always
@@ -58,7 +46,6 @@ $(call path_for_arch_jni_lib,$(1)): $$(BUILD_DIR)/$(1)/%.so | $$$$(@D)/.
$(Q) cp $$< $$@
endef
$(foreach ARCH,$(ARCHS),$(eval $(call rule_for_arch_executable,$(ARCH))))
$(foreach ARCH,$(ARCHS),$(eval $(call rule_for_arch_jni_lib,$(ARCH))))
apk_deps = $(foreach ARCH,$(ARCHS),$(call path_for_arch_jni_lib,$(ARCH)))
@@ -68,15 +55,8 @@ apk_deps += $(addprefix $(BUILD_DIR)/app/res/,mipmap/ic_launcher.png mipmap-v26/
.PRECIOUS: $(apk_deps)
$(BUILD_DIR)/%.apk: $(apk_deps)
@echo "GRADLE ion/src/simulator/android/build.gradle"
$(call rule_label,GRADLE)
$(Q) ANDROID_HOME=$(ANDROID_HOME) EPSILON_VERSION=$(EPSILON_VERSION) BUILD_DIR=$(BUILD_DIR) EPSILON_VARIANT=$* ion/src/simulator/android/gradlew -b ion/src/simulator/android/build.gradle assembleRelease
$(Q) cp $(BUILD_DIR)/app/outputs/apk/release/android-release*.apk $@
DEFAULT = epsilon.apk
.PHONY: %_run
%_run: $(BUILD_DIR)/%.apk
@echo "ADB $*.apk"
$(Q) adb install $<
endif

View File

@@ -26,6 +26,8 @@ LDFLAGS += -framework CoreData
LDFLAGS += -Lion/src/simulator/ios/GoogleAnalyticsServices
endif
ifndef ARCH
# App resources
SIMULATOR_ICON_SIZES = 20x20 29x29 40x40 40x40 40x40 58x58 58x58 60x60 76x76 \
@@ -33,9 +35,9 @@ SIMULATOR_ICON_SIZES = 20x20 29x29 40x40 40x40 40x40 58x58 58x58 60x60 76x76 \
SIMULATOR_ASSETS_PATH = $(BUILD_DIR)/app/assets/Assets.xcassets
SIMULATOR_ICONSET = $(SIMULATOR_ASSETS_PATH)/AppIcon.appiconset
include ion/src/simulator/shared/apple/Makefile
include ion/src/simulator/shared/apple/helpers.mak
$(call simulator_app_plist,%,Info.plist): ion/src/simulator/ios/Info.plist $(call simulator_app_resource,%,Assets.car)
$(call simulator_app_plist,Info.plist): ion/src/simulator/ios/Info.plist $(call simulator_app_resource,Assets.car)
$(call rule_label,PLUTIL)
$(Q) cp $< $@
$(Q) plutil -insert "BuildMachineOSBuild" -string "$(IOS_BUILD_MACHINE_OS_BUILD)" $@
@@ -54,12 +56,12 @@ $(call simulator_app_plist,%,Info.plist): ion/src/simulator/ios/Info.plist $(cal
$(Q) plutil -replace CFBundleIcons -json `plutil -extract CFBundleIcons json -o - $(BUILD_DIR)/app/assets/partial.plist` $@
$(Q) plutil -replace CFBundleIcons~ipad -json `plutil -extract CFBundleIcons~ipad json -o - $(BUILD_DIR)/app/assets/partial.plist` $@
$(call simulator_app_resource,%,launch.storyboardc): ion/src/simulator/ios/launch.storyboard | $$(@D)/.
$(call simulator_app_resource,launch.storyboardc): ion/src/simulator/ios/launch.storyboard | $$(@D)/.
$(call rule_label,IBTOOL)
$(Q) $(IBTOOL) --minimum-deployment-target $(APPLE_PLATFORM_MIN_VERSION) --compile $@ $^
ifdef IOS_PROVISIONNING_PROFILE
$(call simulator_app_resource,%,embedded.mobileprovision): $(IOS_PROVISIONNING_PROFILE) | $$(@D)/.
$(call simulator_app_resource,embedded.mobileprovision): $(IOS_PROVISIONNING_PROFILE) | $$(@D)/.
$(call rule_label,COPY)
$(Q) cp $^ $@
@@ -68,9 +70,9 @@ $(BUILD_DIR)/app/entitlements.plist: $(IOS_PROVISIONNING_PROFILE)
$(Q) security cms -D -i $(IOS_PROVISIONNING_PROFILE) | plutil -extract Entitlements xml1 - -o $@
simulator_app_deps += $(BUILD_DIR)/app/entitlements.plist
simulator_app_deps += $(call simulator_app_resource,$1,embedded.mobileprovision)
simulator_app_deps += $(call simulator_app_resource,embedded.mobileprovision)
else
$(call simulator_app_resource,%,embedded.mobileprovision):
$(call simulator_app_resource,embedded.mobileprovision):
$(warning Building without a provisionning profile. Please define IOS_PROVISIONNING_PROFILE to point to the .mobileprovision file you want to use.)
endif
@@ -78,29 +80,13 @@ $(SIMULATOR_ICONSET)/Contents.json: ion/src/simulator/ios/icon_assets.json $(SIM
$(call rule_label,COPY)
$(Q) cp $< $@
$(call simulator_app_resource,%,Assets.car): $(SIMULATOR_ICONSET)/Contents.json | $$(@D)/.
$(call simulator_app_resource,Assets.car): $(SIMULATOR_ICONSET)/Contents.json | $$(@D)/.
$(call rule_label,ACTOOL)
$(Q) $(ACTOOL) --compile $(BUILD_DIR)/app/Payload/$*.app --minimum-deployment-target $(APPLE_PLATFORM_MIN_VERSION) --platform $(APPLE_SDK) --app-icon AppIcon --output-partial-info-plist $(BUILD_DIR)/app/assets/partial.plist $(SIMULATOR_ASSETS_PATH) > /dev/null
$(Q) $(ACTOOL) --compile $(BUILD_DIR)/$*.app --minimum-deployment-target $(APPLE_PLATFORM_MIN_VERSION) --platform $(APPLE_SDK) --app-icon AppIcon --output-partial-info-plist $(BUILD_DIR)/app/assets/partial.plist $(SIMULATOR_ASSETS_PATH) > /dev/null
simulator_app_deps += $(call simulator_app_resource,$(1), \
Assets.car \
launch.storyboardc \
)
simulator_app_deps += $(call simulator_app_resource,Assets.car)
simulator_app_deps += $(call simulator_app_resource,launch.storyboardc)
include ion/src/simulator/shared/apple/targets.mak
$(BUILD_DIR)/app/epsilon%ipa: $$(subst ..,.,$$(call simulator_app_deps,Epsilon$$*))
ifdef IOS_PROVISIONNING_PROFILE
$(call rule_label,SIGN)
$(Q) codesign --force --entitlements $(BUILD_DIR)/app/entitlements.plist --sign "Apple Distribution: NumWorks" $(BUILD_DIR)/app/Payload/Epsilon$*app
endif
$(call rule_label,ZIP)
$(Q) cd $(dir $@) ; zip -qr9 $(notdir $@) Payload
ifndef ARCH
DEFAULT := $(BUILD_DIR)/app/epsilon.ipa
endif
ifeq ($(APPLE_PLATFORM),ios-simulator)
.PHONY: epsilon%run
epsilon%run: $(subst _.,.,$(call simulator_app_deps,Epsilon$*))
xcrun simctl install booted $(BUILD_DIR)/app/Payload/Epsilon$(subst _,.,$*)app
endif

Some files were not shown because too many files have changed in this diff Show More