fix multithread logic in template app, update gpio HAL (#250)
* fix multithread logic * more buffer for dallas id string * update apps to use new logic * delay_us small speedup * add consant qualifier to gpio records and some core api * fix some apps to use simpler method of getting gpio record * fix ibutton app, stupid stack problem
This commit is contained in:
		
							parent
							
								
									ccd40497eb
								
							
						
					
					
						commit
						a96f23af9b
					
				| @ -7,11 +7,8 @@ static void event_cb(const void* value, void* ctx) { | ||||
| const uint32_t BACKLIGHT_TIME = 10000; | ||||
| 
 | ||||
| void backlight_control(void* p) { | ||||
|     // create pin
 | ||||
|     GpioPin backlight = backlight_gpio; | ||||
| 
 | ||||
|     // TODO open record
 | ||||
|     GpioPin* backlight_record = &backlight; | ||||
|     const GpioPin* backlight_record = &backlight_gpio; | ||||
| 
 | ||||
|     // configure pin
 | ||||
|     gpio_init(backlight_record, GpioModeOutputPushPull); | ||||
|  | ||||
| @ -1,21 +1,22 @@ | ||||
| #include "flipper_v2.h" | ||||
| 
 | ||||
| void rgb_set(bool r, bool g, bool b, GpioPin* led_r, GpioPin* led_g, GpioPin* led_b) { | ||||
| void rgb_set( | ||||
|     bool r, | ||||
|     bool g, | ||||
|     bool b, | ||||
|     const GpioPin* led_r, | ||||
|     const GpioPin* led_g, | ||||
|     const GpioPin* led_b) { | ||||
|     gpio_write(led_r, !r); | ||||
|     gpio_write(led_g, !g); | ||||
|     gpio_write(led_b, !b); | ||||
| } | ||||
| 
 | ||||
| void application_blink(void* p) { | ||||
|     // create pin
 | ||||
|     GpioPin led_r = led_gpio[0]; | ||||
|     GpioPin led_g = led_gpio[1]; | ||||
|     GpioPin led_b = led_gpio[2]; | ||||
| 
 | ||||
|     // TODO open record
 | ||||
|     GpioPin* led_r_record = &led_r; | ||||
|     GpioPin* led_g_record = &led_g; | ||||
|     GpioPin* led_b_record = &led_b; | ||||
|     const GpioPin* led_r_record = &led_gpio[0]; | ||||
|     const GpioPin* led_g_record = &led_gpio[1]; | ||||
|     const GpioPin* led_b_record = &led_gpio[2]; | ||||
| 
 | ||||
|     // configure pin
 | ||||
|     gpio_init(led_r_record, GpioModeOutputOpenDrain); | ||||
|  | ||||
| @ -4,25 +4,21 @@ | ||||
| 
 | ||||
| // start app
 | ||||
| void AppiButton::run() { | ||||
|     acquire_state(); | ||||
|     mode[0] = new AppiButtonModeDallasRead(this); | ||||
|     mode[1] = new AppiButtonModeDallasEmulate(this); | ||||
|     release_state(); | ||||
| 
 | ||||
|     switch_to_mode(0); | ||||
| 
 | ||||
|     // create pin
 | ||||
|     GpioPin red_led = led_gpio[0]; | ||||
|     GpioPin green_led = led_gpio[1]; | ||||
| 
 | ||||
|     // TODO open record
 | ||||
|     red_led_record = &red_led; | ||||
|     green_led_record = &green_led; | ||||
|     red_led_record = &led_gpio[0]; | ||||
|     green_led_record = &led_gpio[1]; | ||||
| 
 | ||||
|     // configure pin
 | ||||
|     gpio_init(red_led_record, GpioModeOutputOpenDrain); | ||||
|     gpio_init(green_led_record, GpioModeOutputOpenDrain); | ||||
| 
 | ||||
|     app_ready(); | ||||
| 
 | ||||
|     AppiButtonEvent event; | ||||
|     while(1) { | ||||
|         if(get_event(&event, 100)) { | ||||
| @ -61,9 +57,7 @@ void AppiButton::render(CanvasApi* canvas) { | ||||
|     canvas->set_font(canvas, FontPrimary); | ||||
|     canvas->draw_str(canvas, 2, 12, "iButton"); | ||||
| 
 | ||||
|     if(mode[state.mode_index] != NULL) { | ||||
|         mode[state.mode_index]->render(canvas, &state); | ||||
|     } | ||||
|     mode[state.mode_index]->render(canvas, &state); | ||||
| } | ||||
| 
 | ||||
| void AppiButton::blink_red() { | ||||
|  | ||||
| @ -38,11 +38,11 @@ public: | ||||
| // with template variables <state, events>
 | ||||
| class AppiButton : public AppTemplate<AppiButtonState, AppiButtonEvent> { | ||||
| public: | ||||
|     GpioPin* red_led_record; | ||||
|     GpioPin* green_led_record; | ||||
|     const GpioPin* red_led_record; | ||||
|     const GpioPin* green_led_record; | ||||
| 
 | ||||
|     static const uint8_t modes_count = 2; | ||||
|     AppTemplateMode<AppiButtonState, AppiButtonEvent>* mode[modes_count] = {NULL, NULL}; | ||||
|     AppTemplateMode<AppiButtonState, AppiButtonEvent>* mode[modes_count]; | ||||
| 
 | ||||
|     void run(); | ||||
|     void render(CanvasApi* canvas); | ||||
|  | ||||
| @ -17,8 +17,7 @@ public: | ||||
|         app = parent_app; | ||||
| 
 | ||||
|         // TODO open record
 | ||||
|         GpioPin one_wire_pin = ibutton_gpio; | ||||
|         GpioPin* one_wire_pin_record = &one_wire_pin; | ||||
|         const GpioPin* one_wire_pin_record = &ibutton_gpio; | ||||
|         onewire_slave = new OneWireGpioSlave(one_wire_pin_record); | ||||
|     }; | ||||
| }; | ||||
| @ -39,9 +38,11 @@ void AppiButtonModeDallasEmulate::render(CanvasApi* canvas, AppiButtonState* sta | ||||
|     canvas->draw_str(canvas, 2, 25, "< dallas emulate"); | ||||
|     canvas->draw_str(canvas, 2, 37, "unimplemented"); | ||||
|     { | ||||
|         char buf[24]; | ||||
|         sprintf( | ||||
|         const uint8_t buffer_size = 32; | ||||
|         char buf[buffer_size]; | ||||
|         snprintf( | ||||
|             buf, | ||||
|             buffer_size, | ||||
|             "%x:%x:%x:%x:%x:%x:%x:%x", | ||||
|             state->dallas_address[0], | ||||
|             state->dallas_address[1], | ||||
|  | ||||
| @ -17,8 +17,7 @@ public: | ||||
|         app = parent_app; | ||||
| 
 | ||||
|         // TODO open record
 | ||||
|         GpioPin one_wire_pin = ibutton_gpio; | ||||
|         GpioPin* one_wire_pin_record = &one_wire_pin; | ||||
|         const GpioPin* one_wire_pin_record = &ibutton_gpio; | ||||
|         onewire = new OneWireGpio(one_wire_pin_record); | ||||
|     }; | ||||
| 
 | ||||
| @ -68,9 +67,11 @@ void AppiButtonModeDallasRead::render(CanvasApi* canvas, AppiButtonState* state) | ||||
|     canvas->draw_str(canvas, 2, 25, "dallas read >"); | ||||
|     canvas->draw_str(canvas, 2, 37, "touch me, iButton"); | ||||
|     { | ||||
|         char buf[24]; | ||||
|         sprintf( | ||||
|         const uint8_t buffer_size = 32; | ||||
|         char buf[buffer_size]; | ||||
|         snprintf( | ||||
|             buf, | ||||
|             buffer_size, | ||||
|             "%x:%x:%x:%x:%x:%x:%x:%x", | ||||
|             state->dallas_address[0], | ||||
|             state->dallas_address[1], | ||||
|  | ||||
| @ -5,10 +5,10 @@ | ||||
| 
 | ||||
| class OneWireGpio { | ||||
| private: | ||||
|     GpioPin* gpio; | ||||
|     const GpioPin* gpio; | ||||
| 
 | ||||
| public: | ||||
|     OneWireGpio(GpioPin* one_wire_gpio); | ||||
|     OneWireGpio(const GpioPin* one_wire_gpio); | ||||
|     ~OneWireGpio(); | ||||
|     bool reset(void); | ||||
|     bool read_bit(void); | ||||
| @ -20,7 +20,7 @@ public: | ||||
|     void stop(void); | ||||
| }; | ||||
| 
 | ||||
| OneWireGpio::OneWireGpio(GpioPin* one_wire_gpio) { | ||||
| OneWireGpio::OneWireGpio(const GpioPin* one_wire_gpio) { | ||||
|     gpio = one_wire_gpio; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -5,10 +5,10 @@ | ||||
| 
 | ||||
| class OneWireGpioSlave { | ||||
| private: | ||||
|     GpioPin* gpio; | ||||
|     const GpioPin* gpio; | ||||
| 
 | ||||
| public: | ||||
|     OneWireGpioSlave(GpioPin* one_wire_gpio); | ||||
|     OneWireGpioSlave(const GpioPin* one_wire_gpio); | ||||
|     ~OneWireGpioSlave(); | ||||
|     void start(void); | ||||
|     void stop(void); | ||||
| @ -25,7 +25,7 @@ public: | ||||
|     OneWiteTimeType wait_while_gpio(volatile OneWiteTimeType retries, const bool pin_value); | ||||
| }; | ||||
| 
 | ||||
| OneWireGpioSlave::OneWireGpioSlave(GpioPin* one_wire_gpio) { | ||||
| OneWireGpioSlave::OneWireGpioSlave(const GpioPin* one_wire_gpio) { | ||||
|     gpio = one_wire_gpio; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -264,11 +264,8 @@ void irda(void* p) { | ||||
|     gui->add_widget(gui, widget, GuiLayerFullscreen); | ||||
| 
 | ||||
|     // Red LED
 | ||||
|     // create pin
 | ||||
|     GpioPin led = led_gpio[0]; | ||||
| 
 | ||||
|     // TODO open record
 | ||||
|     GpioPin* led_record = &led; | ||||
|     const GpioPin* led_record = &led_gpio[0]; | ||||
| 
 | ||||
|     // configure pin
 | ||||
|     gpio_init(led_record, GpioModeOutputOpenDrain); | ||||
|  | ||||
| @ -95,6 +95,8 @@ void SdTest::run() { | ||||
|     gpio_init(red_led_record, GpioModeOutputOpenDrain); | ||||
|     gpio_init(green_led_record, GpioModeOutputOpenDrain); | ||||
| 
 | ||||
|     app_ready(); | ||||
| 
 | ||||
|     detect_sd_card(); | ||||
|     show_warning(); | ||||
|     init_sd_card(); | ||||
|  | ||||
| @ -77,6 +77,8 @@ void AppSdNFC::run() { | ||||
|     gpio_init(red_led_record, GpioModeOutputOpenDrain); | ||||
|     gpio_init(green_led_record, GpioModeOutputOpenDrain); | ||||
| 
 | ||||
|     app_ready(); | ||||
| 
 | ||||
|     uint8_t rfal_result = rfalNfcInitialize(); | ||||
|     if(rfal_result) { | ||||
|         set_text("rfal init fail"); | ||||
|  | ||||
| @ -33,7 +33,7 @@ void* acquire_mutex(ValueMutex* valuemutex, uint32_t timeout) { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool release_mutex(ValueMutex* valuemutex, void* value) { | ||||
| bool release_mutex(ValueMutex* valuemutex, const void* value) { | ||||
|     if(value != valuemutex->value) return false; | ||||
| 
 | ||||
|     if(osMutexRelease(valuemutex->mutex) != osOK) return false; | ||||
|  | ||||
| @ -58,7 +58,7 @@ static inline void* acquire_mutex_block(ValueMutex* valuemutex) { | ||||
| Release mutex after end of work with data. | ||||
| Call `release_mutex` and pass ValueData instance and pointer to data. | ||||
| */ | ||||
| bool release_mutex(ValueMutex* valuemutex, void* value); | ||||
| bool release_mutex(ValueMutex* valuemutex, const void* value); | ||||
| 
 | ||||
| /*
 | ||||
| Instead of take-access-give sequence you can use `read_mutex` and `write_mutex` functions. | ||||
|  | ||||
| @ -9,7 +9,7 @@ bool gpio_api_init(void) { | ||||
| } | ||||
| 
 | ||||
| // init GPIO
 | ||||
| void gpio_init(GpioPin* gpio, GpioMode mode) { | ||||
| void gpio_init(const GpioPin* gpio, const GpioMode mode) { | ||||
|     if(osMutexAcquire(gpioInitMutex, osWaitForever) == osOK) { | ||||
|         hal_gpio_init(gpio, mode, GpioPullNo, GpioSpeedLow); | ||||
|         osMutexRelease(gpioInitMutex); | ||||
| @ -17,13 +17,17 @@ void gpio_init(GpioPin* gpio, GpioMode mode) { | ||||
| } | ||||
| 
 | ||||
| // init GPIO, extended version
 | ||||
| void gpio_init_ex(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed) { | ||||
| void gpio_init_ex( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|     const GpioSpeed speed) { | ||||
|     hal_gpio_init(gpio, mode, pull, speed); | ||||
| } | ||||
| 
 | ||||
| // put GPIO to Z-state
 | ||||
| void gpio_disable(GpioDisableRecord* gpio_record) { | ||||
|     GpioPin* gpio_pin = acquire_mutex(gpio_record->gpio_mutex, 0); | ||||
|     const GpioPin* gpio_pin = acquire_mutex(gpio_record->gpio_mutex, 0); | ||||
|     if(gpio_pin == NULL) { | ||||
|         gpio_pin = gpio_record->gpio; | ||||
|     } | ||||
|  | ||||
| @ -12,13 +12,17 @@ typedef struct { | ||||
| bool gpio_api_init(); | ||||
| 
 | ||||
| // init GPIO
 | ||||
| void gpio_init(GpioPin* gpio, GpioMode mode); | ||||
| void gpio_init(const GpioPin* gpio, const GpioMode mode); | ||||
| 
 | ||||
| // init GPIO, extended version
 | ||||
| void gpio_init_ex(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed); | ||||
| void gpio_init_ex( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|     const GpioSpeed speed); | ||||
| 
 | ||||
| // write value to GPIO, false = LOW, true = HIGH
 | ||||
| static inline void gpio_write(GpioPin* gpio, bool state) { | ||||
| static inline void gpio_write(const GpioPin* gpio, const bool state) { | ||||
|     hal_gpio_write(gpio, state); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,11 @@ | ||||
| #include "api-hal-gpio.h" | ||||
| 
 | ||||
| // init GPIO
 | ||||
| void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed) { | ||||
| void hal_gpio_init( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|     const GpioSpeed speed) { | ||||
|     // TODO: Alternate Functions
 | ||||
|     GPIO_InitTypeDef GPIO_InitStruct = {0}; | ||||
| 
 | ||||
|  | ||||
| @ -39,10 +39,14 @@ typedef struct { | ||||
| } GpioPin; | ||||
| 
 | ||||
| // init GPIO
 | ||||
| void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed); | ||||
| void hal_gpio_init( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|     const GpioSpeed speed); | ||||
| 
 | ||||
| // write value to GPIO, false = LOW, true = HIGH
 | ||||
| static inline void hal_gpio_write(GpioPin* gpio, bool state) { | ||||
| static inline void hal_gpio_write(const GpioPin* gpio, const bool state) { | ||||
|     // writing to BSSR is an atomic operation
 | ||||
|     if(state == true) { | ||||
|         gpio->port->BSRR = gpio->pin; | ||||
|  | ||||
| @ -2,15 +2,18 @@ | ||||
| #include "assert.h" | ||||
| #include "cmsis_os2.h" | ||||
| 
 | ||||
| static uint32_t clk_per_microsecond; | ||||
| 
 | ||||
| void delay_us_init_DWT(void) { | ||||
|     CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; | ||||
|     DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; | ||||
|     DWT->CYCCNT = 0U; | ||||
|     clk_per_microsecond = SystemCoreClock / 1000000.0f; | ||||
| } | ||||
| 
 | ||||
| void delay_us(float microseconds) { | ||||
|     uint32_t start = DWT->CYCCNT; | ||||
|     uint32_t time_ticks = microseconds * (SystemCoreClock / 1000000.0f); | ||||
|     uint32_t time_ticks = microseconds * clk_per_microsecond; | ||||
|     while((DWT->CYCCNT - start) < time_ticks) { | ||||
|     }; | ||||
| } | ||||
|  | ||||
| @ -2,7 +2,11 @@ | ||||
| #include "api-hal-resources.h" | ||||
| 
 | ||||
| // init GPIO
 | ||||
| void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed) { | ||||
| void hal_gpio_init( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|     const GpioSpeed speed) { | ||||
|     // TODO: Alternate Functions
 | ||||
|     GPIO_InitTypeDef GPIO_InitStruct = {0}; | ||||
| 
 | ||||
| @ -16,10 +20,9 @@ void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed) | ||||
| 
 | ||||
| bool hal_gpio_read_sd_detect(void) { | ||||
|     bool result = false; | ||||
|     // create pin
 | ||||
|     GpioPin sd_cs_pin = sd_cs_gpio; | ||||
|      | ||||
|     // TODO open record
 | ||||
|     GpioPin* sd_cs_record = &sd_cs_pin; | ||||
|     const GpioPin* sd_cs_record = &sd_cs_gpio; | ||||
| 
 | ||||
|     // configure pin as input
 | ||||
|     gpio_init_ex(sd_cs_record, GpioModeInput, GpioPullUp, GpioSpeedVeryHigh); | ||||
|  | ||||
| @ -39,10 +39,14 @@ typedef struct { | ||||
| } GpioPin; | ||||
| 
 | ||||
| // init GPIO
 | ||||
| void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed); | ||||
| void hal_gpio_init( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|     const GpioSpeed speed); | ||||
| 
 | ||||
| // write value to GPIO, false = LOW, true = HIGH
 | ||||
| static inline void hal_gpio_write(GpioPin* gpio, bool state) { | ||||
| static inline void hal_gpio_write(const GpioPin* gpio, const bool state) { | ||||
|     // writing to BSSR is an atomic operation
 | ||||
|     if(state == true) { | ||||
|         gpio->port->BSRR = gpio->pin; | ||||
|  | ||||
| @ -2,7 +2,11 @@ | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| // init GPIO
 | ||||
| void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed){ | ||||
| void hal_gpio_init( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|     const GpioSpeed speed) { | ||||
|     // TODO more mode
 | ||||
|     if(gpio->pin != 0) { | ||||
|         switch(mode) { | ||||
| @ -17,7 +21,7 @@ void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed) | ||||
|         case GpioModeOutputOpenDrain: | ||||
|             printf("[GPIO] %s%d open drain\n", gpio->port, gpio->pin); | ||||
|             break; | ||||
|          | ||||
| 
 | ||||
|         default: | ||||
|             printf("[GPIO] %s%d mode %d unsupported\n", gpio->port, gpio->pin, mode); | ||||
|             break; | ||||
| @ -28,7 +32,7 @@ void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed) | ||||
| } | ||||
| 
 | ||||
| // write value to GPIO, false = LOW, true = HIGH
 | ||||
| void hal_gpio_write(GpioPin* gpio, bool state){ | ||||
| void hal_gpio_write(const GpioPin* gpio, const bool state) { | ||||
|     if(gpio->pin != 0) { | ||||
|         if(state) { | ||||
|             printf("[GPIO] %s%d on\n", gpio->port, gpio->pin); | ||||
| @ -41,7 +45,7 @@ void hal_gpio_write(GpioPin* gpio, bool state){ | ||||
| } | ||||
| 
 | ||||
| // read value from GPIO, false = LOW, true = HIGH
 | ||||
| bool hal_gpio_read(const GpioPin* gpio){ | ||||
| bool hal_gpio_read(const GpioPin* gpio) { | ||||
|     // TODO emulate pin state?
 | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| @ -40,10 +40,14 @@ typedef struct { | ||||
| } GpioPin; | ||||
| 
 | ||||
| // init GPIO
 | ||||
| void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed); | ||||
| void hal_gpio_init( | ||||
|     const GpioPin* gpio, | ||||
|     const GpioMode mode, | ||||
|     const GpioPull pull, | ||||
|     const GpioSpeed speed); | ||||
| 
 | ||||
| // write value to GPIO, false = LOW, true = HIGH
 | ||||
| void hal_gpio_write(GpioPin* gpio, bool state); | ||||
| void hal_gpio_write(const GpioPin* gpio, const bool state); | ||||
| 
 | ||||
| // read value from GPIO, false = LOW, true = HIGH
 | ||||
| bool hal_gpio_read(const GpioPin* gpio); | ||||
| @ -21,7 +21,7 @@ public: | ||||
| 
 | ||||
|     // state initializer
 | ||||
|     AppExampleState() { | ||||
|         example_data = 12; | ||||
|         example_data = 0; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| @ -51,6 +51,16 @@ public: | ||||
| 
 | ||||
| // start app
 | ||||
| void AppExample::run() { | ||||
|     // here we dont need to acquire or release state
 | ||||
|     // because before we call app_ready our application is "single threaded"
 | ||||
|     state.example_data = 12; | ||||
| 
 | ||||
|     // signal that we ready to render and ipc
 | ||||
|     app_ready(); | ||||
| 
 | ||||
|     // from here, any data that pass in render function must be guarded
 | ||||
|     // by calling acquire_state and release_state
 | ||||
| 
 | ||||
|     AppExampleEvent event; | ||||
|     while(1) { | ||||
|         if(get_event(&event, 1000)) { | ||||
|  | ||||
| @ -6,20 +6,21 @@ | ||||
| // simple app class with template variables <state, events>
 | ||||
| template <class TState, class TEvent> class AppTemplate { | ||||
| public: | ||||
|     AppTemplate(); | ||||
|     ~AppTemplate(); | ||||
|     void input_callback(InputEvent* input_event, void* ctx); | ||||
|     void draw_callback(CanvasApi* canvas, void* ctx); | ||||
|     virtual void render(CanvasApi* canvas) = 0; | ||||
|     Widget* widget; | ||||
|     osMessageQueueId_t event_queue; | ||||
|     TState state; | ||||
|     ValueMutex state_mutex; | ||||
|     GuiApi* gui; | ||||
| 
 | ||||
|     AppTemplate(); | ||||
|     ~AppTemplate(); | ||||
|     void input_callback(InputEvent* input_event, void* ctx); | ||||
|     void draw_callback(CanvasApi* canvas, void* ctx); | ||||
|     virtual void render(CanvasApi* canvas) = 0; | ||||
|     void acquire_state(void); | ||||
|     void release_state(void); | ||||
|     bool get_event(TEvent* event, uint32_t timeout); | ||||
|     void app_ready(void); | ||||
|     void exit(void); | ||||
|     void update_gui(void); | ||||
| }; | ||||
| @ -35,24 +36,15 @@ template <class TState, class TEvent> AppTemplate<TState, TEvent>::AppTemplate() | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
| 
 | ||||
|     // allocate widget
 | ||||
|     widget = widget_alloc(); | ||||
| 
 | ||||
|     // connect widget with input callback
 | ||||
|     auto input_cb_ref = cbc::obtain_connector(this, &AppTemplate::input_callback); | ||||
|     widget_input_callback_set(widget, input_cb_ref, this); | ||||
| 
 | ||||
|     // connect widget with draw callback
 | ||||
|     auto draw_cb_ref = cbc::obtain_connector(this, &AppTemplate::draw_callback); | ||||
|     widget_draw_callback_set(widget, draw_cb_ref, this); | ||||
| 
 | ||||
|     // open gui and add widget
 | ||||
|     // open gui
 | ||||
|     gui = (GuiApi*)furi_open("gui"); | ||||
|     if(gui == NULL) { | ||||
|         printf("gui is not available\n"); | ||||
|         furiac_exit(NULL); | ||||
|     } | ||||
|     gui->add_widget(gui, widget, GuiLayerFullscreen); | ||||
| 
 | ||||
|     // allocate widget
 | ||||
|     widget = widget_alloc(); | ||||
| } | ||||
| 
 | ||||
| template <class TState, class TEvent> AppTemplate<TState, TEvent>::~AppTemplate() { | ||||
| @ -96,6 +88,24 @@ bool AppTemplate<TState, TEvent>::get_event(TEvent* event, uint32_t timeout) { | ||||
|     return (event_status == osOK); | ||||
| } | ||||
| 
 | ||||
| // signal that app is ready, and we can render something
 | ||||
| // also unblock dependent tasks
 | ||||
| template <class TState, class TEvent> void AppTemplate<TState, TEvent>::app_ready(void) { | ||||
|     // connect widget with input callback
 | ||||
|     auto input_cb_ref = cbc::obtain_connector(this, &AppTemplate::input_callback); | ||||
|     widget_input_callback_set(widget, input_cb_ref, this); | ||||
| 
 | ||||
|     // connect widget with draw callback
 | ||||
|     auto draw_cb_ref = cbc::obtain_connector(this, &AppTemplate::draw_callback); | ||||
|     widget_draw_callback_set(widget, draw_cb_ref, this); | ||||
| 
 | ||||
|     // add widget
 | ||||
|     gui->add_widget(gui, widget, GuiLayerFullscreen); | ||||
| 
 | ||||
|     // signal that our app ready to work
 | ||||
|     furiac_ready(); | ||||
| } | ||||
| 
 | ||||
| template <class TState, class TEvent> void AppTemplate<TState, TEvent>::exit(void) { | ||||
|     // TODO remove all widgets create by app
 | ||||
|     widget_enabled_set(widget, false); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrZlo13
						DrZlo13