diff --git a/apps/code/editor_controller.cpp b/apps/code/editor_controller.cpp index aba355959..c799d8ff8 100644 --- a/apps/code/editor_controller.cpp +++ b/apps/code/editor_controller.cpp @@ -18,6 +18,22 @@ EditorController::EditorController(MenuController * menuController, App * python m_editorView.setTextAreaDelegates(this, this); } +#ifdef MAX_SCRIPTSIZE +void EditorController::setScript(Script script) { + m_script = script; + Script::Data scriptData = m_script.value(); + size_t s=scriptData.size,ms=sizeof(m_areaBuffer); + if (s>ms) + s=ms; + size_t availableScriptSize = s + Ion::Storage::sharedStorage()->availableSize(); + if (availableScriptSize>ms) + availableScriptSize=ms; + // assert(sizeof(m_areaBuffer) >= availableScriptSize); + // We cannot use strlcpy as the first char reprensenting the importation status can be 0. + memcpy(m_areaBuffer, (const char *)scriptData.buffer, s); + m_editorView.setText(m_areaBuffer+1, availableScriptSize-1); // 1 char is taken by the importation status flag +} +#else void EditorController::setScript(Script script) { m_script = script; Script::Data scriptData = m_script.value(); @@ -27,7 +43,7 @@ void EditorController::setScript(Script script) { memcpy(m_areaBuffer, (const char *)scriptData.buffer, scriptData.size); m_editorView.setText(m_areaBuffer+1, availableScriptSize-1); // 1 char is taken by the importation status flag } - +#endif // TODO: this should be done in textAreaDidFinishEditing maybe?? bool EditorController::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK || event == Ion::Events::Back || event == Ion::Events::Home) { diff --git a/apps/code/editor_controller.h b/apps/code/editor_controller.h index 284bf1af3..d5b948d4e 100644 --- a/apps/code/editor_controller.h +++ b/apps/code/editor_controller.h @@ -1,6 +1,8 @@ #ifndef CODE_EDITOR_CONTROLLER_H #define CODE_EDITOR_CONTROLLER_H +#define MAX_SCRIPTSIZE 12288 + #include #include "script.h" #include "editor_view.h" @@ -39,7 +41,7 @@ private: /* m_areaBuffer first character is dedicated to the importation status. * Thereby, we avoid wasteful copy while adding the Script to the storage * (in order to add the importation status char before the areaBuffer). */ - char m_areaBuffer[Ion::Storage::k_storageSize]; // this could be slightly optimize + char m_areaBuffer[Ion::Storage::k_storageSize>MAX_SCRIPTSIZE?MAX_SCRIPTSIZE:Ion::Storage::k_storageSize]; // this could be slightly optimize Script m_script; MenuController * m_menuController; }; diff --git a/apps/external/Makefile b/apps/external/Makefile new file mode 100644 index 000000000..b767dad8d --- /dev/null +++ b/apps/external/Makefile @@ -0,0 +1,30 @@ +apps += External::App +app_headers += apps/external/app.h + +app_external_src = $(addprefix apps/external/,\ + app.cpp \ + extapp_api.cpp \ + archive.cpp \ + main_controller.cpp \ + pointer_text_table_cell.cpp \ +) + +SFLAGS += -Iapps/external/ + +ifeq ($(PLATFORM),device) + SFLAGS += -DDEVICE +else + include apps/external/app/sources.mak +endif + +app_src += $(app_external_src) + +i18n_files += $(addprefix apps/external/,\ + base.de.i18n\ + base.en.i18n\ + base.es.i18n\ + base.fr.i18n\ + base.pt.i18n\ +) + +$(eval $(call depends_on_image,apps/external/app.cpp,apps/external/external_icon.png)) diff --git a/apps/external/app.cpp b/apps/external/app.cpp new file mode 100644 index 000000000..ac0f6141c --- /dev/null +++ b/apps/external/app.cpp @@ -0,0 +1,44 @@ +#include "app.h" +#include "external_icon.h" +#include + +namespace External { + +I18n::Message App::Descriptor::name() { + return I18n::Message::ExternalApp; +} + +I18n::Message App::Descriptor::upperName() { + return I18n::Message::ExternalAppCapital; +} + +const Image * App::Descriptor::icon() { + return ImageStore::ExternalIcon; +} + +App * App::Snapshot::unpack(Container * container) { + return new (container->currentAppBuffer()) App(this); +} + +App::Descriptor * App::Snapshot::descriptor() { + static Descriptor descriptor; + return &descriptor; +} + +void App::didBecomeActive(Window * window) { + ::App::didBecomeActive(window); + m_window = window; +} + +void App::redraw() { + m_window->redraw(true); +} + +App::App(Snapshot * snapshot) : + ::App(snapshot, &m_stackViewController), + m_mainController(&m_stackViewController, this), + m_stackViewController(&m_modalViewController, &m_mainController) +{ +} + +} diff --git a/apps/external/app.h b/apps/external/app.h new file mode 100644 index 000000000..e1dd47043 --- /dev/null +++ b/apps/external/app.h @@ -0,0 +1,37 @@ +#ifndef EXTERNAL_APP_H +#define EXTERNAL_APP_H + +#include +#include "main_controller.h" + +namespace External { + +class App : public ::App { +public: + class Descriptor : public ::App::Descriptor { + public: + I18n::Message name() override; + I18n::Message upperName() override; + const Image * icon() override; + }; + class Snapshot : public ::App::Snapshot { + public: + App * unpack(Container * container) override; + Descriptor * descriptor() override; + }; + void redraw(); + virtual void didBecomeActive(Window * window); + int heapSize() { return k_externalHeapSize; } + char * heap() { return m_externalHeap; } +private: + App(Snapshot * snapshot); + MainController m_mainController; + StackViewController m_stackViewController; + Window * m_window; + static constexpr int k_externalHeapSize = 131072; + char m_externalHeap[k_externalHeapSize]; +}; + +} + +#endif diff --git a/apps/external/app/sample.c b/apps/external/app/sample.c new file mode 100644 index 000000000..dbc13fd95 --- /dev/null +++ b/apps/external/app/sample.c @@ -0,0 +1,6 @@ +#include + +void extapp_main() { + extapp_pushRectUniform(10, 10, LCD_WIDTH-20, LCD_HEIGHT-20, 0); + extapp_msleep(1000); +} diff --git a/apps/external/app/sources.mak b/apps/external/app/sources.mak new file mode 100644 index 000000000..3f285e23a --- /dev/null +++ b/apps/external/app/sources.mak @@ -0,0 +1,3 @@ +app_external_src += $(addprefix apps/external/app/,\ + sample.c \ +) \ No newline at end of file diff --git a/apps/external/archive.cpp b/apps/external/archive.cpp new file mode 100644 index 000000000..aaa89373a --- /dev/null +++ b/apps/external/archive.cpp @@ -0,0 +1,141 @@ +#include "archive.h" +#include "extapp_api.h" + +#include +#include + +namespace External { +namespace Archive { + +#ifdef DEVICE + +struct TarHeader +{ /* byte offset */ + char name[100]; /* 0 */ + char mode[8]; /* 100 */ + char uid[8]; /* 108 */ + char gid[8]; /* 116 */ + char size[12]; /* 124 */ + char mtime[12]; /* 136 */ + char chksum[8]; /* 148 */ + char typeflag; /* 156 */ + char linkname[100]; /* 157 */ + char magic[8]; /* 257 */ + char uname[32]; /* 265 */ + char gname[32]; /* 297 */ + char devmajor[8]; /* 329 */ + char devminor[8]; /* 337 */ + char padding[167]; /* 345 */ +} __attribute__((packed)); + +static_assert(sizeof(TarHeader) == 512); + +bool isSane(const TarHeader* tar) { + return !memcmp(tar->magic, "ustar ", 8) && tar->name[0] != '\x00' && tar->name[0] != '\xFF'; +} + +bool fileAtIndex(size_t index, File &entry) { + const TarHeader* tar = reinterpret_cast(0x90200000); + unsigned size = 0; + + // Sanity check. + if (!isSane(tar)) { + return false; + } + + /** + * TAR files are comprised of a set of records aligned to 512 bytes boundary + * followed by data. + */ + while (index-- > 0) { + size = 0; + for (int i = 0; i < 11; i++) + size = size * 8 + (tar->size[i] - '0'); + + // Move to the next TAR header. + unsigned stride = (sizeof(TarHeader) + size + 511); + stride = (stride >> 9) << 9; + tar = reinterpret_cast(reinterpret_cast(tar) + stride); + + // Sanity check. + if (!isSane(tar)) { + return false; + } + } + + // File entry found, copy data out. + entry.name = tar->name; + entry.data = reinterpret_cast(tar) + sizeof(TarHeader); + entry.dataLength = size; + entry.isExecutable = (tar->mode[4] & 0x01) == 1; + + return true; +} + +extern "C" void (* const apiPointers[])(void); +typedef uint32_t (*entrypoint)(const uint32_t, const void *, void *, const uint32_t); + +uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize) { + File entry; + if(fileAtIndex(indexFromName(name), entry)) { + if(!entry.isExecutable) { + return 0; + } + uint32_t ep = *reinterpret_cast(entry.data); + if(ep >= 0x90200000 && ep < 0x90800000) { + return ((entrypoint)ep)(API_VERSION, apiPointers, heap, heapSize); + } + } + return -1; +} + +int indexFromName(const char *name) { + File entry; + + for (int i = 0; fileAtIndex(i, entry); i++) { + if (strcmp(name, entry.name) == 0) { + return i; + } + } + + return -1; +} + +size_t numberOfFiles() { + File dummy; + size_t count; + + for (count = 0; fileAtIndex(count, dummy); count++); + + return count; +} + +#else + +bool fileAtIndex(size_t index, File &entry) { + entry.name = "App"; + entry.data = NULL; + entry.dataLength = 0; + entry.isExecutable = true; + return true; +} + +extern "C" void extapp_main(void); + +uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize) { + extapp_main(); + return 0; +} + +int indexFromName(const char *name) { + return 0; +} + +size_t numberOfFiles() { + return 1; +} + +#endif + +} +} diff --git a/apps/external/archive.h b/apps/external/archive.h new file mode 100644 index 000000000..80b71d0e1 --- /dev/null +++ b/apps/external/archive.h @@ -0,0 +1,27 @@ +#ifndef EXTERNAL_ARCHIVE_H +#define EXTERNAL_ARCHIVE_H + +#include +#include + +namespace External { +namespace Archive { + +constexpr int MaxNameLength = 40; + +struct File { + const char *name; + const uint8_t *data; + size_t dataLength; + bool isExecutable; +}; + +bool fileAtIndex(size_t index, File &entry); +int indexFromName(const char *name); +size_t numberOfFiles(); +uint32_t executeFile(const char *name, void * heap, const uint32_t heapSize); + +} +} + +#endif diff --git a/apps/external/base.de.i18n b/apps/external/base.de.i18n new file mode 100644 index 000000000..6072a563a --- /dev/null +++ b/apps/external/base.de.i18n @@ -0,0 +1,4 @@ +ExternalApp = "External" +ExternalAppCapital = "EXTERNAL" +ExternalAppApiMismatch = "API mismatch" +ExternalAppExecError = "Cannot execute file" diff --git a/apps/external/base.en.i18n b/apps/external/base.en.i18n new file mode 100644 index 000000000..6072a563a --- /dev/null +++ b/apps/external/base.en.i18n @@ -0,0 +1,4 @@ +ExternalApp = "External" +ExternalAppCapital = "EXTERNAL" +ExternalAppApiMismatch = "API mismatch" +ExternalAppExecError = "Cannot execute file" diff --git a/apps/external/base.es.i18n b/apps/external/base.es.i18n new file mode 100644 index 000000000..6072a563a --- /dev/null +++ b/apps/external/base.es.i18n @@ -0,0 +1,4 @@ +ExternalApp = "External" +ExternalAppCapital = "EXTERNAL" +ExternalAppApiMismatch = "API mismatch" +ExternalAppExecError = "Cannot execute file" diff --git a/apps/external/base.fr.i18n b/apps/external/base.fr.i18n new file mode 100644 index 000000000..6072a563a --- /dev/null +++ b/apps/external/base.fr.i18n @@ -0,0 +1,4 @@ +ExternalApp = "External" +ExternalAppCapital = "EXTERNAL" +ExternalAppApiMismatch = "API mismatch" +ExternalAppExecError = "Cannot execute file" diff --git a/apps/external/base.pt.i18n b/apps/external/base.pt.i18n new file mode 100644 index 000000000..6072a563a --- /dev/null +++ b/apps/external/base.pt.i18n @@ -0,0 +1,4 @@ +ExternalApp = "External" +ExternalAppCapital = "EXTERNAL" +ExternalAppApiMismatch = "API mismatch" +ExternalAppExecError = "Cannot execute file" diff --git a/apps/external/extapp_api.cpp b/apps/external/extapp_api.cpp new file mode 100644 index 000000000..03cbef00a --- /dev/null +++ b/apps/external/extapp_api.cpp @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include +#include "extapp_api.h" + +#include + +extern "C" { + #include +} + +uint64_t extapp_millis() { + return Ion::Timing::millis(); +} + +void extapp_msleep(uint32_t ms) { + Ion::Timing::msleep(ms); +} + +uint64_t extapp_scanKeyboard() { + return Ion::Keyboard::scan(); +} + +void extapp_pushRect(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t * pixels) { + KDRect rect(x, y, w, h); + + Ion::Display::pushRect(rect, reinterpret_cast(pixels)); +} + +void extapp_pushRectUniform(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color) { + KDRect rect(x, y, w, h); + + Ion::Display::pushRectUniform(rect, KDColor::RGB16(color)); +} + +int16_t extapp_drawTextLarge(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg) { + KDPoint point(x, y); + + auto ctx = KDIonContext::sharedContext(); + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,0)); + ctx->drawString(text, point, KDFont::LargeFont, KDColor::RGB16(fg), KDColor::RGB16(bg)); + + return point.x(); +} + +int16_t extapp_drawTextSmall(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg) { + KDPoint point(x, y); + + auto ctx = KDIonContext::sharedContext(); + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,0)); + ctx->drawString(text, point, KDFont::SmallFont, KDColor::RGB16(fg), KDColor::RGB16(bg)); + + return point.x(); +} + +void extapp_waitForVBlank() { + Ion::Display::waitForVBlank(); +} + +void extapp_clipboardStore(const char *text) { + Clipboard::sharedClipboard()->store(text); +} + +const char * extapp_clipboardText() { + return Clipboard::sharedClipboard()->storedText(); +} + +extern "C" void (* const apiPointers[])(void) = { + (void (*)(void)) extapp_millis, + (void (*)(void)) extapp_msleep, + (void (*)(void)) extapp_scanKeyboard, + (void (*)(void)) extapp_pushRect, + (void (*)(void)) extapp_pushRectUniform, + (void (*)(void)) extapp_drawTextLarge, + (void (*)(void)) extapp_drawTextSmall, + (void (*)(void)) extapp_waitForVBlank, + (void (*)(void)) extapp_clipboardStore, + (void (*)(void)) extapp_clipboardText, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + + // khicas from here, subject to change + (void (*)(void)) numworks_draw_string, + (void (*)(void)) numworks_draw_string_small, + (void (*)(void)) numworks_set_pixel, + (void (*)(void)) numworks_fill_rect, + (void (*)(void)) numworks_get_pixel, + (void (*)(void)) numworks_hide_graph, + (void (*)(void)) numworks_wait_1ms, + (void (*)(void)) waitforvblank, + (void (*)(void)) statuslinemsg, + (void (*)(void)) statusline, + (void (*)(void)) getkey, + (void (*)(void)) GetKey, + (void (*)(void)) alphawasactive, + (void (*)(void)) lock_alpha, + (void (*)(void)) reset_kbd, + (void (*)(void)) back_key_pressed, + (void (*)(void)) enable_back_interrupt, + (void (*)(void)) disable_back_interrupt, + (void (*)(void)) os_set_angle_unit, + (void (*)(void)) os_get_angle_unit, + (void (*)(void)) os_file_browser, + (void (*)(void)) file_exists, + (void (*)(void)) erase_file, + (void (*)(void)) read_file, + (void (*)(void)) write_file, + (void (*)(void)) mp_hal_input, + (void (*)(void)) nullptr +}; diff --git a/apps/external/extapp_api.h b/apps/external/extapp_api.h new file mode 100644 index 000000000..12ae53ba6 --- /dev/null +++ b/apps/external/extapp_api.h @@ -0,0 +1,76 @@ +#ifndef EXTERNAL_API_H +#define EXTERNAL_API_H + +#include + +#define API_VERSION 1 + +#ifdef __cplusplus +#define EXTERNC extern "C" +#else +#define EXTERNC +#endif + +#define LCD_WIDTH 320 +#define LCD_HEIGHT 240 + +#define KEY_Left ((uint64_t)1 << 0) +#define KEY_Up ((uint64_t)1 << 1) +#define KEY_Down ((uint64_t)1 << 2) +#define KEY_Right ((uint64_t)1 << 3) +#define KEY_OK ((uint64_t)1 << 4) +#define KEY_Back ((uint64_t)1 << 5) +#define KEY_Home ((uint64_t)1 << 6) +#define KEY_OnOff (((uint64_t)1 << 7) || ((uint64_t)1 << 8)) +#define KEY_Shift ((uint64_t)1 << 12) +#define KEY_Alpha ((uint64_t)1 << 13) +#define KEY_XNT ((uint64_t)1 << 14) +#define KEY_Var ((uint64_t)1 << 15) +#define KEY_Toolbox ((uint64_t)1 << 16) +#define KEY_Backspace ((uint64_t)1 << 17) +#define KEY_Exp ((uint64_t)1 << 18) +#define KEY_Ln ((uint64_t)1 << 19) +#define KEY_Log ((uint64_t)1 << 20) +#define KEY_Imaginary ((uint64_t)1 << 21) +#define KEY_Comma ((uint64_t)1 << 22) +#define KEY_Power ((uint64_t)1 << 23) +#define KEY_Sine ((uint64_t)1 << 24) +#define KEY_Cosine ((uint64_t)1 << 25) +#define KEY_Tangent ((uint64_t)1 << 26) +#define KEY_Pi ((uint64_t)1 << 27) +#define KEY_Sqrt ((uint64_t)1 << 28) +#define KEY_Square ((uint64_t)1 << 29) +#define KEY_Seven ((uint64_t)1 << 30) +#define KEY_Eight ((uint64_t)1 << 31) +#define KEY_Nine ((uint64_t)1 << 32) +#define KEY_LeftParenthesis ((uint64_t)1 << 33) +#define KEY_RightParenthesis ((uint64_t)1 << 34) +#define KEY_Four ((uint64_t)1 << 36) +#define KEY_Five ((uint64_t)1 << 37) +#define KEY_Six ((uint64_t)1 << 38) +#define KEY_Multiplication ((uint64_t)1 << 39) +#define KEY_Division ((uint64_t)1 << 40) +#define KEY_One ((uint64_t)1 << 42) +#define KEY_Two ((uint64_t)1 << 43) +#define KEY_Three ((uint64_t)1 << 44) +#define KEY_Plus ((uint64_t)1 << 45) +#define KEY_Minus ((uint64_t)1 << 46) +#define KEY_Zero ((uint64_t)1 << 48) +#define KEY_Dot ((uint64_t)1 << 49) +#define KEY_EE ((uint64_t)1 << 50) +#define KEY_Ans ((uint64_t)1 << 51) +#define KEY_EXE ((uint64_t)1 << 52) +#define KEY_None ((uint64_t)1 << 54) + +EXTERNC uint64_t extapp_millis(); +EXTERNC void extapp_msleep(uint32_t ms); +EXTERNC uint64_t extapp_scanKeyboard(); +EXTERNC void extapp_pushRect(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t * pixels); +EXTERNC void extapp_pushRectUniform(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color); +EXTERNC int16_t extapp_drawTextLarge(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg); +EXTERNC int16_t extapp_drawTextSmall(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg); +EXTERNC void extapp_waitForVBlank(); +EXTERNC void extapp_clipboardStore(const char *text); +EXTERNC const char * extapp_clipboardText(); + +#endif diff --git a/apps/external/external_icon.png b/apps/external/external_icon.png new file mode 100644 index 000000000..297dc31c6 Binary files /dev/null and b/apps/external/external_icon.png differ diff --git a/apps/external/main_controller.cpp b/apps/external/main_controller.cpp new file mode 100644 index 000000000..627fbca08 --- /dev/null +++ b/apps/external/main_controller.cpp @@ -0,0 +1,98 @@ +#include "main_controller.h" +#include +#include +#include +#include "archive.h" +#include "app.h" + +using namespace Poincare; + +namespace External { + +using namespace Archive; + +MainController::MainController(Responder * parentResponder, ::App * app) : + ViewController(parentResponder), + m_selectableTableView(this) +{ + m_app = app; +} + +View * MainController::view() { + return &m_selectableTableView; +} + +void MainController::didBecomeFirstResponder() { + if (selectedRow() < 0) { + selectCellAtLocation(0, 0); + } + Container::activeApp()->setFirstResponder(&m_selectableTableView); +} + +bool MainController::handleEvent(Ion::Events::Event event) { + if (numberOfRows() > 0 && (event == Ion::Events::OK || event == Ion::Events::EXE)) { + uint32_t res = executeFile(m_cells[selectedRow()].text(), ((App *)m_app)->heap(), ((App *)m_app)->heapSize()); + ((App*)m_app)->redraw(); + switch(res) { + case 0: + break; + case 1: + Container::activeApp()->displayWarning(I18n::Message::ExternalAppApiMismatch); + break; + case 2: + Container::activeApp()->displayWarning(I18n::Message::StorageMemoryFull1); + break; + default: + Container::activeApp()->displayWarning(I18n::Message::ExternalAppExecError); + break; + } + return true; + } + return false; +} + +int MainController::numberOfRows() const { + return k_numberOfCells; +}; + +KDCoordinate MainController::rowHeight(int j) { + return Metric::ParameterCellHeight; +} + +KDCoordinate MainController::cumulatedHeightFromIndex(int j) { + return j*rowHeight(0); +} + +int MainController::indexFromCumulatedHeight(KDCoordinate offsetY) { + return offsetY/rowHeight(0); +} + +HighlightCell * MainController::reusableCell(int index, int type) { + assert(index < k_numberOfCells); + return &m_cells[index]; +} + +int MainController::reusableCellCount(int type) { + return k_numberOfCells; +} + +int MainController::typeAtLocation(int i, int j) { + return 0; +} + +void MainController::willDisplayCellForIndex(HighlightCell * cell, int index) { + PointerTextTableCell * myTextCell = (PointerTextTableCell *)cell; + struct File f; + if(fileAtIndex(index, f)) { + myTextCell->setText(f.name); + myTextCell->setTextColor(f.isExecutable ? KDColorBlack : Palette::GreyDark); + } +} + +void MainController::viewWillAppear() { + int count = numberOfFiles(); + k_numberOfCells = count <= k_maxNumberOfCells ? count : k_maxNumberOfCells; + m_selectableTableView.reloadData(); +} + +} diff --git a/apps/external/main_controller.h b/apps/external/main_controller.h new file mode 100644 index 000000000..bdb6d275b --- /dev/null +++ b/apps/external/main_controller.h @@ -0,0 +1,34 @@ +#ifndef EXTERNAL_MAIN_CONTROLLER_H +#define EXTERNAL_MAIN_CONTROLLER_H + +#include +#include "pointer_text_table_cell.h" + +namespace External { + +class MainController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource { +public: + MainController(Responder * parentResponder, App * app); + View * view() override; + bool handleEvent(Ion::Events::Event event) override; + void didBecomeFirstResponder() override; + int numberOfRows() const override; + KDCoordinate rowHeight(int j) override; + KDCoordinate cumulatedHeightFromIndex(int j) override; + int indexFromCumulatedHeight(KDCoordinate offsetY) override; + HighlightCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + int typeAtLocation(int i, int j) override; + void willDisplayCellForIndex(HighlightCell * cell, int index) override; + void viewWillAppear() override; +private: + App * m_app; + SelectableTableView m_selectableTableView; + int k_numberOfCells = 1; + constexpr static int k_maxNumberOfCells = 16; + PointerTextTableCell m_cells[k_maxNumberOfCells]; +}; + +} + +#endif diff --git a/apps/external/pointer_text_table_cell.cpp b/apps/external/pointer_text_table_cell.cpp new file mode 100644 index 000000000..00967fafb --- /dev/null +++ b/apps/external/pointer_text_table_cell.cpp @@ -0,0 +1,38 @@ +#include "pointer_text_table_cell.h" +#include +#include +#include + +PointerTextTableCell::PointerTextTableCell(const char * text, const KDFont * font, Layout layout) : + TableCell(layout), + m_pointerTextView(font, text, 0, 0.5, KDColorBlack, KDColorWhite) +{ +} + +View * PointerTextTableCell::labelView() const { + return (View *)&m_pointerTextView; +} + +const char * PointerTextTableCell::text() const { + return m_pointerTextView.text(); +} + +void PointerTextTableCell::setHighlighted(bool highlight) { + HighlightCell::setHighlighted(highlight); + KDColor backgroundColor = highlight? Palette::ListCellBackgroundSelected : Palette::ListCellBackground; + m_pointerTextView.setBackgroundColor(backgroundColor); +} + +void PointerTextTableCell::setText(const char * text) { + m_pointerTextView.setText(text); + layoutSubviews(); +} + +void PointerTextTableCell::setTextColor(KDColor color) { + m_pointerTextView.setTextColor(color); +} + +void PointerTextTableCell::setTextFont(const KDFont * font) { + m_pointerTextView.setFont(font); + layoutSubviews(); +} diff --git a/apps/external/pointer_text_table_cell.h b/apps/external/pointer_text_table_cell.h new file mode 100644 index 000000000..be011b76e --- /dev/null +++ b/apps/external/pointer_text_table_cell.h @@ -0,0 +1,20 @@ +#ifndef ESCHER_POINTER_TEXT_TABLE_CELL_H +#define ESCHER_POINTER_TEXT_TABLE_CELL_H + +#include +#include + +class PointerTextTableCell : public TableCell { +public: + PointerTextTableCell(const char * text = "", const KDFont * font = KDFont::SmallFont, Layout layout = Layout::Horizontal); + View * labelView() const override; + const char * text() const override; + virtual void setHighlighted(bool highlight) override; + void setText(const char * text); + virtual void setTextColor(KDColor color); + void setTextFont(const KDFont * font); +private: + PointerTextView m_pointerTextView; +}; + +#endif diff --git a/build/config.mak b/build/config.mak index 8de2af89d..a59637cc0 100644 --- a/build/config.mak +++ b/build/config.mak @@ -7,7 +7,7 @@ EPSILON_VERSION ?= 12.0.0 EPSILON_CUSTOM_VERSION ?= 1.18.0-0 # USERNAME ?= N/A # Valid values are "none", "update", "beta" -EPSILON_APPS ?= calculation rpn graph code statistics probability solver atom sequence regression settings +EPSILON_APPS ?= calculation rpn graph code statistics probability solver atom sequence regression settings external EPSILON_I18N ?= en fr es de pt EPSILON_GETOPT ?= 0 ESCHER_LOG_EVENTS_BINARY ?= 0 diff --git a/ion/include/ion/events.h b/ion/include/ion/events.h index 92905e9ca..ec55f9ea4 100644 --- a/ion/include/ion/events.h +++ b/ion/include/ion/events.h @@ -138,6 +138,25 @@ constexpr Event Arctangent = Event::ShiftKey(Keyboard::Key::Tangent); constexpr Event Equal = Event::ShiftKey(Keyboard::Key::Pi); constexpr Event Lower = Event::ShiftKey(Keyboard::Key::Sqrt); constexpr Event Greater = Event::ShiftKey(Keyboard::Key::Square); +constexpr Event shiftans = Event::ShiftKey(Keyboard::Key::Ans); +constexpr Event shiftplus = Event::ShiftKey(Keyboard::Key::Plus); +constexpr Event shiftfois = Event::ShiftKey(Keyboard::Key::Multiplication); +constexpr Event shiftdiv = Event::ShiftKey(Keyboard::Key::Division); +constexpr Event shiftminus = Event::ShiftKey(Keyboard::Key::Minus); +constexpr Event shift1 = Event::ShiftKey(Keyboard::Key::One); +constexpr Event shift2 = Event::ShiftKey(Keyboard::Key::Two); +constexpr Event shift3 = Event::ShiftKey(Keyboard::Key::Three); +constexpr Event shift4 = Event::ShiftKey(Keyboard::Key::Four); +constexpr Event shift5 = Event::ShiftKey(Keyboard::Key::Five); +constexpr Event shift6 = Event::ShiftKey(Keyboard::Key::Six); +constexpr Event shift7 = Event::ShiftKey(Keyboard::Key::Seven); +constexpr Event shift8 = Event::ShiftKey(Keyboard::Key::Eight); +constexpr Event shift9 = Event::ShiftKey(Keyboard::Key::Nine); +constexpr Event shift0 = Event::ShiftKey(Keyboard::Key::Zero); +constexpr Event shiftdot = Event::ShiftKey(Keyboard::Key::Dot); +constexpr Event shiftee = Event::ShiftKey(Keyboard::Key::EE); +constexpr Event shiftlp = Event::ShiftKey(Keyboard::Key::LeftParenthesis); +constexpr Event shiftrp = Event::ShiftKey(Keyboard::Key::RightParenthesis); constexpr Event BrightnessPlus = Event::ShiftKey(Keyboard::Key::Plus); constexpr Event BrightnessMinus = Event::ShiftKey(Keyboard::Key::Minus); @@ -161,7 +180,6 @@ constexpr Event ShiftThree = Event::ShiftKey(Keyboard::Key::Three); constexpr Event Colon = Event::AlphaKey(Keyboard::Key::XNT); constexpr Event SemiColon = Event::AlphaKey(Keyboard::Key::Var); constexpr Event DoubleQuotes = Event::AlphaKey(Keyboard::Key::Toolbox); -constexpr Event Percent = Event::AlphaKey(Keyboard::Key::Backspace); constexpr Event LowerA = Event::AlphaKey(Keyboard::Key::Exp); constexpr Event LowerB = Event::AlphaKey(Keyboard::Key::Ln); @@ -197,8 +215,11 @@ constexpr Event Space = Event::AlphaKey(Keyboard::Key::Minus); constexpr Event Question = Event::AlphaKey(Keyboard::Key::Zero); constexpr Event Exclamation = Event::AlphaKey(Keyboard::Key::Dot); +constexpr Event alphaans = Event::AlphaKey(Keyboard::Key::Ans); // Shift + Alpha +constexpr Event Percent = Event::ShiftAlphaKey(Keyboard::Key::Back); +constexpr Event SimpleQuote = Event::ShiftAlphaKey(Keyboard::Key::Toolbox); constexpr Event UpperA = Event::ShiftAlphaKey(Keyboard::Key::Exp); constexpr Event UpperB = Event::ShiftAlphaKey(Keyboard::Key::Ln); @@ -231,6 +252,7 @@ constexpr Event UpperX = Event::ShiftAlphaKey(Keyboard::Key::Two); constexpr Event UpperY = Event::ShiftAlphaKey(Keyboard::Key::Three); constexpr Event UpperZ = Event::ShiftAlphaKey(Keyboard::Key::Plus); +constexpr Event shiftalphaans = Event::ShiftAlphaKey(Keyboard::Key::Ans); // Special constexpr Event None = Event::Special(0); diff --git a/ion/include/ion/keyboard/layout_B2/layout_events.h b/ion/include/ion/keyboard/layout_B2/layout_events.h index 3a1f75260..01338d947 100644 --- a/ion/include/ion/keyboard/layout_B2/layout_events.h +++ b/ion/include/ion/keyboard/layout_B2/layout_events.h @@ -25,30 +25,30 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - TL(), TL(), TL(), T("(\x11)"), U(), U(), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), TL(), TL(), U(), - U(), U(), U(), U(), U(), U(), + T("17"), T("18"), T("19"), T("20"), T("21"), U(), + T("14"), T("15"), T("16"), T("factor(\x11)"), T("%"), U(), + T("11"), T("12"), T("13"), T("normal(\x11)"), T("\\"), U(), + T("10"), T("11"), T("12"), T("20"), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), T(":"), T(";"), T("\""), T("%"), + U(), U(), T(":"), T(";"), T("\""), U(), T("a"), T("b"), T("c"), T("d"), T("e"), T("f"), T("g"), T("h"), T("i"), T("j"), T("k"), T("l"), T("m"), T("n"), T("o"), T("p"), T("q"), U(), T("r"), T("s"), T("t"), T("u"), T("v"), U(), T("w"), T("x"), T("y"), T("z"), T(" "), U(), - T("?"), T("!"), U(), U(), U(), U(), + T("?"), T("!"), U(), TL(), U(), U(), // Shift+Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), U(), T("'"), T("%"), T("A"), T("B"), T("C"), T("D"), T("E"), T("F"), T("G"), T("H"), T("I"), T("J"), T("K"), T("L"), T("M"), T("N"), T("O"), T("P"), T("Q"), U(), T("R"), T("S"), T("T"), T("U"), T("V"), U(), T("W"), T("X"), T("Y"), T("Z"), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), TL(), U(), U(), }; #if DEBUG diff --git a/ion/include/ion/keyboard/layout_B3/layout_events.h b/ion/include/ion/keyboard/layout_B3/layout_events.h index a1f9502fa..fc9f20fe2 100644 --- a/ion/include/ion/keyboard/layout_B3/layout_events.h +++ b/ion/include/ion/keyboard/layout_B3/layout_events.h @@ -25,14 +25,14 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), TL(), TL(), U(), - U(), U(), U(), U(), U(), U(), + T("17"), T("18"), T("19"), T("20"), T("21"), U(), + T("14"), T("15"), T("16"), T("factor(\x11)"), T("%"), U(), + T("11"), T("12"), T("13"), T("normal(\x11)"), T("\\"), U(), + T("10"), T("11"), T("12"), T("20"), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), T(":"), T(";"), T("\""), T("%"), + U(), U(), T(":"), T(";"), T("\""), U(), T("a"), T("b"), T("c"), T("d"), T("e"), T("f"), T("g"), T("h"), T("i"), T("j"), T("k"), T("l"), T("m"), T("n"), T("o"), T("p"), T("q"), U(), @@ -42,7 +42,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { // Shift+Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), U(), T("'"), T("%"), T("A"), T("B"), T("C"), T("D"), T("E"), T("F"), T("G"), T("H"), T("I"), T("J"), T("K"), T("L"), T("M"), T("N"), T("O"), T("P"), T("Q"), U(), diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index 41c7001de..fedd6ba35 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -16,7 +16,7 @@ class StorageDelegate; class Storage { public: typedef uint16_t record_size_t; - constexpr static size_t k_storageSize = 16384; + constexpr static size_t k_storageSize = 20480; static Storage * sharedStorage(); constexpr static char k_dotChar = '.'; @@ -115,7 +115,6 @@ public: void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension); void destroyRecordsWithExtension(const char * extension); -private: constexpr static uint32_t Magic = 0xEE0BDDBA; constexpr static size_t k_maxRecordSize = (1 << sizeof(record_size_t)*8); diff --git a/kandinsky/include/kandinsky/color.h b/kandinsky/include/kandinsky/color.h index 8e1cafa50..d15835ae7 100644 --- a/kandinsky/include/kandinsky/color.h +++ b/kandinsky/include/kandinsky/color.h @@ -34,8 +34,8 @@ public: static KDColor blend(KDColor first, KDColor second, uint8_t alpha); KDColor invert() const { return KDColor(~m_value); } operator uint16_t() const { return m_value; } -private: constexpr KDColor(uint16_t value) : m_value(value) {} +private: uint16_t m_value; }; diff --git a/kandinsky/include/kandinsky/context.h b/kandinsky/include/kandinsky/context.h index bcfc4ee74..9e267cea0 100644 --- a/kandinsky/include/kandinsky/context.h +++ b/kandinsky/include/kandinsky/context.h @@ -33,13 +33,10 @@ public: void fillRectWithPixels(KDRect rect, const KDColor * pixels, KDColor * workingBuffer); void blendRectWithMask(KDRect rect, KDColor color, const uint8_t * mask, KDColor * workingBuffer); void strokeRect(KDRect rect, KDColor color); - + KDContext(KDPoint origin, KDRect clippingRect); virtual void pushRect(KDRect, const KDColor * pixels) = 0; virtual void pushRectUniform(KDRect rect, KDColor color) = 0; virtual void pullRect(KDRect rect, KDColor * pixels) = 0; -protected: - KDContext(KDPoint origin, KDRect clippingRect); -private: KDRect absoluteFillRect(KDRect rect); KDPoint pushOrPullString(const char * text, KDPoint p, const KDFont * font, KDColor textColor, KDColor backgroundColor, int maxByteLength, bool push, int * result = nullptr); KDPoint m_origin; diff --git a/kandinsky/include/kandinsky/ion_context.h b/kandinsky/include/kandinsky/ion_context.h index 5cfd6cd9e..0dc1774fb 100644 --- a/kandinsky/include/kandinsky/ion_context.h +++ b/kandinsky/include/kandinsky/ion_context.h @@ -27,7 +27,6 @@ public: bool zoomInhibit; bool gammaEnabled; int zoomPosition; -private: KDIonContext(); void pushRect(KDRect rect, const KDColor * pixels) override; void pushRectUniform(KDRect rect, KDColor color) override; diff --git a/poincare/include/poincare/tree_pool.h b/poincare/include/poincare/tree_pool.h index a124964e3..8e6a3d6f4 100644 --- a/poincare/include/poincare/tree_pool.h +++ b/poincare/include/poincare/tree_pool.h @@ -49,7 +49,7 @@ public: int numberOfNodes() const; private: - constexpr static int BufferSize = 32768; + constexpr static int BufferSize = 16384; constexpr static int MaxNumberOfNodes = BufferSize/sizeof(TreeNode); static TreePool * SharedStaticPool; diff --git a/poincare/src/trigonometry_cheat_table.cpp b/poincare/src/trigonometry_cheat_table.cpp index eac4f3a4b..9eae9bc33 100644 --- a/poincare/src/trigonometry_cheat_table.cpp +++ b/poincare/src/trigonometry_cheat_table.cpp @@ -82,7 +82,7 @@ Expression TrigonometryCheatTable::simplify(const Expression e, ExpressionNode:: * For instance, when simplfy a Cosine, we always compute the value for an angle * in the top right trigonometric quadrant. */ const TrigonometryCheatTable * TrigonometryCheatTable::Table() { - static Row sTableRows[] = { + const Row sTableRows[] = { Row(Row::Pair("-90", -90.0f), Row::Pair("π*(-2)^(-1)", -1.5707963267948966f), Row::Pair("-100", -100.0f), diff --git a/python/port/genhdr/qstrdefs.in.h b/python/port/genhdr/qstrdefs.in.h index 58c36bc71..5b96067ed 100644 --- a/python/port/genhdr/qstrdefs.in.h +++ b/python/port/genhdr/qstrdefs.in.h @@ -129,6 +129,8 @@ Q(.) Q(EE) Q(Ans) Q(EXE) +Q(get_key) +Q(Pause) // Turtle QSTRs Q(turtle) diff --git a/python/port/helpers.cpp b/python/port/helpers.cpp index 438f7ca47..71fb5e879 100644 --- a/python/port/helpers.cpp +++ b/python/port/helpers.cpp @@ -1,5 +1,8 @@ #include "helpers.h" #include +#ifdef SIMULATOR +#include +#endif extern "C" { #include "mphalport.h" } diff --git a/python/port/mod/kandinsky/modkandinsky.cpp b/python/port/mod/kandinsky/modkandinsky.cpp index 469fdb86b..6b8a3db5c 100644 --- a/python/port/mod/kandinsky/modkandinsky.cpp +++ b/python/port/mod/kandinsky/modkandinsky.cpp @@ -8,19 +8,22 @@ extern "C" { #include "port.h" static KDColor ColorForTuple(mp_obj_t tuple) { - size_t len; - mp_obj_t * elem; + if (MP_OBJ_IS_SMALL_INT(tuple)) // BP change: accept int for color + return MP_OBJ_SMALL_INT_VALUE(tuple); - mp_obj_get_array(tuple, &len, &elem); - if (len != 3) { - mp_raise_TypeError("color needs 3 components"); - } + size_t len; + mp_obj_t * elem; - return KDColor::RGB888( - mp_obj_get_int(elem[0]), - mp_obj_get_int(elem[1]), - mp_obj_get_int(elem[2]) - ); + mp_obj_get_array(tuple, &len, &elem); + if (len != 3) { + mp_raise_TypeError("color needs 3 components"); + } + + return KDColor::RGB888( + mp_obj_get_int(elem[0]), + mp_obj_get_int(elem[1]), + mp_obj_get_int(elem[2]) + ); } static mp_obj_t TupleForRGB(uint8_t r, uint8_t g, uint8_t b) { @@ -179,3 +182,117 @@ mp_obj_t modkandinsky_get_keys() { return result; } + +/* C-- SDK (c) B. Parisse, 2019 */ +mp_obj_t modkandinsky_Pause(mp_obj_t x) { + double d=mp_obj_get_float(x); + numworks_wait_1ms(d*1000); + return mp_const_none; +} + +#define LCD_WIDTH_PX 320 +#define LCD_HEIGHT_PX 222 + +void numworks_set_pixel(int x, int y, int color) { + if (x<0 || x>=LCD_WIDTH_PX || y<0 || y>=LCD_HEIGHT_PX) + return; + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,0)); + KDColor c(color); + KDPoint point(x,y+18); + KDIonContext::sharedContext()->pushRect(KDRect(point, 1, 1), &c); + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +void numworks_fill_rect(int x,int y,int w,int h,int c){ + KDColor color = c; + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,0)); +#if 1 + if (x<0){ + w += x; + x=0; + } + if (y<0){ + h += y; + y=0; + } + if (h+y>=LCD_HEIGHT_PX) + h=LCD_HEIGHT_PX-y; + if (x+w>=LCD_WIDTH_PX) + w=LCD_WIDTH_PX-x; + if (h<=0 || w<=0) + return; + KDRect rect(x,y+18,w,h); + KDIonContext::sharedContext()->pushRectUniform(rect,color); +#else + KDRect rect(x,y,w,h); + KDIonContext::sharedContext()->fillRect(rect, color); +#endif + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +int numworks_get_pixel(int x, int y) { + KDPoint point(x,y); + KDColor c = KDIonContext::sharedContext()->getPixel(point); + return c; +} + +int numworks_draw_string(int x,int y,int c,int bg,const char * text,bool fake){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + KDPoint point(x,y); + if (ptr) + ptr->displaySandbox(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,18,320,fake?0:222)); + ctx->setOrigin(KDPoint(0,18)); + point=KDIonContext::sharedContext()->drawString(text, point, KDFont::LargeFont, c, bg); + ctx->setClippingRect(save); + ctx->setOrigin(o); + return point.x(); +} + +int numworks_draw_string_small(int x,int y,int c,int bg,const char * text,bool fake){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + KDPoint point(x,y); + if (ptr) + ptr->displaySandbox(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,18,320,fake?0:222)); + ctx->setOrigin(KDPoint(0,18)); + point=ctx->drawString(text, point, KDFont::SmallFont, c, bg); + ctx->setClippingRect(save); + ctx->setOrigin(o); + return point.x(); +} + +void numworks_hide_graph(){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + if (ptr) + ptr->hideSandbox(); +} + +void numworks_show_graph(){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + if (ptr) + ptr->displaySandbox(); +} + +// Python module get_key() addition +mp_obj_t modkandinsky_get_key() { + micropython_port_interrupt_if_needed(); + int key=getkey(false); // no suspend + return mp_obj_new_int(key); +} diff --git a/python/port/mod/kandinsky/modkandinsky.h b/python/port/mod/kandinsky/modkandinsky.h index 4191155bc..15bc28a31 100644 --- a/python/port/mod/kandinsky/modkandinsky.h +++ b/python/port/mod/kandinsky/modkandinsky.h @@ -7,3 +7,5 @@ mp_obj_t modkandinsky_draw_string(size_t n_args, const mp_obj_t *args); mp_obj_t modkandinsky_fill_rect(size_t n_args, const mp_obj_t *args); mp_obj_t modkandinsky_wait_vblank(); mp_obj_t modkandinsky_get_keys(); +mp_obj_t modkandinsky_get_key(); +mp_obj_t modkandinsky_Pause(mp_obj_t x) ; diff --git a/python/port/mod/kandinsky/modkandinsky_table.c b/python/port/mod/kandinsky/modkandinsky_table.c index 253f856a7..cf8490c6f 100644 --- a/python/port/mod/kandinsky/modkandinsky_table.c +++ b/python/port/mod/kandinsky/modkandinsky_table.c @@ -7,6 +7,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_draw_string_obj, 3, 5, m STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_fill_rect_obj, 5, 5, modkandinsky_fill_rect); STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_wait_vblank_obj, modkandinsky_wait_vblank); STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_get_keys_obj, modkandinsky_get_keys); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_get_key_obj, modkandinsky_get_key); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(modkandinsky_Pause_obj, modkandinsky_Pause); STATIC const mp_rom_map_elem_t modkandinsky_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_kandinsky) }, @@ -17,6 +19,8 @@ STATIC const mp_rom_map_elem_t modkandinsky_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_fill_rect), (mp_obj_t)&modkandinsky_fill_rect_obj }, { MP_ROM_QSTR(MP_QSTR_wait_vblank), (mp_obj_t)&modkandinsky_wait_vblank_obj }, { MP_ROM_QSTR(MP_QSTR_get_keys), (mp_obj_t)&modkandinsky_get_keys_obj }, + { MP_ROM_QSTR(MP_QSTR_get_key), (mp_obj_t)&modkandinsky_get_key_obj }, + { MP_ROM_QSTR(MP_QSTR_Pause), (mp_obj_t)&modkandinsky_Pause_obj }, }; STATIC MP_DEFINE_CONST_DICT(modkandinsky_module_globals, modkandinsky_module_globals_table); diff --git a/python/port/port.cpp b/python/port/port.cpp index 163aefd24..0a1735bdd 100644 --- a/python/port/port.cpp +++ b/python/port/port.cpp @@ -1,6 +1,14 @@ +#ifdef SIMULATOR +#include +#endif +#include #include "port.h" -#include +#include +#include +#include +#include "../../apps/apps_container.h" +#include "../../apps/global_preferences.h" #include #include @@ -78,9 +86,9 @@ void MicroPython::ExecutionEnvironment::runCode(const char * str) { /* End of mp_obj_print_exception. */ } - assert(sCurrentExecutionEnvironment == this); - sCurrentExecutionEnvironment = nullptr; -} + assert(sCurrentExecutionEnvironment == this); + sCurrentExecutionEnvironment = nullptr; + } void MicroPython::ExecutionEnvironment::interrupt() { mp_keyboard_interrupt(); @@ -197,11 +205,485 @@ mp_import_stat_t mp_import_stat(const char *path) { } void mp_hal_stdout_tx_strn_cooked(const char * str, size_t len) { - assert(sCurrentExecutionEnvironment != nullptr); - sCurrentExecutionEnvironment->printText(str, len); + if (sCurrentExecutionEnvironment != nullptr) + sCurrentExecutionEnvironment->printText(str, len); } const char * mp_hal_input(const char * prompt) { - assert(sCurrentExecutionEnvironment != nullptr); - return sCurrentExecutionEnvironment->inputText(prompt); + if (sCurrentExecutionEnvironment != nullptr) + return sCurrentExecutionEnvironment->inputText(prompt); + return 0; } + +/* C-- SDK , (c) B. Parisse 2019 */ + +const char * read_file(const char * filename){ +#if 1 + Ion::Storage * s=Ion::Storage::sharedStorage(); + const Ion::Storage::Record r=s->recordNamed(filename); + if (r.isNull()) + return 0; + Ion::Storage::Record::Data d=r.value(); + const char * ptr=(const char *)d.buffer; + if (ptr) + return ptr+1; + else + return 0; +#endif + if (sScriptProvider != nullptr) + return sScriptProvider->contentOfScript(filename); + return "undef"; +} + +bool write_file(const char * filename,const char * content,size_t len){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + auto res=s->createRecordWithFullName(filename,content,strlen(content)+1); + if (res==Ion::Storage::Record::ErrorStatus::NameTaken){ + auto r=s->recordNamed(filename); + Ion::Storage::Record::Data d; + d.buffer=content; + d.size=(len?len:strlen(content))+1; + return r.setValue(d)==Ion::Storage::Record::ErrorStatus::None; + } + if (res==Ion::Storage::Record::ErrorStatus::None) + return write_file(filename,content,len); + return false; +} + +bool file_exists(const char * filename){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + return s->isFullNameTaken(filename); +} + +bool erase_file(const char * filename){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + auto r= s->recordNamed(filename); + if (r.isNull()) + return false; + r.destroy(); + return true; +} + + +#if 1 +int os_file_browser(const char ** filenames,int maxrecords,const char * extension){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + int n=s->numberOfRecordsWithExtension(extension); + if (!n) return 0; + if (n>maxrecords) n=maxrecords; + for (int i=0;irecordWithExtensionAtIndex(extension, i); + filenames[i]=r.fullName(); + } + filenames[n]=0; + return n; +} + // const char * ptr=(const char *)r.value().buffer; + /* storage.h + Ion::Storage::Record::Data structure avec 2 membres + const void * buffer et size_t size + + Record(const char * fullName = nullptr); + Record(const char * basename, const char * extension); + Data value(); + Ion::Storage::Record::ErrorStatus setValue(Ion::Storage::Record::Data); + void destroy(void); + + // Record creation + Record::ErrorStatus createRecordWithFullName(const char * fullName, const void * data, size_t size); + Record::ErrorStatus createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size); + + // Record getters + Record recordWithExtensionAtIndex(const char * extension, int index); + Record recordNamed(const char * fullName); + Record recordBaseNamedWithExtension(const char * baseName, const char * extension); + Record recordBaseNamedWithExtensions(const char * baseName, const char * const extension[], size_t numberOfExtensions); + + // Record destruction + void destroyAllRecords(); + void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension); + void destroyRecordsWithExtension(const char * extension); + + + */ +#endif + +void statuslinemsg(const char * msg){ + AppsContainer::sharedAppsContainer()->reloadTitleBarView(); + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + if (ptr) + ptr->displaySandbox(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,280,18)); + ctx->setOrigin(KDPoint(0,0)); + KDRect rect(0,0,280,18); + KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + if (strlen(msg)>25) + ctx->drawString(msg, KDPoint(0,0), KDFont::SmallFont, 0, 64934); + else + ctx->drawString(msg, KDPoint(0,0), KDFont::LargeFont, 0, 64934); + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +bool os_set_angle_unit(int mode){ + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + if (mode==0){ // rad + preferences->setAngleUnit(Poincare::Preferences::AngleUnit::Radian); + return true; + } + if (mode==1){ // deg + preferences->setAngleUnit(Poincare::Preferences::AngleUnit::Degree); + return true; + } + return false; + if (mode==2){ // grad + return true; + } +} + +int os_get_angle_unit(){ + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + if (preferences->angleUnit()==Poincare::Preferences::AngleUnit::Radian) + return 0; + if (preferences->angleUnit()==Poincare::Preferences::AngleUnit::Degree) + return 1; + return 2; +} + +#ifdef SIMULATOR +#define TICKS_PER_MINUTE 60000 +#else +#define TICKS_PER_MINUTE 11862 +extern const void * _stack_start; +extern const void * _heap_start; +#endif +//int time_shift=0; // set it via time() command in KhiCAS +void statusline(int mode, size_t heap){ + AppsContainer::sharedAppsContainer()->reloadTitleBarView(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,18)); + ctx->setOrigin(KDPoint(0,0)); + KDRect rect(0,0,mode==1?320:280,18); + KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + const char * text=0; + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + if (preferences->angleUnit() == Poincare::Preferences::AngleUnit::Radian) + text="rad"; + else + text="deg"; + // ctx->drawString(text, KDPoint(5,1), KDFont::SmallFont, 0, 63488 /* Palette::Red*/); + ctx->drawString(text, KDPoint(5,1), KDFont::SmallFont, 0, 64934); +#ifdef GIAC_LINKED + if (khicas_eval) + text="KHICAS"; + else + text="PYTHON"; +#else + text="KHICAS"; +#endif + ctx->drawString(text, KDPoint(70,1), KDFont::SmallFont, 0, 64934); + char bufheap[16]; +#if 0 //ndef SIMULATOR +#endif + int x; + x=(heap&0xf0000000)>>28; + bufheap[0]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf000000)>>24; + bufheap[1]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf00000)>>20; + bufheap[2]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf0000)>>16; + bufheap[3]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf000)>>12; + bufheap[4]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf00)>>8; + bufheap[5]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf0)>>4; + bufheap[6]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf); + bufheap[7]=(x>9?'a'+(x-10):'0'+x); + bufheap[8]=0; + if(heap != 0) ctx->drawString(bufheap,KDPoint(130,1),KDFont::SmallFont, 0, 64934); +#ifdef GIAC_SHOWTIME + int d=(Ion::Timing::millis()/TICKS_PER_MINUTE +time_shift) % (24*60); // minutes + char buf[32]={0,0,0,0}; + int h=d/60; + buf[0]='0'+h/10; + buf[1]='0'+(h%10); + buf[2]=':'; + ctx->drawString(buf, KDPoint(148,1), KDFont::SmallFont, 0, 64934); + int mn=d%60; + buf[0]='0'+mn/10; + buf[1]='0'+(mn%10); + buf[2]=0; + ctx->drawString(buf, KDPoint(168,1), KDFont::SmallFont, 0, 64934); +#endif + text=" "; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::Shift) + text="shift "; + else { + if (Ion::Events::isAlphaActive()){ + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::AlphaLock) + text="alphal"; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::ShiftAlphaLock) + text="ALPHAL"; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::Alpha) + text="1alpha"; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::ShiftAlpha) + text="1ALPHA"; + } + } + ctx->drawString(text, KDPoint(232,1), KDFont::SmallFont, 0, 64934 /* Palette::YellowDark*/); + if (mode==1){ + if (Ion::USB::isPlugged()) + text="charge"; + else { + auto c=Ion::Battery::level(); + if (c==Ion::Battery::Charge::EMPTY) + text="empty "; + if (c==Ion::Battery::Charge::LOW) + text="low "; + if (c==Ion::Battery::Charge::FULL) + text="full "; + } + ctx->drawString(text, KDPoint(280,1), KDFont::SmallFont, 0, 64934 /* Palette::YellowDark*/); + } + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +bool isalphaactive(){ + return Ion::Events::isAlphaActive(); +} + +void lock_alpha(){ + Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock); + statusline(0,0); +} + +void reset_kbd(){ + Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default); + statusline(0,0); +} + +bool alphawasactive_=false; +bool alphawasactive(){ + return alphawasactive_; +} + +bool waitforvblank(){ + return Ion::Display::waitForVBlank(); +} + +bool back_key_pressed() { + static int c = 0; + + ++c ; + if (c<400 || (c & 0xf)!= 0) { + return false; + } +#ifdef SIMULATOR + Fl::wait(0.00001); +#endif + + Ion::Keyboard::State scan = Ion::Keyboard::scan(); + // if (scan!=16) std::cerr << scan << '\n'; + Ion::Keyboard::Key interruptKey = static_cast(mp_interrupt_char); + if (scan.keyDown(interruptKey) + // || scan.keyDown(static_cast(16)) + ) + return true; + return false; +} + +int getkey_raw(bool allow_suspend){ + int key=-1; + size_t t1=Ion::Timing::millis(); + for (;;){ + int timeout=10000; + alphawasactive_=Ion::Events::isAlphaActive(); + Ion::Events::Event event=Ion::Events::getEvent(&timeout); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,18)); + KDRect rect(90,63,140,75); + if (event==Ion::Events::None){ + size_t t2=Ion::Timing::millis(); + if (t2-t1>2*TICKS_PER_MINUTE){ + // KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + event=Ion::Events::OnOff; + } + } + else + t1=Ion::Timing::millis(); + if (event == Ion::Events::USBPlug) { + statusline(0,0); + // KDIonContext::sharedContext()->pushRectUniform(rect,33333); + if (Ion::USB::isPlugged()) { + if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { + Ion::LED::setColor(KDColorBlack); + Ion::LED::updateColorWithPlugAndCharge(); + GlobalPreferences::sharedGlobalPreferences()->setExamMode(false); + // displayExamModePopUp(false); + } else { + Ion::USB::enable(); + } + Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); + } else { + Ion::USB::disable(); + } + } + if (event == Ion::Events::USBEnumeration || event == Ion::Events::USBPlug || event == Ion::Events::BatteryCharging) { + Ion::LED::updateColorWithPlugAndCharge(); + } + if (event == Ion::Events::USBEnumeration + ) { + KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + if (Ion::USB::isPlugged()) { + /* Just after a software update, the battery timer does not have time to + * fire before the calculator enters DFU mode. As the DFU mode blocks the + * event loop, we update the battery state "manually" here. + * We do it before switching to USB application to redraw the battery + * pictogram. */ + // updateBatteryState(); + KDIonContext::sharedContext()->pushRectUniform(rect,22222); + auto ctx=KDIonContext::sharedContext(); + int y=58; + ctx->drawString("Connecte ! ", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + y+=18; + ctx->drawString(" DFU mode ", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + y+=18; + ctx->drawString("Back quitte", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + y-=18; + Ion::USB::DFU(); + KDIonContext::sharedContext()->pushRectUniform(rect,44444); + ctx->drawString("Deconnecte!", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + // Update LED when exiting DFU mode + Ion::LED::updateColorWithPlugAndCharge(); + } else { + /* Sometimes, the device gets an ENUMDNE interrupts when being unplugged + * from a non-USB communicating host (e.g. a USB charger). The interrupt + * must me cleared: if not the next enumeration attempts will not be + * detected. */ + Ion::USB::clearEnumerationInterrupt(); + } + } + if (event.isKeyboardEvent()) { + // m_backlightDimmingTimer.reset(); + // m_suspendTimer.reset(); + Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); + } + ctx->setClippingRect(save); + ctx->setOrigin(o); + + if (event==Ion::Events::Shift || event==Ion::Events::Alpha){ + statusline(0,0); + continue; + } + if (event.isKeyboardEvent()){ + key=event.id(); + if (key==17 || key==4 || key==5 || key==52) + reset_kbd(); + if (allow_suspend && (key==7 || key==8) ){ // power + Ion::Power::suspend(true); + numworks_fill_rect(0,0,320,240,65535); + Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); + AppsContainer::sharedAppsContainer()->reloadTitleBarView(); + //AppsContainer::sharedAppsContainer()->redrawWindow(); + statusline(1,0); + //continue; + } + else + statusline(0,0); + break; + } + } + return key; +} + +const short int translated_keys[]= + { + // non shifted + KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_XTT,KEY_CTRL_VARS,KEY_CTRL_CATALOG,KEY_CTRL_DEL, + KEY_CHAR_EXPN,KEY_CHAR_LN,KEY_CHAR_LOG,KEY_CHAR_IMGNRY,',',KEY_CHAR_POW, + KEY_CHAR_SIN,KEY_CHAR_COS,KEY_CHAR_TAN,KEY_CHAR_PI,KEY_CHAR_ROOT,KEY_CHAR_SQUARE, + '7','8','9','(',')',-1, + '4','5','6','*','/',-1, + '1','2','3','+','-',-1, + '0','.',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, + // shifted + KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_CUT,KEY_CTRL_CLIP,KEY_CTRL_PASTE,KEY_CTRL_AC, + KEY_CHAR_LBRCKT,KEY_CHAR_RBRCKT,KEY_CHAR_LBRACE,KEY_CHAR_RBRACE,'_',KEY_CHAR_STORE, + KEY_CHAR_ASIN,KEY_CHAR_ACOS,KEY_CHAR_ATAN,'=','<','>', + KEY_CTRL_F7,KEY_CTRL_F8,KEY_CTRL_F9,KEY_CTRL_F13,KEY_CTRL_F14,-1, + KEY_CTRL_F4,KEY_CTRL_F5,KEY_CTRL_F6,KEY_CHAR_FACTOR,'%',-1, + KEY_CTRL_F1,KEY_CTRL_F2,KEY_CTRL_F3,KEY_CHAR_NORMAL,'\\',-1, + KEY_CTRL_F10,KEY_CTRL_F11,KEY_CTRL_F12,KEY_SHIFT_ANS,KEY_CTRL_EXE,-1, + // alpha + KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','"',KEY_CTRL_DEL, + 'a','b','c','d','e','f', + 'g','h','i','j','k','l', + 'm','n','o','p','q',-1, + 'r','s','t','u','v',-1, + 'w','x','y','z',' ',-1, + '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, + // alpha shifted + KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','\'','%', + 'A','B','C','D','E','F', + 'G','H','I','J','K','L', + 'M','N','O','P','Q',-1, + 'R','S','T','U','V',-1, + 'W','X','Y','Z',' ',-1, + '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, + }; + +int getkey(bool allow_suspend){ + int k=getkey_raw(allow_suspend); + // translate + return translated_keys[k]; +} + +// Casio prototype +void GetKey(int * key){ + *key=getkey(true); +} + + +void numworks_wait_1ms(int ms){ + for (int i=0;i(Ion::Keyboard::Key::Back); + if (scan.keyDown(interruptKey)) + return; + Ion::Timing::msleep(128); + } + Ion::Timing::msleep(ms % 128); +} + +void enable_back_interrupt(){ + mp_interrupt_char = (int)Ion::Keyboard::Key::Back; +} + +void disable_back_interrupt(){ + mp_interrupt_char = -1; +} + diff --git a/python/port/port.h b/python/port/port.h index f0b3a0407..869b6f937 100644 --- a/python/port/port.h +++ b/python/port/port.h @@ -36,4 +36,212 @@ void registerScriptProvider(ScriptProvider * s); }; +extern "C" { +/* + basic SDK for direct control of the calculator like in KhiCAS + */ + bool waitforvblank(); + int os_file_browser(const char ** filenames,int maxrecords,const char * extension); + void numworks_hide_graph(); + void numworks_show_graph(); + void enable_back_interrupt(); + void disable_back_interrupt(); + int os_get_angle_unit(); + bool os_set_angle_unit(int mode); + const char * read_file(const char * filename); + bool write_file(const char * filename,const char * content,size_t len); +int getkey_raw(bool allow_suspend); // Numworks scan code +int getkey(bool allow_suspend); // transformed +void GetKey(int * key); // Casio like +bool isalphaactive(); +bool alphawasactive(); // alpha status before getkey +bool back_key_pressed() ; +void lock_alpha(); +void reset_kbd(); +void statusline(int mode=0, size_t=0); // display status line +void statuslinemsg(const char * msg); // display a message in statusline +void numworks_fill_rect(int x,int y,int w,int h,int c); // y=0 is automatically translated by 18 for statusline +void numworks_set_pixel(int x,int y,int c); +int numworks_get_pixel(int x,int y); +/* draw_string returns new x position, use fake=true to compute without drawing */ +int numworks_draw_string(int x,int y,int c,int bg,const char * s,bool fake=false); +int numworks_draw_string_small(int x,int y,int c,int bg,const char * s,bool fake=false); +// scriptstore +bool file_exists(const char * filename); +bool erase_file(const char * filename); +const char * read_file(const char * filename); +bool write_file(const char * filename,const char * s,size_t len=0); +int giac_filebrowser(char * filename,const char * extension,const char * title); +void numworks_wait_1ms(int ms); +//double millis(); +//extern int time_shift; // shift for the clock + + +// Character codes +#define KEY_CHAR_0 0x30 +#define KEY_CHAR_1 0x31 +#define KEY_CHAR_2 0x32 +#define KEY_CHAR_3 0x33 +#define KEY_CHAR_4 0x34 +#define KEY_CHAR_5 0x35 +#define KEY_CHAR_6 0x36 +#define KEY_CHAR_7 0x37 +#define KEY_CHAR_8 0x38 +#define KEY_CHAR_9 0x39 +#define KEY_CHAR_DP 0x2e +#define KEY_CHAR_EXP 0x0f +#define KEY_CHAR_PMINUS 30200 +#define KEY_CHAR_PLUS 43 +#define KEY_CHAR_MINUS 45 +#define KEY_CHAR_MULT 42 +#define KEY_CHAR_DIV 47 +#define KEY_CHAR_FRAC 0xbb +#define KEY_CHAR_LPAR 0x28 +#define KEY_CHAR_RPAR 0x29 +#define KEY_CHAR_COMMA 0x2c +#define KEY_CHAR_STORE 0x0e +#define KEY_CHAR_LOG 0x95 +#define KEY_CHAR_LN 0x85 +#define KEY_CHAR_SIN 0x81 +#define KEY_CHAR_COS 0x82 +#define KEY_CHAR_TAN 0x83 +#define KEY_CHAR_SQUARE 0x8b +#define KEY_CHAR_POW 0xa8 +#define KEY_CHAR_IMGNRY 0x7f50 +#define KEY_CHAR_LIST 0x7f51 +#define KEY_CHAR_MAT 0x7f40 +#define KEY_CHAR_EQUAL 0x3d +#define KEY_CHAR_PI 0xd0 +#define KEY_CHAR_ANS 0xc0 +#define KEY_SHIFT_ANS 0xc1 +#define KEY_CHAR_LBRCKT 0x5b +#define KEY_CHAR_RBRCKT 0x5d +#define KEY_CHAR_LBRACE 0x7b +#define KEY_CHAR_RBRACE 0x7d +#define KEY_CHAR_CR 0x0d +#define KEY_CHAR_CUBEROOT 0x96 +#define KEY_CHAR_RECIP 0x9b +#define KEY_CHAR_ANGLE 0x7f54 +#define KEY_CHAR_EXPN10 0xb5 +#define KEY_CHAR_EXPN 0xa5 +#define KEY_CHAR_ASIN 0x91 +#define KEY_CHAR_ACOS 0x92 +#define KEY_CHAR_ATAN 0x93 +#define KEY_CHAR_ROOT 0x86 +#define KEY_CHAR_POWROOT 0xb8 +#define KEY_CHAR_SPACE 0x20 +#define KEY_CHAR_DQUATE 0x22 +#define KEY_CHAR_VALR 0xcd +#define KEY_CHAR_THETA 0xce +#define KEY_CHAR_FACTOR 0xda +#define KEY_CHAR_NORMAL 0xdb +#define KEY_CHAR_A 0x41 +#define KEY_CHAR_B 0x42 +#define KEY_CHAR_C 0x43 +#define KEY_CHAR_D 0x44 +#define KEY_CHAR_E 0x45 +#define KEY_CHAR_F 0x46 +#define KEY_CHAR_G 0x47 +#define KEY_CHAR_H 0x48 +#define KEY_CHAR_I 0x49 +#define KEY_CHAR_J 0x4a +#define KEY_CHAR_K 0x4b +#define KEY_CHAR_L 0x4c +#define KEY_CHAR_M 0x4d +#define KEY_CHAR_N 0x4e +#define KEY_CHAR_O 0x4f +#define KEY_CHAR_P 0x50 +#define KEY_CHAR_Q 0x51 +#define KEY_CHAR_R 0x52 +#define KEY_CHAR_S 0x53 +#define KEY_CHAR_T 0x54 +#define KEY_CHAR_U 0x55 +#define KEY_CHAR_V 0x56 +#define KEY_CHAR_W 0x57 +#define KEY_CHAR_X 0x58 +#define KEY_CHAR_Y 0x59 +#define KEY_CHAR_Z 0x5a + + +// Control codes +#define KEY_CTRL_NOP 30202 +#define KEY_CTRL_EXE 30201 +#define KEY_CTRL_DEL 30025 +#define KEY_CTRL_AC 30070 +#define KEY_CTRL_FD 30046 +#define KEY_CTRL_UNDO 30045 +#define KEY_CTRL_XTT 30001 +#define KEY_CTRL_EXIT 5 +#define KEY_CTRL_OK 4 +#define KEY_CTRL_SHIFT 30006 +#define KEY_CTRL_ALPHA 30007 +#define KEY_CTRL_OPTN 30008 +#define KEY_CTRL_VARS 30030 +#define KEY_CTRL_UP 1 +#define KEY_CTRL_DOWN 2 +#define KEY_CTRL_LEFT 0 +#define KEY_CTRL_RIGHT 3 +#define KEY_CTRL_F1 30009 +#define KEY_CTRL_F2 30010 +#define KEY_CTRL_F3 30011 +#define KEY_CTRL_F4 30012 +#define KEY_CTRL_F5 30013 +#define KEY_CTRL_F6 30014 +#define KEY_CTRL_F7 30015 +#define KEY_CTRL_F8 30016 +#define KEY_CTRL_F9 30017 +#define KEY_CTRL_F10 30018 +#define KEY_CTRL_F11 30019 +#define KEY_CTRL_F12 30020 +#define KEY_CTRL_F13 30021 +#define KEY_CTRL_F14 30022 +#define KEY_CTRL_CATALOG 30100 +#define KEY_CTRL_CAPTURE 30055 +#define KEY_CTRL_CLIP 30050 +#define KEY_CTRL_CUT 30250 +#define KEY_CTRL_PASTE 30036 +#define KEY_CTRL_INS 30033 +#define KEY_CTRL_MIXEDFRAC 30054 +#define KEY_CTRL_FRACCNVRT 30026 +#define KEY_CTRL_QUIT 30029 +#define KEY_CTRL_PRGM 30028 +#define KEY_CTRL_SETUP 30037 +#define KEY_CTRL_PAGEUP 30052 +#define KEY_CTRL_PAGEDOWN 30053 +#define KEY_CTRL_MENU 30003 +#define KEY_SHIFT_OPTN 30059 +#define KEY_CTRL_RESERVE1 30060 +#define KEY_CTRL_RESERVE2 30061 +#define KEY_SHIFT_LEFT 30062 +#define KEY_SHIFT_RIGHT 30063 + +#define KEY_PRGM_ACON 10 +#define KEY_PRGM_DOWN 37 +#define KEY_PRGM_EXIT 47 +#define KEY_PRGM_F1 79 +#define KEY_PRGM_F2 69 +#define KEY_PRGM_F3 59 +#define KEY_PRGM_F4 49 +#define KEY_PRGM_F5 39 +#define KEY_PRGM_F6 29 +#define KEY_PRGM_LEFT 38 +#define KEY_PRGM_NONE 0 +#define KEY_PRGM_RETURN 31 +#define KEY_PRGM_RIGHT 27 +#define KEY_PRGM_UP 28 +#define KEY_PRGM_1 72 +#define KEY_PRGM_2 62 +#define KEY_PRGM_3 52 +#define KEY_PRGM_4 73 +#define KEY_PRGM_5 63 +#define KEY_PRGM_6 53 +#define KEY_PRGM_7 74 +#define KEY_PRGM_8 64 +#define KEY_PRGM_9 54 +#define KEY_PRGM_A 76 +#define KEY_PRGM_F 26 +#define KEY_PRGM_ALPHA 77 +#define KEY_PRGM_SHIFT 78 +#define KEY_PRGM_MENU 48 +} #endif