diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index 0e277be3b..5aa4624bc 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -6,8 +6,8 @@ AppsContainer::AppsContainer() : { } -bool AppsContainer::handleEvent(ion_event_t event) { - if (event == F1) { +bool AppsContainer::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::Event::F1) { m_activeAppIndex++; if (m_activeAppIndex >= (int)(AppId::Count)) { m_activeAppIndex = 0; diff --git a/apps/apps_container.h b/apps/apps_container.h index 73f4ea872..feafc9314 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -23,7 +23,7 @@ public: #endif }; void switchTo(AppId appId); - bool handleEvent(ion_event_t event) override; + bool handleEvent(Ion::Events::Event event) override; private: App * appWithId(AppId appId); int m_activeAppIndex; diff --git a/apps/graph/graph/graph_controller.cpp b/apps/graph/graph/graph_controller.cpp index 0da378b34..466d5b6d0 100644 --- a/apps/graph/graph/graph_controller.cpp +++ b/apps/graph/graph/graph_controller.cpp @@ -22,9 +22,9 @@ void GraphController::setFocused(bool focused) { */ } -bool GraphController::handleEvent(ion_event_t event) { +bool GraphController::handleEvent(Ion::Events::Event event) { switch (event) { - case ENTER: + case Ion::Events::Event::ENTER: m_view.moveCursorRight(); return true; default: diff --git a/apps/graph/graph/graph_controller.h b/apps/graph/graph/graph_controller.h index e3d7f2445..662f6eb11 100644 --- a/apps/graph/graph/graph_controller.h +++ b/apps/graph/graph/graph_controller.h @@ -11,7 +11,7 @@ public: View * view() override; const char * title() const override; void setFocused(bool focused) override; - bool handleEvent(ion_event_t event) override; + bool handleEvent(Ion::Events::Event event) override; private: GraphView m_view; }; diff --git a/apps/graph/list/list_controller.cpp b/apps/graph/list/list_controller.cpp index 4db52ebe0..3b6498590 100644 --- a/apps/graph/list/list_controller.cpp +++ b/apps/graph/list/list_controller.cpp @@ -30,15 +30,15 @@ void ListController::setActiveCell(int index) { app()->focus(cell); } -bool ListController::handleEvent(ion_event_t event) { +bool ListController::handleEvent(Ion::Events::Event event) { switch (event) { - case DOWN_ARROW: + case Ion::Events::Event::DOWN_ARROW: setActiveCell(m_activeCell+1); return true; - case UP_ARROW: + case Ion::Events::Event::UP_ARROW: setActiveCell(m_activeCell-1); return true; - case ENTER: + case Ion::Events::Event::ENTER: m_manualScrolling += 10; m_tableView.setContentOffset({0, m_manualScrolling}); return true; diff --git a/apps/graph/list/list_controller.h b/apps/graph/list/list_controller.h index ea9c8b89f..832904a8b 100644 --- a/apps/graph/list/list_controller.h +++ b/apps/graph/list/list_controller.h @@ -13,7 +13,7 @@ public: View * view() override; const char * title() const override; - bool handleEvent(ion_event_t event) override; + bool handleEvent(Ion::Events::Event event) override; int numberOfCells() override; void willDisplayCellForIndex(View * cell, int index) override; diff --git a/apps/probability/law/law_controller.cpp b/apps/probability/law/law_controller.cpp index 6bea972b8..6e4e9a1c9 100644 --- a/apps/probability/law/law_controller.cpp +++ b/apps/probability/law/law_controller.cpp @@ -41,15 +41,15 @@ void Probability::LawController::setActiveCell(int index) { app()->focus(cell); } -bool Probability::LawController::handleEvent(ion_event_t event) { +bool Probability::LawController::handleEvent(Ion::Events::Event event) { switch (event) { - case DOWN_ARROW: + case Ion::Events::Event::DOWN_ARROW: setActiveCell(m_activeCell+1); return true; - case UP_ARROW: + case Ion::Events::Event::UP_ARROW: setActiveCell(m_activeCell-1); return true; - case ENTER: + case Ion::Events::Event::ENTER: ((Probability::App *)app())->setLaw(App::Law::Normal); return true; default: diff --git a/apps/probability/law/law_controller.h b/apps/probability/law/law_controller.h index 4217d9564..f98300c2e 100644 --- a/apps/probability/law/law_controller.h +++ b/apps/probability/law/law_controller.h @@ -14,7 +14,7 @@ public: View * view() override; const char * title() const override; - bool handleEvent(ion_event_t event) override; + bool handleEvent(Ion::Events::Event event) override; int numberOfCells() override; void willDisplayCellForIndex(View * cell, int index) override; diff --git a/apps/probability/parameters/parameters_controller.cpp b/apps/probability/parameters/parameters_controller.cpp index ff619268c..e607de017 100644 --- a/apps/probability/parameters/parameters_controller.cpp +++ b/apps/probability/parameters/parameters_controller.cpp @@ -14,6 +14,6 @@ const char * Probability::ParametersController::title() const { return "Parameters"; } -bool Probability::ParametersController::handleEvent(ion_event_t event) { +bool Probability::ParametersController::handleEvent(Ion::Events::Event event) { return false; } diff --git a/apps/probability/parameters/parameters_controller.h b/apps/probability/parameters/parameters_controller.h index 3de7bb261..eb129d91d 100644 --- a/apps/probability/parameters/parameters_controller.h +++ b/apps/probability/parameters/parameters_controller.h @@ -11,7 +11,7 @@ public: View * view() override; const char * title() const override; - bool handleEvent(ion_event_t event) override; + bool handleEvent(Ion::Events::Event event) override; private: SolidColorView m_view; }; diff --git a/escher/include/escher/app.h b/escher/include/escher/app.h index eeb4055e8..9afe972ff 100644 --- a/escher/include/escher/app.h +++ b/escher/include/escher/app.h @@ -18,7 +18,7 @@ public: App(); void setWindow(Window * window); void focus(Responder * responder); - void processEvent(ion_event_t event); + void processEvent(Ion::Events::Event event); protected: virtual ViewController * rootViewController() = 0; private: diff --git a/escher/include/escher/container.h b/escher/include/escher/container.h index 0127974bb..aca02ef17 100644 --- a/escher/include/escher/container.h +++ b/escher/include/escher/container.h @@ -12,16 +12,14 @@ #include #include -extern "C" { -#include -} +#include class Container { public: Container(); void run(); App * activeApp(); - virtual bool handleEvent(ion_event_t event); + virtual bool handleEvent(Ion::Events::Event event); protected: void switchTo(App * app); private: diff --git a/escher/include/escher/responder.h b/escher/include/escher/responder.h index c9af9ffb3..5f2350e0b 100644 --- a/escher/include/escher/responder.h +++ b/escher/include/escher/responder.h @@ -1,16 +1,14 @@ #ifndef ESCHER_RESPONDER_H #define ESCHER_RESPONDER_H -extern "C" { -#include -} +#include class App; class Responder { public: Responder(Responder * parentResponder); - virtual bool handleEvent(ion_event_t event); // Default implementation does nothing + virtual bool handleEvent(Ion::Events::Event event); // Default implementation does nothing virtual void setFocused(bool focused); // Default implementation does nothing. Used by subclasses to know when active or not Responder * parentResponder() const; void setParentResponder(Responder * responder); diff --git a/escher/include/escher/stack_view_controller.h b/escher/include/escher/stack_view_controller.h index 288c39e9f..7b78f86c5 100644 --- a/escher/include/escher/stack_view_controller.h +++ b/escher/include/escher/stack_view_controller.h @@ -18,7 +18,7 @@ public: View * view() override; void handleKeyEvent(int key) override; - bool handleEvent(ion_event_t event) override; + bool handleEvent(Ion::Events::Event event) override; private: class ControllerView : public View { public: diff --git a/escher/include/escher/tab_view_controller.h b/escher/include/escher/tab_view_controller.h index 2acd9ccb7..205ecc902 100644 --- a/escher/include/escher/tab_view_controller.h +++ b/escher/include/escher/tab_view_controller.h @@ -15,7 +15,7 @@ public: uint8_t numberOfTabs(); const char * tabName(uint8_t index); - bool handleEvent(ion_event_t event) override; + bool handleEvent(Ion::Events::Event event) override; private: class ContentView : public View { public: diff --git a/escher/include/escher/text_field.h b/escher/include/escher/text_field.h index 15ebd38fa..1765ce600 100644 --- a/escher/include/escher/text_field.h +++ b/escher/include/escher/text_field.h @@ -11,7 +11,7 @@ public: // View void drawRect(KDContext * ctx, KDRect rect) const override; // Responder - bool handleEvent(ion_event_t event) override; + bool handleEvent(Ion::Events::Event event) override; protected: #if ESCHER_VIEW_LOGGING const char * className() const override; diff --git a/escher/src/app.cpp b/escher/src/app.cpp index acaa38a4a..fe8a6c48b 100644 --- a/escher/src/app.cpp +++ b/escher/src/app.cpp @@ -1,7 +1,6 @@ #include #include extern "C" { -#include #include } @@ -25,7 +24,7 @@ void App::setWindow(Window * window) { window->redraw(); } -void App::processEvent(ion_event_t event) { +void App::processEvent(Ion::Events::Event event) { Responder * responder = m_focusedResponder; bool didHandleEvent = false; while (responder) { diff --git a/escher/src/container.cpp b/escher/src/container.cpp index b2f31ba90..475c1704a 100644 --- a/escher/src/container.cpp +++ b/escher/src/container.cpp @@ -1,7 +1,5 @@ #include -extern "C" { -#include -} +#include Container::Container() : m_activeApp(nullptr) @@ -18,16 +16,16 @@ App * Container::activeApp() { return m_activeApp; } -bool Container::handleEvent(ion_event_t event) { +bool Container::handleEvent(Ion::Events::Event event) { return false; } void Container::run() { - m_window.setFrame(KDRect(0, 0, ION_SCREEN_WIDTH, ION_SCREEN_HEIGHT)); + m_window.setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height)); m_window.redraw(); while (true) { - ion_event_t event = ion_get_event(); // This is a blocking call + Ion::Events::Event event = Ion::Events::getEvent(); // This is a blocking call if (handleEvent(event)) { continue; } diff --git a/escher/src/responder.cpp b/escher/src/responder.cpp index 6f011b2a0..6373a806b 100644 --- a/escher/src/responder.cpp +++ b/escher/src/responder.cpp @@ -13,7 +13,7 @@ void Responder::setParentResponder(Responder * responder) { m_parentResponder = responder; } -bool Responder::handleEvent(ion_event_t event) { +bool Responder::handleEvent(Ion::Events::Event event) { return false; } diff --git a/escher/src/stack_view_controller.cpp b/escher/src/stack_view_controller.cpp index 728117224..31e793ede 100644 --- a/escher/src/stack_view_controller.cpp +++ b/escher/src/stack_view_controller.cpp @@ -91,8 +91,8 @@ void StackViewController::handleKeyEvent(int key) { } -bool StackViewController::handleEvent(ion_event_t event) { - if (event == ESC && m_numberOfChildren > 1) { +bool StackViewController::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::Event::ESC && m_numberOfChildren > 1) { pop(); return true; } diff --git a/escher/src/tab_view_controller.cpp b/escher/src/tab_view_controller.cpp index b38752139..24992d590 100644 --- a/escher/src/tab_view_controller.cpp +++ b/escher/src/tab_view_controller.cpp @@ -71,14 +71,14 @@ TabViewController::TabViewController(Responder * parentResponder, ViewController } } -bool TabViewController::handleEvent(ion_event_t event) { +bool TabViewController::handleEvent(Ion::Events::Event event) { switch(event) { - case LEFT_ARROW: + case Ion::Events::Event::LEFT_ARROW: if (m_activeChildIndex > 0) { setActiveTab(m_activeChildIndex-1); } return true; - case RIGHT_ARROW: + case Ion::Events::Event::RIGHT_ARROW: if (m_activeChildIndex < m_numberOfChildren-1) { setActiveTab(m_activeChildIndex+1); } diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index 5ad7ec547..f9f9dece0 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -24,16 +24,16 @@ const char * TextField::className() const { /* Responder */ -bool TextField::handleEvent(ion_event_t event) { - if (event == DELETE && m_currentTextLength > 0) { +bool TextField::handleEvent(Ion::Events::Event event) { + if (event == Ion::Events::Event::DELETE && m_currentTextLength > 0) { m_currentTextLength--; return true; } - if (event >= 0x100) { + if ((int)event >= 0x100) { return false; } if (m_currentTextLength-1 < m_textBufferSize) { - m_textBuffer[m_currentTextLength++] = event; + m_textBuffer[m_currentTextLength++] = (int)event; markRectAsDirty(bounds()); // TODO: Could be optimized } return true; diff --git a/ion/include/ion.h b/ion/include/ion.h index 962968d23..b140c12a4 100644 --- a/ion/include/ion.h +++ b/ion/include/ion.h @@ -1,9 +1,10 @@ #ifndef ION_ION_H #define ION_ION_H +#include #include #include -#include + /* ION is not your regular library. It is a library you link against, but it * will take care of configuring the whole environment for you. In POSIX terms, @@ -13,12 +14,13 @@ void ion_app(); -void ion_display_on(); -void ion_display_off(); +namespace Ion { -void ion_sleep(long ms); +void msleep(long ms); /* CAUTION: This is a complete reset! */ -void ion_reset(); +void reset(); + +} #endif diff --git a/ion/include/ion/display.h b/ion/include/ion/display.h new file mode 100644 index 000000000..cd6412586 --- /dev/null +++ b/ion/include/ion/display.h @@ -0,0 +1,30 @@ +#ifndef ION_DISPLAY_H +#define ION_DISPLAY_H + +/* ION abstracts pushing pixels to the screen. + * + * There could be a single entry point, set_pixel, but setting pixels one by one + * incurs quite a large overhead because you need to send the coordinate of each + * pixel to the screen. + * + * Many displays support sending contiguous pixels without having to repeat the + * pixel coordinates every time. We're therefore leveraging this capability + * which results in a very consequent speedup (up to ~10x faster). */ + +#include +#include + +namespace Ion { +namespace Display { + +void pushRect(KDRect r, const KDColor * pixels); +void pushRectUniform(KDRect r, KDColor c); +void pullRect(KDRect r, KDColor * pixels); + +constexpr int Width = 320; +constexpr int Height = 240; + +} +} + +#endif diff --git a/ion/include/ion/events.h b/ion/include/ion/events.h index e98cbf701..414adf5b4 100644 --- a/ion/include/ion/events.h +++ b/ion/include/ion/events.h @@ -1,7 +1,10 @@ #ifndef ION_EVENTS_H #define ION_EVENTS_H -typedef enum { +namespace Ion { +namespace Events { + +enum class Event { LEFT_PARENTHESIS = '(', // 0x28 RIGHT_PARENTHESIS = ')', // 0x29 COMMA = ',', @@ -97,9 +100,12 @@ typedef enum { MODE, CATALOG, CLEAR, - ERROR = 0xffffffff, -} ion_event_t; + //ERROR = 0xffffffff, +}; -ion_event_t ion_get_event(); +Event getEvent(); + +} +} #endif diff --git a/ion/include/ion/keyboard.h b/ion/include/ion/keyboard.h index b7693b6bb..c7daf6109 100644 --- a/ion/include/ion/keyboard.h +++ b/ion/include/ion/keyboard.h @@ -1,72 +1,27 @@ #ifndef ION_KEYBOARD_H #define ION_KEYBOARD_H -#include +namespace Ion { +namespace Keyboard { -typedef enum { - ION_KEY_A_1, - ION_KEY_A_2, - ION_KEY_A_3, - ION_KEY_A_4, - ION_KEY_A_5, +enum class Key { + A1 = 0, A2 = 1, A3 = 2, A4 = 3, A5 = 4, + B1 = 5, B2 = 6, B3 = 7, B4 = 8, B5 = 9, + C1 = 10, C2 = 11, C3 = 12, C4 = 13, C5 = 14, + D1, D2, D3, D4, D5, + E1, E2, E3, E4, E5, + F1, F2, F3, F4, F5, + G1, G2, G3, G4, G5, + H1, H2, H3, H4, H5, + I1, I2, I3, I4, I5, + J1, J2, J3, J4, J5 +}; - ION_KEY_B_1, - ION_KEY_B_2, - ION_KEY_B_3, - ION_KEY_B_4, - ION_KEY_B_5, +constexpr int NumberOfKeys = 50; - ION_KEY_C_1, - ION_KEY_C_2, - ION_KEY_C_3, - ION_KEY_C_4, - ION_KEY_C_5, +bool keyDown(Key k); - ION_KEY_D_1, - ION_KEY_D_2, - ION_KEY_D_3, - ION_KEY_D_4, - ION_KEY_D_5, - - ION_KEY_E_1, - ION_KEY_E_2, - ION_KEY_E_3, - ION_KEY_E_4, - ION_KEY_E_5, - - ION_KEY_F_1, - ION_KEY_F_2, - ION_KEY_F_3, - ION_KEY_F_4, - ION_KEY_F_5, - - ION_KEY_G_1, - ION_KEY_G_2, - ION_KEY_G_3, - ION_KEY_G_4, - ION_KEY_G_5, - - ION_KEY_H_1, - ION_KEY_H_2, - ION_KEY_H_3, - ION_KEY_H_4, - ION_KEY_H_5, - - ION_KEY_I_1, - ION_KEY_I_2, - ION_KEY_I_3, - ION_KEY_I_4, - ION_KEY_I_5, - - ION_KEY_J_1, - ION_KEY_J_2, - ION_KEY_J_3, - ION_KEY_J_4, - ION_KEY_J_5 -} ion_key_t; - -#define ION_NUMBER_OF_KEYS 50 - -bool ion_key_down(ion_key_t key); +} +} #endif diff --git a/ion/include/ion/led.h b/ion/include/ion/led.h index fbed450ea..8ca251504 100644 --- a/ion/include/ion/led.h +++ b/ion/include/ion/led.h @@ -1,20 +1,14 @@ #ifndef ION_LED_H #define ION_LED_H -/* ION abstracts pushing pixels to the screen. - * - * There could be a single entry point, set_pixel, but setting pixels one by one - * incurs quite a large overhead because you need to send the coordinate of each - * pixel to the screen. - * - * Many displays support sending contiguous pixels without having to repeat the - * pixel coordinates every time. We're therefore leveraging this capability - * which results in a very consequent speedup (up to ~10x faster). */ +#include -#include +namespace Ion { +namespace LED { -typedef uint16_t ion_color_t; +void setColor(KDColor c); -void ion_led_set_color(ion_color_t color); +} +} #endif diff --git a/ion/include/ion/screen.h b/ion/include/ion/screen.h deleted file mode 100644 index 17dc5878d..000000000 --- a/ion/include/ion/screen.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef ION_SCREEN_H -#define ION_SCREEN_H - -/* ION abstracts pushing pixels to the screen. - * - * There could be a single entry point, set_pixel, but setting pixels one by one - * incurs quite a large overhead because you need to send the coordinate of each - * pixel to the screen. - * - * Many displays support sending contiguous pixels without having to repeat the - * pixel coordinates every time. We're therefore leveraging this capability - * which results in a very consequent speedup (up to ~10x faster). */ - -#include - -typedef uint16_t ion_color_t; - -void ion_screen_push_rect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const ion_color_t * pixels); -void ion_screen_push_rect_uniform(uint16_t x, uint16_t y, uint16_t width, uint16_t height, ion_color_t color); -void ion_screen_pull_rect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, ion_color_t * pixels); -/* -void ion_screen_set_working_area(KDRect area); -void ion_screen_push_pixels(const KDColor * pixels, size_t count); -void ion_screen_pull_pixels(KDColor * pixels, size_t count); -*/ - -#define ION_SCREEN_WIDTH 320 -#define ION_SCREEN_HEIGHT 240 - -#endif diff --git a/ion/src/device/Makefile b/ion/src/device/Makefile index 0fadd2545..28ab72cc8 100644 --- a/ion/src/device/Makefile +++ b/ion/src/device/Makefile @@ -1,5 +1,11 @@ include ion/src/device/boot/Makefile -objs += $(addprefix ion/src/device/, init.o heap.o led.o display.o) +objs += $(addprefix ion/src/device/, \ + device.o\ + display.o\ + heap.o\ + keyboard.o\ + led.o\ +) # When using the register.h C++ file in production mode, we expect the compiler # to completely inline all bit manipulations. For some reason, if we build using @@ -14,4 +20,4 @@ ion/src/device/display.o: SFLAGS+=-O3 endif endif -objs += $(addprefix ion/src/device/keyboard/, keyboard.o) +#objs += $(addprefix ion/src/device/keyboard/, keyboard.o) diff --git a/ion/src/device/boot/Makefile b/ion/src/device/boot/Makefile index a4c81b9d3..80bbec9b7 100644 --- a/ion/src/device/boot/Makefile +++ b/ion/src/device/boot/Makefile @@ -1,4 +1,4 @@ -objs += $(addprefix ion/src/device/boot/, isr.o crt0.o) +objs += $(addprefix ion/src/device/boot/, isr.o rt0.o) LDFLAGS += -T ion/src/device/boot/flash.ld LDFLAGS += -M -Map output.map diff --git a/ion/src/device/boot/crt0.c b/ion/src/device/boot/rt0.cpp similarity index 90% rename from ion/src/device/boot/crt0.c rename to ion/src/device/boot/rt0.cpp index b530e7532..38de5a534 100644 --- a/ion/src/device/boot/crt0.c +++ b/ion/src/device/boot/rt0.cpp @@ -1,7 +1,7 @@ #include #include #include -#include "../init.h" +#include "../device.h" extern char _data_section_start_flash; extern char _data_section_start_ram; @@ -9,16 +9,21 @@ extern char _data_section_end_ram; extern char _bss_section_start_ram; extern char _bss_section_end_ram; +extern "C" { + void _start(); + void abort(); +} + void abort() { #ifdef DEBUG while (1) { } #else - ion_reset(); + Ion::reset(); #endif } -void _start(void) { +void _start() { // This is where execution starts after reset. // Many things are not initialized yet so the code here has to pay attention. @@ -35,7 +40,7 @@ void _start(void) { size_t bssSectionLength = (&_bss_section_end_ram - &_bss_section_start_ram); memset(&_bss_section_start_ram, 0, bssSectionLength); - init_platform(); + Ion::Device::init(); ion_app(); diff --git a/ion/src/device/device.cpp b/ion/src/device/device.cpp new file mode 100644 index 000000000..3a9d27521 --- /dev/null +++ b/ion/src/device/device.cpp @@ -0,0 +1,54 @@ +#include "device.h" +#include "regs/regs.h" +extern "C" { +#include +#include "registers/registers.h" +} +#include +#include "led.h" +#include "display.h" +#include "keyboard.h" + +// Public Ion methods + +void Ion::msleep(long ms) { + for (volatile long i=0; i<1040*ms; i++) { + __asm volatile("nop"); + } +} + +void Ion::reset() { + AIRCR = AIRCR_VECTKEY_MASK | AIRCR_SYSRESETREQ; +} + +// Private Ion::Device methods + +void Ion::Device::init() { + initFPU(); + initClocks(); + LED::Device::init(); + Display::Device::init(); + Keyboard::Device::init(); +} + +void Ion::Device::initClocks() { + // Our peripherals are using GPIO A, B, C and D. + // We're not using the CRC nor DMA engines. + class RCC::AHB1ENR ahb1enr(0); // Reset value + ahb1enr.setGPIOAEN(true); + ahb1enr.setGPIOBEN(true); + ahb1enr.setGPIOCEN(true); + ahb1enr.setGPIODEN(true); + RCC.AHB1ENR()->set(ahb1enr); +} + +void Ion::Device::initFPU() { + // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/BABDBFBJ.html + //CPACR |= (0xF << 20); // Set the bits 20-23 to enable CP10 and CP11 coprocessors + CPACR |= ( + REGISTER_FIELD_VALUE(CPACR_CP(10), CPACR_ACCESS_FULL) + | + REGISTER_FIELD_VALUE(CPACR_CP(11), CPACR_ACCESS_FULL) + ); + // FIXME: The pipeline should be flushed at this point +} diff --git a/ion/src/device/device.h b/ion/src/device/device.h new file mode 100644 index 000000000..37be0f9e4 --- /dev/null +++ b/ion/src/device/device.h @@ -0,0 +1,50 @@ +#ifndef ION_DEVICE_H +#define ION_DEVICE_H + +namespace Ion { +namespace Device { + +void init(); +void initFPU(); +void initClocks(); + +/* Pin | Role | Mode | Function + * -----+-------------------+-----------------------+---------- + * PA0 | Battery sensing | | + * PA2 | LCD D4 | Alternate Function 12 | FMSC_D4 + * PA3 | LCD D5 | Alternate Function 12 | FSMC_D5 + * PA4 | LCD D6 | Alternate Function 12 | FSMC_D6 + * PA5 | LCD D7 | Alternate Function 12 | FSMC_D7 + * PA6 | LED red | Alternate Function XX | TIM3_CH1 + * PA7 | LED green | Alternate Function XX | TIM3_CH2 + * PB0 | LED blue | Alternate Function XX | TIM3_CH3 + * PB1 | Keyboard row A | Output, open-drain | + * PB2 | Keyboard row B | Output, open-drain | + * PB3 | Keyboard row C | Output, open-drain | + * PB4 | Keyboard row D | Output, open-drain | + * PB5 | Keyboard row E | Output, open-drain | + * PB6 | Keyboard row F | Output, open-drain | + * PB7 | Keyboard row G | Output, open-drain | + * PB8 | Keyboard row H | Output, open-drain | + * PB9 | Keyboard row I | Output, open-drain | + * PB10 | Keyboard row J | Output, open-drain | + * PB14 | LCD D0 | Alternate Function 12 | FSMC_D0 + * PC0 | Keyboard column 1 | Input, pulled-up | + * PC1 | Keyboard column 2 | Input, pulled-up | + * PC3 | LCD data/command | Alternate Function 12 | FSMC_A0 + * PC4 | LCD chip select | Alternate Function 12 | FSMC_NE4 + * PC5 | LCD read signal | Alternate Function 12 | FSMC_NOE + * PC6 | LCD D1 | Alternate Function 12 | FSMC_D7 + * PC9 | LCD backlight | Alternate Function 12 | TIM3_CH4 + * PC11 | LCD D2 | Alternate Function 12 | FSMC_D2 + * PC12 | LCD D3 | Alternate Function 12 | FSMC_D3 + * PC13 | Keyboard column 3 | Input, pulled-up | + * PC14 | Keyboard column 4 | Input, pulled-up | + * PC15 | Keyboard column 5 | Input, pulled-up | + * PD2 | LCD write signal | Alternate Function 12 | FSMC_NWE + */ + +} +} + +#endif diff --git a/ion/src/device/display.cpp b/ion/src/device/display.cpp index a46085d26..8557be835 100644 --- a/ion/src/device/display.cpp +++ b/ion/src/device/display.cpp @@ -1,54 +1,78 @@ +#include #include "display.h" #include "regs/regs.h" extern "C" { #include -#include } +// Public Ion::Display methods + +namespace Ion { +namespace Display { + +void pushRect(KDRect r, const KDColor * pixels) { + Device::setDrawingArea(r); + Device::pushPixels(pixels, r.width()*r.height()); +} + +void pushRectUniform(KDRect r, KDColor c) { + Device::setDrawingArea(r); + for (size_t i=0; isetGPIOCEN(true); - GPIOC.MODER()->setMODER(9, GPIO::MODER::MODE::Output); - GPIOC.ODR()->setODR(9, true); + GPIOC.MODER()->setMode(9, GPIO::MODER::Mode::Output); + GPIOC.ODR()->set(9, true); // Turn on the reset pin RCC.AHB1ENR()->setGPIOBEN(true); - GPIOB.MODER()->setMODER(13, GPIO::MODER::MODE::Output); - GPIOB.ODR()->setODR(13, true); + GPIOB.MODER()->setMode(13, GPIO::MODER::Mode::Output); + GPIOB.ODR()->set(13, true); - ion_sleep(120); + msleep(120); - Ion::Screen::initGPIO(); - Ion::Screen::initFSMC(); - Ion::Screen::initPanel(); + initGPIO(); + initFSMC(); + initPanel(); } -void Ion::Screen::initGPIO() { - // We use GPIOA to GPIOD - RCC.AHB1ENR()->setGPIOAEN(true); - RCC.AHB1ENR()->setGPIOBEN(true); - RCC.AHB1ENR()->setGPIOCEN(true); - RCC.AHB1ENR()->setGPIODEN(true); - +void initGPIO() { // Configure GPIOs to use AF - GPIOA.MODER()->setMODER(2, GPIO::MODER::MODE::AlternateFunction); - GPIOA.MODER()->setMODER(3, GPIO::MODER::MODE::AlternateFunction); - GPIOA.MODER()->setMODER(4, GPIO::MODER::MODE::AlternateFunction); - GPIOA.MODER()->setMODER(5, GPIO::MODER::MODE::AlternateFunction); + GPIOA.MODER()->setMode(2, GPIO::MODER::Mode::AlternateFunction); + GPIOA.MODER()->setMode(3, GPIO::MODER::Mode::AlternateFunction); + GPIOA.MODER()->setMode(4, GPIO::MODER::Mode::AlternateFunction); + GPIOA.MODER()->setMode(5, GPIO::MODER::Mode::AlternateFunction); - GPIOB.MODER()->setMODER(14, GPIO::MODER::MODE::AlternateFunction); + GPIOB.MODER()->setMode(14, GPIO::MODER::Mode::AlternateFunction); - GPIOC.MODER()->setMODER(3, GPIO::MODER::MODE::AlternateFunction); - GPIOC.MODER()->setMODER(4, GPIO::MODER::MODE::AlternateFunction); - GPIOC.MODER()->setMODER(5, GPIO::MODER::MODE::AlternateFunction); - GPIOC.MODER()->setMODER(6, GPIO::MODER::MODE::AlternateFunction); - GPIOC.MODER()->setMODER(11, GPIO::MODER::MODE::AlternateFunction); - GPIOC.MODER()->setMODER(12, GPIO::MODER::MODE::AlternateFunction); + GPIOC.MODER()->setMode(3, GPIO::MODER::Mode::AlternateFunction); + GPIOC.MODER()->setMode(4, GPIO::MODER::Mode::AlternateFunction); + GPIOC.MODER()->setMode(5, GPIO::MODER::Mode::AlternateFunction); + GPIOC.MODER()->setMode(6, GPIO::MODER::Mode::AlternateFunction); + GPIOC.MODER()->setMode(11, GPIO::MODER::Mode::AlternateFunction); + GPIOC.MODER()->setMode(12, GPIO::MODER::Mode::AlternateFunction); - GPIOD.MODER()->setMODER(2, GPIO::MODER::MODE::AlternateFunction); + GPIOD.MODER()->setMode(2, GPIO::MODER::Mode::AlternateFunction); /* More precisely, we want to use the FSMC alternate function. * Oddly enough, this isn't always the same AF number. That equals to: @@ -57,24 +81,24 @@ void Ion::Screen::initGPIO() { * AF12 for PC3,4,5 * AF10 for PC6,11,12 * AF10 for PD2 */ - GPIOA.AFR()->setAFR(2, GPIO::AFR::AlternateFunction::AF12); - GPIOA.AFR()->setAFR(3, GPIO::AFR::AlternateFunction::AF12); - GPIOA.AFR()->setAFR(4, GPIO::AFR::AlternateFunction::AF12); - GPIOA.AFR()->setAFR(5, GPIO::AFR::AlternateFunction::AF12); + GPIOA.AFR()->setAlternateFunction(2, GPIO::AFR::AlternateFunction::AF12); + GPIOA.AFR()->setAlternateFunction(3, GPIO::AFR::AlternateFunction::AF12); + GPIOA.AFR()->setAlternateFunction(4, GPIO::AFR::AlternateFunction::AF12); + GPIOA.AFR()->setAlternateFunction(5, GPIO::AFR::AlternateFunction::AF12); - GPIOB.AFR()->setAFR(14, GPIO::AFR::AlternateFunction::AF10); + GPIOB.AFR()->setAlternateFunction(14, GPIO::AFR::AlternateFunction::AF10); - GPIOC.AFR()->setAFR(3, GPIO::AFR::AlternateFunction::AF12); - GPIOC.AFR()->setAFR(4, GPIO::AFR::AlternateFunction::AF12); - GPIOC.AFR()->setAFR(5, GPIO::AFR::AlternateFunction::AF12); - GPIOC.AFR()->setAFR(6, GPIO::AFR::AlternateFunction::AF10); - GPIOC.AFR()->setAFR(11, GPIO::AFR::AlternateFunction::AF10); - GPIOC.AFR()->setAFR(12, GPIO::AFR::AlternateFunction::AF10); + GPIOC.AFR()->setAlternateFunction(3, GPIO::AFR::AlternateFunction::AF12); + GPIOC.AFR()->setAlternateFunction(4, GPIO::AFR::AlternateFunction::AF12); + GPIOC.AFR()->setAlternateFunction(5, GPIO::AFR::AlternateFunction::AF12); + GPIOC.AFR()->setAlternateFunction(6, GPIO::AFR::AlternateFunction::AF10); + GPIOC.AFR()->setAlternateFunction(11, GPIO::AFR::AlternateFunction::AF10); + GPIOC.AFR()->setAlternateFunction(12, GPIO::AFR::AlternateFunction::AF10); - GPIOD.AFR()->setAFR(2, GPIO::AFR::AlternateFunction::AF10); + GPIOD.AFR()->setAlternateFunction(2, GPIO::AFR::AlternateFunction::AF10); } -void Ion::Screen::initFSMC() { +void initFSMC() { // FSMC lives on the AHB3 bus. Let's enable its clock. */ RCC.AHB3ENR()->setFSMCEN(true); @@ -98,13 +122,13 @@ void Ion::Screen::initFSMC() { FSMC.BTR(4)->setBUSTURN(0); } -void Ion::Screen::initPanel() { +void initPanel() { //*CommandAddress = 0x01; //software reset - //ion_sleep(5); + // msleep(5); *CommandAddress = Command::SleepOut; - ion_sleep(120); + msleep(120); SEND_COMMAND(PowerControlB, 0x00, 0x83, 0x30); SEND_COMMAND(PowerOnSequenceControl, 0x64, 0x03, 0x12, 0x81); @@ -126,17 +150,17 @@ void Ion::Screen::initPanel() { SEND_COMMAND(NegativeGammaCorrection, 0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3a, 0x78, 0x4d, 0x05, 0x18, 0x0d, 0x38, 0x3a, 0x1f); *CommandAddress = Command::SleepOut; //Exit Sleep - ion_sleep(120); + msleep(120); *CommandAddress = Command::DisplayOn; //Display on - ion_sleep(50); + msleep(50); } -void Ion::Screen::setDrawingArea(uint16_t x, uint16_t y, uint16_t width, uint16_t height) { - uint16_t x_start = x; - uint16_t x_end = x + width - 1; - uint16_t y_start = y; - uint16_t y_end = y + height - 1; +void setDrawingArea(KDRect r) { + uint16_t x_start = r.x(); + uint16_t x_end = r.x() + r.width() - 1; + uint16_t y_start = r.y(); + uint16_t y_end = r.y() + r.height() - 1; *CommandAddress = Command::ColumnAddressSet; *DataAddress = (x_start >> 8); @@ -153,26 +177,15 @@ void Ion::Screen::setDrawingArea(uint16_t x, uint16_t y, uint16_t width, uint16_ *CommandAddress = Command::MemoryWrite; } -void Ion::Screen::pushPixels(const ion_color_t * pixels, size_t numberOfPixels) { - assert(sizeof(ion_color_t) == 2); // We expect KDColor to be RGB565 +void pushPixels(const KDColor * pixels, size_t numberOfPixels) { + assert(sizeof(KDColor) == 2); // We expect KDColor to be RGB565 for (size_t i=0; i> 8); - *DataAddress = (pixels[i] & 0xFF); + uint16_t pixel = pixels[i]; + *DataAddress = (pixel >> 8); + *DataAddress = (pixel & 0xFF); } } -void ion_screen_push_rect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const ion_color_t * pixels) { - Ion::Screen::setDrawingArea(x, y, width, height); - Ion::Screen::pushPixels(pixels, width*height); } - -void ion_screen_push_rect_uniform(uint16_t x, uint16_t y, uint16_t width, uint16_t height, ion_color_t color) { - Ion::Screen::setDrawingArea(x, y, width, height); - for (size_t i=0; i -#include -#include -} +#ifndef ION_DEVICE_DISPLAY_H +#define ION_DEVICE_DISPLAY_H -/* Pinout: - * PA2 - D4 - * PA3 - D5 - * PA4 - D6 - * PA5 - D7 - * PB14 - D0 - * PC3 - A0 - * PC4 - NE4 - * PC5 - NOE - * PC6 - D1 - * PC11 - D2 - * PC12 - D3 - * PD2 - NWE - */ +#include +#include +extern "C" { +#include +} namespace Ion { -namespace Screen { - void init(); - void initGPIO(); - void initFSMC(); - void initPanel(); +namespace Display { +namespace Device { - void setDrawingArea(uint16_t x, uint16_t y, uint16_t width, uint16_t height); - void pushPixels(const ion_color_t * pixels, size_t numberOfPixels); +/* Pin | Role | Mode | Function + * -----+-------------------+-----------------------+---------- + * PA2 | LCD D4 | Alternate Function 12 | FMSC_D4 + * PA3 | LCD D5 | Alternate Function 12 | FSMC_D5 + * PA4 | LCD D6 | Alternate Function 12 | FSMC_D6 + * PA5 | LCD D7 | Alternate Function 12 | FSMC_D7 + * PB13 | LCD reset | Output | + * PB14 | LCD D0 | Alternate Function 12 | FSMC_D0 + * PC3 | LCD data/command | Alternate Function 12 | FSMC_A0 + * PC4 | LCD chip select | Alternate Function 12 | FSMC_NE4 + * PC5 | LCD read signal | Alternate Function 12 | FSMC_NOE + * PC6 | LCD D1 | Alternate Function 12 | FSMC_D7 + * PC9 | LCD backlight | Alternate Function 12 | TIM3_CH4 + * PC11 | LCD D2 | Alternate Function 12 | FSMC_D2 + * PC12 | LCD D3 | Alternate Function 12 | FSMC_D3 + * PD2 | LCD write signal | Alternate Function 12 | FSMC_NWE + */ - enum class Command : uint8_t { - SleepOut = 0x11, - DisplayOn = 0x29, - ColumnAddressSet = 0x2A, - GammaSet = 0x26, - PageAddressSet = 0x2B, - MemoryWrite = 0x2C, - MemoryAccessControl = 0x36, - PixelFormatSet = 0x3A, - FrameRateControl = 0xB1, - DisplayFunctionControl = 0xB6, - EntryMode = 0xB7, - PowerControl2 = 0xC1, - VCOMControl1 = 0xC5, - VCOMControl2 = 0xC7, - PowerControlA = 0xCB, - PowerControlB = 0xCF, - PositiveGammaCorrection = 0xE0, - NegativeGammaCorrection = 0xE1, - DriverTimingControlA = 0xE8, - DriverTimingControlB = 0xEA, - PowerOnSequenceControl = 0xED, - Enable3G = 0xF2, - PumpRatioControl = 0xF7, - }; +void init(); +void initGPIO(); +void initFSMC(); +void initPanel(); + +void setDrawingArea(KDRect r); +void pushPixels(const KDColor * pixels, size_t numberOfPixels); + +enum class Command : uint8_t { + SleepOut = 0x11, + DisplayOn = 0x29, + ColumnAddressSet = 0x2A, + GammaSet = 0x26, + PageAddressSet = 0x2B, + MemoryWrite = 0x2C, + MemoryAccessControl = 0x36, + PixelFormatSet = 0x3A, + FrameRateControl = 0xB1, + DisplayFunctionControl = 0xB6, + EntryMode = 0xB7, + PowerControl2 = 0xC1, + VCOMControl1 = 0xC5, + VCOMControl2 = 0xC7, + PowerControlA = 0xCB, + PowerControlB = 0xCF, + PositiveGammaCorrection = 0xE0, + NegativeGammaCorrection = 0xE1, + DriverTimingControlA = 0xE8, + DriverTimingControlB = 0xEA, + PowerOnSequenceControl = 0xED, + Enable3G = 0xF2, + PumpRatioControl = 0xF7, +}; + +static volatile Command * const CommandAddress = (Command *)0x6C000000; +static volatile uint8_t * const DataAddress = (uint8_t *)0x6C000001; - static volatile Command * const CommandAddress = (Command *)0x6C000000; - static volatile uint8_t * const DataAddress = (uint8_t *)0x6C000001; } } +} + +#endif diff --git a/ion/src/device/init.cpp b/ion/src/device/init.cpp deleted file mode 100644 index 29e308bd2..000000000 --- a/ion/src/device/init.cpp +++ /dev/null @@ -1,36 +0,0 @@ -extern "C" { -#include "init.h" -#include -#include -#include "keyboard/keyboard.h" -#include "registers/registers.h" -} -#include "display.h" - -void enable_fpu() { - // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/BABDBFBJ.html - //CPACR |= (0xF << 20); // Set the bits 20-23 to enable CP10 and CP11 coprocessors - CPACR |= ( - REGISTER_FIELD_VALUE(CPACR_CP(10), CPACR_ACCESS_FULL) - | - REGISTER_FIELD_VALUE(CPACR_CP(11), CPACR_ACCESS_FULL) - ); - // FIXME: The pipeline should be flushed at this point -} - -void init_platform() { - enable_fpu(); - init_keyboard(); - //ion_led_init(); - Ion::Screen::init(); -} - -void ion_sleep(long ms) { - for (volatile long i=0; i<1040*ms; i++) { - __asm volatile("nop"); - } -} - -void ion_reset() { - AIRCR = AIRCR_VECTKEY_MASK | AIRCR_SYSRESETREQ; -} diff --git a/ion/src/device/init.h b/ion/src/device/init.h deleted file mode 100644 index fd72445cb..000000000 --- a/ion/src/device/init.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef ION_DEVICE_PLATFORM_INIT_H -#define ION_DEVICE_PLATFORM_INIT_H - -void init_platform(); - -#endif diff --git a/ion/src/device/keyboard.cpp b/ion/src/device/keyboard.cpp new file mode 100644 index 000000000..a5cf6340a --- /dev/null +++ b/ion/src/device/keyboard.cpp @@ -0,0 +1,94 @@ +/* Keyboard initialization code + * + * The job of this code is to implement the "ion_key_state" function. + * + * The keyboard is a matrix that is laid out as follow: + * + * | PC0 | PC1 | PC13 | PC14 | PC15 | + * -----+------+------+------+------+------+ + * PB1 | K_A1 | K_A2 | K_A3 | K_A4 | K_A5 | + * -----+------+------+------+------+------+ + * PB2 | K_B1 | K_B2 | K_B3 | K_B4 | K_B5 | + * -----+------+------+------+------+------+ + * PB3 | K_C1 | K_C2 | K_C3 | K_C4 | K_C5 | + * -----+------+------+------+------+------+ + * PB4 | K_D1 | K_D2 | K_D3 | K_D4 | K_D5 | + * -----+------+------+------+------+------+ + * PB5 | K_E1 | K_E2 | K_E3 | K_E4 | K_E5 | + * -----+------+------+------+------+------+ + * PB6 | K_F1 | K_F2 | K_F3 | K_F4 | K_F5 | + * -----+------+------+------+------+------+ + * PB7 | K_G1 | K_G2 | K_G3 | K_G4 | K_G5 | + * -----+------+------+------+------+------+ + * PB8 | K_H1 | K_H2 | K_H3 | K_H4 | K_H5 | + * -----+------+------+------+------+------+ + * PB9 | K_I1 | K_I2 | K_I3 | K_I4 | K_I5 | + * -----+------+------+------+------+------+ + * PB10 | K_J1 | K_J2 | K_J3 | K_J4 | K_J5 | + * -----+------+------+------+------+------+ + * + * We decide to drive the rows (PB1-10) and read the columns (PC0,1,13,14,15). + * + * To avoid short-circuits, the pins B1-B10 will not be standard outputs but + * only open-drain. Open drain means the pin is either driven low or left + * floating. + * When a user presses multiple keys, a connection between two rows can happen. + * If we dont' use open drain outputs, this situation could trigger a short + * circuit between an output driving high and another driving low. + * + * If the outputs are open-drain, this means that the input must be pulled up. + * So if the input reads "1", this means the key is in fact *not* pressed, and + * if it reads "0" it means that there's a short to an open-drain output. Which + * means the corresponding key is pressed. + */ + +#include +#include "keyboard.h" + +// Public Ion::Keyboard methods + +namespace Ion { +namespace Keyboard { + +bool keyDown(Key k) { + // Drive the corresponding row low, and let all the others float. + int row = Device::rowForKey(k); + for (uint8_t i=0; iset(pin, state); + } + + msleep(1); + + // Read the input of the proper column + uint8_t column = Device::columnForKey(k); + uint8_t pin = Device::ColumnPins[column]; + bool input = Device::ColumnGPIO.IDR()->get(pin); + + /* The key is down if the input is brought low by the output. In other words, + * we want to return true if the input is low (false). */ + return (input == false); +} + +} +} + +// Private Ion::Keyboard::Device methods + +void Ion::Keyboard::Device::init() { + for (uint8_t i=0; isetMode(pin, GPIO::MODER::Mode::Output); + RowGPIO.OTYPER()->setType(pin, GPIO::OTYPER::Type::OpenDrain); + } + + for (uint8_t i=0; isetMode(pin, GPIO::MODER::Mode::Input); + ColumnGPIO.PUPDR()->setPull(pin, GPIO::PUPDR::Pull::Up); + } +} diff --git a/ion/src/device/keyboard.h b/ion/src/device/keyboard.h new file mode 100644 index 000000000..c9c102def --- /dev/null +++ b/ion/src/device/keyboard.h @@ -0,0 +1,50 @@ +#ifndef ION_DEVICE_KEYBOARD_H +#define ION_DEVICE_KEYBOARD_H + +#include "regs/regs.h" + +namespace Ion { +namespace Keyboard { +namespace Device { + +/* Pin | Role | Mode + * -----+-------------------+-------------------- + * PB1 | Keyboard row A | Output, open drain + * PB2 | Keyboard row B | Output, open drain + * PB3 | Keyboard row C | Output, open drain + * PB4 | Keyboard row D | Output, open drain + * PB5 | Keyboard row E | Output, open drain + * PB6 | Keyboard row F | Output, open drain + * PB7 | Keyboard row G | Output, open drain + * PB8 | Keyboard row H | Output, open drain + * PB9 | Keyboard row I | Output, open drain + * PB10 | Keyboard row J | Output, open drain + * PC0 | Keyboard column 1 | Input, pulled up + * PC1 | Keyboard column 2 | Input, pulled up + * PC13 | Keyboard column 3 | Input, pulled up + * PC14 | Keyboard column 4 | Input, pulled up + * PC15 | Keyboard column 5 | Input, pulled up + */ + +void init(); + +constexpr GPIO RowGPIO = GPIOB; +constexpr uint8_t numberOfRows = 10; +constexpr uint8_t RowPins[numberOfRows] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + +constexpr GPIO ColumnGPIO = GPIOC; +constexpr uint8_t numberOfColumns = 5; +constexpr uint8_t ColumnPins[numberOfColumns] = {0, 1, 13, 14, 15}; + +inline uint8_t rowForKey(Ion::Keyboard::Key key) { + return (int)key/numberOfColumns; +} +inline uint8_t columnForKey(Ion::Keyboard::Key key) { + return (int)key%numberOfColumns; +} + +} +} +} + +#endif diff --git a/ion/src/device/keyboard/keyboard.c b/ion/src/device/keyboard/keyboard.c deleted file mode 100644 index b61f651ab..000000000 --- a/ion/src/device/keyboard/keyboard.c +++ /dev/null @@ -1,112 +0,0 @@ -/* Keyboard initialization code - * - * The job of this code is to implement the "ion_key_state" function. - * - * The keyboard is a matrix that is laid out as follow: - * - * | PC0 | PC1 | PC13 | PC14 | PC15 | - * -----+------+------+------+------+------+ - * PB1 | K_A1 | K_A2 | K_A3 | K_A4 | K_A5 | - * -----+------+------+------+------+------+ - * PB2 | K_B1 | K_B2 | K_B3 | K_B4 | K_B5 | - * -----+------+------+------+------+------+ - * PB3 | K_C1 | K_C2 | K_C3 | K_C4 | K_C5 | - * -----+------+------+------+------+------+ - * PB4 | K_D1 | K_D2 | K_D3 | K_D4 | K_D5 | - * -----+------+------+------+------+------+ - * PB5 | K_E1 | K_E2 | K_E3 | K_E4 | K_E5 | - * -----+------+------+------+------+------+ - * PB6 | K_F1 | K_F2 | K_F3 | K_F4 | K_F5 | - * -----+------+------+------+------+------+ - * PB7 | K_G1 | K_G2 | K_G3 | K_G4 | K_G5 | - * -----+------+------+------+------+------+ - * PB8 | K_H1 | K_H2 | K_H3 | K_H4 | K_H5 | - * -----+------+------+------+------+------+ - * PB9 | K_I1 | K_I2 | K_I3 | K_I4 | K_I5 | - * -----+------+------+------+------+------+ - * PB10 | K_J1 | K_J2 | K_J3 | K_J4 | K_J5 | - * -----+------+------+------+------+------+ - * - * We decide to drive the rows (PB1-10) and read the columns (PC0,1,13,14,15). - * - * To avoid short-circuits, the pins B1-B10 will not be standard outputs but - * only open-drain. Open drain means the pin is either driven low or left - * floating. - * When a user presses multiple keys, a connection between two rows can happen. - * If we dont' use open drain outputs, this situation could trigger a short - * circuit between an output driving high and another driving low. - * - * If the outputs are open-drain, this means that the input must be pulled up. - * So if the input reads "1", this means the key is in fact *not* pressed, and - * if it reads "0" it means that there's a short to an open-drain output. Which - * means the corresponding key is pressed. - */ - -#include -#include "../registers/registers.h" - -/* This driver expects that row pins are contiguous. It also expects that - * column pins are contiguous too. This is not mandatory but it makes the code - * a lot simpler. */ - -#define ROW_GPIO GPIOB -#define LOW_BIT_ROW 1 -#define HIGH_BIT_ROW 10 - -#define COLUMN_GPIO GPIOC - -static inline uint8_t row_for_key(ion_key_t key) { - return key/5; -} -static inline uint8_t column_for_key(ion_key_t key) { - return key%5; -} - -bool ion_key_down(ion_key_t key) { - /* Drive the corresponding row low, and let all the others float. - * Note: In open-drain mode, a 0 in the register drives low, and a 1 lets the - * pin floating (Hi-Z). */ - uint32_t new_row_value = ~((uint32_t)1 << row_for_key(key)); - uint32_t previous_row_value = REGISTER_GET_VALUE(GPIO_ODR(ROW_GPIO), ROW); - - if (new_row_value != previous_row_value) { - REGISTER_SET_VALUE(GPIO_ODR(ROW_GPIO), ROW, new_row_value); - // We changed the outputs, give the hardware some time to react to this change - // FIXME: Real delay! - for (volatile int i=0;i<1000; i++) { - } - } - - // Read the input of the proper column - uint8_t column = column_for_key(key); - uint8_t bit_for_column = (column <= 1 ? column : column+11); - uint32_t input = (GPIO_IDR(COLUMN_GPIO) & (1 << bit_for_column)); - - /* The key is down if the input is brought low by the output. In other words, - * we want to return "true" (1) if the input is low (0). */ - return (input == 0); -} - -void init_keyboard() { - /* We are using GPIOs, let's start by enabling their clock. */ - /* Note: All GPIOs live on the AHB1 bus */ - RCC_AHB1ENR |= GPIO_EN(ROW_GPIO) | GPIO_EN(COLUMN_GPIO); - - // Configure the row pins as open-drain outputs - for (int pin=LOW_BIT_ROW; pin<=HIGH_BIT_ROW; pin++) { - REGISTER_SET_VALUE(GPIO_MODER(ROW_GPIO), MODER(pin), GPIO_MODE_OUTPUT); - REGISTER_SET_VALUE(GPIO_OTYPER(ROW_GPIO), OTYPER(pin), GPIO_OTYPE_OPEN_DRAIN); - } - - // Configure the column as are pulled-up inputs - REGISTER_SET_VALUE(GPIO_MODER(COLUMN_GPIO), MODER(0), GPIO_MODE_INPUT); - REGISTER_SET_VALUE(GPIO_PUPDR(COLUMN_GPIO), PUPDR(0), GPIO_PUPD_PULL_UP); - REGISTER_SET_VALUE(GPIO_MODER(COLUMN_GPIO), MODER(1), GPIO_MODE_INPUT); - REGISTER_SET_VALUE(GPIO_PUPDR(COLUMN_GPIO), PUPDR(1), GPIO_PUPD_PULL_UP); - REGISTER_SET_VALUE(GPIO_MODER(COLUMN_GPIO), MODER(13), GPIO_MODE_INPUT); - REGISTER_SET_VALUE(GPIO_PUPDR(COLUMN_GPIO), PUPDR(13), GPIO_PUPD_PULL_UP); - REGISTER_SET_VALUE(GPIO_MODER(COLUMN_GPIO), MODER(14), GPIO_MODE_INPUT); - REGISTER_SET_VALUE(GPIO_PUPDR(COLUMN_GPIO), PUPDR(14), GPIO_PUPD_PULL_UP); - REGISTER_SET_VALUE(GPIO_MODER(COLUMN_GPIO), MODER(15), GPIO_MODE_INPUT); - REGISTER_SET_VALUE(GPIO_PUPDR(COLUMN_GPIO), PUPDR(15), GPIO_PUPD_PULL_UP); -} diff --git a/ion/src/device/keyboard/keyboard.h b/ion/src/device/keyboard/keyboard.h deleted file mode 100644 index 2e78d677d..000000000 --- a/ion/src/device/keyboard/keyboard.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef ION_DEVICE_KEYBOARD_H -#define ION_DEVICE_KEYBOARD_H - -void init_keyboard(); - -#endif diff --git a/ion/src/device/led.cpp b/ion/src/device/led.cpp index 827e9631a..3be818a67 100644 --- a/ion/src/device/led.cpp +++ b/ion/src/device/led.cpp @@ -1,40 +1,39 @@ -extern "C" { #include -} +#include "led.h" #include "regs/regs.h" -extern "C" { - void ion_led_init(); +// Public Ion::LED methods + +void Ion::LED::setColor(KDColor c) { + TIM1.CCR1()->set(15000); } -/* Pin used : - * PA8 - Red LED - TIM1_CH1 - * PA9 - Green LED - TIM1_CH2 - * PA10 - Blue LED -TIM1_CH3 - */ +// Private Ion::Device::LED methods -void sleep() { - for (volatile int i=0;i<100000; i++) { - } +namespace Ion { +namespace LED { +namespace Device { + +void init() { + initGPIO(); + initTimer(); } -void ion_led_gpio_init() { - RCC.AHB1ENR()->setGPIOAEN(true); - +void initGPIO() { /* RED_LED(PA8), GREEN_LED(PA9), BLUE_LED(PA10) are driven using a timer, * which is an alternate function. */ - GPIOA.MODER()->setMODER(8, GPIO::MODER::MODE::AlternateFunction); - GPIOA.MODER()->setMODER(9, GPIO::MODER::MODE::AlternateFunction); - GPIOA.MODER()->setMODER(10, GPIO::MODER::MODE::AlternateFunction); + GPIOA.MODER()->setMode(8, GPIO::MODER::Mode::AlternateFunction); + GPIOA.MODER()->setMode(9, GPIO::MODER::Mode::AlternateFunction); + GPIOA.MODER()->setMode(10, GPIO::MODER::Mode::AlternateFunction); /* More precisely, we will use AF01, which maps PA8 to TIM1_CH1, PA9 to * TIM1_CH2 and PA10 to TIM1_CH3. */ - GPIOA.AFR()->setAFR(8, GPIO::AFR::AlternateFunction::AF1); - GPIOA.AFR()->setAFR(9, GPIO::AFR::AlternateFunction::AF1); - GPIOA.AFR()->setAFR(10, GPIO::AFR::AlternateFunction::AF1); + GPIOA.AFR()->setAlternateFunction(8, GPIO::AFR::AlternateFunction::AF1); + GPIOA.AFR()->setAlternateFunction(9, GPIO::AFR::AlternateFunction::AF1); + GPIOA.AFR()->setAlternateFunction(10, GPIO::AFR::AlternateFunction::AF1); } -void ion_led_timer_init() { +void initTimer() { /* TIM1 lives on the APB2 bus. Let's enable its clock. */ RCC.APB2ENR()->setTIM1EN(true); TIM1.PSC()->set(1000); @@ -75,11 +74,6 @@ void ion_led_timer_init() { TIM1.CR1()->setCEN(true); } -void ion_led_init() { - ion_led_gpio_init(); - ion_led_timer_init(); } - - -void ion_led_set_color(ion_color_t color) { +} } diff --git a/ion/src/device/led.h b/ion/src/device/led.h new file mode 100644 index 000000000..84453e5ea --- /dev/null +++ b/ion/src/device/led.h @@ -0,0 +1,24 @@ +#ifndef ION_DEVICE_LED_H +#define ION_DEVICE_LED_H + +namespace Ion { +namespace LED { +namespace Device { + +/* Pin | Role | Mode | Function + * -----+-------------------+-----------------------+---------- + * PA6 | LED red | Alternate Function 12 | TIM3_CH1 + * PA7 | LED green | Alternate Function 12 | TIM3_CH2 + * PB0 | LED blue | Alternate Function 12 | TIM3_CH3 + * PC9 | LCD backlight | Alternate Function 12 | TIM3_CH4 + */ + +void init(); +void initGPIO(); +void initTimer(); + +} +} +} + +#endif diff --git a/ion/src/device/regs/gpio.h b/ion/src/device/regs/gpio.h index d78e2c40f..a133ecef7 100644 --- a/ion/src/device/regs/gpio.h +++ b/ion/src/device/regs/gpio.h @@ -7,20 +7,47 @@ class GPIO { public: class MODER : Register32 { public: - enum class MODE { + enum class Mode { Input = 0, Output = 1, AlternateFunction = 2, Analog = 3 }; - MODE getMODER(int index) { return (MODE)get(2*index+1, 2*index); }; - void setMODER(int index, MODE mode) volatile { set(2*index+1, 2*index, (uint32_t)mode); }; + Mode getMode(int index) { return (Mode)getBitRange(2*index+1, 2*index); } + void setMode(int index, Mode mode) volatile { setBitRange(2*index+1, 2*index, (uint32_t)mode); } + }; + + class OTYPER : Register32 { + public: + enum class Type { + PushPull = 0, + OpenDrain = 1 + }; + Type getType(int index) { return (Type)getBitRange(index, index); } + void setType(int index, Type type) volatile { setBitRange(index, index, (uint32_t)type); } + }; + + class PUPDR : Register32 { + public: + enum class Pull { + None = 0, + Up = 1, + Down = 2, + Reserved = 3 + }; + Pull getPull(int index) { return (Pull)getBitRange(2*index+1, 2*index); } + void setPull(int index, Pull pull) volatile { setBitRange(2*index+1, 2*index, (uint32_t)pull); } + }; + + class IDR : Register32 { + public: + bool get(int index) volatile { return (bool)getBitRange(index, index); } }; class ODR : Register32 { public: - bool getODR(int index) { return (bool)get(index, index); } - void setODR(int index, bool state) volatile { set(index, index, state); } + bool get(int index) { return (bool)getBitRange(index, index); } + void set(int index, bool state) volatile { setBitRange(index, index, state); } }; class AFR : Register64 { @@ -33,16 +60,19 @@ public: AF8 = 8, AF9 = 9, AF10 = 10, AF11 = 11, AF12 = 12, AF13 = 13, AF14 = 14, AF15 = 15 }; - AlternateFunction getAFR(int index) { - return (AlternateFunction)get(4*index+3, 4*index); + AlternateFunction getAlternateFunction(int index) { + return (AlternateFunction)getBitRange(4*index+3, 4*index); }; - void setAFR(int index, AlternateFunction af) volatile { - set(4*index+3, 4*index, (uint64_t)af); + void setAlternateFunction(int index, AlternateFunction af) volatile { + setBitRange(4*index+3, 4*index, (uint64_t)af); }; }; constexpr GPIO(int i) : m_index(i) {} REGS_REGISTER_AT(MODER, 0x00); + REGS_REGISTER_AT(OTYPER, 0x04); + REGS_REGISTER_AT(PUPDR, 0x0C); + REGS_REGISTER_AT(IDR, 0x10); REGS_REGISTER_AT(ODR, 0x14); REGS_REGISTER_AT(AFR, 0x20); private: diff --git a/ion/src/device/regs/rcc.h b/ion/src/device/regs/rcc.h index 83e0f2174..28270accb 100644 --- a/ion/src/device/regs/rcc.h +++ b/ion/src/device/regs/rcc.h @@ -5,8 +5,9 @@ class RCC { public: - class AHB1ENR : Register32 { + class AHB1ENR : public Register32 { public: + AHB1ENR(uint32_t v) : Register32(v) {} REGS_BOOL_FIELD(GPIOAEN, 0); REGS_BOOL_FIELD(GPIOBEN, 1); REGS_BOOL_FIELD(GPIOCEN, 2); diff --git a/ion/src/device/regs/register.h b/ion/src/device/regs/register.h index 803570dda..a65b367f2 100644 --- a/ion/src/device/regs/register.h +++ b/ion/src/device/regs/register.h @@ -7,10 +7,14 @@ template class Register { public: Register() = delete; + Register(T v) : m_value(v) {} + void set(Register value) volatile { + m_value = value.m_value; + } void set(T value) volatile { m_value = value; } - T get() volatile { + T get() { return m_value; } protected: @@ -23,10 +27,10 @@ protected: static constexpr T bit_range_set_value(uint8_t high, uint8_t low, T originalValue, T targetValue) { return (originalValue & ~bit_range_mask(high,low))|bit_range_value(targetValue, high, low); } - void set(uint8_t high, uint8_t low, T value) volatile { + void setBitRange(uint8_t high, uint8_t low, T value) volatile { m_value = bit_range_set_value(high, low, m_value, value); } - T get(uint8_t high, uint8_t low) volatile { + T getBitRange(uint8_t high, uint8_t low) volatile { return (m_value & bit_range_mask(high,low)) >> low; } private: @@ -37,7 +41,7 @@ typedef Register Register16; typedef Register Register32; typedef Register Register64; -#define REGS_FIELD(name,type,high,low) type get##name() volatile { return (type)get(high,low); }; void set##name(type v) volatile { set(high, low, (uint8_t)v); }; +#define REGS_FIELD(name,type,high,low) type get##name() volatile { return (type)getBitRange(high,low); }; void set##name(type v) volatile { setBitRange(high, low, (uint8_t)v); }; #define REGS_TYPE_FIELD(name,high,low) REGS_FIELD(name,name,high,low) #define REGS_BOOL_FIELD(name,bit) REGS_FIELD(name,bool,bit,bit) #define REGS_REGISTER_AT(name, offset) volatile name * name() const { return (class name *)(Base() + offset); }; diff --git a/ion/src/shared/Makefile b/ion/src/shared/Makefile index 519560249..8e6ad2d9d 100644 --- a/ion/src/shared/Makefile +++ b/ion/src/shared/Makefile @@ -1,2 +1,3 @@ objs += $(addprefix ion/src/shared/,\ - events.o) + events.o\ +) diff --git a/ion/src/shared/events.c b/ion/src/shared/events.c deleted file mode 100644 index 4e89ab459..000000000 --- a/ion/src/shared/events.c +++ /dev/null @@ -1,67 +0,0 @@ -#include - -// More event type will be added later. -typedef enum { - KEY_DOWN, -} ion_key_event_type_t; - -typedef struct { - ion_key_t key; - ion_key_event_type_t event; -} ion_key_event_t; - -// Debouncing, qnd change to get_key event. -static ion_key_event_t ion_get_key_event() { - // Let's start by saving which keys we've seen up - bool key_seen_up[ION_NUMBER_OF_KEYS]; - for (ion_key_t k=0; k + +const Ion::Events::Event kEventForKeyDown[] = { + Ion::Events::Event::F1, Ion::Events::Event::F2, Ion::Events::Event::F3, Ion::Events::Event::F4, Ion::Events::Event::F5, Ion::Events::Event::SECOND, Ion::Events::Event::SHIFT, Ion::Events::Event::ESC, Ion::Events::Event::LEFT_ARROW, Ion::Events::Event::UP_ARROW, Ion::Events::Event::DIAMOND, Ion::Events::Event::ALPHA, Ion::Events::Event::APPS, Ion::Events::Event::DOWN_ARROW, Ion::Events::Event::RIGHT_ARROW, Ion::Events::Event::HOME, Ion::Events::Event::MODE, Ion::Events::Event::CATALOG, Ion::Events::Event::DELETE, Ion::Events::Event::CLEAR, Ion::Events::Event::LOWER_CASE_X, Ion::Events::Event::LOWER_CASE_Y, Ion::Events::Event::LOWER_CASE_Z, Ion::Events::Event::LOWER_CASE_T, Ion::Events::Event::POWER, Ion::Events::Event::EQUAL, Ion::Events::Event::LEFT_PARENTHESIS, Ion::Events::Event::RIGHT_PARENTHESIS, Ion::Events::Event::COMMA, Ion::Events::Event::DIVISION, Ion::Events::Event::DOT, Ion::Events::Event::SEVEN, Ion::Events::Event::EIGHT, Ion::Events::Event::NINE, Ion::Events::Event::PRODUCT, Ion::Events::Event::UPPER_CASE_E, Ion::Events::Event::FOUR, Ion::Events::Event::FIVE, Ion::Events::Event::SIX, Ion::Events::Event::MINUS, Ion::Events::Event::DOT, Ion::Events::Event::ONE, Ion::Events::Event::TWO, Ion::Events::Event::THREE, Ion::Events::Event::PLUS, Ion::Events::Event::DOT, Ion::Events::Event::ZERO, Ion::Events::Event::DOT, Ion::Events::Event::MINUS, Ion::Events::Event::ENTER +}; + +// Debouncing, qnd change to get_key event. +Ion::Events::Event Ion::Events::getEvent() { + // Let's start by saving which keys we've seen up + bool key_seen_up[Ion::Keyboard::NumberOfKeys]; + for (int k=0; k #include #include #include -#include -#include "init.h" } +#include "init.h" +#include +#include #include #include #include @@ -23,14 +23,14 @@ void init_platform() { Fl::visual(FL_RGB); int margin = 10; - int screen_width = ION_SCREEN_WIDTH; - int screen_height = ION_SCREEN_HEIGHT; + int screen_width = Ion::Display::Width; + int screen_height = Ion::Display::Height; int keyboard_height = screen_width; Fl_Window * window = new Fl_Window(screen_width+2*margin, margin+screen_height+margin+keyboard_height+margin); - KDColor * pixels = (KDColor *)malloc(ION_SCREEN_WIDTH*ION_SCREEN_HEIGHT*sizeof(KDColor)); - sFrameBuffer = new KDFrameBuffer(pixels, KDSize(ION_SCREEN_WIDTH, ION_SCREEN_HEIGHT)); + KDColor * pixels = (KDColor *)malloc(Ion::Display::Width*Ion::Display::Height*sizeof(KDColor)); + sFrameBuffer = new KDFrameBuffer(pixels, KDSize(Ion::Display::Width, Ion::Display::Height)); /* sFrameBuffer.drawingArea.origin = KDPointZero; sFrameBuffer.drawingArea.size = sFrameBuffer.size; @@ -46,40 +46,23 @@ void init_platform() { //KDCurrentContext->fillRect = NULL; } -void ion_screen_push_rect(uint16_t x, uint16_t y, - uint16_t width, uint16_t height, - const ion_color_t * pixels) -{ - // FIXME: Boy those casts are fugly - const void * foo = static_cast(pixels); - const KDColor * pouet = static_cast(foo); - sFrameBuffer->pushRect(KDRect(x,y,width,height), pouet); +void Ion::Display::pushRect(KDRect r, const KDColor * pixels) { + sFrameBuffer->pushRect(r, pixels); } -void ion_screen_push_rect_uniform(uint16_t x, uint16_t y, - uint16_t width, uint16_t height, - ion_color_t color) -{ - ion_color_t * foo = &color; - const void * bar = static_cast(foo); - const KDColor * baz = static_cast(bar); - sFrameBuffer->pushRectUniform(KDRect(x,y,width,height), *baz); +void Ion::Display::pushRectUniform(KDRect r, KDColor c) { + sFrameBuffer->pushRectUniform(r, c); } -void ion_screen_pull_rect(uint16_t x, uint16_t y, - uint16_t width, uint16_t height, - ion_color_t * pixels) -{ - void * foo = static_cast(pixels); - KDColor * pouet = static_cast(foo); - sFrameBuffer->pullRect(KDRect(x,y,width,height), pouet); +void Ion::Display::pullRect(KDRect r, KDColor * pixels) { + sFrameBuffer->pullRect(r, pixels); } -bool ion_key_down(ion_key_t key) { +bool Ion::Keyboard::keyDown(Ion::Keyboard::Key key) { return sKeyboard->key_down(key); } -void ion_sleep(long ms) { +void Ion::msleep(long ms) { usleep(1000*ms); sDisplay->redraw(); Fl::wait(); diff --git a/ion/src/simulator/keyboard/fltkkbd.cpp b/ion/src/simulator/keyboard/fltkkbd.cpp index 042dfed32..1729004ca 100644 --- a/ion/src/simulator/keyboard/fltkkbd.cpp +++ b/ion/src/simulator/keyboard/fltkkbd.cpp @@ -1,10 +1,10 @@ #include #include "fltkkbd.h" -#define KEYBOARD_ROWS 10 -#define KEYBOARD_COLUMNS 5 +constexpr int KeyboardRows = 10; +constexpr int KeyboardColumns = 5; -static const char* kCharForKey[ION_NUMBER_OF_KEYS] = { +static const char* kCharForKey[Ion::Keyboard::NumberOfKeys] = { "F1", "F2", "F3", "F4", "F5", "2nd", "Shift", "ESC", "LEFT", "UP", "Diamond", "alpha", "APPS", "DOWN", "RIGHT", @@ -18,12 +18,12 @@ static const char* kCharForKey[ION_NUMBER_OF_KEYS] = { }; FltkKbd::FltkKbd(int x, int y, int w, int h) : Fl_Group(x, y, w, h) { - assert(KEYBOARD_ROWS*KEYBOARD_COLUMNS == ION_NUMBER_OF_KEYS); - int key_width = w/KEYBOARD_COLUMNS; - int key_height = h/KEYBOARD_ROWS; - for (int k=0; kvalue(); +bool FltkKbd::key_down(Ion::Keyboard::Key key) { + return m_buttons[(int)key]->value(); } diff --git a/ion/src/simulator/keyboard/fltkkbd.h b/ion/src/simulator/keyboard/fltkkbd.h index fa60d0572..3ff1673f4 100644 --- a/ion/src/simulator/keyboard/fltkkbd.h +++ b/ion/src/simulator/keyboard/fltkkbd.h @@ -3,16 +3,14 @@ #include #include -extern "C" { #include -} class FltkKbd : public Fl_Group { public: FltkKbd(int x, int y, int w, int h); - bool key_down(ion_key_t key); + bool key_down(Ion::Keyboard::Key key); private: - Fl_Button * m_buttons[ION_NUMBER_OF_KEYS]; + Fl_Button * m_buttons[Ion::Keyboard::NumberOfKeys]; }; #endif diff --git a/kandinsky/include/kandinsky/color.h b/kandinsky/include/kandinsky/color.h index 9d78a2a96..8b2a2b23f 100644 --- a/kandinsky/include/kandinsky/color.h +++ b/kandinsky/include/kandinsky/color.h @@ -14,7 +14,7 @@ public: uint8_t green(); uint8_t blue(); KDColor blend(KDColor other, uint8_t alpha); - operator uint16_t() { return m_value; } + operator uint16_t() const { return m_value; } private: uint16_t m_value; }; diff --git a/kandinsky/src/ion_context.cpp b/kandinsky/src/ion_context.cpp index d66889479..ee7fcb5af 100644 --- a/kandinsky/src/ion_context.cpp +++ b/kandinsky/src/ion_context.cpp @@ -1,7 +1,5 @@ #include -extern "C" { #include -} KDIonContext * KDIonContext::sharedContext() { static KDIonContext context; @@ -10,18 +8,18 @@ KDIonContext * KDIonContext::sharedContext() { KDIonContext::KDIonContext() : KDContext(KDPointZero, - KDRect(0, 0, ION_SCREEN_WIDTH, ION_SCREEN_HEIGHT)) + KDRect(0, 0, Ion::Display::Width, Ion::Display::Height)) { } void KDIonContext::pushRect(KDRect rect, const KDColor * pixels) { - ion_screen_push_rect(rect.x(), rect.y(), rect.width(), rect.height(), (const ion_color_t *)pixels); + Ion::Display::pushRect(rect, pixels); } void KDIonContext::pushRectUniform(KDRect rect, KDColor color) { - ion_screen_push_rect_uniform(rect.x(), rect.y(), rect.width(), rect.height(), color); + Ion::Display::pushRectUniform(rect, color); } void KDIonContext::pullRect(KDRect rect, KDColor * pixels) { - ion_screen_pull_rect(rect.x(), rect.y(), rect.width(), rect.height(), (ion_color_t *)pixels); + Ion::Display::pullRect(rect, pixels); } diff --git a/quiz/src/runner.cpp b/quiz/src/runner.cpp index 45050a511..d1e207e4f 100644 --- a/quiz/src/runner.cpp +++ b/quiz/src/runner.cpp @@ -1,9 +1,7 @@ #include "symbols.h" #include #include -extern "C" { #include -} void print(const char * message) { static int line_y = 0; @@ -11,7 +9,7 @@ void print(const char * message) { int line_height = KDText::stringSize("M").height(); ctx->drawString(message, KDPoint(0, line_y), 0); line_y += line_height; - if (line_y > ION_SCREEN_HEIGHT) { + if (line_y > Ion::Display::Height) { line_y = 0; // Clear screen maybe? } @@ -27,6 +25,6 @@ void ion_app() { } print("ALL TESTS FINISHED"); while (1) { - ion_sleep(1000); + Ion::msleep(1000); } }