From 472929c0284a2ac6a7e1d8881a91cec4510fa0fe Mon Sep 17 00:00:00 2001 From: Damien Nicolet Date: Fri, 13 Dec 2019 01:02:14 +0100 Subject: [PATCH] External API for KhiCAS --- apps/external/extapp_api.cpp | 82 +++ ion/include/ion/events.h | 24 +- .../ion/keyboard/layout_B2/layout_events.h | 16 +- .../ion/keyboard/layout_B3/layout_events.h | 12 +- ion/include/ion/storage.h | 1 - kandinsky/include/kandinsky/color.h | 2 +- kandinsky/include/kandinsky/context.h | 5 +- kandinsky/include/kandinsky/ion_context.h | 1 - python/port/genhdr/qstrdefs.in.h | 2 + python/port/helpers.cpp | 3 + python/port/mod/kandinsky/modkandinsky.cpp | 139 ++++- python/port/mod/kandinsky/modkandinsky.h | 2 + .../port/mod/kandinsky/modkandinsky_table.c | 4 + python/port/port.cpp | 498 +++++++++++++++++- python/port/port.h | 208 ++++++++ 15 files changed, 958 insertions(+), 41 deletions(-) diff --git a/apps/external/extapp_api.cpp b/apps/external/extapp_api.cpp index 1e7fd7aeb..03cbef00a 100644 --- a/apps/external/extapp_api.cpp +++ b/apps/external/extapp_api.cpp @@ -81,5 +81,87 @@ extern "C" void (* const apiPointers[])(void) = { (void (*)(void)) extapp_waitForVBlank, (void (*)(void)) extapp_clipboardStore, (void (*)(void)) extapp_clipboardText, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + (void (*)(void)) nullptr, + + // khicas from here, subject to change + (void (*)(void)) numworks_draw_string, + (void (*)(void)) numworks_draw_string_small, + (void (*)(void)) numworks_set_pixel, + (void (*)(void)) numworks_fill_rect, + (void (*)(void)) numworks_get_pixel, + (void (*)(void)) numworks_hide_graph, + (void (*)(void)) numworks_wait_1ms, + (void (*)(void)) waitforvblank, + (void (*)(void)) statuslinemsg, + (void (*)(void)) statusline, + (void (*)(void)) getkey, + (void (*)(void)) GetKey, + (void (*)(void)) alphawasactive, + (void (*)(void)) lock_alpha, + (void (*)(void)) reset_kbd, + (void (*)(void)) back_key_pressed, + (void (*)(void)) enable_back_interrupt, + (void (*)(void)) disable_back_interrupt, + (void (*)(void)) os_set_angle_unit, + (void (*)(void)) os_get_angle_unit, + (void (*)(void)) os_file_browser, + (void (*)(void)) file_exists, + (void (*)(void)) erase_file, + (void (*)(void)) read_file, + (void (*)(void)) write_file, + (void (*)(void)) mp_hal_input, (void (*)(void)) nullptr }; diff --git a/ion/include/ion/events.h b/ion/include/ion/events.h index 92905e9ca..ec55f9ea4 100644 --- a/ion/include/ion/events.h +++ b/ion/include/ion/events.h @@ -138,6 +138,25 @@ constexpr Event Arctangent = Event::ShiftKey(Keyboard::Key::Tangent); constexpr Event Equal = Event::ShiftKey(Keyboard::Key::Pi); constexpr Event Lower = Event::ShiftKey(Keyboard::Key::Sqrt); constexpr Event Greater = Event::ShiftKey(Keyboard::Key::Square); +constexpr Event shiftans = Event::ShiftKey(Keyboard::Key::Ans); +constexpr Event shiftplus = Event::ShiftKey(Keyboard::Key::Plus); +constexpr Event shiftfois = Event::ShiftKey(Keyboard::Key::Multiplication); +constexpr Event shiftdiv = Event::ShiftKey(Keyboard::Key::Division); +constexpr Event shiftminus = Event::ShiftKey(Keyboard::Key::Minus); +constexpr Event shift1 = Event::ShiftKey(Keyboard::Key::One); +constexpr Event shift2 = Event::ShiftKey(Keyboard::Key::Two); +constexpr Event shift3 = Event::ShiftKey(Keyboard::Key::Three); +constexpr Event shift4 = Event::ShiftKey(Keyboard::Key::Four); +constexpr Event shift5 = Event::ShiftKey(Keyboard::Key::Five); +constexpr Event shift6 = Event::ShiftKey(Keyboard::Key::Six); +constexpr Event shift7 = Event::ShiftKey(Keyboard::Key::Seven); +constexpr Event shift8 = Event::ShiftKey(Keyboard::Key::Eight); +constexpr Event shift9 = Event::ShiftKey(Keyboard::Key::Nine); +constexpr Event shift0 = Event::ShiftKey(Keyboard::Key::Zero); +constexpr Event shiftdot = Event::ShiftKey(Keyboard::Key::Dot); +constexpr Event shiftee = Event::ShiftKey(Keyboard::Key::EE); +constexpr Event shiftlp = Event::ShiftKey(Keyboard::Key::LeftParenthesis); +constexpr Event shiftrp = Event::ShiftKey(Keyboard::Key::RightParenthesis); constexpr Event BrightnessPlus = Event::ShiftKey(Keyboard::Key::Plus); constexpr Event BrightnessMinus = Event::ShiftKey(Keyboard::Key::Minus); @@ -161,7 +180,6 @@ constexpr Event ShiftThree = Event::ShiftKey(Keyboard::Key::Three); constexpr Event Colon = Event::AlphaKey(Keyboard::Key::XNT); constexpr Event SemiColon = Event::AlphaKey(Keyboard::Key::Var); constexpr Event DoubleQuotes = Event::AlphaKey(Keyboard::Key::Toolbox); -constexpr Event Percent = Event::AlphaKey(Keyboard::Key::Backspace); constexpr Event LowerA = Event::AlphaKey(Keyboard::Key::Exp); constexpr Event LowerB = Event::AlphaKey(Keyboard::Key::Ln); @@ -197,8 +215,11 @@ constexpr Event Space = Event::AlphaKey(Keyboard::Key::Minus); constexpr Event Question = Event::AlphaKey(Keyboard::Key::Zero); constexpr Event Exclamation = Event::AlphaKey(Keyboard::Key::Dot); +constexpr Event alphaans = Event::AlphaKey(Keyboard::Key::Ans); // Shift + Alpha +constexpr Event Percent = Event::ShiftAlphaKey(Keyboard::Key::Back); +constexpr Event SimpleQuote = Event::ShiftAlphaKey(Keyboard::Key::Toolbox); constexpr Event UpperA = Event::ShiftAlphaKey(Keyboard::Key::Exp); constexpr Event UpperB = Event::ShiftAlphaKey(Keyboard::Key::Ln); @@ -231,6 +252,7 @@ constexpr Event UpperX = Event::ShiftAlphaKey(Keyboard::Key::Two); constexpr Event UpperY = Event::ShiftAlphaKey(Keyboard::Key::Three); constexpr Event UpperZ = Event::ShiftAlphaKey(Keyboard::Key::Plus); +constexpr Event shiftalphaans = Event::ShiftAlphaKey(Keyboard::Key::Ans); // Special constexpr Event None = Event::Special(0); diff --git a/ion/include/ion/keyboard/layout_B2/layout_events.h b/ion/include/ion/keyboard/layout_B2/layout_events.h index 3a1f75260..01338d947 100644 --- a/ion/include/ion/keyboard/layout_B2/layout_events.h +++ b/ion/include/ion/keyboard/layout_B2/layout_events.h @@ -25,30 +25,30 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - TL(), TL(), TL(), T("(\x11)"), U(), U(), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), TL(), TL(), U(), - U(), U(), U(), U(), U(), U(), + T("17"), T("18"), T("19"), T("20"), T("21"), U(), + T("14"), T("15"), T("16"), T("factor(\x11)"), T("%"), U(), + T("11"), T("12"), T("13"), T("normal(\x11)"), T("\\"), U(), + T("10"), T("11"), T("12"), T("20"), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), T(":"), T(";"), T("\""), T("%"), + U(), U(), T(":"), T(";"), T("\""), U(), T("a"), T("b"), T("c"), T("d"), T("e"), T("f"), T("g"), T("h"), T("i"), T("j"), T("k"), T("l"), T("m"), T("n"), T("o"), T("p"), T("q"), U(), T("r"), T("s"), T("t"), T("u"), T("v"), U(), T("w"), T("x"), T("y"), T("z"), T(" "), U(), - T("?"), T("!"), U(), U(), U(), U(), + T("?"), T("!"), U(), TL(), U(), U(), // Shift+Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), U(), T("'"), T("%"), T("A"), T("B"), T("C"), T("D"), T("E"), T("F"), T("G"), T("H"), T("I"), T("J"), T("K"), T("L"), T("M"), T("N"), T("O"), T("P"), T("Q"), U(), T("R"), T("S"), T("T"), T("U"), T("V"), U(), T("W"), T("X"), T("Y"), T("Z"), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), TL(), U(), U(), }; #if DEBUG diff --git a/ion/include/ion/keyboard/layout_B3/layout_events.h b/ion/include/ion/keyboard/layout_B3/layout_events.h index a1f9502fa..fc9f20fe2 100644 --- a/ion/include/ion/keyboard/layout_B3/layout_events.h +++ b/ion/include/ion/keyboard/layout_B3/layout_events.h @@ -25,14 +25,14 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), U(), U(), U(), - TL(), TL(), TL(), TL(), TL(), U(), - U(), U(), U(), U(), U(), U(), + T("17"), T("18"), T("19"), T("20"), T("21"), U(), + T("14"), T("15"), T("16"), T("factor(\x11)"), T("%"), U(), + T("11"), T("12"), T("13"), T("normal(\x11)"), T("\\"), U(), + T("10"), T("11"), T("12"), T("20"), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), T(":"), T(";"), T("\""), T("%"), + U(), U(), T(":"), T(";"), T("\""), U(), T("a"), T("b"), T("c"), T("d"), T("e"), T("f"), T("g"), T("h"), T("i"), T("j"), T("k"), T("l"), T("m"), T("n"), T("o"), T("p"), T("q"), U(), @@ -42,7 +42,7 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { // Shift+Alpha U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + U(), U(), U(), U(), T("'"), T("%"), T("A"), T("B"), T("C"), T("D"), T("E"), T("F"), T("G"), T("H"), T("I"), T("J"), T("K"), T("L"), T("M"), T("N"), T("O"), T("P"), T("Q"), U(), diff --git a/ion/include/ion/storage.h b/ion/include/ion/storage.h index 5138c1b76..fedd6ba35 100644 --- a/ion/include/ion/storage.h +++ b/ion/include/ion/storage.h @@ -115,7 +115,6 @@ public: void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension); void destroyRecordsWithExtension(const char * extension); -private: constexpr static uint32_t Magic = 0xEE0BDDBA; constexpr static size_t k_maxRecordSize = (1 << sizeof(record_size_t)*8); diff --git a/kandinsky/include/kandinsky/color.h b/kandinsky/include/kandinsky/color.h index 8e1cafa50..d15835ae7 100644 --- a/kandinsky/include/kandinsky/color.h +++ b/kandinsky/include/kandinsky/color.h @@ -34,8 +34,8 @@ public: static KDColor blend(KDColor first, KDColor second, uint8_t alpha); KDColor invert() const { return KDColor(~m_value); } operator uint16_t() const { return m_value; } -private: constexpr KDColor(uint16_t value) : m_value(value) {} +private: uint16_t m_value; }; diff --git a/kandinsky/include/kandinsky/context.h b/kandinsky/include/kandinsky/context.h index bcfc4ee74..9e267cea0 100644 --- a/kandinsky/include/kandinsky/context.h +++ b/kandinsky/include/kandinsky/context.h @@ -33,13 +33,10 @@ public: void fillRectWithPixels(KDRect rect, const KDColor * pixels, KDColor * workingBuffer); void blendRectWithMask(KDRect rect, KDColor color, const uint8_t * mask, KDColor * workingBuffer); void strokeRect(KDRect rect, KDColor color); - + KDContext(KDPoint origin, KDRect clippingRect); virtual void pushRect(KDRect, const KDColor * pixels) = 0; virtual void pushRectUniform(KDRect rect, KDColor color) = 0; virtual void pullRect(KDRect rect, KDColor * pixels) = 0; -protected: - KDContext(KDPoint origin, KDRect clippingRect); -private: KDRect absoluteFillRect(KDRect rect); KDPoint pushOrPullString(const char * text, KDPoint p, const KDFont * font, KDColor textColor, KDColor backgroundColor, int maxByteLength, bool push, int * result = nullptr); KDPoint m_origin; diff --git a/kandinsky/include/kandinsky/ion_context.h b/kandinsky/include/kandinsky/ion_context.h index 5cfd6cd9e..0dc1774fb 100644 --- a/kandinsky/include/kandinsky/ion_context.h +++ b/kandinsky/include/kandinsky/ion_context.h @@ -27,7 +27,6 @@ public: bool zoomInhibit; bool gammaEnabled; int zoomPosition; -private: KDIonContext(); void pushRect(KDRect rect, const KDColor * pixels) override; void pushRectUniform(KDRect rect, KDColor color) override; diff --git a/python/port/genhdr/qstrdefs.in.h b/python/port/genhdr/qstrdefs.in.h index 58c36bc71..5b96067ed 100644 --- a/python/port/genhdr/qstrdefs.in.h +++ b/python/port/genhdr/qstrdefs.in.h @@ -129,6 +129,8 @@ Q(.) Q(EE) Q(Ans) Q(EXE) +Q(get_key) +Q(Pause) // Turtle QSTRs Q(turtle) diff --git a/python/port/helpers.cpp b/python/port/helpers.cpp index 438f7ca47..71fb5e879 100644 --- a/python/port/helpers.cpp +++ b/python/port/helpers.cpp @@ -1,5 +1,8 @@ #include "helpers.h" #include +#ifdef SIMULATOR +#include +#endif extern "C" { #include "mphalport.h" } diff --git a/python/port/mod/kandinsky/modkandinsky.cpp b/python/port/mod/kandinsky/modkandinsky.cpp index 469fdb86b..6b8a3db5c 100644 --- a/python/port/mod/kandinsky/modkandinsky.cpp +++ b/python/port/mod/kandinsky/modkandinsky.cpp @@ -8,19 +8,22 @@ extern "C" { #include "port.h" static KDColor ColorForTuple(mp_obj_t tuple) { - size_t len; - mp_obj_t * elem; + if (MP_OBJ_IS_SMALL_INT(tuple)) // BP change: accept int for color + return MP_OBJ_SMALL_INT_VALUE(tuple); - mp_obj_get_array(tuple, &len, &elem); - if (len != 3) { - mp_raise_TypeError("color needs 3 components"); - } + size_t len; + mp_obj_t * elem; - return KDColor::RGB888( - mp_obj_get_int(elem[0]), - mp_obj_get_int(elem[1]), - mp_obj_get_int(elem[2]) - ); + mp_obj_get_array(tuple, &len, &elem); + if (len != 3) { + mp_raise_TypeError("color needs 3 components"); + } + + return KDColor::RGB888( + mp_obj_get_int(elem[0]), + mp_obj_get_int(elem[1]), + mp_obj_get_int(elem[2]) + ); } static mp_obj_t TupleForRGB(uint8_t r, uint8_t g, uint8_t b) { @@ -179,3 +182,117 @@ mp_obj_t modkandinsky_get_keys() { return result; } + +/* C-- SDK (c) B. Parisse, 2019 */ +mp_obj_t modkandinsky_Pause(mp_obj_t x) { + double d=mp_obj_get_float(x); + numworks_wait_1ms(d*1000); + return mp_const_none; +} + +#define LCD_WIDTH_PX 320 +#define LCD_HEIGHT_PX 222 + +void numworks_set_pixel(int x, int y, int color) { + if (x<0 || x>=LCD_WIDTH_PX || y<0 || y>=LCD_HEIGHT_PX) + return; + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,0)); + KDColor c(color); + KDPoint point(x,y+18); + KDIonContext::sharedContext()->pushRect(KDRect(point, 1, 1), &c); + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +void numworks_fill_rect(int x,int y,int w,int h,int c){ + KDColor color = c; + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,0)); +#if 1 + if (x<0){ + w += x; + x=0; + } + if (y<0){ + h += y; + y=0; + } + if (h+y>=LCD_HEIGHT_PX) + h=LCD_HEIGHT_PX-y; + if (x+w>=LCD_WIDTH_PX) + w=LCD_WIDTH_PX-x; + if (h<=0 || w<=0) + return; + KDRect rect(x,y+18,w,h); + KDIonContext::sharedContext()->pushRectUniform(rect,color); +#else + KDRect rect(x,y,w,h); + KDIonContext::sharedContext()->fillRect(rect, color); +#endif + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +int numworks_get_pixel(int x, int y) { + KDPoint point(x,y); + KDColor c = KDIonContext::sharedContext()->getPixel(point); + return c; +} + +int numworks_draw_string(int x,int y,int c,int bg,const char * text,bool fake){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + KDPoint point(x,y); + if (ptr) + ptr->displaySandbox(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,18,320,fake?0:222)); + ctx->setOrigin(KDPoint(0,18)); + point=KDIonContext::sharedContext()->drawString(text, point, KDFont::LargeFont, c, bg); + ctx->setClippingRect(save); + ctx->setOrigin(o); + return point.x(); +} + +int numworks_draw_string_small(int x,int y,int c,int bg,const char * text,bool fake){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + KDPoint point(x,y); + if (ptr) + ptr->displaySandbox(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,18,320,fake?0:222)); + ctx->setOrigin(KDPoint(0,18)); + point=ctx->drawString(text, point, KDFont::SmallFont, c, bg); + ctx->setClippingRect(save); + ctx->setOrigin(o); + return point.x(); +} + +void numworks_hide_graph(){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + if (ptr) + ptr->hideSandbox(); +} + +void numworks_show_graph(){ + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + if (ptr) + ptr->displaySandbox(); +} + +// Python module get_key() addition +mp_obj_t modkandinsky_get_key() { + micropython_port_interrupt_if_needed(); + int key=getkey(false); // no suspend + return mp_obj_new_int(key); +} diff --git a/python/port/mod/kandinsky/modkandinsky.h b/python/port/mod/kandinsky/modkandinsky.h index 4191155bc..15bc28a31 100644 --- a/python/port/mod/kandinsky/modkandinsky.h +++ b/python/port/mod/kandinsky/modkandinsky.h @@ -7,3 +7,5 @@ mp_obj_t modkandinsky_draw_string(size_t n_args, const mp_obj_t *args); mp_obj_t modkandinsky_fill_rect(size_t n_args, const mp_obj_t *args); mp_obj_t modkandinsky_wait_vblank(); mp_obj_t modkandinsky_get_keys(); +mp_obj_t modkandinsky_get_key(); +mp_obj_t modkandinsky_Pause(mp_obj_t x) ; diff --git a/python/port/mod/kandinsky/modkandinsky_table.c b/python/port/mod/kandinsky/modkandinsky_table.c index 253f856a7..cf8490c6f 100644 --- a/python/port/mod/kandinsky/modkandinsky_table.c +++ b/python/port/mod/kandinsky/modkandinsky_table.c @@ -7,6 +7,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_draw_string_obj, 3, 5, m STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modkandinsky_fill_rect_obj, 5, 5, modkandinsky_fill_rect); STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_wait_vblank_obj, modkandinsky_wait_vblank); STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_get_keys_obj, modkandinsky_get_keys); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(modkandinsky_get_key_obj, modkandinsky_get_key); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(modkandinsky_Pause_obj, modkandinsky_Pause); STATIC const mp_rom_map_elem_t modkandinsky_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_kandinsky) }, @@ -17,6 +19,8 @@ STATIC const mp_rom_map_elem_t modkandinsky_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_fill_rect), (mp_obj_t)&modkandinsky_fill_rect_obj }, { MP_ROM_QSTR(MP_QSTR_wait_vblank), (mp_obj_t)&modkandinsky_wait_vblank_obj }, { MP_ROM_QSTR(MP_QSTR_get_keys), (mp_obj_t)&modkandinsky_get_keys_obj }, + { MP_ROM_QSTR(MP_QSTR_get_key), (mp_obj_t)&modkandinsky_get_key_obj }, + { MP_ROM_QSTR(MP_QSTR_Pause), (mp_obj_t)&modkandinsky_Pause_obj }, }; STATIC MP_DEFINE_CONST_DICT(modkandinsky_module_globals, modkandinsky_module_globals_table); diff --git a/python/port/port.cpp b/python/port/port.cpp index 163aefd24..0a1735bdd 100644 --- a/python/port/port.cpp +++ b/python/port/port.cpp @@ -1,6 +1,14 @@ +#ifdef SIMULATOR +#include +#endif +#include #include "port.h" -#include +#include +#include +#include +#include "../../apps/apps_container.h" +#include "../../apps/global_preferences.h" #include #include @@ -78,9 +86,9 @@ void MicroPython::ExecutionEnvironment::runCode(const char * str) { /* End of mp_obj_print_exception. */ } - assert(sCurrentExecutionEnvironment == this); - sCurrentExecutionEnvironment = nullptr; -} + assert(sCurrentExecutionEnvironment == this); + sCurrentExecutionEnvironment = nullptr; + } void MicroPython::ExecutionEnvironment::interrupt() { mp_keyboard_interrupt(); @@ -197,11 +205,485 @@ mp_import_stat_t mp_import_stat(const char *path) { } void mp_hal_stdout_tx_strn_cooked(const char * str, size_t len) { - assert(sCurrentExecutionEnvironment != nullptr); - sCurrentExecutionEnvironment->printText(str, len); + if (sCurrentExecutionEnvironment != nullptr) + sCurrentExecutionEnvironment->printText(str, len); } const char * mp_hal_input(const char * prompt) { - assert(sCurrentExecutionEnvironment != nullptr); - return sCurrentExecutionEnvironment->inputText(prompt); + if (sCurrentExecutionEnvironment != nullptr) + return sCurrentExecutionEnvironment->inputText(prompt); + return 0; } + +/* C-- SDK , (c) B. Parisse 2019 */ + +const char * read_file(const char * filename){ +#if 1 + Ion::Storage * s=Ion::Storage::sharedStorage(); + const Ion::Storage::Record r=s->recordNamed(filename); + if (r.isNull()) + return 0; + Ion::Storage::Record::Data d=r.value(); + const char * ptr=(const char *)d.buffer; + if (ptr) + return ptr+1; + else + return 0; +#endif + if (sScriptProvider != nullptr) + return sScriptProvider->contentOfScript(filename); + return "undef"; +} + +bool write_file(const char * filename,const char * content,size_t len){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + auto res=s->createRecordWithFullName(filename,content,strlen(content)+1); + if (res==Ion::Storage::Record::ErrorStatus::NameTaken){ + auto r=s->recordNamed(filename); + Ion::Storage::Record::Data d; + d.buffer=content; + d.size=(len?len:strlen(content))+1; + return r.setValue(d)==Ion::Storage::Record::ErrorStatus::None; + } + if (res==Ion::Storage::Record::ErrorStatus::None) + return write_file(filename,content,len); + return false; +} + +bool file_exists(const char * filename){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + return s->isFullNameTaken(filename); +} + +bool erase_file(const char * filename){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + auto r= s->recordNamed(filename); + if (r.isNull()) + return false; + r.destroy(); + return true; +} + + +#if 1 +int os_file_browser(const char ** filenames,int maxrecords,const char * extension){ + Ion::Storage * s=Ion::Storage::sharedStorage(); + int n=s->numberOfRecordsWithExtension(extension); + if (!n) return 0; + if (n>maxrecords) n=maxrecords; + for (int i=0;irecordWithExtensionAtIndex(extension, i); + filenames[i]=r.fullName(); + } + filenames[n]=0; + return n; +} + // const char * ptr=(const char *)r.value().buffer; + /* storage.h + Ion::Storage::Record::Data structure avec 2 membres + const void * buffer et size_t size + + Record(const char * fullName = nullptr); + Record(const char * basename, const char * extension); + Data value(); + Ion::Storage::Record::ErrorStatus setValue(Ion::Storage::Record::Data); + void destroy(void); + + // Record creation + Record::ErrorStatus createRecordWithFullName(const char * fullName, const void * data, size_t size); + Record::ErrorStatus createRecordWithExtension(const char * baseName, const char * extension, const void * data, size_t size); + + // Record getters + Record recordWithExtensionAtIndex(const char * extension, int index); + Record recordNamed(const char * fullName); + Record recordBaseNamedWithExtension(const char * baseName, const char * extension); + Record recordBaseNamedWithExtensions(const char * baseName, const char * const extension[], size_t numberOfExtensions); + + // Record destruction + void destroyAllRecords(); + void destroyRecordWithBaseNameAndExtension(const char * baseName, const char * extension); + void destroyRecordsWithExtension(const char * extension); + + + */ +#endif + +void statuslinemsg(const char * msg){ + AppsContainer::sharedAppsContainer()->reloadTitleBarView(); + auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment(); + if (ptr) + ptr->displaySandbox(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,280,18)); + ctx->setOrigin(KDPoint(0,0)); + KDRect rect(0,0,280,18); + KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + if (strlen(msg)>25) + ctx->drawString(msg, KDPoint(0,0), KDFont::SmallFont, 0, 64934); + else + ctx->drawString(msg, KDPoint(0,0), KDFont::LargeFont, 0, 64934); + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +bool os_set_angle_unit(int mode){ + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + if (mode==0){ // rad + preferences->setAngleUnit(Poincare::Preferences::AngleUnit::Radian); + return true; + } + if (mode==1){ // deg + preferences->setAngleUnit(Poincare::Preferences::AngleUnit::Degree); + return true; + } + return false; + if (mode==2){ // grad + return true; + } +} + +int os_get_angle_unit(){ + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + if (preferences->angleUnit()==Poincare::Preferences::AngleUnit::Radian) + return 0; + if (preferences->angleUnit()==Poincare::Preferences::AngleUnit::Degree) + return 1; + return 2; +} + +#ifdef SIMULATOR +#define TICKS_PER_MINUTE 60000 +#else +#define TICKS_PER_MINUTE 11862 +extern const void * _stack_start; +extern const void * _heap_start; +#endif +//int time_shift=0; // set it via time() command in KhiCAS +void statusline(int mode, size_t heap){ + AppsContainer::sharedAppsContainer()->reloadTitleBarView(); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,18)); + ctx->setOrigin(KDPoint(0,0)); + KDRect rect(0,0,mode==1?320:280,18); + KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + const char * text=0; + Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); + if (preferences->angleUnit() == Poincare::Preferences::AngleUnit::Radian) + text="rad"; + else + text="deg"; + // ctx->drawString(text, KDPoint(5,1), KDFont::SmallFont, 0, 63488 /* Palette::Red*/); + ctx->drawString(text, KDPoint(5,1), KDFont::SmallFont, 0, 64934); +#ifdef GIAC_LINKED + if (khicas_eval) + text="KHICAS"; + else + text="PYTHON"; +#else + text="KHICAS"; +#endif + ctx->drawString(text, KDPoint(70,1), KDFont::SmallFont, 0, 64934); + char bufheap[16]; +#if 0 //ndef SIMULATOR +#endif + int x; + x=(heap&0xf0000000)>>28; + bufheap[0]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf000000)>>24; + bufheap[1]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf00000)>>20; + bufheap[2]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf0000)>>16; + bufheap[3]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf000)>>12; + bufheap[4]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf00)>>8; + bufheap[5]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf0)>>4; + bufheap[6]=(x>9?'a'+(x-10):'0'+x); + x=(heap&0xf); + bufheap[7]=(x>9?'a'+(x-10):'0'+x); + bufheap[8]=0; + if(heap != 0) ctx->drawString(bufheap,KDPoint(130,1),KDFont::SmallFont, 0, 64934); +#ifdef GIAC_SHOWTIME + int d=(Ion::Timing::millis()/TICKS_PER_MINUTE +time_shift) % (24*60); // minutes + char buf[32]={0,0,0,0}; + int h=d/60; + buf[0]='0'+h/10; + buf[1]='0'+(h%10); + buf[2]=':'; + ctx->drawString(buf, KDPoint(148,1), KDFont::SmallFont, 0, 64934); + int mn=d%60; + buf[0]='0'+mn/10; + buf[1]='0'+(mn%10); + buf[2]=0; + ctx->drawString(buf, KDPoint(168,1), KDFont::SmallFont, 0, 64934); +#endif + text=" "; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::Shift) + text="shift "; + else { + if (Ion::Events::isAlphaActive()){ + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::AlphaLock) + text="alphal"; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::ShiftAlphaLock) + text="ALPHAL"; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::Alpha) + text="1alpha"; + if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::ShiftAlpha) + text="1ALPHA"; + } + } + ctx->drawString(text, KDPoint(232,1), KDFont::SmallFont, 0, 64934 /* Palette::YellowDark*/); + if (mode==1){ + if (Ion::USB::isPlugged()) + text="charge"; + else { + auto c=Ion::Battery::level(); + if (c==Ion::Battery::Charge::EMPTY) + text="empty "; + if (c==Ion::Battery::Charge::LOW) + text="low "; + if (c==Ion::Battery::Charge::FULL) + text="full "; + } + ctx->drawString(text, KDPoint(280,1), KDFont::SmallFont, 0, 64934 /* Palette::YellowDark*/); + } + ctx->setClippingRect(save); + ctx->setOrigin(o); +} + +bool isalphaactive(){ + return Ion::Events::isAlphaActive(); +} + +void lock_alpha(){ + Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock); + statusline(0,0); +} + +void reset_kbd(){ + Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default); + statusline(0,0); +} + +bool alphawasactive_=false; +bool alphawasactive(){ + return alphawasactive_; +} + +bool waitforvblank(){ + return Ion::Display::waitForVBlank(); +} + +bool back_key_pressed() { + static int c = 0; + + ++c ; + if (c<400 || (c & 0xf)!= 0) { + return false; + } +#ifdef SIMULATOR + Fl::wait(0.00001); +#endif + + Ion::Keyboard::State scan = Ion::Keyboard::scan(); + // if (scan!=16) std::cerr << scan << '\n'; + Ion::Keyboard::Key interruptKey = static_cast(mp_interrupt_char); + if (scan.keyDown(interruptKey) + // || scan.keyDown(static_cast(16)) + ) + return true; + return false; +} + +int getkey_raw(bool allow_suspend){ + int key=-1; + size_t t1=Ion::Timing::millis(); + for (;;){ + int timeout=10000; + alphawasactive_=Ion::Events::isAlphaActive(); + Ion::Events::Event event=Ion::Events::getEvent(&timeout); + auto ctx=KDIonContext::sharedContext(); + KDRect save=ctx->m_clippingRect; + KDPoint o=ctx->m_origin; + ctx->setClippingRect(KDRect(0,0,320,240)); + ctx->setOrigin(KDPoint(0,18)); + KDRect rect(90,63,140,75); + if (event==Ion::Events::None){ + size_t t2=Ion::Timing::millis(); + if (t2-t1>2*TICKS_PER_MINUTE){ + // KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + event=Ion::Events::OnOff; + } + } + else + t1=Ion::Timing::millis(); + if (event == Ion::Events::USBPlug) { + statusline(0,0); + // KDIonContext::sharedContext()->pushRectUniform(rect,33333); + if (Ion::USB::isPlugged()) { + if (GlobalPreferences::sharedGlobalPreferences()->examMode()) { + Ion::LED::setColor(KDColorBlack); + Ion::LED::updateColorWithPlugAndCharge(); + GlobalPreferences::sharedGlobalPreferences()->setExamMode(false); + // displayExamModePopUp(false); + } else { + Ion::USB::enable(); + } + Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); + } else { + Ion::USB::disable(); + } + } + if (event == Ion::Events::USBEnumeration || event == Ion::Events::USBPlug || event == Ion::Events::BatteryCharging) { + Ion::LED::updateColorWithPlugAndCharge(); + } + if (event == Ion::Events::USBEnumeration + ) { + KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/); + if (Ion::USB::isPlugged()) { + /* Just after a software update, the battery timer does not have time to + * fire before the calculator enters DFU mode. As the DFU mode blocks the + * event loop, we update the battery state "manually" here. + * We do it before switching to USB application to redraw the battery + * pictogram. */ + // updateBatteryState(); + KDIonContext::sharedContext()->pushRectUniform(rect,22222); + auto ctx=KDIonContext::sharedContext(); + int y=58; + ctx->drawString("Connecte ! ", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + y+=18; + ctx->drawString(" DFU mode ", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + y+=18; + ctx->drawString("Back quitte", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + y-=18; + Ion::USB::DFU(); + KDIonContext::sharedContext()->pushRectUniform(rect,44444); + ctx->drawString("Deconnecte!", KDPoint(100,y), KDFont::LargeFont, 65535, 0); + // Update LED when exiting DFU mode + Ion::LED::updateColorWithPlugAndCharge(); + } else { + /* Sometimes, the device gets an ENUMDNE interrupts when being unplugged + * from a non-USB communicating host (e.g. a USB charger). The interrupt + * must me cleared: if not the next enumeration attempts will not be + * detected. */ + Ion::USB::clearEnumerationInterrupt(); + } + } + if (event.isKeyboardEvent()) { + // m_backlightDimmingTimer.reset(); + // m_suspendTimer.reset(); + Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); + } + ctx->setClippingRect(save); + ctx->setOrigin(o); + + if (event==Ion::Events::Shift || event==Ion::Events::Alpha){ + statusline(0,0); + continue; + } + if (event.isKeyboardEvent()){ + key=event.id(); + if (key==17 || key==4 || key==5 || key==52) + reset_kbd(); + if (allow_suspend && (key==7 || key==8) ){ // power + Ion::Power::suspend(true); + numworks_fill_rect(0,0,320,240,65535); + Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()); + AppsContainer::sharedAppsContainer()->reloadTitleBarView(); + //AppsContainer::sharedAppsContainer()->redrawWindow(); + statusline(1,0); + //continue; + } + else + statusline(0,0); + break; + } + } + return key; +} + +const short int translated_keys[]= + { + // non shifted + KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_XTT,KEY_CTRL_VARS,KEY_CTRL_CATALOG,KEY_CTRL_DEL, + KEY_CHAR_EXPN,KEY_CHAR_LN,KEY_CHAR_LOG,KEY_CHAR_IMGNRY,',',KEY_CHAR_POW, + KEY_CHAR_SIN,KEY_CHAR_COS,KEY_CHAR_TAN,KEY_CHAR_PI,KEY_CHAR_ROOT,KEY_CHAR_SQUARE, + '7','8','9','(',')',-1, + '4','5','6','*','/',-1, + '1','2','3','+','-',-1, + '0','.',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, + // shifted + KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_CUT,KEY_CTRL_CLIP,KEY_CTRL_PASTE,KEY_CTRL_AC, + KEY_CHAR_LBRCKT,KEY_CHAR_RBRCKT,KEY_CHAR_LBRACE,KEY_CHAR_RBRACE,'_',KEY_CHAR_STORE, + KEY_CHAR_ASIN,KEY_CHAR_ACOS,KEY_CHAR_ATAN,'=','<','>', + KEY_CTRL_F7,KEY_CTRL_F8,KEY_CTRL_F9,KEY_CTRL_F13,KEY_CTRL_F14,-1, + KEY_CTRL_F4,KEY_CTRL_F5,KEY_CTRL_F6,KEY_CHAR_FACTOR,'%',-1, + KEY_CTRL_F1,KEY_CTRL_F2,KEY_CTRL_F3,KEY_CHAR_NORMAL,'\\',-1, + KEY_CTRL_F10,KEY_CTRL_F11,KEY_CTRL_F12,KEY_SHIFT_ANS,KEY_CTRL_EXE,-1, + // alpha + KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','"',KEY_CTRL_DEL, + 'a','b','c','d','e','f', + 'g','h','i','j','k','l', + 'm','n','o','p','q',-1, + 'r','s','t','u','v',-1, + 'w','x','y','z',' ',-1, + '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, + // alpha shifted + KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT, + KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11, + KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','\'','%', + 'A','B','C','D','E','F', + 'G','H','I','J','K','L', + 'M','N','O','P','Q',-1, + 'R','S','T','U','V',-1, + 'W','X','Y','Z',' ',-1, + '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1, + }; + +int getkey(bool allow_suspend){ + int k=getkey_raw(allow_suspend); + // translate + return translated_keys[k]; +} + +// Casio prototype +void GetKey(int * key){ + *key=getkey(true); +} + + +void numworks_wait_1ms(int ms){ + for (int i=0;i(Ion::Keyboard::Key::Back); + if (scan.keyDown(interruptKey)) + return; + Ion::Timing::msleep(128); + } + Ion::Timing::msleep(ms % 128); +} + +void enable_back_interrupt(){ + mp_interrupt_char = (int)Ion::Keyboard::Key::Back; +} + +void disable_back_interrupt(){ + mp_interrupt_char = -1; +} + diff --git a/python/port/port.h b/python/port/port.h index f0b3a0407..869b6f937 100644 --- a/python/port/port.h +++ b/python/port/port.h @@ -36,4 +36,212 @@ void registerScriptProvider(ScriptProvider * s); }; +extern "C" { +/* + basic SDK for direct control of the calculator like in KhiCAS + */ + bool waitforvblank(); + int os_file_browser(const char ** filenames,int maxrecords,const char * extension); + void numworks_hide_graph(); + void numworks_show_graph(); + void enable_back_interrupt(); + void disable_back_interrupt(); + int os_get_angle_unit(); + bool os_set_angle_unit(int mode); + const char * read_file(const char * filename); + bool write_file(const char * filename,const char * content,size_t len); +int getkey_raw(bool allow_suspend); // Numworks scan code +int getkey(bool allow_suspend); // transformed +void GetKey(int * key); // Casio like +bool isalphaactive(); +bool alphawasactive(); // alpha status before getkey +bool back_key_pressed() ; +void lock_alpha(); +void reset_kbd(); +void statusline(int mode=0, size_t=0); // display status line +void statuslinemsg(const char * msg); // display a message in statusline +void numworks_fill_rect(int x,int y,int w,int h,int c); // y=0 is automatically translated by 18 for statusline +void numworks_set_pixel(int x,int y,int c); +int numworks_get_pixel(int x,int y); +/* draw_string returns new x position, use fake=true to compute without drawing */ +int numworks_draw_string(int x,int y,int c,int bg,const char * s,bool fake=false); +int numworks_draw_string_small(int x,int y,int c,int bg,const char * s,bool fake=false); +// scriptstore +bool file_exists(const char * filename); +bool erase_file(const char * filename); +const char * read_file(const char * filename); +bool write_file(const char * filename,const char * s,size_t len=0); +int giac_filebrowser(char * filename,const char * extension,const char * title); +void numworks_wait_1ms(int ms); +//double millis(); +//extern int time_shift; // shift for the clock + + +// Character codes +#define KEY_CHAR_0 0x30 +#define KEY_CHAR_1 0x31 +#define KEY_CHAR_2 0x32 +#define KEY_CHAR_3 0x33 +#define KEY_CHAR_4 0x34 +#define KEY_CHAR_5 0x35 +#define KEY_CHAR_6 0x36 +#define KEY_CHAR_7 0x37 +#define KEY_CHAR_8 0x38 +#define KEY_CHAR_9 0x39 +#define KEY_CHAR_DP 0x2e +#define KEY_CHAR_EXP 0x0f +#define KEY_CHAR_PMINUS 30200 +#define KEY_CHAR_PLUS 43 +#define KEY_CHAR_MINUS 45 +#define KEY_CHAR_MULT 42 +#define KEY_CHAR_DIV 47 +#define KEY_CHAR_FRAC 0xbb +#define KEY_CHAR_LPAR 0x28 +#define KEY_CHAR_RPAR 0x29 +#define KEY_CHAR_COMMA 0x2c +#define KEY_CHAR_STORE 0x0e +#define KEY_CHAR_LOG 0x95 +#define KEY_CHAR_LN 0x85 +#define KEY_CHAR_SIN 0x81 +#define KEY_CHAR_COS 0x82 +#define KEY_CHAR_TAN 0x83 +#define KEY_CHAR_SQUARE 0x8b +#define KEY_CHAR_POW 0xa8 +#define KEY_CHAR_IMGNRY 0x7f50 +#define KEY_CHAR_LIST 0x7f51 +#define KEY_CHAR_MAT 0x7f40 +#define KEY_CHAR_EQUAL 0x3d +#define KEY_CHAR_PI 0xd0 +#define KEY_CHAR_ANS 0xc0 +#define KEY_SHIFT_ANS 0xc1 +#define KEY_CHAR_LBRCKT 0x5b +#define KEY_CHAR_RBRCKT 0x5d +#define KEY_CHAR_LBRACE 0x7b +#define KEY_CHAR_RBRACE 0x7d +#define KEY_CHAR_CR 0x0d +#define KEY_CHAR_CUBEROOT 0x96 +#define KEY_CHAR_RECIP 0x9b +#define KEY_CHAR_ANGLE 0x7f54 +#define KEY_CHAR_EXPN10 0xb5 +#define KEY_CHAR_EXPN 0xa5 +#define KEY_CHAR_ASIN 0x91 +#define KEY_CHAR_ACOS 0x92 +#define KEY_CHAR_ATAN 0x93 +#define KEY_CHAR_ROOT 0x86 +#define KEY_CHAR_POWROOT 0xb8 +#define KEY_CHAR_SPACE 0x20 +#define KEY_CHAR_DQUATE 0x22 +#define KEY_CHAR_VALR 0xcd +#define KEY_CHAR_THETA 0xce +#define KEY_CHAR_FACTOR 0xda +#define KEY_CHAR_NORMAL 0xdb +#define KEY_CHAR_A 0x41 +#define KEY_CHAR_B 0x42 +#define KEY_CHAR_C 0x43 +#define KEY_CHAR_D 0x44 +#define KEY_CHAR_E 0x45 +#define KEY_CHAR_F 0x46 +#define KEY_CHAR_G 0x47 +#define KEY_CHAR_H 0x48 +#define KEY_CHAR_I 0x49 +#define KEY_CHAR_J 0x4a +#define KEY_CHAR_K 0x4b +#define KEY_CHAR_L 0x4c +#define KEY_CHAR_M 0x4d +#define KEY_CHAR_N 0x4e +#define KEY_CHAR_O 0x4f +#define KEY_CHAR_P 0x50 +#define KEY_CHAR_Q 0x51 +#define KEY_CHAR_R 0x52 +#define KEY_CHAR_S 0x53 +#define KEY_CHAR_T 0x54 +#define KEY_CHAR_U 0x55 +#define KEY_CHAR_V 0x56 +#define KEY_CHAR_W 0x57 +#define KEY_CHAR_X 0x58 +#define KEY_CHAR_Y 0x59 +#define KEY_CHAR_Z 0x5a + + +// Control codes +#define KEY_CTRL_NOP 30202 +#define KEY_CTRL_EXE 30201 +#define KEY_CTRL_DEL 30025 +#define KEY_CTRL_AC 30070 +#define KEY_CTRL_FD 30046 +#define KEY_CTRL_UNDO 30045 +#define KEY_CTRL_XTT 30001 +#define KEY_CTRL_EXIT 5 +#define KEY_CTRL_OK 4 +#define KEY_CTRL_SHIFT 30006 +#define KEY_CTRL_ALPHA 30007 +#define KEY_CTRL_OPTN 30008 +#define KEY_CTRL_VARS 30030 +#define KEY_CTRL_UP 1 +#define KEY_CTRL_DOWN 2 +#define KEY_CTRL_LEFT 0 +#define KEY_CTRL_RIGHT 3 +#define KEY_CTRL_F1 30009 +#define KEY_CTRL_F2 30010 +#define KEY_CTRL_F3 30011 +#define KEY_CTRL_F4 30012 +#define KEY_CTRL_F5 30013 +#define KEY_CTRL_F6 30014 +#define KEY_CTRL_F7 30015 +#define KEY_CTRL_F8 30016 +#define KEY_CTRL_F9 30017 +#define KEY_CTRL_F10 30018 +#define KEY_CTRL_F11 30019 +#define KEY_CTRL_F12 30020 +#define KEY_CTRL_F13 30021 +#define KEY_CTRL_F14 30022 +#define KEY_CTRL_CATALOG 30100 +#define KEY_CTRL_CAPTURE 30055 +#define KEY_CTRL_CLIP 30050 +#define KEY_CTRL_CUT 30250 +#define KEY_CTRL_PASTE 30036 +#define KEY_CTRL_INS 30033 +#define KEY_CTRL_MIXEDFRAC 30054 +#define KEY_CTRL_FRACCNVRT 30026 +#define KEY_CTRL_QUIT 30029 +#define KEY_CTRL_PRGM 30028 +#define KEY_CTRL_SETUP 30037 +#define KEY_CTRL_PAGEUP 30052 +#define KEY_CTRL_PAGEDOWN 30053 +#define KEY_CTRL_MENU 30003 +#define KEY_SHIFT_OPTN 30059 +#define KEY_CTRL_RESERVE1 30060 +#define KEY_CTRL_RESERVE2 30061 +#define KEY_SHIFT_LEFT 30062 +#define KEY_SHIFT_RIGHT 30063 + +#define KEY_PRGM_ACON 10 +#define KEY_PRGM_DOWN 37 +#define KEY_PRGM_EXIT 47 +#define KEY_PRGM_F1 79 +#define KEY_PRGM_F2 69 +#define KEY_PRGM_F3 59 +#define KEY_PRGM_F4 49 +#define KEY_PRGM_F5 39 +#define KEY_PRGM_F6 29 +#define KEY_PRGM_LEFT 38 +#define KEY_PRGM_NONE 0 +#define KEY_PRGM_RETURN 31 +#define KEY_PRGM_RIGHT 27 +#define KEY_PRGM_UP 28 +#define KEY_PRGM_1 72 +#define KEY_PRGM_2 62 +#define KEY_PRGM_3 52 +#define KEY_PRGM_4 73 +#define KEY_PRGM_5 63 +#define KEY_PRGM_6 53 +#define KEY_PRGM_7 74 +#define KEY_PRGM_8 64 +#define KEY_PRGM_9 54 +#define KEY_PRGM_A 76 +#define KEY_PRGM_F 26 +#define KEY_PRGM_ALPHA 77 +#define KEY_PRGM_SHIFT 78 +#define KEY_PRGM_MENU 48 +} #endif