mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
Compare commits
137 Commits
O1.22.1-E1
...
omega-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a6dfd8a20 | ||
|
|
c8afdcacab | ||
|
|
ef45fab63d | ||
|
|
0366c4cd00 | ||
|
|
c3b752d6cc | ||
|
|
c5ca1e916a | ||
|
|
24f3ccf007 | ||
|
|
25b74ea2f8 | ||
|
|
0e7db3ce8a | ||
|
|
786a3273da | ||
|
|
ed54927c5b | ||
|
|
2ee86ce52f | ||
|
|
a3720d3d76 | ||
|
|
ba94c7db00 | ||
|
|
4c29b05b53 | ||
|
|
85f8f4fedd | ||
|
|
e62c328661 | ||
|
|
080ac51aae | ||
|
|
bf5f24f96c | ||
|
|
7e24502414 | ||
|
|
dd45419006 | ||
|
|
aba2388253 | ||
|
|
5fca77a8f8 | ||
|
|
f258da16f1 | ||
|
|
35e4146551 | ||
|
|
76dad83aec | ||
|
|
f999c796c3 | ||
|
|
f86c22f10b | ||
|
|
c841362a63 | ||
|
|
33ad74e1be | ||
|
|
e4aa82e62a | ||
|
|
f40fe27b68 | ||
|
|
3e071a59fe | ||
|
|
f50f22081c | ||
|
|
313b5ed222 | ||
|
|
f8798aa561 | ||
|
|
46acd4eb61 | ||
|
|
018ea07796 | ||
|
|
d7f41e306c | ||
|
|
029dc2be5e | ||
|
|
bf99a2976b | ||
|
|
03c85c0b0e | ||
|
|
bd0c7de2bf | ||
|
|
08f351fe31 | ||
|
|
0282104086 | ||
|
|
ed95b46c5b | ||
|
|
b8727bc256 | ||
|
|
5ccf8d6b97 | ||
|
|
b80daf70d3 | ||
|
|
36655f1c19 | ||
|
|
ed18f1e95f | ||
|
|
cbb435d656 | ||
|
|
00b74430cd | ||
|
|
8705ddaf8a | ||
|
|
ddae6607f9 | ||
|
|
c4ef2016ba | ||
|
|
524a7d9619 | ||
|
|
e456667d5e | ||
|
|
3000431f3b | ||
|
|
50a32b470d | ||
|
|
3746354f26 | ||
|
|
8fae36bcd3 | ||
|
|
9e9c088e9e | ||
|
|
a635ecf59b | ||
|
|
a6ae1957d1 | ||
|
|
3686f819d6 | ||
|
|
382c303bd2 | ||
|
|
402858739e | ||
|
|
192794e299 | ||
|
|
58602544e2 | ||
|
|
ed03aae9ed | ||
|
|
ece6aa5f27 | ||
|
|
30cfa022d1 | ||
|
|
23f3407267 | ||
|
|
1006b951b9 | ||
|
|
43b7f767ee | ||
|
|
eb0ca7b118 | ||
|
|
0cdfc44c6f | ||
|
|
2ebff40c62 | ||
|
|
c66db8c98d | ||
|
|
a6b13185ab | ||
|
|
e8956f4293 | ||
|
|
36a40faaaf | ||
|
|
2554ec666e | ||
|
|
1aac2a1d4d | ||
|
|
32d591317b | ||
|
|
2703f9a506 | ||
|
|
497e4890b1 | ||
|
|
6c389c9a1d | ||
|
|
699cf22023 | ||
|
|
543d3d540e | ||
|
|
2f2e45a6a5 | ||
|
|
a834c954b8 | ||
|
|
2bee7eb267 | ||
|
|
6d18c33068 | ||
|
|
8242113641 | ||
|
|
7c8c7f79f6 | ||
|
|
f578c24af1 | ||
|
|
8059821025 | ||
|
|
b32497da23 | ||
|
|
c3c7651ca8 | ||
|
|
e8f1ea6aa5 | ||
|
|
ba3109e47a | ||
|
|
c2f8bbaf3c | ||
|
|
0587e41b3c | ||
|
|
ab1df4fbef | ||
|
|
a4213dcca8 | ||
|
|
2cf6f15dde | ||
|
|
f37008d8d7 | ||
|
|
3740e0f135 | ||
|
|
cb3a6694a5 | ||
|
|
cba596dde7 | ||
|
|
11f2b92e5d | ||
|
|
a69fc679a9 | ||
|
|
f4905c59a2 | ||
|
|
22b6990e63 | ||
|
|
09a7b9daca | ||
|
|
0116dc2e07 | ||
|
|
37b8c56b3d | ||
|
|
1a4cb3ad37 | ||
|
|
d4984722cf | ||
|
|
cbc3951ab1 | ||
|
|
62aafa7597 | ||
|
|
baf8b8cbf0 | ||
|
|
90b25ecf51 | ||
|
|
d02ce2dd16 | ||
|
|
79985a0199 | ||
|
|
f10cd19616 | ||
|
|
945a7b8d56 | ||
|
|
784234690c | ||
|
|
fd0284756f | ||
|
|
4f2ea99c85 | ||
|
|
bef8719ce0 | ||
|
|
ba64458660 | ||
|
|
73172f8d0c | ||
|
|
5a20d914df | ||
|
|
05e6fbbcca |
8
.github/workflows/ci-workflow.yml
vendored
8
.github/workflows/ci-workflow.yml
vendored
@@ -129,6 +129,8 @@ jobs:
|
||||
submodules: 'recursive'
|
||||
- run: pacman -S --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config make mingw-w64-x86_64-python3 mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-libpng
|
||||
- run: make -j2 PLATFORM=simulator
|
||||
- run: make -j2 PLATFORM=simulator test.exe
|
||||
- run: cmd /c output\release\simulator\windows\test.exe --headless
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-windows.exe
|
||||
@@ -143,6 +145,8 @@ jobs:
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 PLATFORM=simulator TARGET=web
|
||||
- run: make -j2 PLATFORM=simulator TARGET=web test.js
|
||||
- run: node output/release/simulator/web/test.js --headless
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-web.zip
|
||||
@@ -155,6 +159,8 @@ jobs:
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 PLATFORM=simulator
|
||||
- run: make -j2 PLATFORM=simulator test.bin
|
||||
- run: output/release/simulator/linux/test.bin --headless
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-linux.bin
|
||||
@@ -168,6 +174,8 @@ jobs:
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 PLATFORM=simulator
|
||||
- run: make -j2 PLATFORM=simulator ARCH=x86_64 test.bin
|
||||
- run: output/release/simulator/macos/x86_64/test.bin --headless
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: epsilon-macos.zip
|
||||
|
||||
14
.github/workflows/unit-workflow.yml
vendored
14
.github/workflows/unit-workflow.yml
vendored
@@ -1,14 +0,0 @@
|
||||
name: Unit tests
|
||||
on: [pull_request_target]
|
||||
|
||||
jobs:
|
||||
units:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 PLATFORM=simulator test.headless.bin
|
||||
- run: output/release/simulator/linux/test.headless.bin
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
image: gcc
|
||||
|
||||
stages:
|
||||
- build
|
||||
|
||||
job:build:
|
||||
stage: build
|
||||
before_script:
|
||||
- "echo 'deb http://httpredir.debian.org/debian jessie main contrib \n deb-src http://httpredir.debian.org/debian jessie main contrib \n deb http://httpredir.debian.org/debian jessie-updates main contrib \n deb-src http://httpredir.debian.org/debian jessie-updates main contrib \n deb http://security.debian.org/ jessie/updates main contrib \n deb-src http://security.debian.org/ jessie/updates main contrib ' > /etc/apt/source.list"
|
||||
- "apt-get update"
|
||||
- "apt -y install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config fltk1.3-dev gcc-arm-none-eabi nodejs npm"
|
||||
- "git submodule update --init --recursive"
|
||||
- "git clone https://github.com/RedGl0w/omega-auto-increment"
|
||||
- "cd omega-auto-increment"
|
||||
- "npm i request exeq"
|
||||
- "PrivateToken=$PrivateToken node index.js"
|
||||
- "cd .."
|
||||
script:
|
||||
- make clean
|
||||
- make MODEL=n0100 epsilon.bin
|
||||
artifacts:
|
||||
paths:
|
||||
- output/release/device/n0100/epsilon.bin
|
||||
- omega-auto-increment/version.txt
|
||||
name: artifact:build:simulator
|
||||
|
||||
@@ -85,9 +85,6 @@ language_preferences = apps/language_preferences.csv
|
||||
SFLAGS += -I$(BUILD_DIR)
|
||||
|
||||
i18n_files += $(addprefix apps/language_,$(addsuffix .universal.i18n, $(EPSILON_I18N)))
|
||||
ifeq ($(EPSILON_GETOPT),1)
|
||||
i18n_files += $(addprefix apps/language_,$(addsuffix _iso6391.universal.i18n, $(EPSILON_I18N)))
|
||||
endif
|
||||
|
||||
i18n_files += $(call i18n_with_universal_for,shared)
|
||||
i18n_files += $(call i18n_with_universal_for,toolbox)
|
||||
@@ -97,7 +94,7 @@ $(eval $(call rule_for, \
|
||||
I18N, \
|
||||
apps/i18n.cpp, \
|
||||
$(i18n_files), \
|
||||
$$(PYTHON) apps/i18n.py --codepoints $(code_points) --countrypreferences $(country_preferences) --languagepreferences $(language_preferences) --header $$(subst .cpp,.h,$$@) --implementation $$@ --locales $$(EPSILON_I18N) --countries $$(EPSILON_COUNTRIES) --files $$^ --generateISO6391locales $$(EPSILON_GETOPT), \
|
||||
$$(PYTHON) apps/i18n.py --codepoints $(code_points) --countrypreferences $(country_preferences) --languagepreferences $(language_preferences) --header $$(subst .cpp,.h,$$@) --implementation $$@ --locales $$(EPSILON_I18N) --countries $$(EPSILON_COUNTRIES) --files $$^, \
|
||||
global \
|
||||
))
|
||||
|
||||
@@ -113,6 +110,8 @@ $(call object_for,$(apps_src) $(tests_src)): $(BUILD_DIR)/apps/i18n.h
|
||||
$(call object_for,$(apps_src) $(tests_src)): $(BUILD_DIR)/apps/home/apps_layout.h
|
||||
$(call object_for,$(apps_src) $(tests_src)): $(BUILD_DIR)/python/port/genhdr/qstrdefs.generated.h
|
||||
|
||||
$(call object_for,$(apps_src)): $(BUILD_DIR)/apps/home/apps_layout.h
|
||||
|
||||
apps_tests_src = $(app_calculation_test_src) $(app_code_test_src) $(app_graph_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/,\
|
||||
|
||||
@@ -30,6 +30,7 @@ app_code_test_src = $(addprefix apps/code/,\
|
||||
|
||||
tests_src += $(addprefix apps/code/test/,\
|
||||
variable_box_controller.cpp\
|
||||
toolbox_ion_keys_dummy.cpp \
|
||||
)
|
||||
|
||||
app_code_src += $(app_code_test_src)
|
||||
|
||||
@@ -124,10 +124,6 @@ Toolbox * App::toolboxForInputEventHandler(InputEventHandler * textInput) {
|
||||
return &m_toolbox;
|
||||
}
|
||||
|
||||
Code::toolboxIonKeys * App::toolboxIonKeys() {
|
||||
return &m_toolboxIonKeys;
|
||||
}
|
||||
|
||||
VariableBoxController * App::variableBoxForInputEventHandler(InputEventHandler * textInput) {
|
||||
return &m_variableBoxController;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "python_toolbox.h"
|
||||
#include "variable_box_controller.h"
|
||||
#include "../shared/shared_app.h"
|
||||
#include "toolbox_ion_keys.h"
|
||||
|
||||
namespace Code {
|
||||
|
||||
@@ -78,8 +77,6 @@ public:
|
||||
|
||||
static constexpr int k_pythonHeapSize = 100000;
|
||||
|
||||
Code::toolboxIonKeys * toolboxIonKeys();
|
||||
|
||||
private:
|
||||
/* Python delegate:
|
||||
* MicroPython requires a heap. To avoid dynamic allocation, we keep a working
|
||||
@@ -96,7 +93,6 @@ private:
|
||||
StackViewController m_codeStackViewController;
|
||||
PythonToolbox m_toolbox;
|
||||
VariableBoxController m_variableBoxController;
|
||||
Code::toolboxIonKeys m_toolboxIonKeys;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
AddScript = "Skript hinzufügen"
|
||||
AllowedCharactersaz09 = "Erlaubte Zeichen: a-z, 0-9, _"
|
||||
Autocomplete = "Autovervollständigung"
|
||||
AutoImportScript = "Automatischer Import in Konsole"
|
||||
BuiltinsAndKeywords = "Native Funktionen und Schlüsselwörter"
|
||||
AutoImportScript = "Automatischer Import in die Konsole"
|
||||
BuiltinsAndKeywords = "Native Funktionen & Schlüsselwörter"
|
||||
Console = "Interaktive Konsole"
|
||||
DeleteScript = "Skript löschen"
|
||||
DuplicateScript = "Skript duplizieren"
|
||||
ExecuteScript = "Skript ausführen"
|
||||
FunctionsAndVariables = "Funktionen und Variablen"
|
||||
ImportedModulesAndScripts = "Importierte Module und Skripte"
|
||||
NoWordAvailableHere = "Kein Wort ist hier verfübar."
|
||||
ScriptInProgress = "Aktuelle Skript"
|
||||
NoWordAvailableHere = "Hier ist kein Wort verfügbar."
|
||||
ScriptInProgress = "Aktuelles Skript"
|
||||
ScriptOptions = "Skriptoptionen"
|
||||
ScriptSize = "Script size"
|
||||
ScriptSize = "Skriptgröße"
|
||||
|
||||
@@ -3,175 +3,176 @@ PythonPercent = "Modulo"
|
||||
Python1J = "Imaginäres i"
|
||||
PythonLF = "Zeilenvorschub"
|
||||
PythonTab = "Tabulator"
|
||||
PythonAmpersand = "Bitweise und"
|
||||
PythonSymbolExp = "Bitweise exklusiv oder"
|
||||
PythonVerticalBar = "Bitweise oder"
|
||||
PythonAmpersand = "Bitweises und"
|
||||
PythonSymbolExp = "Bitweises exklusives oder"
|
||||
PythonVerticalBar = "Bitweises oder"
|
||||
PythonImag = "Imaginärteil von z"
|
||||
PythonReal = "Realteil von z"
|
||||
PythonSingleQuote = "Einfaches Anführungszeichen"
|
||||
PythonAbs = "Absolute/r Wert/Größe"
|
||||
PythonAcos = "Arkuskosinus"
|
||||
PythonAcosh = "Hyperbelkosinus"
|
||||
PythonAppend = "Hängt x an das Ende der Liste"
|
||||
PythonArrow = "Arrow from (x,y) to (x+dx,y+dy)"
|
||||
PythonAsin = "Arkussinus"
|
||||
PythonAsinh = "Hyperbelsinus"
|
||||
PythonAbs = "Absoluter Wert/Absolute Größe"
|
||||
PythonAcos = "Bogenkosinus"
|
||||
PythonAcosh = "Bogenhyperbolischer Kosinus"
|
||||
PythonAppend = "x an das Ende der Liste anfügen"
|
||||
PythonArrow = "Pfeil von (x,y) nach (x+dx,y+dy)"
|
||||
PythonAsin = "Sinusbogen"
|
||||
PythonAsinh = "Kreisbogen hyperbolischer Sinus"
|
||||
PythonAtan = "Arkustangens"
|
||||
PythonAtan2 = "Gib atan(y/x)"
|
||||
PythonAtan2 = "Rückgabe atan(y/x)"
|
||||
PythonAtanh = "Hyperbeltangens"
|
||||
PythonAxis = "Set axes to (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Draw a bar plot with x values"
|
||||
PythonBin = "Ganzzahl nach binär konvertieren"
|
||||
PythonCeil = "Aufrundung"
|
||||
PythonChoice = "Zufallszahl aus der Liste"
|
||||
PythonClear = "Leere die Liste"
|
||||
PythonAxis = "Achsen auf (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Balkendiagramm mit x-Werten"
|
||||
PythonBin = "Ganzzahl in Binärwert umwandeln"
|
||||
PythonCeil = "Aufrunden"
|
||||
PythonChoice = "Zufällige Zahl in der Liste"
|
||||
PythonClear = "Liste leeren"
|
||||
PythonCmathFunction = "cmath-Modul-Funktionspräfix"
|
||||
PythonColor = "Definiere eine RGB-Farbe"
|
||||
PythonColorBlack = "Black color"
|
||||
PythonColorBlue = "Blue color"
|
||||
PythonColorBrown = "Brown color"
|
||||
PythonColorGray = "Gray color"
|
||||
PythonColorGreen = "Green color"
|
||||
PythonColorOrange = "Orange color"
|
||||
PythonColorPink = "Pink color"
|
||||
PythonColorPurple = "Purple color"
|
||||
PythonColorRed = "Red color"
|
||||
PythonColorWhite = "White color"
|
||||
PythonColorYellow = "Yellow color"
|
||||
PythonComplex = "a+ib zurückgeben"
|
||||
PythonCopySign = "x mit dem Vorzeichen von y"
|
||||
PythonColor = "Eine RGB-Farbe definieren"
|
||||
PythonColorBlack = "Farbe Schwarz"
|
||||
PythonColorBlue = "Farbe Blau"
|
||||
PythonColorBrown = "Farbe Braun"
|
||||
PythonColorGray = "Farbe Grau"
|
||||
PythonColorGreen = "Farbe Grün"
|
||||
PythonColorOrange = "Farbe Orange"
|
||||
PythonColorPink = "Farbe Rosa"
|
||||
PythonColorPurple = "Farbe Violett"
|
||||
PythonColorRed = "Farbe Rot"
|
||||
PythonColorWhite = "Farbe Weiß"
|
||||
PythonColorYellow = "Farbe Gelb"
|
||||
PythonComplex = "Gib a+ib zurück"
|
||||
PythonCopySign = "Gib x mit Vorzeichen von y zurück"
|
||||
PythonCos = "Kosinus"
|
||||
PythonCosh = "Hyperbolic cosine"
|
||||
PythonCount = "Zählt wie oft x vorkommt"
|
||||
PythonDegrees = "x von Radian zu Grad umwandeln"
|
||||
PythonCosh = "Hyperbolischer Kosinus"
|
||||
PythonCount = "Zählt die Vorkommen von x"
|
||||
PythonDegrees = "x von Bogenmaß in Grad umrechnen"
|
||||
PythonDivMod = "Quotient und Rest"
|
||||
PythonDrawLine = "Draw a line"
|
||||
PythonDrawString = "Schreibt Text bei (x,y)"
|
||||
PythonDrawLine = "Eine Linie zeichnen"
|
||||
PythonDrawString = "Text bei Pixel (x,y) darstellen"
|
||||
PythonErf = "Fehlerfunktion"
|
||||
PythonErfc = "Complementary error function"
|
||||
PythonEval = "Return the evaluated expression"
|
||||
PythonErfc = "Komplementäre Fehlerfunktion"
|
||||
PythonEval = "Rückgabe ausgewerteter Ausdruck"
|
||||
PythonExp = "Exponentialfunktion"
|
||||
PythonExpm1 = "Berechne exp(x)-1"
|
||||
PythonFabs = "Absoluter Wert"
|
||||
PythonFillRect = "Malt ein Rechteck bei Pixel (x,y)"
|
||||
PythonFloat = "Wandelt x zu float um"
|
||||
PythonFloor = "Floor"
|
||||
PythonFillRect = "Gefülltes Rechteck bei Pixel (x,y)"
|
||||
PythonFloat = "x in einen Fließkommawert umwandeln"
|
||||
PythonFloor = "Abrunden"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "Mantissa and exponent of x: (m,e)"
|
||||
PythonGamma = "Gamma function"
|
||||
PythonGetPixel = "Return pixel (x,y) color"
|
||||
PythonGetrandbits = "Integer with k random bits"
|
||||
PythonGrid = "Toggle the visibility of the grid"
|
||||
PythonHex = "Ganzzahl zu Hexadecimal"
|
||||
PythonHist = "Draw the histogram of x"
|
||||
PythonImportCmath = "cmath Modul importieren"
|
||||
PythonImportIon = "ion Modul importieren"
|
||||
PythonImportKandinsky = "kandinsky Modul importieren"
|
||||
PythonImportRandom = "random Modul importieren"
|
||||
PythonImportMath = "math Modul importieren"
|
||||
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
|
||||
PythonImportOs = "os Modul importieren"
|
||||
PythonOsUname = "Informieren Sie sich über das System"
|
||||
PythonFrExp = "Mantisse und Exponent von x: (m,e)"
|
||||
PythonGamma = "Gamma-Funktion"
|
||||
PythonGetPixel = "Farbe von Pixel (x,y) zurückgeben"
|
||||
PythonGetrandbits = "Ganzzahl mit k Zufallsbits"
|
||||
PythonGrid = "Sichtbarkeit des Gitters umschalten"
|
||||
PythonHex = "Ganzzahl in Hexadezimal umwandeln"
|
||||
PythonHist = "Zeichnet das Histogramm von x"
|
||||
PythonImportCmath = "cmath-Modul importieren"
|
||||
PythonImportIon = "Ion-Modul importieren"
|
||||
PythonImportKandinsky = "Kandinsky-Modul importieren"
|
||||
PythonImportRandom = "Random-Modul importieren"
|
||||
PythonImportMath = "Math-Modul importieren"
|
||||
PythonImportMatplotlibPyplot = "Matplotlib.pyplot-Modul importieren"
|
||||
PythonImportOs = "OS-Modul importieren"
|
||||
PythonOsUname = "Informationen über das System holen"
|
||||
PythonOsGetlogin = "Benutzernamen holen"
|
||||
PythonOsRemove = "Datei namens Dateiname entfernen"
|
||||
PythonOsRename = "Datei mit altem Namen in neuen Namen umbenennen"
|
||||
PythonOsRename = "Datei umbenennen von Alt nach Neu"
|
||||
PythonOsListdir = "Dateien im Speicher auflisten"
|
||||
PythonImportTime = "time Modul importieren"
|
||||
PythonImportTurtle = "turtle Modul importieren"
|
||||
PythonIndex = "Index, bei dem x zuerst vorkommt"
|
||||
PythonInput = "Eingabeaufforderung"
|
||||
PythonInsert = "x bei index i in der Liste einsetzen"
|
||||
PythonInt = "x zu Ganzzahl"
|
||||
PythonIonFunction = "ion module function prefix"
|
||||
PythonIsFinite = "Prüft ob x endlich ist"
|
||||
PythonIsInfinite = "Prüft ob x unendlich ist"
|
||||
PythonIsNaN = "Prüft ob x NaN ist"
|
||||
PythonIsKeyDown = "true wenn k gedrückt ist"
|
||||
PythonKandinskyFunction = "kandinsky module function prefix"
|
||||
PythonLdexp = "Return x*(2**i), inverse of frexp"
|
||||
PythonLength = "Length of an object"
|
||||
PythonLgamma = "Log-gamma function"
|
||||
PythonLog = "Logarithm to base a"
|
||||
PythonLog10 = "Logarithm to base 10"
|
||||
PythonLog2 = "Logarithm to base 2"
|
||||
PythonMathFunction = "math module function prefix"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot module prefix"
|
||||
PythonImportTime = "Time-Modul importieren"
|
||||
PythonImportTurtle = "Turtle-Modul importieren"
|
||||
PythonIndex = "Index des ersten x-Vorkommens"
|
||||
PythonInput = "Einen Wert abfragen"
|
||||
PythonInsert = "x an Index i in die Liste einfügen"
|
||||
PythonInt = "x in eine ganze Zahl umwandeln"
|
||||
PythonIonFunction = "Ion-Modul-Funktionspräfix"
|
||||
PythonIsFinite = "Prüfen, ob x endlich ist"
|
||||
PythonIsInfinite = "Prüfen, ob x unendlich ist"
|
||||
PythonIsNaN = "Prüfen, ob x keine Zahl ist"
|
||||
PythonIsKeyDown = "Wahr, wenn die Taste k gedrückt ist"
|
||||
PythonKandinskyFunction = "Kandinsky-Modul Funktionspräfix"
|
||||
PythonLdexp = "Liefert x*(2**i), Inverse von frexp"
|
||||
PythonLength = "Länge eines Objekts"
|
||||
PythonLgamma = "Log-Gamma-Funktion"
|
||||
PythonLog = "Logarithmus zur Basis a"
|
||||
PythonLog10 = "Logarithmus zur Basis 10"
|
||||
PythonLog2 = "Logarithmus zur Basis 2"
|
||||
PythonMathFunction = "Funktionspräfix des Math-Moduls"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot Modul-Präfix"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Fractional and integer parts of x"
|
||||
PythonMonotonic = "Value of a monotonic clock"
|
||||
PythonOct = "Convert integer to octal"
|
||||
PythonPhase = "Phase of z"
|
||||
PythonPlot = "Plot y versus x as lines"
|
||||
PythonPolar = "z in polar coordinates"
|
||||
PythonPop = "Remove and return the last item"
|
||||
PythonPower = "x raised to the power y"
|
||||
PythonPrint = "Print object"
|
||||
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)"
|
||||
PythonRangeStartStop = "List from start to stop-1"
|
||||
PythonRangeStop = "List from 0 to stop-1"
|
||||
PythonRect = "Convert to cartesian coordinates"
|
||||
PythonRemove = "Remove the first occurrence of x"
|
||||
PythonReverse = "Reverse the elements of the list"
|
||||
PythonRound = "Round to n digits"
|
||||
PythonScatter = "Draw a scatter plot of y versus x"
|
||||
PythonSeed = "Initialize random number generator"
|
||||
PythonSetPixel = "Color pixel (x,y)"
|
||||
PythonShow = "Display the figure"
|
||||
PythonSin = "Sine"
|
||||
PythonSinh = "Hyperbolic sine"
|
||||
PythonSleep = "Suspend the execution for t seconds"
|
||||
PythonSort = "Sort the list"
|
||||
PythonSqrt = "Wurzel"
|
||||
PythonSum = "Sum the items of a list"
|
||||
PythonModf = "Bruch- und Ganzzahl-Anteile von x"
|
||||
PythonMonotonic = "Wert einer monotonen Uhr"
|
||||
PythonOct = "Ganzzahl in Oktal umwandeln"
|
||||
PythonPhase = "Phase von z"
|
||||
PythonPlot = "Plotten von y gegen x als Linien"
|
||||
PythonPolar = "z in Polarkoordinaten"
|
||||
PythonPop = "Letztes Element abnehmen"
|
||||
PythonPower = "x erhöht mit der Potenz y"
|
||||
PythonPrint = "Objekt drucken"
|
||||
PythonRadians = "x von Grad in Bogenmaß umrechnen"
|
||||
PythonRandint = "Zufällige Ganzzahl in [a,b]"
|
||||
PythonRandom = "Fließkommazahl in [0,1]"
|
||||
PythonRandomFunction = "Random-Modul Funktionspräfix"
|
||||
PythonRandrange = "Zufallszahl im Bereich(start,stop)"
|
||||
PythonRangeStartStop = "Liste von Start bis Stop-1"
|
||||
PythonRangeStop = "Liste von 0 bis Stop-1"
|
||||
PythonRect = "In kartesische Koordinaten"
|
||||
PythonRemove = "Entferne das erste Vorkommen von x"
|
||||
PythonReverse = "Kehrt die Elemente der Liste um"
|
||||
PythonRound = "Runden auf n Stellen"
|
||||
PythonScatter = "Streudiagramm von y gg. x zeichnen"
|
||||
PythonSeed = "Zufallszahlengenerator initiieren"
|
||||
PythonSetPixel = "Pixel (x,y) einfärben"
|
||||
PythonShow = "Figur anzeigen"
|
||||
PythonSin = "Sinus"
|
||||
PythonSinh = "Hyperbolischer Sinus"
|
||||
PythonSleep = "Ausführung aussetzen für t Sekunden"
|
||||
PythonSort = "Die Liste sortieren"
|
||||
PythonSqrt = "Quadratwurzel"
|
||||
PythonSum = "Summe der Elemente einer Liste"
|
||||
PythonTan = "Tangens"
|
||||
PythonTanh = "Hyperbolic tangent"
|
||||
PythonText = "Display a text at (x,y) coordinates"
|
||||
PythonTimeFunction = "time module function prefix"
|
||||
PythonTrunc = "x truncated to an integer"
|
||||
PythonTurtleBackward = "Move backward by x pixels"
|
||||
PythonTurtleCircle = "Circle of radius r pixels"
|
||||
PythonTurtleColor = "Stiftfarbe setzen"
|
||||
PythonTurtleColorMode = "Set the color mode to 1.0 or 255"
|
||||
PythonTurtleForward = "Move forward by x pixels"
|
||||
PythonTurtleFunction = "turtle module function prefix"
|
||||
PythonTurtleGoto = "Move to (x,y) coordinates"
|
||||
PythonTurtleHeading = "Return the current heading"
|
||||
PythonTurtleHideturtle = "Hide the turtle"
|
||||
PythonTurtleIsdown = "Return True if the pen is down"
|
||||
PythonTurtleLeft = "Turn left by a degrees"
|
||||
PythonTurtlePendown = "Pull the pen down"
|
||||
PythonTurtlePensize = "Set the line thickness to x pixels"
|
||||
PythonTurtlePenup = "Pull the pen up"
|
||||
PythonTurtlePosition = "Return the current (x,y) location"
|
||||
PythonTurtleReset = "Reset the drawing"
|
||||
PythonTurtleRight = "Turn right by a degrees"
|
||||
PythonTurtleSetheading = "Set the orientation to a degrees"
|
||||
PythonTurtleSetposition = "Positionne la tortue"
|
||||
PythonTurtleShowturtle = "Show the turtle"
|
||||
PythonTurtleSpeed = "Drawing speed between 0 and 10"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
PythonUniform = "Floating point number in [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonTanh = "Hyperbolischer Tangens"
|
||||
PythonText = "Text an (x,y) Koordinaten anzeigen"
|
||||
PythonTimeFunction = "Time-Modul-Funktionspräfix"
|
||||
PythonTrunc = "x abgeschnitten auf eine ganze Zahl"
|
||||
PythonTurtleBackward = "Um x Pixel rückwärts bewegen"
|
||||
PythonTurtleCircle = "Kreis mit Radius r Pixel"
|
||||
PythonTurtleColor = "Setzt die Stiftfarbe"
|
||||
PythonTurtleColorMode = "Setzt Farbmodus auf 1.0 oder 255"
|
||||
PythonTurtleForward = "Um x Pixel vorwärts bewegen"
|
||||
PythonTurtleFunction = "Turtle-Modul-Funktionspräfix"
|
||||
PythonTurtleGoto = "Bewegen zu (x,y) Koordinaten"
|
||||
PythonTurtleHeading = "Liefert den aktuellen Kurs"
|
||||
PythonTurtleHideturtle = "Versteckt den Igel"
|
||||
PythonTurtleIsdown = "Wahr, wenn der Stift unten ist"
|
||||
PythonTurtleLeft = "Nach links um ein Grad drehen"
|
||||
PythonTurtlePendown = "Den Stift nach unten ziehen"
|
||||
PythonTurtlePensize = "Linienstärke auf x Pixel setzen"
|
||||
PythonTurtlePenup = "Den Stift nach oben ziehen"
|
||||
PythonTurtlePosition = "Aktuelle (x,y) Position zurückgeben"
|
||||
PythonTurtleReset = "Die Zeichnung zurücksetzen"
|
||||
PythonTurtleRight = "Um ein Grad nach rechts drehen"
|
||||
PythonTurtleSetheading = "Ausrichtung auf einen Grad setzen"
|
||||
PythonTurtleSetposition = "Den Igel auf Position setzen"
|
||||
PythonTurtleShowturtle = "Den Igel anzeigen"
|
||||
PythonTurtleSpeed = "Zeichengeschwindigkeit von 0 bis 10"
|
||||
PythonTurtleWrite = "Einen Text anzeigen"
|
||||
PythonUniform = "Fließkommazahl in [a,b]"
|
||||
PythonImportTime = "Time-Modul importieren"
|
||||
PythonTimePrefix = "Zeitmodul-Funktionspräfix"
|
||||
PythonTimeSleep = "Warte für n Sekunden"
|
||||
PythonMonotonic = "Monotone Zeit zurückgeben"
|
||||
PythonFileOpen = "Öffnet eine Datei"
|
||||
PythonFileSeekable = "Ist eine Datei durchsuchbar?"
|
||||
PythonFileSeek = "Dateicursor verschieben"
|
||||
PythonFileTell = "Cursorposition der Datei abrufen"
|
||||
PythonFileSeekable = "Kann Datei durchsucht werden?"
|
||||
PythonFileSeek = "Bewegt den Cursor einer Datei"
|
||||
PythonFileTell = "Position des Cursors ermitteln"
|
||||
PythonFileClose = "Schließt eine Datei"
|
||||
PythonFileClosed = "Wenn Datei geschlossen wurde"
|
||||
PythonFileRead = "Bis zu size Bytes lesen"
|
||||
PythonFileWrite = "Schreibe b in die Datei"
|
||||
PythonFileReadline = "Lies eine Zeile"
|
||||
PythonFileClosed = "Wahr, wenn Datei geschlossen wurde"
|
||||
PythonFileRead = "Lesen bis zu einer Größe von Bytes"
|
||||
PythonFileWrite = "Schreibe b in Datei"
|
||||
PythonFileReadline = "Liest Zeile oder Anzahl Bytes"
|
||||
PythonFileReadlines = "Liest eine Liste von Zeilen"
|
||||
PythonFileTruncate = "Größe der Datei ändern"
|
||||
PythonFileTruncate = "Verkleinert die Datei auf Größe"
|
||||
PythonFileWritelines = "Schreibt eine Liste von Zeilen"
|
||||
PythonFileName = "Dateiname"
|
||||
PythonFileMode = "Dateiöffnungsmodus"
|
||||
PythonFileReadable = "Ist die Datei lesbar?"
|
||||
PythonFileWritable = "Ist die Datei beschreibbar?"
|
||||
PythonFileName = "Enthält den Namen der Datei"
|
||||
PythonFileMode = "Enthält den Öffnungsmodus der Datei"
|
||||
PythonFileReadable = "Kann Datei gelesen werden?"
|
||||
PythonFileWritable = "Kann Datei geschrieben werden?"
|
||||
|
||||
@@ -103,7 +103,7 @@ PythonPower = "x raised to the power y"
|
||||
PythonPrint = "Print object"
|
||||
PythonRadians = "Convert x from degrees to radians"
|
||||
PythonRandint = "Random integer in [a,b]"
|
||||
PythonRandom = "Floating point number in [0,1["
|
||||
PythonRandom = "Floating point number in [0,1]"
|
||||
PythonRandomFunction = "random module function prefix"
|
||||
PythonRandrange = "Random number in range(start,stop)"
|
||||
PythonRangeStartStop = "List from start to stop-1"
|
||||
@@ -153,6 +153,7 @@ PythonUniform = "Floating point number in [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonImportOs = "Import os module"
|
||||
PythonOsUname = "Get infos about the system"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Remove file named filename"
|
||||
PythonOsRename = "Rename file oldname to newname"
|
||||
PythonOsListdir = "List files in memory"
|
||||
|
||||
@@ -153,6 +153,7 @@ PythonUniform = "Floating point number in [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonImportOs = "Import os module"
|
||||
PythonOsUname = " Información del sistema "
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Eliminar un archivo"
|
||||
PythonOsRename = "Renombrar archivo"
|
||||
PythonOsListdir = "Archivos de la lista"
|
||||
|
||||
@@ -153,6 +153,7 @@ PythonUniform = "Nombre décimal dans [a,b]"
|
||||
PythonImportTime = "Importation du module temps"
|
||||
PythonImportOs = "Importation du module os"
|
||||
PythonOsUname = "Donne des infos sur le système"
|
||||
PythonOsGetlogin = "Donne le nom d'utilisateur"
|
||||
PythonOsRemove = "Supprime le fichier nommé filename"
|
||||
PythonOsRename = "Renomme oldname en newname"
|
||||
PythonOsListdir = "Liste les fichiers"
|
||||
|
||||
@@ -172,6 +172,7 @@ PythonFileReadable = "read-et lehete használni"
|
||||
PythonFileWritable = "write-ot lehete használni"
|
||||
PythonImportOs = "os modul importálása"
|
||||
PythonOsUname = "Rendszer informaciók"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Fájl törlése"
|
||||
PythonOsRename = "Fájl átnevezése"
|
||||
PythonOsListdir = "Fájlok listája"
|
||||
|
||||
@@ -74,6 +74,7 @@ PythonImportTurtle = "Importa del modulo turtle"
|
||||
PythonImportTime = "Importa del modulo time"
|
||||
PythonImportOs = "Importa modulo os"
|
||||
PythonOsUname = "Ottieni informazioni sul sistema"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Rimuovere un file"
|
||||
PythonOsRename = "Rinomina file"
|
||||
PythonOsListdir = "Elenca file"
|
||||
|
||||
@@ -73,6 +73,7 @@ PythonImportMatplotlibPyplot = "Importeer matplotlib.pyplot module"
|
||||
PythonImportTime = "Importeer time module"
|
||||
PythonImportOs = "Importeer os module"
|
||||
PythonOsUname = " Krijg systeeminfo"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Een bestand verwijderen"
|
||||
PythonOsRename = "Hernoem bestand"
|
||||
PythonOsListdir = "Lijstbestanden"
|
||||
|
||||
@@ -153,6 +153,7 @@ PythonUniform = "Número decimal em [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonImportOs = "Import os module"
|
||||
PythonOsUname = " Obter informações do sistema"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Remover um ficheiro"
|
||||
PythonOsRename = "Renomear ficheiro"
|
||||
PythonOsListdir = "Listar ficheiros"
|
||||
|
||||
@@ -216,6 +216,7 @@ PythonCommandUniform = "uniform(a,b)"
|
||||
PythonConstantE = "2.718281828459045"
|
||||
PythonConstantPi = "3.141592653589793"
|
||||
PythonOsCommandUname = "uname()"
|
||||
PythonOsCommandGetlogin = "getlogin()"
|
||||
PythonOsCommandRemove = "remove(filename)"
|
||||
PythonOsCommandRename = "rename(oldname, newname)"
|
||||
PythonOsCommandRemoveWithoutArg = "remove(\x11)"
|
||||
|
||||
@@ -217,6 +217,7 @@ const ToolboxMessageTree OsModuleChildren[] = {
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportOs, I18n::Message::PythonImportOs, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandImportFromOs, I18n::Message::PythonImportOs, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonOsCommandUname, I18n::Message::PythonOsUname, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonOsCommandGetlogin, I18n::Message::PythonOsGetlogin, false),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonOsCommandRemove, I18n::Message::PythonOsRemove, false, I18n::Message::PythonOsCommandRemoveWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonOsCommandRename, I18n::Message::PythonOsRename, false, I18n::Message::PythonOsCommandRenameWithoutArg),
|
||||
ToolboxMessageTree::Leaf(I18n::Message::PythonOsCommandListdir, I18n::Message::PythonOsListdir, false)
|
||||
@@ -495,8 +496,8 @@ bool PythonToolbox::selectLeaf(int selectedRow) {
|
||||
m_selectableTableView.deselectTable();
|
||||
ToolboxMessageTree * node = (ToolboxMessageTree *)m_messageTreeModel->childAtIndex(selectedRow);
|
||||
if(node->insertedText() == I18n::Message::IonSelector){
|
||||
App::app()->toolboxIonKeys()->setSender(sender());
|
||||
Container::activeApp()->displayModalViewController(static_cast<ViewController*>(App::app()->toolboxIonKeys()), 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin);
|
||||
m_ionKeys.setSender(sender());
|
||||
Container::activeApp()->displayModalViewController(static_cast<ViewController*>(&m_ionKeys), 0.f, 0.f, Metric::PopUpTopMargin, Metric::PopUpLeftMargin, 0, Metric::PopUpRightMargin);
|
||||
return true;
|
||||
}
|
||||
const char * editedText = I18n::translate(node->insertedText());
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <escher.h>
|
||||
#include <ion/events.h>
|
||||
#include <kandinsky/font.h>
|
||||
#include "toolbox_ion_keys.h"
|
||||
|
||||
namespace Code {
|
||||
|
||||
@@ -32,6 +33,7 @@ private:
|
||||
void scrollToAndSelectChild(int i);
|
||||
MessageTableCellWithMessage m_leafCells[k_maxNumberOfDisplayedRows];
|
||||
MessageTableCellWithChevron m_nodeCells[k_maxNumberOfDisplayedRows];
|
||||
toolboxIonKeys m_ionKeys;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
27
apps/code/test/toolbox_ion_keys_dummy.cpp
Normal file
27
apps/code/test/toolbox_ion_keys_dummy.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "../toolbox_ion_keys.h"
|
||||
|
||||
namespace Code {
|
||||
toolboxIonKeys::toolboxIonKeys() :
|
||||
ViewController(nullptr),
|
||||
m_view()
|
||||
{
|
||||
}
|
||||
|
||||
bool toolboxIonKeys::handleEvent(Ion::Events::Event e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
toolboxIonKeys::toolboxIonView::toolboxIonView():
|
||||
View()
|
||||
{
|
||||
}
|
||||
|
||||
void toolboxIonKeys::toolboxIonView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
return;
|
||||
}
|
||||
|
||||
View * toolboxIonKeys::view(){
|
||||
return &m_view;
|
||||
}
|
||||
|
||||
}
|
||||
12
apps/external/base.de.i18n
vendored
12
apps/external/base.de.i18n
vendored
@@ -1,9 +1,9 @@
|
||||
ExternalApp = "External"
|
||||
ExternalAppCapital = "EXTERNAL"
|
||||
ExternalAppApiMismatch = "API mismatch"
|
||||
ExternalAppExecError = "Cannot execute file"
|
||||
ExternalNotCompatible = "External ist nicht kompatibel"
|
||||
ExternalAppApiMismatch = "API stimmt nicht überein"
|
||||
ExternalAppExecError = "Datei kann nicht ausgeführt werden"
|
||||
ExternalNotCompatible = "Externe App ist nicht kompatibel"
|
||||
WithSimulator = "mit dem Simulator"
|
||||
WithN0100 = "mit n0100"
|
||||
GetMoreAppsAt = "Weitere Apps erhalten Sie auf"
|
||||
NoAppsInstalled = "Keine Apps installiert"
|
||||
WithN0100 = "mit N0100"
|
||||
GetMoreAppsAt = "Weitere Apps abrufen bei"
|
||||
NoAppsInstalled = "Keine Apps installiert"
|
||||
@@ -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 = "Erlaubt: A..Z, a..z, 0..9, _"
|
||||
ReservedName = "Reserviertes Wort"
|
||||
|
||||
@@ -3,6 +3,7 @@ app_home_src = $(addprefix apps/home/,\
|
||||
app_cell.cpp \
|
||||
apps_layout.py \
|
||||
controller.cpp \
|
||||
selectable_table_view_with_background.cpp \
|
||||
)
|
||||
|
||||
apps_src += $(app_home_src)
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Home {
|
||||
AppCell::AppCell() :
|
||||
HighlightCell(),
|
||||
m_nameView(KDFont::SmallFont, (I18n::Message)0, 0.5f, 0.5f, Palette::HomeCellText, Palette::HomeCellBackground),
|
||||
m_backgroundView(nullptr),
|
||||
m_visible(true), m_external_app(false)
|
||||
{
|
||||
}
|
||||
@@ -15,8 +16,8 @@ AppCell::AppCell() :
|
||||
|
||||
void AppCell::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
KDSize nameSize = m_nameView.minimalSizeForOptimalDisplay();
|
||||
ctx->fillRect(KDRect(0, bounds().height()-nameSize.height() - 2*k_nameHeightMargin, bounds().width(), nameSize.height()+2*k_nameHeightMargin), Palette::HomeBackground);
|
||||
}
|
||||
m_backgroundView->drawRect(ctx, KDRect(0, bounds().height()-nameSize.height() - 2*k_nameHeightMargin, bounds().width(), nameSize.height()+2*k_nameHeightMargin));
|
||||
}
|
||||
|
||||
int AppCell::numberOfSubviews() const {
|
||||
return m_visible ? 2 : 0;
|
||||
@@ -70,6 +71,10 @@ void AppCell::setVisible(bool visible) {
|
||||
}
|
||||
}
|
||||
|
||||
void AppCell::setBackgroundView(const BackgroundView * backgroundView) {
|
||||
m_backgroundView = backgroundView;
|
||||
}
|
||||
|
||||
void AppCell::reloadCell() {
|
||||
m_nameView.setTextColor(isHighlighted() ? (m_external_app ? Palette::HomeCellTextExternalActive : Palette::HomeCellTextActive) : (m_external_app ? Palette::HomeCellTextExternal : Palette::HomeCellText));
|
||||
m_nameView.setBackgroundColor(isHighlighted() ? Palette::HomeCellBackgroundActive : Palette::HomeCellBackground);
|
||||
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
void layoutSubviews(bool force = false) override;
|
||||
|
||||
void setVisible(bool visible);
|
||||
void setBackgroundView(const BackgroundView * backgroundView);
|
||||
void reloadCell() override;
|
||||
void setAppDescriptor(::App::Descriptor * appDescriptor);
|
||||
void setExtAppDescriptor(const char* name, const Image* icon);
|
||||
@@ -25,8 +26,9 @@ private:
|
||||
static constexpr KDCoordinate k_iconHeight = 56;
|
||||
static constexpr KDCoordinate k_nameWidthMargin = 4;
|
||||
static constexpr KDCoordinate k_nameHeightMargin = 1;
|
||||
ImageView m_iconView;
|
||||
IconView m_iconView;
|
||||
MessageTextView m_nameView;
|
||||
const BackgroundView * m_backgroundView;
|
||||
bool m_visible;
|
||||
bool m_external_app;
|
||||
};
|
||||
|
||||
@@ -18,11 +18,11 @@ extern "C" {
|
||||
namespace Home {
|
||||
|
||||
Controller::ContentView::ContentView(Controller * controller, SelectableTableViewDataSource * selectionDataSource) :
|
||||
m_selectableTableView(controller, controller, selectionDataSource, controller)
|
||||
m_selectableTableView(controller, controller, &m_backgroundView, selectionDataSource, controller),
|
||||
m_backgroundView()
|
||||
{
|
||||
m_selectableTableView.setVerticalCellOverlap(0);
|
||||
m_selectableTableView.setMargins(0, k_sideMargin, k_bottomMargin, k_sideMargin);
|
||||
m_selectableTableView.setBackgroundColor(Palette::HomeBackground);
|
||||
static_cast<ScrollView::BarDecorator *>(m_selectableTableView.decorator())->verticalBar()->setMargin(k_indicatorMargin);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ SelectableTableView * Controller::ContentView::selectableTableView() {
|
||||
}
|
||||
|
||||
void Controller::ContentView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
ctx->fillRect(bounds(), Palette::HomeBackground);
|
||||
m_selectableTableView.drawRect(ctx, rect);
|
||||
}
|
||||
|
||||
void Controller::ContentView::reloadBottomRow(SimpleTableViewDataSource * dataSource, int numberOfIcons, int numberOfColumns) {
|
||||
@@ -45,6 +45,10 @@ void Controller::ContentView::reloadBottomRow(SimpleTableViewDataSource * dataSo
|
||||
}
|
||||
}
|
||||
|
||||
BackgroundView * Controller::ContentView::backgroundView() {
|
||||
return &m_backgroundView;
|
||||
}
|
||||
|
||||
int Controller::ContentView::numberOfSubviews() const {
|
||||
return 1;
|
||||
}
|
||||
@@ -56,6 +60,8 @@ View * Controller::ContentView::subviewAtIndex(int index) {
|
||||
|
||||
void Controller::ContentView::layoutSubviews(bool force) {
|
||||
m_selectableTableView.setFrame(bounds(), force);
|
||||
m_backgroundView.setFrame(KDRect(0, Metric::TitleBarHeight, Ion::Display::Width, Ion::Display::Height-Metric::TitleBarHeight), force);
|
||||
m_backgroundView.updateDataValidity();
|
||||
}
|
||||
|
||||
Controller::Controller(Responder * parentResponder, SelectableTableViewDataSource * selectionDataSource, ::App * app) :
|
||||
@@ -63,6 +69,21 @@ Controller::Controller(Responder * parentResponder, SelectableTableViewDataSourc
|
||||
m_view(this, selectionDataSource)
|
||||
{
|
||||
m_app = app;
|
||||
for (int i = 0; i < k_maxNumberOfCells; i++) {
|
||||
m_cells[i].setBackgroundView(m_view.backgroundView());
|
||||
}
|
||||
|
||||
m_view.backgroundView()->setDefaultColor(Palette::HomeBackground);
|
||||
|
||||
|
||||
#ifdef HOME_DISPLAY_EXTERNALS
|
||||
int index = External::Archive::indexFromName("wallpaper.obm");
|
||||
if(index > -1) {
|
||||
External::Archive::File image;
|
||||
External::Archive::fileAtIndex(index, image);
|
||||
m_view.backgroundView()->setBackgroundImage(image.data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Controller::handleEvent(Ion::Events::Event event) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define HOME_CONTROLLER_H
|
||||
|
||||
#include <escher.h>
|
||||
#include "selectable_table_view_with_background.h"
|
||||
#include "app_cell.h"
|
||||
|
||||
namespace Home {
|
||||
@@ -35,11 +36,13 @@ private:
|
||||
SelectableTableView * selectableTableView();
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void reloadBottomRow(SimpleTableViewDataSource * dataSource, int numberOfIcons, int numberOfColumns);
|
||||
BackgroundView * backgroundView();
|
||||
private:
|
||||
int numberOfSubviews() const override;
|
||||
View * subviewAtIndex(int index) override;
|
||||
void layoutSubviews(bool force = false) override;
|
||||
SelectableTableView m_selectableTableView;
|
||||
SelectableTableViewWithBackground m_selectableTableView;
|
||||
BackgroundView m_backgroundView;
|
||||
};
|
||||
static constexpr KDCoordinate k_sideMargin = 4;
|
||||
static constexpr KDCoordinate k_bottomMargin = 14;
|
||||
|
||||
16
apps/home/selectable_table_view_with_background.cpp
Normal file
16
apps/home/selectable_table_view_with_background.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "selectable_table_view_with_background.h"
|
||||
|
||||
SelectableTableViewWithBackground::SelectableTableViewWithBackground(Responder * parentResponder, TableViewDataSource * dataSource, BackgroundView * backgroundView, SelectableTableViewDataSource * selectionDataSource, SelectableTableViewDelegate * delegate) :
|
||||
SelectableTableView(parentResponder, dataSource, selectionDataSource, delegate),
|
||||
m_backgroundInnerView(this, backgroundView)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SelectableTableViewWithBackground::BackgroundInnerView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
m_backgroundView->drawRect(ctx, rect);
|
||||
}
|
||||
|
||||
void SelectableTableViewWithBackground::BackgroundInnerView::setBackgroundView(const uint8_t * data) {
|
||||
m_backgroundView->setBackgroundImage(data);
|
||||
}
|
||||
25
apps/home/selectable_table_view_with_background.h
Normal file
25
apps/home/selectable_table_view_with_background.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef ESCHER_SELECTABLE_TABLE_VIEW_WITH_BACKGROUND_H
|
||||
#define ESCHER_SELECTABLE_TABLE_VIEW_WITH_BACKGROUND_H
|
||||
|
||||
#include <escher/selectable_table_view.h>
|
||||
#include <escher/background_view.h>
|
||||
|
||||
class SelectableTableViewWithBackground : public SelectableTableView {
|
||||
public:
|
||||
SelectableTableViewWithBackground(Responder * parentResponder, TableViewDataSource * dataSource, BackgroundView * backgroundView,
|
||||
SelectableTableViewDataSource * selectionDataSource = nullptr, SelectableTableViewDelegate * delegate = nullptr);
|
||||
View * subviewAtIndex(int index) override { return (index == 0) ? &m_backgroundInnerView : decorator()->indicatorAtIndex(index); }
|
||||
protected:
|
||||
virtual InnerView * getInnerView() { return &m_backgroundInnerView; }
|
||||
class BackgroundInnerView : public ScrollView::InnerView {
|
||||
public:
|
||||
BackgroundInnerView(ScrollView * scrollView, BackgroundView * backgroundView): InnerView(scrollView), m_backgroundView(backgroundView) {}
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void setBackgroundView(const uint8_t * data);
|
||||
private:
|
||||
BackgroundView * m_backgroundView;
|
||||
};
|
||||
BackgroundInnerView m_backgroundInnerView;
|
||||
};
|
||||
|
||||
#endif
|
||||
17
apps/i18n.py
17
apps/i18n.py
@@ -23,13 +23,9 @@ parser.add_argument('--codepoints', help='the code_points.h file')
|
||||
parser.add_argument('--countrypreferences', help='the country_preferences.csv file')
|
||||
parser.add_argument('--languagepreferences', help='the language_preferences.csv file')
|
||||
parser.add_argument('--files', nargs='+', help='an i18n file')
|
||||
parser.add_argument('--generateISO6391locales', type=int, nargs='+', help='whether to generate the ISO6391 codes for the languages (for instance "en" for english)')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
def generate_ISO6391():
|
||||
return args.generateISO6391locales[0] == 1
|
||||
|
||||
def has_glyph(glyph):
|
||||
return glyph in codepoints
|
||||
|
||||
@@ -196,13 +192,6 @@ def print_header(data, path, locales, countries):
|
||||
lambda arg: arg.upper(),
|
||||
" Message::Language")
|
||||
|
||||
if generate_ISO6391():
|
||||
print_block_from_list(f,
|
||||
"constexpr const Message LanguageISO6391Names[NumberOfLanguages] = {\n",
|
||||
locales,
|
||||
lambda arg: arg.upper(),
|
||||
" Message::LanguageISO6391")
|
||||
|
||||
# Countries enumeration
|
||||
print_block_from_list(f,
|
||||
"enum class Country : uint8_t {\n",
|
||||
@@ -236,6 +225,12 @@ def print_header(data, path, locales, countries):
|
||||
f.write(line[:-2] + "),\n")
|
||||
f.write("};\n\n")
|
||||
|
||||
# Language ISO639-1 codes
|
||||
f.write("constexpr const char * LanguageISO6391Codes[NumberOfLanguages] = {\n");
|
||||
for locale in locales:
|
||||
f.write(" \"" + locale + "\",\n")
|
||||
f.write("};\n\n")
|
||||
|
||||
f.write("}\n\n")
|
||||
f.write("#endif\n")
|
||||
f.close()
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
LanguageISO6391DE = "de"
|
||||
@@ -1 +0,0 @@
|
||||
LanguageISO6391EN = "en"
|
||||
@@ -1 +0,0 @@
|
||||
LanguageISO6391ES = "es"
|
||||
@@ -1 +0,0 @@
|
||||
LanguageISO6391FR = "fr"
|
||||
@@ -1 +0,0 @@
|
||||
LanguageISO6391IT = "it"
|
||||
@@ -1 +0,0 @@
|
||||
LanguageISO6391NL = "nl"
|
||||
@@ -1 +0,0 @@
|
||||
LanguageISO6391PT = "pt"
|
||||
@@ -19,6 +19,12 @@ void ion_main(int argc, const char * const argv[]) {
|
||||
#else
|
||||
|
||||
void ion_main(int argc, const char * const argv[]) {
|
||||
/* Lock OTP on older devices to prevent garbage being written where the PCB
|
||||
* version is read. */
|
||||
#if 0 // We don't want OTP locked on omega :p
|
||||
Ion::Board::lockUnlockedPCBVersion();
|
||||
#endif
|
||||
|
||||
// Initialize Poincare::TreePool::sharedPool
|
||||
Poincare::Init();
|
||||
|
||||
@@ -36,7 +42,7 @@ void ion_main(int argc, const char * const argv[]) {
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < I18n::NumberOfLanguages; j++) {
|
||||
if (strcmp(requestedLanguageId, I18n::translate(I18n::LanguageISO6391Names[j])) == 0) {
|
||||
if (strcmp(requestedLanguageId, I18n::LanguageISO6391Codes[j]) == 0) {
|
||||
GlobalPreferences::sharedGlobalPreferences()->setLanguage((I18n::Language)j);
|
||||
GlobalPreferences::sharedGlobalPreferences()->setCountry(I18n::DefaultCountryForLanguage[j]);
|
||||
break;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
UpdateAvailable = "UPDATE VERFÜGBAR"
|
||||
UpdateAvailable = "AKTUALISIERUNG VERFÜGBAR"
|
||||
UpdateMessage1 = "Wichtige Verbesserungen für Ihren"
|
||||
UpdateMessage2 = "Rechner stehen zur Verfügung."
|
||||
UpdateMessage3 = "Verbinden Sie sich mit Ihrem Computer auf"
|
||||
UpdateMessage2 = "Taschenrechner stehen zur Verfügung."
|
||||
UpdateMessage3 = "Verbinden Sie sich mit Ihrem PC mit"
|
||||
UpdateMessage4 = "www.numworks.com/update."
|
||||
BetaVersion = "BETA VERSION"
|
||||
BetaVersion = "VORABVERSION"
|
||||
BetaVersionMessage1 = ""
|
||||
BetaVersionMessage2 = "Your device runs a beta software."
|
||||
BetaVersionMessage3 = "You might run into bugs or glitches."
|
||||
BetaVersionMessage2 = "Gerät führt eine Vorabversion aus."
|
||||
BetaVersionMessage3 = "Sie könnten auf Fehler stoßen."
|
||||
BetaVersionMessage4 = ""
|
||||
BetaVersionMessage5 = "Please send any feedback to"
|
||||
BetaVersionMessage5 = "Bitte senden Sie Feedback an"
|
||||
BetaVersionMessage6 = "contact@numworks.com"
|
||||
Skip = "Überspringen"
|
||||
|
||||
@@ -5,7 +5,7 @@ MeanDot = "mittel"
|
||||
RegressionCurve = "Regressionskurve"
|
||||
XPrediction = "Berechne Y"
|
||||
YPrediction = "Berechne X"
|
||||
ValueNotReachedByRegression = "Wert in diesem Fenster nicht erreicht"
|
||||
ValueNotReachedByRegression = "Wert im Fenster nicht erreicht"
|
||||
NumberOfDots = "Punktanzahl"
|
||||
Covariance = "Kovarianz"
|
||||
Linear = "Lineare"
|
||||
|
||||
@@ -2,7 +2,7 @@ SequenceApp = "Folge"
|
||||
SequenceAppCapital = "FOLGE"
|
||||
SequenceTab = "Folgen"
|
||||
AddSequence = "Folge hinzufügen"
|
||||
ChooseSequenceType = "Das Bildungsgesetz der Folge auswählen"
|
||||
ChooseSequenceType = "Bildungsgesetz der Folge auswählen"
|
||||
SequenceType = "Bildungsgesetz der Folge"
|
||||
Explicit = "Explizit"
|
||||
SingleRecurrence = "Rekursion 1. Ordnung"
|
||||
@@ -17,6 +17,6 @@ NEnd = "Endwert"
|
||||
TermSum = "Summe der Terme"
|
||||
SelectFirstTerm = "Erster Term "
|
||||
SelectLastTerm = "Letzter Term "
|
||||
ValueNotReachedBySequence = "Der Wert wird von der Folge nicht erreicht"
|
||||
ValueNotReachedBySequence = "Wert wird von Folge nicht erreicht"
|
||||
NColumn = "n-te Spalte"
|
||||
FirstTermIndex = "Anfangsindex"
|
||||
|
||||
@@ -9,8 +9,8 @@ ComplexFormat = "Komplexe Zahlen"
|
||||
ExamMode = "Prüfungsmodus"
|
||||
ExamModeActive = "Modus erneut starten"
|
||||
ToDeactivateExamMode1 = "Um den Prüfungsmodus auszuschalten,"
|
||||
ToDeactivateExamMode2 = "schließen Sie den Rechner an einen"
|
||||
ToDeactivateExamMode3 = "Computer oder eine Steckdose an."
|
||||
ToDeactivateExamMode2 = "schließen Sie den Taschenrechner an"
|
||||
ToDeactivateExamMode3 = "einen Computer an."
|
||||
# --------------------- Please do not edit these messages ---------------------
|
||||
ExamModeWarning1 = "Caution: compliance of this"
|
||||
ExamModeWarning2 = "unofficial software's exam mode"
|
||||
@@ -40,9 +40,9 @@ FontSizes = "Python-Schriftgröße"
|
||||
LargeFont = "Große "
|
||||
SmallFont = "Kleine "
|
||||
SerialNumber = "Seriennummer"
|
||||
UpdatePopUp = "Erinnerung: Update"
|
||||
BetaPopUp = "Beta pop-up"
|
||||
Contributors = "Beiträger"
|
||||
UpdatePopUp = "Erinnerung: Aktualisierung"
|
||||
BetaPopUp = "Erinnerung: Vorabversion"
|
||||
Contributors = "Mitwirkende"
|
||||
Accessibility = "Barrierefreiheit"
|
||||
AccessibilityInvertColors = "Farbumkehrung"
|
||||
AccessibilityMagnify = "Lupe"
|
||||
@@ -62,9 +62,9 @@ SymbolArgFunction = "Leer "
|
||||
SymbolArgDefaultFunction = "Argument "
|
||||
PythonFont = "Python Schriftart"
|
||||
MemUse = "Speicher"
|
||||
DateTime = "Date/time"
|
||||
ActivateClock = "Activate clock"
|
||||
Date = "Date"
|
||||
Time = "Time"
|
||||
RTCWarning1 = "Enabling the clock drains the battery faster"
|
||||
RTCWarning2 = "when the calculator is powered off."
|
||||
DateTime = "Datum/Uhrzeit"
|
||||
ActivateClock = "Uhr aktivieren"
|
||||
Date = "Datum"
|
||||
Time = "Uhrzeit"
|
||||
RTCWarning1 = "Das Aktivieren der Uhr verkürzt die"
|
||||
RTCWarning2 = "Akkulaufzeit im Bereitschaftsmodus."
|
||||
|
||||
@@ -48,11 +48,15 @@ bool AboutController::handleEvent(Ion::Events::Event event) {
|
||||
if (!(event == Ion::Events::Right)) {
|
||||
if (childLabel == I18n::Message::SoftwareVersion) {
|
||||
MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)m_selectableTableView.selectedCell();
|
||||
if (strcmp(myCell->accessoryText(), Ion::patchLevel()) == 0) {
|
||||
const char * currentText = myCell->accessoryText();
|
||||
if (strcmp(currentText, Ion::patchLevel()) == 0) {
|
||||
myCell->setAccessoryText(Ion::pcbVersion());
|
||||
} else if (strcmp(currentText, Ion::pcbVersion()) == 0) {
|
||||
myCell->setAccessoryText(Ion::softwareVersion());
|
||||
return true;
|
||||
} else {
|
||||
assert(strcmp(currentText, Ion::softwareVersion()) == 0);
|
||||
myCell->setAccessoryText(Ion::patchLevel());
|
||||
}
|
||||
myCell->setAccessoryText(Ion::patchLevel());
|
||||
return true;
|
||||
}
|
||||
if (childLabel == I18n::Message::OmegaVersion) {
|
||||
|
||||
@@ -4,7 +4,7 @@ ActivateExamMode = "Prüfungsmodus starten"
|
||||
ActiveExamModeMessage1 = "Alle Ihre Daten werden "
|
||||
ActiveExamModeMessage2 = "gelöscht, wenn Sie den "
|
||||
ActiveExamModeMessage3 = "Prüfungsmodus einschalten."
|
||||
ActiveDutchExamModeMessage1 = "Alle Ihre Daten werden gelöscht, wenn"
|
||||
ActiveDutchExamModeMessage1 = "Alle Daten werden gelöscht, wenn"
|
||||
ActiveDutchExamModeMessage2 = "Sie den Prüfungsmodus einschalten. "
|
||||
ActiveDutchExamModeMessage3 = "Python wird nicht verfügbar sein."
|
||||
Axis = "Achse"
|
||||
@@ -25,7 +25,7 @@ CountryNL = "Niederlande "
|
||||
CountryPT = "Portugal "
|
||||
CountryUS = "Vereinigte Staaten "
|
||||
CountryWW = "International "
|
||||
CountryWarning1 = "Diese Einstellung definiert die verwendeten"
|
||||
CountryWarning1 = "Einstellung definiert verwendete"
|
||||
CountryWarning2 = "mathematischen Konventionen."
|
||||
DataNotSuitable = "Daten nicht geeignet"
|
||||
DataTab = "Daten"
|
||||
@@ -43,16 +43,16 @@ FunctionColumn = "0(0) Spalte"
|
||||
FunctionOptions = "Funktionsoptionen"
|
||||
Goto = "Gehe zu"
|
||||
GraphTab = "Graph"
|
||||
HardwareTestLaunch1 = "Sie sind dabei den Hardwaretest zu"
|
||||
HardwareTestLaunch2 = "starten. Um ihn wieder zu verlassen,"
|
||||
HardwareTestLaunch3 = "müssen Sie einen Reset durchfuhren,"
|
||||
HardwareTestLaunch1 = "Sie sind dabei, den Hardwaretest zu"
|
||||
HardwareTestLaunch2 = "starten. Um ihn zu verlassen,"
|
||||
HardwareTestLaunch3 = "müssen Sie einen Reset durchführen,"
|
||||
HardwareTestLaunch4 = "der Ihre Daten löschen wird."
|
||||
IntervalSet = "Intervall einstellen"
|
||||
Language = "Sprache"
|
||||
LowBattery = "Batterie erschöpft"
|
||||
LowBattery = "Akku erschöpft"
|
||||
Mean = "Mittelwert"
|
||||
Move = " Verschieben: "
|
||||
NameCannotStartWithNumber = "Ein Name darf nicht mit einer Zahl beginnen"
|
||||
NameCannotStartWithNumber = "Name darf nicht mit Zahl beginnen"
|
||||
NameTaken = "Dieser Name ist bereits vergeben"
|
||||
NameTooLong = "Der Name ist zu lang"
|
||||
Navigate = "Navigieren"
|
||||
@@ -70,14 +70,14 @@ PoolMemoryFull1 = "Der Arbeitsspeicher ist voll."
|
||||
PoolMemoryFull2 = "Versuchen Sie es erneut."
|
||||
Rename = "Umbenennen"
|
||||
Sci = "wiss"
|
||||
SortValues = "Nach steigenden Werten sortieren"
|
||||
SortSizes = "Nach steigenden Frequenzen sortieren"
|
||||
SortValues = "Nach Werten sortieren"
|
||||
SortSizes = "Nach Frequenzen sortieren"
|
||||
SquareSum = "Quadratsumme"
|
||||
StatTab = "Stats"
|
||||
StandardDeviation = "Standardabweichung"
|
||||
Step = "Schrittwert"
|
||||
StorageMemoryFull1 = "Der Speicher ist voll. Löschen Sie"
|
||||
StorageMemoryFull2 = "einige Daten und versuchen Sie es erneut."
|
||||
StorageMemoryFull2 = "einige Daten, dann erneut versuchen."
|
||||
StoreExpressionNotAllowed = "'store' ist verboten"
|
||||
SyntaxError = "Syntaxfehler"
|
||||
Sym = "sym"
|
||||
|
||||
@@ -13,12 +13,12 @@ LocalizationController::ContentView::ContentView(LocalizationController * contro
|
||||
m_countryTitleMessage(KDFont::LargeFont, I18n::Message::Country),
|
||||
m_borderView(Palette::BackgroundApps)
|
||||
{
|
||||
m_countryTitleMessage.setBackgroundColor(Palette::WallScreen);
|
||||
m_countryTitleMessage.setBackgroundColor(Palette::BackgroundHard);
|
||||
m_countryTitleMessage.setAlignment(0.5f, 0.5f);
|
||||
assert(k_numberOfCountryWarningLines == 2); // textMessages is not overflowed
|
||||
I18n::Message textMessages[k_numberOfCountryWarningLines] = {I18n::Message::CountryWarning1, I18n::Message::CountryWarning2};
|
||||
for (int i = 0; i < k_numberOfCountryWarningLines; i++) {
|
||||
m_countryWarningLines[i].setBackgroundColor(Palette::WallScreen);
|
||||
m_countryWarningLines[i].setBackgroundColor(Palette::BackgroundHard);
|
||||
m_countryWarningLines[i].setFont(KDFont::SmallFont);
|
||||
m_countryWarningLines[i].setAlignment(0.5f, 0.5f);
|
||||
m_countryWarningLines[i].setMessage(textMessages[i]);
|
||||
|
||||
@@ -45,7 +45,7 @@ protected:
|
||||
ContentView(LocalizationController * controller, SelectableTableViewDataSource * dataSource);
|
||||
|
||||
SelectableTableView * selectableTableView() { return &m_selectableTableView; }
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override { ctx->fillRect(bounds(), Palette::WallScreen); }
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override { ctx->fillRect(bounds(), Palette::BackgroundApps); }
|
||||
void modeHasChanged();
|
||||
|
||||
private:
|
||||
|
||||
@@ -4,7 +4,7 @@ AddEquation = "Gleichung hinzufügen"
|
||||
ResolveEquation = "Lösen der Gleichung"
|
||||
ResolveSystem = "Lösen des Gleichungssystems"
|
||||
UseEquationModel = "Verwenden Sie ein Gleichungsmodell"
|
||||
RequireEquation = "Die Eingabe muss eine Gleichung sein"
|
||||
RequireEquation = "Eingabe muss eine Gleichung sein"
|
||||
UndefinedEquation = "Nicht definierte Gleichung"
|
||||
UnrealEquation = "Nicht reelle Gleichung"
|
||||
TooManyVariables = "Es gibt zu viele Unbekannte"
|
||||
@@ -17,8 +17,8 @@ NoSolutionEquation = "Die Gleichung hat keine Lösung"
|
||||
NoSolutionInterval = "Keine Lösung im Intervall gefunden"
|
||||
EnterEquation = "Geben Sie eine Gleichung ein"
|
||||
InfiniteNumberOfSolutions = "Es gibt unendlich viele Lösungen"
|
||||
ApproximateSolutionIntervalInstruction0= "Geben Sie das Intervall für die Suche"
|
||||
ApproximateSolutionIntervalInstruction1= "nach einer ungefähren Lösung ein"
|
||||
ApproximateSolutionIntervalInstruction0= "Geben Sie das Suchintervall"
|
||||
ApproximateSolutionIntervalInstruction1= "für eine ungefähre Lösung ein"
|
||||
OnlyFirstSolutionsDisplayed0 = "Es werden nur die ersten"
|
||||
OnlyFirstSolutionsDisplayed1 = "zehn Lösungen angezeigt."
|
||||
PolynomeHasNoRealSolution0 = "Das Polynom hat"
|
||||
|
||||
@@ -25,15 +25,15 @@ UnitDistanceParsec = "Parsec"
|
||||
UnitDistanceMile = "Meile"
|
||||
UnitDistanceYard = "Yard"
|
||||
UnitDistanceFoot = "Fuß"
|
||||
UnitDistanceInch = "Inch"
|
||||
UnitDistanceInch = "Zoll"
|
||||
UnitMassMenu = "Masse"
|
||||
UnitMassGramKilo = "Kilogramm"
|
||||
UnitMassGram = "Gramm"
|
||||
UnitMassGramMilli = "Milligramm"
|
||||
UnitMassGramMicro = "Mikrogramm"
|
||||
UnitMassGramNano = "Nanogramm"
|
||||
UnitDistanceImperialMenu = "US Customary"
|
||||
UnitMassImperialMenu = "US Customary"
|
||||
UnitDistanceImperialMenu = "Angloamerikanisch"
|
||||
UnitMassImperialMenu = "Angloamerikanisch"
|
||||
UnitMassTonne = "Tonne"
|
||||
UnitMassOunce = "Unze"
|
||||
UnitMassPound = "Pfund"
|
||||
@@ -95,7 +95,7 @@ UnitVolumePint = "Pint"
|
||||
UnitVolumeQuart = "Quart"
|
||||
UnitVolumeGallon = "Gallone"
|
||||
UnitMetricMenu = "Metrisch"
|
||||
UnitImperialMenu = "Empire"
|
||||
UnitImperialMenu = "Angloamerikanisch"
|
||||
Toolbox = "Werkzeugkasten"
|
||||
AbsoluteValue = "Betragsfunktion"
|
||||
NthRoot = "n-te Wurzel"
|
||||
@@ -137,34 +137,34 @@ Vectors = "Vektoren"
|
||||
Dot = "Skalarprodukt"
|
||||
Cross = "Kreuzprodukt"
|
||||
NormVector = "Norm"
|
||||
Sort = "Sortieren aufsteigend"
|
||||
InvSort = "Sortieren absteigend"
|
||||
Sort = "Aufsteigend sortieren"
|
||||
InvSort = "Absteigend sortieren"
|
||||
Maximum = "Maximalwert"
|
||||
Minimum = "Mindestwert"
|
||||
Floor = "Untergrenze"
|
||||
FracPart = "Bruchteil"
|
||||
Ceiling = "Obergrenze"
|
||||
Rounding = "Runden"
|
||||
HyperbolicCosine = "Kosinus hyperbolicus"
|
||||
HyperbolicSine = "Sinus hyperbolicus"
|
||||
HyperbolicTangent = "Tangens hyperbolicus"
|
||||
InverseHyperbolicCosine = "Areakosinus hyperbolicus"
|
||||
InverseHyperbolicSine = "Areasinus hyperbolicus"
|
||||
InverseHyperbolicTangent = "Areatangens hyperbolicus"
|
||||
Prediction95 = "Schwankungsbereich 95%"
|
||||
Prediction = "Einfacher Schwankungsbereich"
|
||||
HyperbolicCosine = "Hyperbolischer Kosinus"
|
||||
HyperbolicSine = "Hyperbolischer Sinus"
|
||||
HyperbolicTangent = "Hyperbolischer Tangens"
|
||||
InverseHyperbolicCosine = "Inverser hyperbolischer Kosinus"
|
||||
InverseHyperbolicSine = "Inverser hyperbolischer Sinus"
|
||||
InverseHyperbolicTangent = "Inverser hyperbolischer Tangens"
|
||||
Prediction95 = "Vorhersageintervall 95%"
|
||||
Prediction = "Einfaches Vorhersageintervall"
|
||||
Confidence = "Konfidenzintervall"
|
||||
RandomAndApproximation = "Zufall und Näherung"
|
||||
RandomFloat = "Dezimalzahl in [0,1]"
|
||||
RandomFloat = "Fließkommazahl in [0,1]"
|
||||
RandomInteger = "Zufällige ganze Zahl in [a,b]"
|
||||
PrimeFactorDecomposition = "Primfaktorzerlegung"
|
||||
NormCDF = "P(X<a) wo X folgt N(μ,σ)"
|
||||
NormCDF2 = "P(a<X<b) wo X folgt N(μ,σ)"
|
||||
InvNorm = "m wo P(X<m)=a und X folgt N(μ,σ)"
|
||||
PrimeFactorDecomposition = "Ganzzahlige Faktorisierung"
|
||||
NormCDF = "P(X<a) wobei X auf N(μ,σ) folgt"
|
||||
NormCDF2 = "P(a<X<b) wobei X auf N(μ,σ) folgt"
|
||||
InvNorm = "m wobei P(X<m)=a, X folgt N(μ,σ)"
|
||||
NormPDF = "Wahrscheinlichkeitsdichte N(μ,σ)"
|
||||
BinomialPDF = "P(X=m) wo X folgt B(n,p)"
|
||||
BinomialCDF = "P(X<=m) wo X folgt B(n,p)"
|
||||
InvBinomial = "m wo P(X<=m)=a und X folgt B(n,p)"
|
||||
BinomialPDF = "P(X=m) wobei X auf B(n,p) folgt"
|
||||
BinomialCDF = "P(X<=m) wobei X auf B(n,p) folgt"
|
||||
InvBinomial = "m wobei P(X<=m)=a, X folgt B(n,p)"
|
||||
Probability = "Wahrscheinlichkeit"
|
||||
BinomialDistribution = "Binomialverteilung"
|
||||
NormalDistribution = "Normalverteilung"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
USBConnected = "DER RECHNER IST ANGESCHLOSSEN"
|
||||
USBConnected = "TASCHENRECHNER IST ANGESCHLOSSEN"
|
||||
ConnectedMessage1 = "Um Daten zu übertragen, verbinden"
|
||||
ConnectedMessage2 = "Sie Sich von Ihrem Computer aus mit"
|
||||
ConnectedMessage2 = "Sie sich von Ihrem Computer aus mit"
|
||||
ConnectedMessage3 = "workshop.numworks.com."
|
||||
ConnectedMessage4 = "Drücken Sie die RETURN-Taste am"
|
||||
ConnectedMessage5 = "Taschenrechner oder ziehen Sie das Kabel,"
|
||||
ConnectedMessage4 = "Drücken Sie die Zurück-Taste am"
|
||||
ConnectedMessage5 = "Taschenrechner oder Kabel abziehen,"
|
||||
ConnectedMessage6 = "um die Verbindung zu trennen."
|
||||
|
||||
@@ -4,7 +4,7 @@ PLATFORM ?= device
|
||||
DEBUG ?= 0
|
||||
|
||||
HOME_DISPLAY_EXTERNALS ?= 1
|
||||
EPSILON_VERSION ?= 15.3.1
|
||||
EPSILON_VERSION ?= 15.5.0
|
||||
OMEGA_VERSION ?= 1.22.0
|
||||
# OMEGA_USERNAME ?= N/A
|
||||
OMEGA_STATE ?= dev
|
||||
@@ -13,7 +13,6 @@ SUBMODULES_APPS = atomic rpn
|
||||
EPSILON_I18N ?= en fr nl pt it de es hu
|
||||
EPSILON_COUNTRIES ?= WW CA DE ES FR GB IT NL PT US
|
||||
EPSILON_GETOPT ?= 0
|
||||
EPSILON_TELEMETRY ?= 0
|
||||
ESCHER_LOG_EVENTS_BINARY ?= 0
|
||||
THEME_NAME ?= omega_light
|
||||
THEME_REPO ?= local
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
TOOLCHAIN ?= host-gcc
|
||||
USE_LIBA ?= 0
|
||||
ION_KEYBOARD_LAYOUT = layout_B2
|
||||
EXE = bin
|
||||
EXE = bin
|
||||
|
||||
EPSILON_TELEMETRY ?= 0
|
||||
@@ -2,6 +2,8 @@ MODEL ?= n0110
|
||||
USE_LIBA = 1
|
||||
EXE = elf
|
||||
|
||||
EPSILON_TELEMETRY ?= 0
|
||||
|
||||
BUILD_DIR := $(BUILD_DIR)/$(MODEL)
|
||||
|
||||
$(BUILD_DIR)/python/port/port.o: CXXFLAGS += -DMP_PORT_USE_STACK_SYMBOLS=1
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
TOOLCHAIN ?= arm-gcc-m4f
|
||||
ION_KEYBOARD_LAYOUT = layout_B2
|
||||
PCB_LATEST = 0
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
TOOLCHAIN ?= arm-gcc-m7f
|
||||
ION_KEYBOARD_LAYOUT = layout_B3
|
||||
PCB_LATEST = 343 # PCB version 3.43
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
TOOLCHAIN = android
|
||||
EXE = so
|
||||
|
||||
EPSILON_TELEMETRY ?= 1
|
||||
EPSILON_TELEMETRY ?= 0
|
||||
|
||||
ARCHS = armeabi-v7a arm64-v8a x86 x86_64
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
TOOLCHAIN = host-gcc
|
||||
EXE = bin
|
||||
|
||||
EPSILON_SIMULATOR_HAS_LIBPNG = 1
|
||||
EPSILON_TELEMETRY ?= 0
|
||||
|
||||
@@ -3,11 +3,10 @@ EXE = bin
|
||||
|
||||
APPLE_PLATFORM = macos
|
||||
APPLE_PLATFORM_MIN_VERSION = 10.10
|
||||
EPSILON_TELEMETRY ?= 0
|
||||
|
||||
ARCHS = x86_64
|
||||
|
||||
EPSILON_SIMULATOR_HAS_LIBPNG = 1
|
||||
|
||||
ifdef ARCH
|
||||
BUILD_DIR := $(BUILD_DIR)/$(ARCH)
|
||||
else
|
||||
|
||||
@@ -8,13 +8,4 @@ TARGET ?= $(HOST)
|
||||
|
||||
BUILD_DIR := $(BUILD_DIR)/$(TARGET)
|
||||
|
||||
EPSILON_SIMULATOR_HAS_LIBPNG ?= 0
|
||||
|
||||
include build/platform.simulator.$(TARGET).mak
|
||||
|
||||
SFLAGS += -DEPSILON_SIMULATOR_HAS_LIBPNG=$(EPSILON_SIMULATOR_HAS_LIBPNG)
|
||||
|
||||
ifeq ($(EPSILON_SIMULATOR_HAS_LIBPNG),1)
|
||||
SFLAGS += `libpng-config --cflags`
|
||||
LDFLAGS += `libpng-config --ldflags`
|
||||
endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
TOOLCHAIN = emscripten
|
||||
EXE = js
|
||||
|
||||
HANDY_TARGETS_EXTENSIONS += zip
|
||||
EPSILON_TELEMETRY ?= 0
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
TOOLCHAIN = windows
|
||||
EXE = exe
|
||||
|
||||
EPSILON_TELEMETRY ?= 0
|
||||
|
||||
@@ -14,7 +14,7 @@ $(eval $(call rule_for, \
|
||||
|
||||
$(eval $(call rule_for, \
|
||||
CPP, %, %.inc, \
|
||||
$$(CPP) -P $$< $$@, \
|
||||
$$(CPP) $$(addprefix -I,$$(dir $$^)) -P $$< $$@, \
|
||||
global \
|
||||
))
|
||||
|
||||
@@ -60,6 +60,12 @@ $(eval $(call rule_for, \
|
||||
global \
|
||||
))
|
||||
|
||||
$(eval $(call rule_for, \
|
||||
ZIP, %.zip, , \
|
||||
rm -rf $$(basename $$@) && mkdir -p $$(basename $$@) && cp $$^ $$(basename $$@) && zip -r -9 -j $$@ $$(basename $$@) > /dev/null && rm -rf $$(basename $$@), \
|
||||
global \
|
||||
))
|
||||
|
||||
ifdef EXE
|
||||
ifeq ($(OS),Windows_NT)
|
||||
# Work around command-line length limit
|
||||
|
||||
@@ -19,4 +19,3 @@ $(BUILD_DIR)/test.external_flash.write.$(EXE): $(BUILD_DIR)/quiz/src/test_ion_ex
|
||||
sleep 2; \
|
||||
fi
|
||||
$(Q) $(PYTHON) build/device/dfu.py -u $(word 1,$^)
|
||||
|
||||
|
||||
@@ -1,8 +1 @@
|
||||
# Headless targets
|
||||
$(eval $(call rule_for_epsilon_flavor,headless))
|
||||
HANDY_TARGETS += epsilon.headless
|
||||
|
||||
$(BUILD_DIR)/test.headless.$(EXE): $(call flavored_object_for,$(test_runner_src),headless)
|
||||
HANDY_TARGETS += test.headless
|
||||
|
||||
-include build/targets.simulator.$(TARGET).mak
|
||||
|
||||
@@ -1 +1,13 @@
|
||||
$(BUILD_DIR)/test.headless.js: EMSCRIPTEN_MODULARIZE = 0
|
||||
$(BUILD_DIR)/test.js: EMSCRIPTEN_MODULARIZE = 0
|
||||
|
||||
HANDY_TARGETS += htmlpack htmlpack.official
|
||||
HANDY_TARGETS_EXTENSIONS += zip
|
||||
|
||||
htmlpack_targets = .\
|
||||
.official. \
|
||||
|
||||
define rule_htmlpack
|
||||
$$(BUILD_DIR)/htmlpack$(1)zip: $$(addprefix $$(BUILD_DIR)/ion/src/simulator/web/,calculator.html calculator.css) $$(BUILD_DIR)/epsilon$(1)js ion/src/simulator/web/calculator.js
|
||||
endef
|
||||
|
||||
$(foreach target,$(htmlpack_targets),$(eval $(call rule_htmlpack,$(target))))
|
||||
|
||||
@@ -22,6 +22,7 @@ endif
|
||||
escher_src += $(addprefix escher/src/,\
|
||||
alternate_empty_view_controller.cpp \
|
||||
app.cpp \
|
||||
background_view.cpp \
|
||||
bank_view_controller.cpp \
|
||||
bordered.cpp \
|
||||
buffer_text_view.cpp \
|
||||
@@ -46,6 +47,7 @@ escher_src += $(addprefix escher/src/,\
|
||||
expression_view.cpp \
|
||||
highlight_cell.cpp \
|
||||
gauge_view.cpp \
|
||||
icon_view.cpp \
|
||||
image_view.cpp \
|
||||
input_event_handler.cpp \
|
||||
invocation.cpp \
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <escher/alternate_empty_view_controller.h>
|
||||
#include <escher/alternate_empty_view_delegate.h>
|
||||
#include <escher/background_view.h>
|
||||
#include <escher/bank_view_controller.h>
|
||||
#include <escher/buffer_text_view.h>
|
||||
#include <escher/button.h>
|
||||
@@ -26,6 +27,7 @@
|
||||
#include <escher/expression_view.h>
|
||||
#include <escher/gauge_view.h>
|
||||
#include <escher/highlight_cell.h>
|
||||
#include <escher/icon_view.h>
|
||||
#include <escher/image.h>
|
||||
#include <escher/image_view.h>
|
||||
#include <escher/input_event_handler.h>
|
||||
|
||||
19
escher/include/escher/background_view.h
Normal file
19
escher/include/escher/background_view.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef ESCHER_BACKGROUND_VIEW_H
|
||||
#define ESCHER_BACKGROUND_VIEW_H
|
||||
|
||||
#include <escher/view.h>
|
||||
|
||||
class BackgroundView : public View {
|
||||
public:
|
||||
BackgroundView();
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void setBackgroundImage(const uint8_t * data);
|
||||
void setDefaultColor(KDColor defaultColor);
|
||||
void updateDataValidity();
|
||||
private:
|
||||
const uint8_t * m_data;
|
||||
bool m_isDataValid;
|
||||
KDColor m_defaultColor;
|
||||
};
|
||||
|
||||
#endif
|
||||
20
escher/include/escher/icon_view.h
Normal file
20
escher/include/escher/icon_view.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef ESCHER_ICON_VIEW_H
|
||||
#define ESCHER_ICON_VIEW_H
|
||||
|
||||
#include <escher/view.h>
|
||||
#include <escher/image.h>
|
||||
|
||||
class IconView : public View {
|
||||
//Unlike the ImageView class, IconView displays an image with rounded corners
|
||||
public:
|
||||
IconView();
|
||||
void setImage(const Image * image);
|
||||
void setImage(const uint8_t *data, size_t dataLength);
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
private:
|
||||
const Image * m_image;
|
||||
const uint8_t * m_data;
|
||||
size_t m_dataLength;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -96,25 +96,6 @@ public:
|
||||
void scrollToContentPoint(KDPoint p, bool allowOverscroll = false);
|
||||
void scrollToContentRect(KDRect rect, bool allowOverscroll = false); // Minimal scrolling to make this rect visible
|
||||
protected:
|
||||
KDCoordinate maxContentWidthDisplayableWithoutScrolling() const {
|
||||
return m_frame.width() - m_leftMargin - m_rightMargin;
|
||||
}
|
||||
KDCoordinate maxContentHeightDisplayableWithoutScrolling() const {
|
||||
return m_frame.height() - m_topMargin - m_bottomMargin;
|
||||
}
|
||||
KDRect visibleContentRect();
|
||||
void layoutSubviews(bool force = false) override;
|
||||
virtual KDSize contentSize() const { return m_contentView->minimalSizeForOptimalDisplay(); }
|
||||
#if ESCHER_VIEW_LOGGING
|
||||
const char * className() const override;
|
||||
void logAttributes(std::ostream &os) const override;
|
||||
#endif
|
||||
View * m_contentView;
|
||||
private:
|
||||
ScrollViewDataSource * m_dataSource;
|
||||
int numberOfSubviews() const override { return 1 + const_cast<ScrollView *>(this)->decorator()->numberOfIndicators(); }
|
||||
View * subviewAtIndex(int index) override { return (index == 0) ? &m_innerView : decorator()->indicatorAtIndex(index); }
|
||||
|
||||
class InnerView : public View {
|
||||
public:
|
||||
InnerView(ScrollView * scrollView) : View(), m_scrollView(scrollView) {}
|
||||
@@ -127,13 +108,33 @@ private:
|
||||
}
|
||||
const ScrollView * m_scrollView;
|
||||
};
|
||||
|
||||
KDCoordinate maxContentWidthDisplayableWithoutScrolling() const {
|
||||
return m_frame.width() - m_leftMargin - m_rightMargin;
|
||||
}
|
||||
KDCoordinate maxContentHeightDisplayableWithoutScrolling() const {
|
||||
return m_frame.height() - m_topMargin - m_bottomMargin;
|
||||
}
|
||||
KDRect visibleContentRect();
|
||||
void layoutSubviews(bool force = false) override;
|
||||
virtual KDSize contentSize() const { return m_contentView->minimalSizeForOptimalDisplay(); }
|
||||
virtual InnerView * getInnerView() { return &m_innerView; }
|
||||
#if ESCHER_VIEW_LOGGING
|
||||
const char * className() const override;
|
||||
void logAttributes(std::ostream &os) const override;
|
||||
#endif
|
||||
View * m_contentView;
|
||||
InnerView m_innerView;
|
||||
private:
|
||||
ScrollViewDataSource * m_dataSource;
|
||||
int numberOfSubviews() const override { return 1 + const_cast<ScrollView *>(this)->decorator()->numberOfIndicators(); }
|
||||
View * subviewAtIndex(int index) override { return (index == 0) ? &m_innerView : decorator()->indicatorAtIndex(index); }
|
||||
|
||||
KDCoordinate m_topMargin;
|
||||
KDCoordinate m_rightMargin;
|
||||
KDCoordinate m_bottomMargin;
|
||||
KDCoordinate m_leftMargin;
|
||||
|
||||
InnerView m_innerView;
|
||||
Decorator::Type m_decoratorType;
|
||||
union Decorators {
|
||||
public:
|
||||
|
||||
65
escher/src/background_view.cpp
Normal file
65
escher/src/background_view.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include <escher/background_view.h>
|
||||
#include <ion.h>
|
||||
#include <kandinsky/ion_context.h>
|
||||
#include <escher/palette.h>//AND THIS
|
||||
#include "apps/home/controller.h"
|
||||
#ifdef HOME_DISPLAY_EXTERNALS
|
||||
#include "apps/external/external_icon.h"
|
||||
#include "apps/external/archive.h"
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
//To store the Omega backgrounds, we use a specific file in the "OmegaBitMap" format.
|
||||
//Here is its header
|
||||
struct OBMHeader
|
||||
{
|
||||
uint32_t signature; //Normally it is 32145
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
const KDColor image_data;
|
||||
};
|
||||
|
||||
BackgroundView::BackgroundView():
|
||||
m_data(nullptr),
|
||||
m_isDataValid(false),
|
||||
m_defaultColor(Palette::BackgroundHard)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void BackgroundView::setBackgroundImage(const uint8_t * data) {
|
||||
m_data = data;
|
||||
updateDataValidity();
|
||||
markRectAsDirty(bounds());
|
||||
}
|
||||
|
||||
void BackgroundView::setDefaultColor(KDColor defaultColor) {
|
||||
m_defaultColor = defaultColor;
|
||||
}
|
||||
|
||||
void BackgroundView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
if(!m_isDataValid) {
|
||||
ctx->fillRect(rect, m_defaultColor);
|
||||
return;
|
||||
}
|
||||
|
||||
OBMHeader* h = (OBMHeader*)m_data;
|
||||
|
||||
int yrectToImage = ctx->origin().y() - m_frame.y();
|
||||
int xrectToImage = ctx->origin().x() - m_frame.x();
|
||||
|
||||
for (int line = rect.y(); line <= rect.bottom(); line++) {
|
||||
int offset = ((line + yrectToImage) * h->width) + (rect.x() + xrectToImage);
|
||||
ctx->fillRectWithPixels(KDRect(rect.x(), line, rect.width(), 1), &(h->image_data) + offset, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundView::updateDataValidity() {
|
||||
if(m_data == nullptr || KDIonContext::sharedContext()->gammaEnabled) {
|
||||
m_isDataValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
OBMHeader* h = (OBMHeader*)m_data;
|
||||
m_isDataValid = h->signature==466512775 && h->height==m_frame.height() && h->width==m_frame.width();
|
||||
}
|
||||
79
escher/src/icon_view.cpp
Normal file
79
escher/src/icon_view.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <escher/icon_view.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
#include <ion.h>
|
||||
#include <kandinsky.h>
|
||||
|
||||
IconView::IconView() :
|
||||
View(),
|
||||
m_image(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr static int iconBufferSize = 3080;
|
||||
// Icon file is 55 x 56 = 3080
|
||||
|
||||
void IconView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
const uint8_t* data;
|
||||
size_t size;
|
||||
|
||||
if (m_image != nullptr) {
|
||||
assert(bounds().width() == m_image->width());
|
||||
assert(bounds().height() == m_image->height());
|
||||
assert(bounds().width() == 55);
|
||||
assert(bounds().height() == 56);
|
||||
|
||||
data = m_image->compressedPixelData();
|
||||
size = m_image->compressedPixelDataSize();
|
||||
} else if (m_data != nullptr) {
|
||||
data = m_data;
|
||||
size = m_dataLength;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
KDColor pixelBuffer[iconBufferSize];
|
||||
assert(Ion::stackSafe()); // That's a VERY big buffer we're allocating on the stack
|
||||
|
||||
Ion::decompress(
|
||||
data,
|
||||
reinterpret_cast<uint8_t *>(pixelBuffer),
|
||||
size,
|
||||
iconBufferSize * sizeof(KDColor)
|
||||
);
|
||||
|
||||
//We push the first 6 lines of the image so that they are truncated on the sides
|
||||
ctx->fillRectWithPixels(KDRect(6, 0, m_frame.width()-12, 1),pixelBuffer+6, nullptr);
|
||||
ctx->fillRectWithPixels(KDRect(4, 1, m_frame.width()-8, 1),pixelBuffer+6+55, nullptr);
|
||||
ctx->fillRectWithPixels(KDRect(3, 2, m_frame.width()-6, 1),pixelBuffer+3+(2*55), nullptr);
|
||||
ctx->fillRectWithPixels(KDRect(2, 3, m_frame.width()-4, 1),pixelBuffer+2+(3*55), nullptr);
|
||||
ctx->fillRectWithPixels(KDRect(1, 4, m_frame.width()-2, 1),pixelBuffer+1+(4*55), nullptr);
|
||||
ctx->fillRectWithPixels(KDRect(1, 5, m_frame.width()-2, 1),pixelBuffer+1+(5*55), nullptr);
|
||||
|
||||
//Then we push the rectangular part of the image
|
||||
ctx->fillRectWithPixels(KDRect(0, 6, m_frame.width(), 44),pixelBuffer+(6*55), nullptr);
|
||||
|
||||
//Finaly we push the last 5 lines of the image so that they are truncated on the sides
|
||||
ctx->fillRectWithPixels(KDRect(1, 50, m_frame.width()-2, 1),pixelBuffer+1+(50*55), nullptr);
|
||||
ctx->fillRectWithPixels(KDRect(1, 51, m_frame.width()-2, 1),pixelBuffer+1+(51*55), nullptr);
|
||||
ctx->fillRectWithPixels(KDRect(2, 52, m_frame.width()-4, 1),pixelBuffer+2+(52*55), nullptr);
|
||||
ctx->fillRectWithPixels(KDRect(3, 53, m_frame.width()-6, 1),pixelBuffer+3+(53*55), nullptr);
|
||||
ctx->fillRectWithPixels(KDRect(4, 54, m_frame.width()-8, 1),pixelBuffer+4+(54*55), nullptr);
|
||||
ctx->fillRectWithPixels(KDRect(6, 55, m_frame.width()-12, 1),pixelBuffer+6+(55*55), nullptr);
|
||||
}
|
||||
|
||||
void IconView::setImage(const uint8_t *data, size_t dataLength) {
|
||||
if (data != m_data && dataLength != m_dataLength) {
|
||||
m_data = data;
|
||||
m_dataLength = dataLength;
|
||||
markRectAsDirty(bounds());
|
||||
}
|
||||
}
|
||||
|
||||
void IconView::setImage(const Image * image) {
|
||||
if (image != m_image) {
|
||||
m_image = image;
|
||||
markRectAsDirty(bounds());
|
||||
}
|
||||
}
|
||||
@@ -9,12 +9,12 @@ extern "C" {
|
||||
ScrollView::ScrollView(View * contentView, ScrollViewDataSource * dataSource) :
|
||||
View(),
|
||||
m_contentView(contentView),
|
||||
m_innerView(this),
|
||||
m_dataSource(dataSource),
|
||||
m_topMargin(0),
|
||||
m_rightMargin(0),
|
||||
m_bottomMargin(0),
|
||||
m_leftMargin(0),
|
||||
m_innerView(this),
|
||||
m_decorators(),
|
||||
m_backgroundColor(Palette::BackgroundApps)
|
||||
{
|
||||
@@ -24,12 +24,12 @@ ScrollView::ScrollView(View * contentView, ScrollViewDataSource * dataSource) :
|
||||
|
||||
ScrollView::ScrollView(ScrollView&& other) :
|
||||
m_contentView(other.m_contentView),
|
||||
m_innerView(this),
|
||||
m_dataSource(other.m_dataSource),
|
||||
m_topMargin(other.m_topMargin),
|
||||
m_rightMargin(other.m_rightMargin),
|
||||
m_bottomMargin(other.m_bottomMargin),
|
||||
m_leftMargin(other.m_leftMargin),
|
||||
m_innerView(this),
|
||||
m_backgroundColor(other.m_backgroundColor)
|
||||
{
|
||||
setDecoratorType(other.m_decoratorType);
|
||||
@@ -144,7 +144,7 @@ void ScrollView::layoutSubviews(bool force) {
|
||||
if (!r2.isEmpty()) {
|
||||
markRectAsDirty(r2);
|
||||
}
|
||||
m_innerView.setFrame(innerFrame, force);
|
||||
getInnerView()->setFrame(innerFrame, force);
|
||||
KDPoint absoluteOffset = contentOffset().opposite().translatedBy(KDPoint(m_leftMargin - innerFrame.x(), m_topMargin - innerFrame.y()));
|
||||
KDRect contentFrame = KDRect(absoluteOffset, contentSize());
|
||||
m_contentView->setFrame(contentFrame, force);
|
||||
|
||||
@@ -25,7 +25,6 @@ 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))" -DOMEGA_USERNAME="$(call initializer_list,$(OMEGA_USERNAME))"
|
||||
|
||||
ion_src += $(addprefix ion/src/shared/, \
|
||||
console_display.cpp:+consoledisplay \
|
||||
console_line.cpp \
|
||||
crc32_eat_byte.cpp \
|
||||
decompress.cpp \
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <ion/backlight.h>
|
||||
#include <ion/battery.h>
|
||||
#include <ion/board.h>
|
||||
#include <ion/clipboard.h>
|
||||
#include <ion/console.h>
|
||||
#include <ion/display.h>
|
||||
@@ -37,6 +38,7 @@ const char * softwareVersion();
|
||||
const char * omegaVersion();
|
||||
const char * patchLevel();
|
||||
const char * fccId();
|
||||
const char * pcbVersion();
|
||||
|
||||
// CRC32 : non xor-ed, non reversed, direct, polynomial 4C11DB7
|
||||
uint32_t crc32Word(const uint32_t * data, size_t length); // Only accepts whole 32bit values
|
||||
|
||||
12
ion/include/ion/board.h
Normal file
12
ion/include/ion/board.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef ION_BOARD_H
|
||||
#define ION_BOARD_H
|
||||
|
||||
namespace Ion {
|
||||
namespace Board {
|
||||
|
||||
void lockUnlockedPCBVersion();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -53,6 +53,18 @@ enum class ShiftAlphaStatus {
|
||||
// Timeout is decremented
|
||||
Event getEvent(int * timeout);
|
||||
|
||||
#if ION_EVENTS_JOURNAL
|
||||
class Journal {
|
||||
public:
|
||||
virtual void pushEvent(Event e) = 0;
|
||||
virtual Event popEvent() = 0;
|
||||
virtual bool isEmpty() = 0;
|
||||
};
|
||||
|
||||
void replayFrom(Journal * l);
|
||||
void logTo(Journal * l);
|
||||
#endif
|
||||
|
||||
ShiftAlphaStatus shiftAlphaStatus();
|
||||
void setShiftAlphaStatus(ShiftAlphaStatus s);
|
||||
void removeShift();
|
||||
|
||||
@@ -12,7 +12,9 @@ endif
|
||||
|
||||
ion_src += ion/src/shared/collect_registers.cpp
|
||||
|
||||
ION_DEVICE_SFLAGS = -Iion/src/device/$(MODEL) -Iion/src/device/shared
|
||||
IN_FACTORY ?= 0
|
||||
|
||||
ION_DEVICE_SFLAGS = -Iion/src/device/$(MODEL) -Iion/src/device/shared -DPCB_LATEST=$(PCB_LATEST) -DIN_FACTORY=$(IN_FACTORY)
|
||||
|
||||
$(call object_for,$(ion_device_src) $(ion_device_flasher_src) $(ion_device_bench_src)): SFLAGS += $(ION_DEVICE_SFLAGS)
|
||||
|
||||
|
||||
@@ -29,4 +29,5 @@ ion_device_bench_src += $(addprefix ion/src/device/bench/command/, \
|
||||
standby.cpp \
|
||||
usb_plugged.cpp \
|
||||
vblank.cpp \
|
||||
write_pcb_version.cpp \
|
||||
)
|
||||
|
||||
@@ -31,6 +31,7 @@ constexpr CommandHandler handles[] = {
|
||||
CommandHandler("STANDBY", Command::Standby),
|
||||
CommandHandler("USB_PLUGGED", Command::USBPlugged),
|
||||
CommandHandler("VBLANK", Command::VBlank),
|
||||
CommandHandler("WRITE_PCB_VERSION", Command::WritePCBVersion),
|
||||
CommandHandler(nullptr, nullptr)
|
||||
};
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ void LCDPins(const char * input);
|
||||
void LCDTiming(const char * input);
|
||||
void LED(const char * input);
|
||||
void MCUSerial(const char * input);
|
||||
void WritePCBVersion(const char * input);
|
||||
void Ping(const char * input);
|
||||
void Print(const char * input);
|
||||
void ScreenID(const char * input);
|
||||
|
||||
34
ion/src/device/bench/command/write_pcb_version.cpp
Normal file
34
ion/src/device/bench/command/write_pcb_version.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "command.h"
|
||||
#include <drivers/board.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
namespace Command {
|
||||
|
||||
void WritePCBVersion(const char * input) {
|
||||
if (input != nullptr) {
|
||||
reply(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
|
||||
/* When running the bench for a diagnostic, we must absolutely not write the
|
||||
* OTP, as N0110 built prior to the PCB revision would still have their OTP
|
||||
* blank and unlocked. */
|
||||
#if IN_FACTORY
|
||||
Board::writePCBVersion(PCB_LATEST);
|
||||
/* Read directly from memory, as when IN_FACTORY is true, the method
|
||||
* pcbVersion always returns PCB_LATEST. */
|
||||
if (Board::readPCBVersionInMemory() != PCB_LATEST) {
|
||||
reply(sKO);
|
||||
return;
|
||||
}
|
||||
Board::lockPCBVersion();
|
||||
#endif
|
||||
reply(sOK);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
ion_device_src += $(addprefix ion/src/device/n0100/drivers/, \
|
||||
board.cpp \
|
||||
external_flash.cpp \
|
||||
led.cpp \
|
||||
power.cpp \
|
||||
reset.cpp \
|
||||
usb.cpp \
|
||||
)
|
||||
|
||||
LDSCRIPT ?= ion/src/device/n0100/flash.ld
|
||||
|
||||
@@ -231,6 +231,23 @@ void shutdownClocks(bool keepLEDAwake) {
|
||||
RCC.AHB1ENR()->set(ahb1enr);
|
||||
}
|
||||
|
||||
/* The following methods regarding PCB version are dummy implementations.
|
||||
* Handling the PCB version is only necessary on the N0110. */
|
||||
|
||||
PCBVersion pcbVersion() {
|
||||
return PCB_LATEST;
|
||||
}
|
||||
|
||||
PCBVersion readPCBVersionInMemory() {
|
||||
return PCB_LATEST;
|
||||
}
|
||||
|
||||
void writePCBVersion(PCBVersion) {}
|
||||
|
||||
void lockPCBVersion() {}
|
||||
|
||||
bool pcbVersionIsLocked() { return true; }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
18
ion/src/device/n0100/drivers/external_flash.cpp
Normal file
18
ion/src/device/n0100/drivers/external_flash.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <drivers/external_flash.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace ExternalFlash {
|
||||
|
||||
void init() {}
|
||||
void shutdown() {}
|
||||
|
||||
void MassErase() {}
|
||||
int SectorAtAddress(uint32_t) { return 0; }
|
||||
void EraseSector(int) {}
|
||||
void WriteMemory(uint8_t *, const uint8_t *, size_t) {}
|
||||
void JDECid(uint8_t *, uint8_t *, uint8_t *) {}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
14
ion/src/device/n0100/drivers/usb.cpp
Normal file
14
ion/src/device/n0100/drivers/usb.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <drivers/usb.h>
|
||||
#include <drivers/config/usb.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace USB {
|
||||
|
||||
void initVbus() {
|
||||
Config::VbusPin.init();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
ion_device_src += $(addprefix ion/src/device/n0110/drivers/, \
|
||||
board.cpp \
|
||||
cache.cpp \
|
||||
external_flash.cpp \
|
||||
led.cpp \
|
||||
power.cpp \
|
||||
reset.cpp \
|
||||
usb.cpp \
|
||||
)
|
||||
|
||||
LDSCRIPT ?= ion/src/device/n0110/flash.ld
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <drivers/board.h>
|
||||
#include <drivers/cache.h>
|
||||
#include <drivers/internal_flash.h>
|
||||
#include <drivers/config/clocks.h>
|
||||
#include <drivers/config/internal_flash.h>
|
||||
#include <drivers/external_flash.h>
|
||||
#include <regs/regs.h>
|
||||
#include <ion.h>
|
||||
@@ -372,6 +374,44 @@ void shutdownClocks(bool keepLEDAwake) {
|
||||
RCC.AHB1ENR()->set(ahb1enr);
|
||||
}
|
||||
|
||||
constexpr int k_pcbVersionOTPIndex = 0;
|
||||
|
||||
/* As we want the PCB versions to be in ascending order chronologically, and
|
||||
* because the OTP are initialized with 1s, we store the bitwise-not of the
|
||||
* version number. This way, devices with blank OTP are considered version 0. */
|
||||
|
||||
PCBVersion pcbVersion() {
|
||||
#if IN_FACTORY
|
||||
/* When flashing for the first time, we want all systems that depend on the
|
||||
* PCB version to function correctly before flashing the PCB version. This
|
||||
* way, flashing the PCB version can be done last. */
|
||||
return PCB_LATEST;
|
||||
#else
|
||||
PCBVersion version = readPCBVersionInMemory();
|
||||
return (version == k_alternateBlankVersion ? 0 : version);
|
||||
#endif
|
||||
}
|
||||
|
||||
PCBVersion readPCBVersionInMemory() {
|
||||
return ~(*reinterpret_cast<const PCBVersion *>(InternalFlash::Config::OTPAddress(k_pcbVersionOTPIndex)));
|
||||
}
|
||||
|
||||
void writePCBVersion(PCBVersion version) {
|
||||
uint8_t * destination = reinterpret_cast<uint8_t *>(InternalFlash::Config::OTPAddress(k_pcbVersionOTPIndex));
|
||||
PCBVersion formattedVersion = ~version;
|
||||
InternalFlash::WriteMemory(destination, reinterpret_cast<uint8_t *>(&formattedVersion), sizeof(formattedVersion));
|
||||
}
|
||||
|
||||
void lockPCBVersion() {
|
||||
uint8_t * destination = reinterpret_cast<uint8_t *>(InternalFlash::Config::OTPLockAddress(k_pcbVersionOTPIndex));
|
||||
uint8_t zero = 0;
|
||||
InternalFlash::WriteMemory(destination, &zero, sizeof(zero));
|
||||
}
|
||||
|
||||
bool pcbVersionIsLocked() {
|
||||
return *reinterpret_cast<const uint8_t *>(InternalFlash::Config::OTPLockAddress(k_pcbVersionOTPIndex)) == 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,13 @@ constexpr static uint32_t SectorAddresses[NumberOfSectors+1] = {
|
||||
0x08010000
|
||||
};
|
||||
|
||||
constexpr static uint32_t OTPStartAddress = 0x1FF07800;
|
||||
constexpr static uint32_t OTPLocksAddress = 0x1FF07A00;
|
||||
constexpr static int NumberOfOTPBlocks = 16;
|
||||
constexpr static uint32_t OTPBlockSize = 0x20;
|
||||
constexpr uint32_t OTPAddress(int block) { return OTPStartAddress + block * OTPBlockSize; };
|
||||
constexpr uint32_t OTPLockAddress(int block) { return OTPLocksAddress + block; }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,14 @@ namespace Config {
|
||||
|
||||
using namespace Regs;
|
||||
|
||||
/* On the STM32F730, PA9 does not actually support alternate function 10.
|
||||
* However, because of the wiring of the USB connector on old N0110, detection
|
||||
* of when the device is plugged required the use of this undocumented setting.
|
||||
* After the revision of the USB connector and ESD protection, we can now
|
||||
* follow the specification and configure the Vbus pin as a floating-input GPIO.
|
||||
*/
|
||||
constexpr static AFGPIOPin VbusPin = AFGPIOPin(GPIOA, 9, GPIO::AFR::AlternateFunction::AF10, GPIO::PUPDR::Pull::None, GPIO::OSPEEDR::OutputSpeed::Fast);
|
||||
|
||||
constexpr static AFGPIOPin DmPin = AFGPIOPin(GPIOA, 11, GPIO::AFR::AlternateFunction::AF10, GPIO::PUPDR::Pull::None, GPIO::OSPEEDR::OutputSpeed::Fast);
|
||||
constexpr static AFGPIOPin DpPin = AFGPIOPin(GPIOA, 12, GPIO::AFR::AlternateFunction::AF10, GPIO::PUPDR::Pull::None, GPIO::OSPEEDR::OutputSpeed::Fast);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "external_flash.h"
|
||||
#include <drivers/external_flash.h>
|
||||
#include <drivers/cache.h>
|
||||
#include <drivers/config/external_flash.h>
|
||||
#include <drivers/config/clocks.h>
|
||||
#include <ion/timing.h>
|
||||
@@ -9,9 +10,9 @@ namespace ExternalFlash {
|
||||
|
||||
using namespace Regs;
|
||||
|
||||
/* The external flash and the Quad-SPI peripheral support
|
||||
* several operating modes, corresponding to different numbers of signals
|
||||
* used to communicate during each phase of the command sequence.
|
||||
/* The external flash and the Quad-SPI peripheral support several operating
|
||||
* modes, corresponding to different numbers of signals used to communicate
|
||||
* during each phase of the command sequence.
|
||||
*
|
||||
* Mode name for | Number of signals used during each phase:
|
||||
* external flash | Instruction | Address | Alt. bytes | Data
|
||||
@@ -23,8 +24,8 @@ using namespace Regs;
|
||||
* Quad-I/O SPI | 1 | 4 | 4 | 4
|
||||
* QPI | 4 | 4 | 4 | 4
|
||||
*
|
||||
* The external flash supports clock frequencies up to 104MHz for all instructions,
|
||||
* except for Read Data (0x03) which is supported up to 50Mhz.
|
||||
* The external flash supports clock frequencies up to 104MHz for all
|
||||
* instructions, except for Read Data (0x03) which is supported up to 50Mhz.
|
||||
*
|
||||
*
|
||||
* Quad-SPI block diagram
|
||||
@@ -37,47 +38,45 @@ using namespace Regs;
|
||||
* matrix --> | register --> FIFO | --> | |
|
||||
* +----------------------+ write +------------+
|
||||
*
|
||||
* Any data transmitted to or from the external flash memory go through a 32-byte FIFO.
|
||||
* Any data transmitted to or from the external flash memory go through a
|
||||
* 32-byte FIFO.
|
||||
*
|
||||
* Read or write operations are performed in burst mode, that is,
|
||||
* after any data byte is transmitted between the Quad-SPI and the flash memory,
|
||||
* the latter automatically increments the specified address and
|
||||
* the next byte to read or write is respectively pushed in or popped from the FIFO.
|
||||
* and so on, as long as the clock continues.
|
||||
* Read or write operations are performed in burst mode, that is, after any data
|
||||
* byte is transmitted between the Quad-SPI and the flash memory, the latter
|
||||
* automatically increments the specified address and the next byte to read or
|
||||
* write is respectively pushed in or popped from the FIFO.
|
||||
* And so on, as long as the clock continues.
|
||||
*
|
||||
* If the FIFO gets full in a read operation or
|
||||
* if the FIFO gets empty in a write operation,
|
||||
* the operation stalls and CLK stays low until firmware services the FIFO.
|
||||
*
|
||||
* If the FIFO gets full in a write operation,
|
||||
* the operation is stalled until the FIFO has enough space to accept the amount of data being written.
|
||||
* If the FIFO does not have as many bytes as requested by the read operation and if BUSY=1,
|
||||
* the operation is stalled until enough data is present or until the transfer is complete, whichever happens first. */
|
||||
* If the FIFO gets full in a write operation, the operation is stalled until
|
||||
* the FIFO has enough space to accept the amount of data being written.
|
||||
* If the FIFO does not have as many bytes as requested by the read operation
|
||||
* and if BUSY=1, the operation is stalled until enough data is present or until
|
||||
* the transfer is complete, whichever happens first. */
|
||||
|
||||
enum class Command : uint8_t {
|
||||
ReadStatusRegister1 = 0x05,
|
||||
ReadStatusRegister2 = 0x35,
|
||||
WriteStatusRegister = 0x01,
|
||||
WriteStatusRegister2 = 0x31,
|
||||
WriteEnable = 0x06,
|
||||
ReadData = 0x03,
|
||||
FastRead = 0x0B,
|
||||
FastReadQuadIO = 0xEB,
|
||||
// Program previously erased memory areas as being "0"
|
||||
PageProgram = 0x02,
|
||||
QuadPageProgram = 0x33,
|
||||
EnableQPI = 0x38,
|
||||
EnableReset = 0x66,
|
||||
Reset = 0x99,
|
||||
// Erase the whole chip or a 64-Kbyte block as being "1"
|
||||
ChipErase = 0xC7,
|
||||
Erase4KbyteBlock = 0x20,
|
||||
Erase32KbyteBlock = 0x52,
|
||||
Erase64KbyteBlock = 0xD8,
|
||||
SetReadParameters = 0xC0,
|
||||
DeepPowerDown = 0xB9,
|
||||
ReleaseDeepPowerDown = 0xAB,
|
||||
ReadJEDECID = 0x9F
|
||||
WriteStatusRegister = 0x01,
|
||||
PageProgram = 0x02, // Program previously erased memory areas as being "0"
|
||||
ReadData = 0x03,
|
||||
ReadStatusRegister1 = 0x05,
|
||||
WriteEnable = 0x06,
|
||||
Erase4KbyteBlock = 0x20,
|
||||
WriteStatusRegister2 = 0x31,
|
||||
QuadPageProgramW25Q64JV = 0x32,
|
||||
QuadPageProgramAT25F641 = 0x33,
|
||||
ReadStatusRegister2 = 0x35,
|
||||
Erase32KbyteBlock = 0x52,
|
||||
EnableReset = 0x66,
|
||||
Reset = 0x99,
|
||||
ReadJEDECID = 0x9F,
|
||||
ReleaseDeepPowerDown = 0xAB,
|
||||
DeepPowerDown = 0xB9,
|
||||
ChipErase = 0xC7, // Erase the whole chip or a 64-Kbyte block as being "1"
|
||||
Erase64KbyteBlock = 0xD8,
|
||||
FastReadQuadIO = 0xEB
|
||||
};
|
||||
|
||||
static constexpr uint8_t NumberOfAddressBitsIn64KbyteBlock = 16;
|
||||
@@ -98,53 +97,95 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
static constexpr QUADSPI::CCR::OperatingMode DefaultOperatingMode = QUADSPI::CCR::OperatingMode::Quad;
|
||||
static constexpr int ClockFrequencyDivisor = 2;
|
||||
static constexpr bool ajustNumberOfDummyCycles = Clocks::Config::AHBFrequency > (80 * ClockFrequencyDivisor);
|
||||
static constexpr int FastReadDummyCycles = (DefaultOperatingMode == QUADSPI::CCR::OperatingMode::Quad && ajustNumberOfDummyCycles) ? 4 : 2;
|
||||
class OperatingModes {
|
||||
public:
|
||||
constexpr OperatingModes(
|
||||
QUADSPI::CCR::OperatingMode instruction,
|
||||
QUADSPI::CCR::OperatingMode address,
|
||||
QUADSPI::CCR::OperatingMode data) :
|
||||
m_instructionOperatingMode(instruction),
|
||||
m_addressOperatingMode(address),
|
||||
m_dataOperatingMode(data)
|
||||
{}
|
||||
QUADSPI::CCR::OperatingMode instructionOperatingMode() const { return m_instructionOperatingMode; }
|
||||
QUADSPI::CCR::OperatingMode addressOperatingMode() const { return m_addressOperatingMode; }
|
||||
QUADSPI::CCR::OperatingMode dataOperatingMode() const { return m_dataOperatingMode; }
|
||||
private:
|
||||
QUADSPI::CCR::OperatingMode m_instructionOperatingMode;
|
||||
QUADSPI::CCR::OperatingMode m_addressOperatingMode;
|
||||
QUADSPI::CCR::OperatingMode m_dataOperatingMode;
|
||||
};
|
||||
|
||||
static void send_command_full(QUADSPI::CCR::FunctionalMode functionalMode, QUADSPI::CCR::OperatingMode operatingMode, Command c, uint8_t * address, uint32_t altBytes, size_t numberOfAltBytes, uint8_t dummyCycles, uint8_t * data, size_t dataLength);
|
||||
/* W25Q64JV does not implement QPI-4-4-4, so we always send the instructions on
|
||||
* one wire only.*/
|
||||
static constexpr OperatingModes sOperatingModes100(QUADSPI::CCR::OperatingMode::Single, QUADSPI::CCR::OperatingMode::NoData, QUADSPI::CCR::OperatingMode::NoData);
|
||||
static constexpr OperatingModes sOperatingModes101(QUADSPI::CCR::OperatingMode::Single, QUADSPI::CCR::OperatingMode::NoData, QUADSPI::CCR::OperatingMode::Single);
|
||||
static constexpr OperatingModes sOperatingModes110(QUADSPI::CCR::OperatingMode::Single, QUADSPI::CCR::OperatingMode::Single, QUADSPI::CCR::OperatingMode::NoData);
|
||||
static constexpr OperatingModes sOperatingModes111(QUADSPI::CCR::OperatingMode::Single, QUADSPI::CCR::OperatingMode::Single, QUADSPI::CCR::OperatingMode::Single);
|
||||
static constexpr OperatingModes sOperatingModes114(QUADSPI::CCR::OperatingMode::Single, QUADSPI::CCR::OperatingMode::Single, QUADSPI::CCR::OperatingMode::Quad);
|
||||
static constexpr OperatingModes sOperatingModes144(QUADSPI::CCR::OperatingMode::Single, QUADSPI::CCR::OperatingMode::Quad, QUADSPI::CCR::OperatingMode::Quad);
|
||||
|
||||
static inline void send_command(Command c, QUADSPI::CCR::OperatingMode operatingMode = DefaultOperatingMode) {
|
||||
static QUADSPI::CCR::OperatingMode sOperatingMode = QUADSPI::CCR::OperatingMode::Single;
|
||||
|
||||
static constexpr int ClockFrequencyDivisor = 2; // F(QUADSPI) = F(AHB) / ClockFrequencyDivisor
|
||||
static constexpr int FastReadQuadIODummyCycles = 4; // Must be 4 for W25Q64JV (Fig 24.A page 34) and for AT25F641 (table 7.19 page 28)
|
||||
/* According to datasheets, the CS signal should stay high (deselect the device)
|
||||
* for t_SHSL = 50ns at least.
|
||||
* -> Max of 30ns (see AT25F641 Sections 8.7 and 8.8),
|
||||
* 10ns and 50ns (see W25Q64JV Section 9.6). */
|
||||
static constexpr float ChipSelectHighTimeInNanoSeconds = 50.0f;
|
||||
|
||||
static void send_command_full(
|
||||
QUADSPI::CCR::FunctionalMode functionalMode,
|
||||
OperatingModes operatingModes,
|
||||
Command c,
|
||||
uint8_t * address,
|
||||
uint32_t altBytes,
|
||||
size_t numberOfAltBytes,
|
||||
uint8_t dummyCycles,
|
||||
uint8_t * data,
|
||||
size_t dataLength);
|
||||
|
||||
static inline void send_command(Command c) {
|
||||
send_command_full(
|
||||
QUADSPI::CCR::FunctionalMode::IndirectWrite,
|
||||
operatingMode,
|
||||
sOperatingModes100,
|
||||
c,
|
||||
reinterpret_cast<uint8_t *>(FlashAddressSpaceSize),
|
||||
0, 0,
|
||||
0,
|
||||
nullptr, 0
|
||||
);
|
||||
nullptr, 0);
|
||||
}
|
||||
|
||||
static inline void send_write_command(Command c, uint8_t * address, const uint8_t * data, size_t dataLength, QUADSPI::CCR::OperatingMode operatingMode = DefaultOperatingMode) {
|
||||
static inline void send_write_command(Command c, uint8_t * address, const uint8_t * data, size_t dataLength, OperatingModes operatingModes) {
|
||||
send_command_full(
|
||||
QUADSPI::CCR::FunctionalMode::IndirectWrite,
|
||||
operatingMode,
|
||||
operatingModes,
|
||||
c,
|
||||
address,
|
||||
0, 0,
|
||||
0,
|
||||
const_cast<uint8_t *>(data), dataLength
|
||||
);
|
||||
const_cast<uint8_t *>(data), dataLength);
|
||||
}
|
||||
|
||||
static inline void send_read_command(Command c, uint8_t * address, uint8_t * data, size_t dataLength, QUADSPI::CCR::OperatingMode operatingMode = DefaultOperatingMode) {
|
||||
static inline void send_read_command(Command c, uint8_t * address, uint8_t * data, size_t dataLength) {
|
||||
send_command_full(
|
||||
QUADSPI::CCR::FunctionalMode::IndirectRead,
|
||||
operatingMode,
|
||||
sOperatingModes101,
|
||||
c,
|
||||
address,
|
||||
0, 0,
|
||||
0,
|
||||
data, dataLength
|
||||
);
|
||||
data, dataLength);
|
||||
}
|
||||
|
||||
static inline void wait(QUADSPI::CCR::OperatingMode operatingMode = DefaultOperatingMode) {
|
||||
static inline void wait() {
|
||||
/* The DSB instruction guarantees the completion of a write operation before
|
||||
* polling the status register. */
|
||||
Cache::dsb();
|
||||
ExternalFlashStatusRegister::StatusRegister1 statusRegister1(0);
|
||||
do {
|
||||
send_read_command(Command::ReadStatusRegister1, reinterpret_cast<uint8_t *>(FlashAddressSpaceSize), reinterpret_cast<uint8_t *>(&statusRegister1), sizeof(statusRegister1), operatingMode);
|
||||
send_read_command(Command::ReadStatusRegister1, reinterpret_cast<uint8_t *>(FlashAddressSpaceSize), reinterpret_cast<uint8_t *>(&statusRegister1), sizeof(statusRegister1));
|
||||
} while (statusRegister1.getBUSY());
|
||||
}
|
||||
|
||||
@@ -160,11 +201,11 @@ static void set_as_memory_mapped() {
|
||||
* (Flash memories tend to consume more when nCS is held low.) */
|
||||
send_command_full(
|
||||
QUADSPI::CCR::FunctionalMode::MemoryMapped,
|
||||
DefaultOperatingMode,
|
||||
sOperatingModes144,
|
||||
Command::FastReadQuadIO,
|
||||
reinterpret_cast<uint8_t *>(FlashAddressSpaceSize),
|
||||
0xA0, 1,
|
||||
FastReadDummyCycles,
|
||||
FastReadQuadIODummyCycles,
|
||||
nullptr, 0
|
||||
);
|
||||
}
|
||||
@@ -174,16 +215,16 @@ static void unset_memory_mapped_mode() {
|
||||
uint8_t dummyData;
|
||||
send_command_full(
|
||||
QUADSPI::CCR::FunctionalMode::IndirectRead,
|
||||
DefaultOperatingMode,
|
||||
sOperatingModes144,
|
||||
Command::FastReadQuadIO,
|
||||
0,
|
||||
~(0xA0), 1,
|
||||
FastReadDummyCycles,
|
||||
FastReadQuadIODummyCycles,
|
||||
&dummyData, 1
|
||||
);
|
||||
}
|
||||
|
||||
static void send_command_full(QUADSPI::CCR::FunctionalMode functionalMode, QUADSPI::CCR::OperatingMode operatingMode, Command c, uint8_t * address, uint32_t altBytes, size_t numberOfAltBytes, uint8_t dummyCycles, uint8_t * data, size_t dataLength) {
|
||||
static void send_command_full(QUADSPI::CCR::FunctionalMode functionalMode, OperatingModes operatingModes, Command c, uint8_t * address, uint32_t altBytes, size_t numberOfAltBytes, uint8_t dummyCycles, uint8_t * data, size_t dataLength) {
|
||||
/* According to ST's Errata Sheet ES0360, "Wrong data can be read in
|
||||
* memory-mapped after an indirect mode operation". This is the workaround. */
|
||||
if (functionalMode == QUADSPI::CCR::FunctionalMode::MemoryMapped) {
|
||||
@@ -214,22 +255,22 @@ static void send_command_full(QUADSPI::CCR::FunctionalMode functionalMode, QUADS
|
||||
class QUADSPI::CCR ccr(0);
|
||||
ccr.setFMODE(functionalMode);
|
||||
if (data != nullptr || functionalMode == QUADSPI::CCR::FunctionalMode::MemoryMapped) {
|
||||
ccr.setDMODE(operatingMode);
|
||||
ccr.setDMODE(operatingModes.dataOperatingMode());
|
||||
}
|
||||
if (functionalMode != QUADSPI::CCR::FunctionalMode::MemoryMapped) {
|
||||
QUADSPI.DLR()->set((dataLength > 0) ? dataLength-1 : 0);
|
||||
}
|
||||
ccr.setDCYC(dummyCycles);
|
||||
if (numberOfAltBytes > 0) {
|
||||
ccr.setABMODE(operatingMode);
|
||||
ccr.setABMODE(operatingModes.addressOperatingMode()); // Seems to always be the same as address mode
|
||||
ccr.setABSIZE(static_cast<QUADSPI::CCR::Size>(numberOfAltBytes - 1));
|
||||
QUADSPI.ABR()->set(altBytes);
|
||||
}
|
||||
if (address != reinterpret_cast<uint8_t *>(FlashAddressSpaceSize) || functionalMode == QUADSPI::CCR::FunctionalMode::MemoryMapped) {
|
||||
ccr.setADMODE(operatingMode);
|
||||
ccr.setADMODE(operatingModes.addressOperatingMode());
|
||||
ccr.setADSIZE(QUADSPI::CCR::Size::ThreeBytes);
|
||||
}
|
||||
ccr.setIMODE(operatingMode);
|
||||
ccr.setIMODE(operatingModes.instructionOperatingMode());
|
||||
ccr.setINSTRUCTION(static_cast<uint8_t>(c));
|
||||
if (functionalMode == QUADSPI::CCR::FunctionalMode::MemoryMapped) {
|
||||
ccr.setSIOO(true);
|
||||
@@ -275,11 +316,8 @@ static void initQSPI() {
|
||||
// Configure controller for target device
|
||||
class QUADSPI::DCR dcr(0);
|
||||
dcr.setFSIZE(NumberOfAddressBitsInChip - 1);
|
||||
/* According to the device's datasheet (see Sections 8.7 and 8.8), the CS
|
||||
* signal should stay high (deselect the device) for t_SHSL = 30ns at least.
|
||||
* */
|
||||
constexpr int ChipSelectHighTime = (30 * Clocks::Config::AHBFrequency + ClockFrequencyDivisor * 1000 - 1) / (ClockFrequencyDivisor * 1000);
|
||||
dcr.setCSHT(ChipSelectHighTime - 1);
|
||||
constexpr int ChipSelectHighTimeCycles = (ChipSelectHighTimeInNanoSeconds * static_cast<float>(Clocks::Config::AHBFrequency)) / (static_cast<float>(ClockFrequencyDivisor) * 1000.0f) + 1.0f;
|
||||
dcr.setCSHT(ChipSelectHighTimeCycles - 1);
|
||||
dcr.setCKMODE(true);
|
||||
QUADSPI.DCR()->set(dcr);
|
||||
class QUADSPI::CR cr(0);
|
||||
@@ -288,36 +326,20 @@ static void initQSPI() {
|
||||
QUADSPI.CR()->set(cr);
|
||||
}
|
||||
|
||||
static QUADSPI::CCR::OperatingMode sOperatingMode = QUADSPI::CCR::OperatingMode::Single;
|
||||
|
||||
static void initChip() {
|
||||
// Release sleep deep
|
||||
send_command(Command::ReleaseDeepPowerDown, sOperatingMode);
|
||||
send_command(Command::ReleaseDeepPowerDown);
|
||||
Timing::usleep(3);
|
||||
|
||||
/* The chip initially expects commands in SPI mode. We need to use SPI to tell
|
||||
* it to switch to QPI. */
|
||||
if (sOperatingMode == QUADSPI::CCR::OperatingMode::Single && DefaultOperatingMode == QUADSPI::CCR::OperatingMode::Quad) {
|
||||
send_command(Command::WriteEnable, QUADSPI::CCR::OperatingMode::Single);
|
||||
* it to switch to QuadSPI/QPI. */
|
||||
if (sOperatingMode == QUADSPI::CCR::OperatingMode::Single) {
|
||||
send_command(Command::WriteEnable);
|
||||
ExternalFlashStatusRegister::StatusRegister2 statusRegister2(0);
|
||||
statusRegister2.setQE(true);
|
||||
wait(QUADSPI::CCR::OperatingMode::Single);
|
||||
send_write_command(Command::WriteStatusRegister2, reinterpret_cast<uint8_t *>(FlashAddressSpaceSize), reinterpret_cast<uint8_t *>(&statusRegister2), sizeof(statusRegister2), QUADSPI::CCR::OperatingMode::Single);
|
||||
wait(QUADSPI::CCR::OperatingMode::Single);
|
||||
send_command(Command::EnableQPI, QUADSPI::CCR::OperatingMode::Single);
|
||||
wait();
|
||||
if (ajustNumberOfDummyCycles) {
|
||||
class ReadParameters : Register8 {
|
||||
public:
|
||||
/* Parameters sent along with SetReadParameters instruction in order
|
||||
* to configure the number of dummy cycles for the QPI Read instructions. */
|
||||
using Register8::Register8;
|
||||
REGS_BOOL_FIELD_W(P5, 5);
|
||||
};
|
||||
ReadParameters readParameters(0);
|
||||
readParameters.setP5(true);
|
||||
send_write_command(Command::SetReadParameters, reinterpret_cast<uint8_t *>(FlashAddressSpaceSize), reinterpret_cast<uint8_t *>(&readParameters), sizeof(readParameters));
|
||||
}
|
||||
send_write_command(Command::WriteStatusRegister2, reinterpret_cast<uint8_t *>(FlashAddressSpaceSize), reinterpret_cast<uint8_t *>(&statusRegister2), sizeof(statusRegister2), sOperatingModes101);
|
||||
wait();
|
||||
sOperatingMode = QUADSPI::CCR::OperatingMode::Quad;
|
||||
}
|
||||
set_as_memory_mapped();
|
||||
@@ -346,10 +368,10 @@ static void shutdownChip() {
|
||||
send_command(Command::EnableReset);
|
||||
send_command(Command::Reset);
|
||||
sOperatingMode = QUADSPI::CCR::OperatingMode::Single;
|
||||
Ion::Timing::usleep(30);
|
||||
Timing::usleep(30);
|
||||
|
||||
// Sleep deep
|
||||
send_command(Command::DeepPowerDown, sOperatingMode);
|
||||
send_command(Command::DeepPowerDown);
|
||||
Timing::usleep(3);
|
||||
}
|
||||
|
||||
@@ -402,7 +424,7 @@ void unlockFlash() {
|
||||
statusRegister2.setQE(currentStatusRegister2.getQE());
|
||||
|
||||
uint8_t registers[] = {statusRegister1.get(), statusRegister2.get()};
|
||||
send_write_command(Command::WriteStatusRegister, reinterpret_cast<uint8_t *>(FlashAddressSpaceSize), reinterpret_cast<uint8_t *>(registers), sizeof(registers));
|
||||
send_write_command(Command::WriteStatusRegister, reinterpret_cast<uint8_t *>(FlashAddressSpaceSize), reinterpret_cast<uint8_t *>(registers), sizeof(registers), sOperatingModes101);
|
||||
wait();
|
||||
}
|
||||
|
||||
@@ -428,18 +450,18 @@ void __attribute__((noinline)) EraseSector(int i) {
|
||||
/* WARNING: this code assumes that the flash sectors are of increasing size:
|
||||
* first all 4K sectors, then all 32K sectors, and finally all 64K sectors. */
|
||||
if (i < Config::NumberOf4KSectors) {
|
||||
send_write_command(Command::Erase4KbyteBlock, reinterpret_cast<uint8_t *>(i << NumberOfAddressBitsIn4KbyteBlock), nullptr, 0);
|
||||
send_write_command(Command::Erase4KbyteBlock, reinterpret_cast<uint8_t *>(i << NumberOfAddressBitsIn4KbyteBlock), nullptr, 0, sOperatingModes110);
|
||||
} else if (i < Config::NumberOf4KSectors + Config::NumberOf32KSectors) {
|
||||
/* If the sector is the number Config::NumberOf4KSectors, we want to write
|
||||
* at the address 1 << NumberOfAddressBitsIn32KbyteBlock, hence the formula
|
||||
* (i - Config::NumberOf4KSectors + 1). */
|
||||
send_write_command(Command::Erase32KbyteBlock, reinterpret_cast<uint8_t *>((i - Config::NumberOf4KSectors + 1) << NumberOfAddressBitsIn32KbyteBlock), nullptr, 0);
|
||||
send_write_command(Command::Erase32KbyteBlock, reinterpret_cast<uint8_t *>((i - Config::NumberOf4KSectors + 1) << NumberOfAddressBitsIn32KbyteBlock), nullptr, 0, sOperatingModes110);
|
||||
} else {
|
||||
/* If the sector is the number
|
||||
* Config::NumberOf4KSectors - Config::NumberOf32KSectors, we want to write
|
||||
* at the address 1 << NumberOfAddressBitsIn32KbyteBlock, hence the formula
|
||||
* (i - Config::NumberOf4KSectors - Config::NumberOf32KSectors + 1). */
|
||||
send_write_command(Command::Erase64KbyteBlock, reinterpret_cast<uint8_t *>((i - Config::NumberOf4KSectors - Config::NumberOf32KSectors + 1) << NumberOfAddressBitsIn64KbyteBlock), nullptr, 0);
|
||||
send_write_command(Command::Erase64KbyteBlock, reinterpret_cast<uint8_t *>((i - Config::NumberOf4KSectors - Config::NumberOf32KSectors + 1) << NumberOfAddressBitsIn64KbyteBlock), nullptr, 0, sOperatingModes110);
|
||||
}
|
||||
wait();
|
||||
set_as_memory_mapped();
|
||||
@@ -455,7 +477,6 @@ void __attribute__((noinline)) WriteMemory(uint8_t * destination, const uint8_t
|
||||
* However, when the end of a page is reached, the addressing wraps to the beginning.
|
||||
* Hence a Page Program instruction must be issued for each page. */
|
||||
static constexpr size_t PageSize = 256;
|
||||
constexpr Command pageProgram = (DefaultOperatingMode == QUADSPI::CCR::OperatingMode::Single) ? Command::PageProgram : Command::QuadPageProgram;
|
||||
uint8_t offset = reinterpret_cast<uint32_t>(destination) & (PageSize - 1);
|
||||
size_t lengthThatFitsInPage = PageSize - offset;
|
||||
while (length > 0) {
|
||||
@@ -464,7 +485,12 @@ void __attribute__((noinline)) WriteMemory(uint8_t * destination, const uint8_t
|
||||
}
|
||||
send_command(Command::WriteEnable);
|
||||
wait();
|
||||
send_write_command(pageProgram, destination, source, lengthThatFitsInPage);
|
||||
|
||||
/* Some chips implement 0x32 only, others 0x33 only, we call both. This does
|
||||
* not seem to affect the writing. */
|
||||
send_write_command(Command::QuadPageProgramAT25F641, destination, source, lengthThatFitsInPage, sOperatingModes144);
|
||||
send_write_command(Command::QuadPageProgramW25Q64JV, destination, source, lengthThatFitsInPage, sOperatingModes114);
|
||||
|
||||
length -= lengthThatFitsInPage;
|
||||
destination += lengthThatFitsInPage;
|
||||
source += lengthThatFitsInPage;
|
||||
27
ion/src/device/n0110/drivers/usb.cpp
Normal file
27
ion/src/device/n0110/drivers/usb.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <drivers/usb.h>
|
||||
#include <drivers/board.h>
|
||||
#include <drivers/config/usb.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
|
||||
using namespace Regs;
|
||||
|
||||
namespace USB {
|
||||
|
||||
bool useAlternateFunctionVbus() {
|
||||
return Board::pcbVersion() == 0;
|
||||
}
|
||||
|
||||
void initVbus() {
|
||||
if (useAlternateFunctionVbus()) {
|
||||
Config::VbusPin.init();
|
||||
} else {
|
||||
Config::VbusPin.group().MODER()->setMode(Config::VbusPin.pin(), GPIO::MODER::Mode::Input);
|
||||
Config::VbusPin.group().PUPDR()->setPull(Config::VbusPin.pin(), GPIO::PUPDR::Pull::None);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,16 +5,18 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \
|
||||
board.cpp \
|
||||
clipboard.cpp \
|
||||
console_uart.cpp:+consoleuart \
|
||||
console_display.cpp:+consoledisplay \
|
||||
console_dummy.cpp:-consoledisplay \
|
||||
console_dummy.cpp:-consoleuart \
|
||||
crc32.cpp \
|
||||
display.cpp \
|
||||
events_keyboard_platform.cpp \
|
||||
exam_mode.cpp \
|
||||
external_flash.cpp \
|
||||
flash.cpp \
|
||||
internal_flash.cpp \
|
||||
keyboard.cpp \
|
||||
led.cpp \
|
||||
pcb_version.cpp \
|
||||
power.cpp\
|
||||
random.cpp\
|
||||
reset.cpp \
|
||||
|
||||
@@ -30,7 +30,7 @@ Charge level() {
|
||||
|
||||
constexpr static int numberOfChargeStates = 4;
|
||||
constexpr static int numberOfThresholds = numberOfChargeStates - 1;
|
||||
constexpr float hysteresis = 0.02f;
|
||||
constexpr float hysteresis = 0.04f;
|
||||
const float thresholds[numberOfThresholds] = {3.6f + hysteresis, 3.7f, 3.8f}; // We do not want to lower the threshold for empty battery, so we add the hysteresis to it
|
||||
int nextLevel = -1;
|
||||
for (int i = 0; i < numberOfThresholds; i++) {
|
||||
|
||||
@@ -94,3 +94,26 @@ void setClockFrequency(Frequency f) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ion {
|
||||
namespace Board {
|
||||
|
||||
using namespace Device::Board;
|
||||
|
||||
void lockUnlockedPCBVersion() {
|
||||
if (pcbVersionIsLocked()) {
|
||||
return;
|
||||
}
|
||||
/* PCB version is unlocked : the device is a N0110 that has been
|
||||
* produced prior to the pcb revision 3.43. */
|
||||
PCBVersion version = pcbVersion();
|
||||
if (version != 0) {
|
||||
/* Some garbage has been written in OTP0. We overwrite it fully, which is
|
||||
* interepreted as blank. */
|
||||
writePCBVersion(k_alternateBlankVersion);
|
||||
}
|
||||
lockPCBVersion();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef ION_DEVICE_SHARED_DRIVERS_BOARD_H
|
||||
#define ION_DEVICE_SHARED_DRIVERS_BOARD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Board {
|
||||
@@ -23,6 +25,20 @@ Frequency standardFrequency();
|
||||
void setStandardFrequency(Frequency f);
|
||||
void setClockFrequency(Frequency f);
|
||||
|
||||
typedef uint32_t PCBVersion;
|
||||
/* On N0110 released before the PCB revision, OTP0 is supposed to be blank and
|
||||
* unlocked. However, such a device with something written in OTP0 will be
|
||||
* unable to configure Vbus properly. In this case, and if OTP0 is still
|
||||
* unlocked, we fully write OTP0 and treat it the same as fully blank.
|
||||
* This way, pcbVersion will be 0 if OTP0 is either 0x00000000 or 0xFFFFFFFF.*/
|
||||
constexpr PCBVersion k_alternateBlankVersion = 0xFFFFFFFF;
|
||||
|
||||
PCBVersion pcbVersion();
|
||||
PCBVersion readPCBVersionInMemory();
|
||||
void writePCBVersion(PCBVersion version);
|
||||
void lockPCBVersion();
|
||||
bool pcbVersionIsLocked();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
39
ion/src/device/shared/drivers/console_display.cpp
Normal file
39
ion/src/device/shared/drivers/console_display.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "console.h"
|
||||
#include <ion/console.h>
|
||||
#include <kandinsky/ion_context.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Console {
|
||||
|
||||
char readChar() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void writeChar(char c) {
|
||||
KDIonContext::putchar(c);
|
||||
}
|
||||
|
||||
bool transmissionDone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Console {
|
||||
|
||||
void init() {
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
}
|
||||
|
||||
bool peerConnected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,22 @@
|
||||
#include "console.h"
|
||||
#include <ion/console.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Console {
|
||||
|
||||
char readChar() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void writeChar(char c) {
|
||||
}
|
||||
|
||||
bool transmissionDone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
|
||||
25
ion/src/device/shared/drivers/pcb_version.cpp
Normal file
25
ion/src/device/shared/drivers/pcb_version.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <ion.h>
|
||||
#include "board.h"
|
||||
|
||||
namespace Ion {
|
||||
|
||||
const char * pcbVersion() {
|
||||
constexpr int pcbVersionLength = 5; // xx.yy
|
||||
static char pcbVer[pcbVersionLength] = {'\0'};
|
||||
if (pcbVer[0] == '\0') {
|
||||
Device::Board::PCBVersion ver = Device::Board::pcbVersion();
|
||||
/* As PCB version only uses 4 chars, value should be at most 9999. */
|
||||
assert(ver < 10000);
|
||||
for (int i = pcbVersionLength - 1; i >= 0; i--) {
|
||||
if (i == 2) {
|
||||
pcbVer[i] = '.';
|
||||
} else {
|
||||
pcbVer[i] = '0' + ver % 10;
|
||||
ver /= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pcbVer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "serial_number.h"
|
||||
#include "board.h"
|
||||
#include <drivers/config/serial_number.h>
|
||||
#include "base64.h"
|
||||
|
||||
|
||||
@@ -65,22 +65,17 @@ void initGPIO() {
|
||||
GPIOC.MODER()->setMode(11, GPIO::MODER::Mode::Output);
|
||||
GPIOC.ODR()->set(11, false);
|
||||
|
||||
/* Configure the GPIO
|
||||
* The VBUS pin is connected to the USB VBUS port. To read if the USB is
|
||||
* plugged, the pin must be pulled down. */
|
||||
// FIXME: Understand how the Vbus pin really works!
|
||||
#if 0
|
||||
Config::VbusPin.group().MODER()->setMode(Config::VbusPin.pin(), GPIO::MODER::Mode::Input);
|
||||
Config::VbusPin.group().PUPDR()->setPull(Config::VbusPin.pin(), GPIO::PUPDR::Pull::Down);
|
||||
#else
|
||||
Config::VbusPin.init();
|
||||
#endif
|
||||
/* Configure the GPIO */
|
||||
/* The Vbus pin is connected to the USB Vbus port. Depending on the
|
||||
* hardware, it should either be configured as an AlternateFunction, or as a
|
||||
* floating Input. */
|
||||
initVbus();
|
||||
Config::DmPin.init();
|
||||
Config::DpPin.init();
|
||||
}
|
||||
|
||||
void shutdownGPIO() {
|
||||
constexpr static AFGPIOPin Pins[] = {Config::DpPin, Config::DmPin, Config::VbusPin};
|
||||
constexpr static AFGPIOPin Pins[] = { Config::DpPin, Config::DmPin, Config::VbusPin };
|
||||
for (const AFGPIOPin & p : Pins) {
|
||||
p.shutdown();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user