diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 96d7194e..bd008e70 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,116 +1,60 @@ -# who owns all the code by default - +# Who owns all the code by default * @skotopes -# unknow applications - +# Applications applications/** @skotopes - -# assets and asset generator - -assets/** @skotopes - -# bootloader - -bootloader/** @skotopes -firmware/targets/f4/api-hal/api-hal-boot.c @skotopes - -# debug tools - -debug/** @skotopes - -# Core, HAL and applocation loader - -applications/app-loader/** @DrZlo13 -core/** @DrZlo13 -firmware/targets/api-hal-include/** @DrZlo13 - -firmware/targets/f4/api-hal/api-hal-clock.c @skotopes -firmware/targets/f4/api-hal/api-hal-clock.h @skotopes -firmware/targets/f4/api-hal/api-hal-delay.c @DrZlo13 -firmware/targets/f4/api-hal/api-hal-flash.c @skotopes -firmware/targets/f4/api-hal/api-hal-flash.h @skotopes -firmware/targets/f4/api-hal/api-hal-gpio.c @DrZlo13 -firmware/targets/f4/api-hal/api-hal-gpio.h @DrZlo13 -firmware/targets/f4/api-hal/api-hal-pwm.c @DrZlo13 -firmware/targets/f4/api-hal/api-hal-pwm.h @DrZlo13 -firmware/targets/f4/api-hal/api-hal-resources.c @DrZlo13 -firmware/targets/f4/api-hal/api-hal-resources.h @DrZlo13 -firmware/targets/f4/api-hal/api-hal-spi-config.c @DrZlo13 -firmware/targets/f4/api-hal/api-hal-spi-config.h @DrZlo13 -firmware/targets/f4/api-hal/api-hal-spi.c @DrZlo13 -firmware/targets/f4/api-hal/api-hal-spi-config.h @DrZlo13 -firmware/targets/f4/api-hal/api-hal-tim.c @DrZlo13 -firmware/targets/f4/api-hal/api-hal-tim.h @DrZlo13 -firmware/targets/f4/api-hal/api-hal-timebase-timer.h @skotopes -firmware/targets/f4/api-hal/api-hal-timebase.c @skotopes -firmware/targets/f4/api-hal/api-hal-timebase.h @skotopes -firmware/targets/f4/api-hal/api-hal-uuid.c @skotopes -firmware/targets/f4/api-hal/api-hal-vcp.c @skotopes -firmware/targets/f4/api-hal/api-hal.c @DrZlo13 -firmware/targets/f4/api-hal/api-interrupts.c @DrZlo13 - -firmware/targets/f4/Src/i2c.c @skotopes -firmware/targets/f5/Src/i2c.c @skotopes - -# BLE - -firmware/targets/f4/ble-glue/** @skotopes +applications/accessor/** @DrZlo13 +applications/app-loader/** @gornekich applications/bt/** @skotopes -firmware/targets/f4/api-hal/api-hal-bt.c @skotopes - -# Dolphin - -applications/dolphin/** @skotopes - -# GUI Stuff - +applications/cli/** @skotopes +applications/dolphin/** @skotopes @itsyourbedtime +applications/gpio-tester/** @skotopes applications/gui/** @skotopes -applications/input/** @skotopes - -# iButton - +applications/gui-test/** @DrZlo13 applications/ibutton/** @DrZlo13 -lib/cyfral/** @DrZlo13 -lib/onewire/** @DrZlo13 - -# IR - -applications/irda/** @DrZlo13 - -# LF-Rfid - -applications/lf-rfid/** @DrZlo13 - -# Menu - +applications/input/** @skotopes +applications/irda/** @DrZlo13 @albkharisov +applications/lf-rfid/** @DrZlo13 applications/menu/** @skotopes - -# NFC - -applications/nfc/** @skotopes -lib/ST25RFAL002/** @skotopes - -# SD Card and filesystem - +applications/music-player/** @DrZlo13 +applications/nfc/** @skotopes @gornekich +applications/power/** @skotopes applications/sd-card-test/** @DrZlo13 applications/sd-filesystem/** @DrZlo13 -lib/common-api/filesystem-api.h @DrZlo13 -lib/fatfs/** @DrZlo13 -firmware/targets/f4/Src/fatfs/** @DrZlo13 +applications/subghz/** @skotopes +applications/template/** @skotopes +applications/tests/** @skotopes @DrZlo13 -# Power control app +# Assets and asset generator +assets/** @skotopes -applications/power/** @skotopes -lib/drivers/bq* @skotopes -firmware/targets/f4/api-hal/api-hal-power.c @skotopes +# Bootloader +bootloader/** @skotopes -# Some applications +# Core, HAL and applocation loader +core/** @DrZlo13 -applications/music-player/** @DrZlo13 -applications/floopper-bloopper/** @skotopes -applications/gui-test/** @DrZlo13 +# Debug tools +debug/** @skotopes +# Firmware +firmware/** @skotopes + +# Lib lib/app-template/** @DrZlo13 -lib/qrcode/** @DrZlo13 lib/callback-connector/** @DrZlo13 +lib/common-api/** @DrZlo13 +lib/cyfral/** @DrZlo13 +lib/drivers/** @skotopes @gornekich +lib/fatfs/** @DrZlo13 +lib/fnv1a-hash/** @DrZlo13 +lib/mlib/** @skotopes +lib/onewire/** @DrZlo13 +lib/qrcode/** @DrZlo13 +lib/ST25RFAL002/** @skotopes @gornekich +lib/STM32CubeWB/** @skotopes +lib/u8g2/** @skotopes +lib/version/** @skotopes + +# Make +make/** @skotopes diff --git a/applications/template/template.c.example b/applications/template/template.c.example deleted file mode 100644 index fcb9bc9d..00000000 --- a/applications/template/template.c.example +++ /dev/null @@ -1,104 +0,0 @@ -#include - -typedef enum { - EventTypeTick, - EventTypeKey, - // add your events type -} EventType; - -typedef struct { - union { - InputEvent input; - // add your events payload - } value; - EventType type; -} Event; - -typedef struct { - // describe state here -} State; - -static void render_callback(Canvas* canvas, void* ctx) { - State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25); - - canvas_clear(canvas); - - // draw your app - - release_mutex((ValueMutex*)ctx, state); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - osMessageQueueId_t event_queue = (QueueHandle_t)ctx; - - Event event; - event.type = EventTypeKey; - event.value.input = *input_event; - osMessageQueuePut(event_queue, &event, 0, 0); -} - -int32_t template_app(void* p) { - osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(Event), NULL); - - State _state; - /* init state here */ - ValueMutex state_mutex; - if(!init_mutex(&state_mutex, &_state, sizeof(State))) { - printf("cannot create mutex\r\n"); - return 255; - } - - ViewPort* view_port = view_port_alloc(); - - view_port_draw_callback_set(view_port, render_callback, &state_mutex); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open("gui"); - if(gui == NULL) { - printf("gui is not available\r\n"); - return 255; - } - gui_add_view_port(gui, view_port, /* specify UI layer */); - - Event event; - while(1) { - osStatus_t event_status = osMessageQueueGet( - event_queue, &event, NULL, - /* specify timeout */ - ); - State* state = (State*)acquire_mutex_block(&state_mutex); - - if(event_status == osOK) { - if(event.type == EventTypeKey) { - // press events - if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyBack) { - } - - if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyUp) { - } - - if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyDown) { - } - - if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyLeft) { - } - - if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyRight) { - } - - if(event.value.input.key == InputKeyOk) { - } - } - } else { - // event timeout - } - - // common code, for example, force update UI - // view_port_update(view_port); - - release_mutex(&state_mutex, state); - } - - return 0; -} diff --git a/flp/.gitignore b/flp/.gitignore deleted file mode 100644 index e69de29b..00000000 diff --git a/flp/Pipfile b/flp/Pipfile deleted file mode 100644 index bf2a7263..00000000 --- a/flp/Pipfile +++ /dev/null @@ -1,14 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] -black = "20.8b1" - -[packages] -pyserial = "3.4" -click = "7.1.2" - -[requires] -python_version = "3.8" diff --git a/flp/Pipfile.lock b/flp/Pipfile.lock deleted file mode 100644 index bc5c414b..00000000 --- a/flp/Pipfile.lock +++ /dev/null @@ -1,142 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "62bedeef792c73b899be0e307396e579f1af2d0c1d49dbccc252cc14e11e50d4" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.8" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "click": { - "hashes": [ - "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", - "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" - ], - "index": "pypi", - "version": "==7.1.2" - }, - "pyserial": { - "hashes": [ - "sha256:6e2d401fdee0eab996cf734e67773a0143b932772ca8b42451440cfed942c627", - "sha256:e0770fadba80c31013896c7e6ef703f72e7834965954a78e71a3049488d4d7d8" - ], - "index": "pypi", - "version": "==3.4" - } - }, - "develop": { - "appdirs": { - "hashes": [ - "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", - "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" - ], - "version": "==1.4.4" - }, - "black": { - "hashes": [ - "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea", - "sha256:70b62ef1527c950db59062cda342ea224d772abdf6adc58b86a45421bab20a6b" - ], - "index": "pypi", - "version": "==20.8b1" - }, - "click": { - "hashes": [ - "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", - "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" - ], - "index": "pypi", - "version": "==7.1.2" - }, - "mypy-extensions": { - "hashes": [ - "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", - "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" - ], - "version": "==0.4.3" - }, - "pathspec": { - "hashes": [ - "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0", - "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061" - ], - "version": "==0.8.0" - }, - "regex": { - "hashes": [ - "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204", - "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162", - "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f", - "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb", - "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6", - "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7", - "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88", - "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99", - "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644", - "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a", - "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840", - "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067", - "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd", - "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4", - "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e", - "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89", - "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e", - "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc", - "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf", - "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341", - "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7" - ], - "version": "==2020.7.14" - }, - "toml": { - "hashes": [ - "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f", - "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88" - ], - "version": "==0.10.1" - }, - "typed-ast": { - "hashes": [ - "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", - "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919", - "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa", - "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652", - "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75", - "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01", - "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d", - "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1", - "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907", - "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c", - "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3", - "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b", - "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614", - "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb", - "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b", - "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41", - "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6", - "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34", - "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe", - "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4", - "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" - ], - "version": "==1.4.1" - }, - "typing-extensions": { - "hashes": [ - "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918", - "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c", - "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f" - ], - "version": "==3.7.4.3" - } - } -} diff --git a/flp/flipper/__init__.py b/flp/flipper/__init__.py deleted file mode 100644 index a8b7b81c..00000000 --- a/flp/flipper/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from flipper import file -from flipper.file import File diff --git a/flp/flipper/file.py b/flp/flipper/file.py deleted file mode 100644 index 2539ec94..00000000 --- a/flp/flipper/file.py +++ /dev/null @@ -1,122 +0,0 @@ -from enum import Enum - -import serial - - -class RemoteIOError(IOError): - pass - - -class UnsupportedOperation(RemoteIOError): - # TODO: Tell more on error - pass - - -class ReadWriteError(RemoteIOError): - pass - - -class FileMode(Enum): - READ = "r" - WRITE = "w" - # APPEND = "a" - Not Impl - # READ_WRITE = "w+" - # READ_APPEND = "a+" - - -class File: - opened: bool = False - filename: str - conn: serial.Serial - mode = FileMode.READ - - def _open(self): - # Opening file on Flipper's end - self.conn.write(f"f_open {self.filename} {self.mode}\n".encode()) - - # Checking, if everything is OK. - self.conn.write(b"f_valid\n") - return bool(int(self.conn.read_until().decode())) - - def __init__(self, conn: serial.Serial, filename: str, mode=FileMode.READ): - self.conn = conn - self.mode = mode - self.filename = filename - - if not self._open(): - raise RemoteIOError - self.opened = True - - def lseek(self, size: int): - self.conn.write(f"f_lseek {size}\n".encode()) - - def tell(self): - self.conn.write(b"f_tell\n") - return int(self.conn.read_until().decode()) - - def size(self): - self.conn.write(b"f_size\n") - return int(self.conn.read_until().decode()) - - def write(self, data: bytes): - if self.mode != FileMode.WRITE: - raise UnsupportedOperation - self.conn.write(f"f_write {len(data)}\n".encode()) - self.conn.write(data) - self.conn.write(b"\n") - - if self.conn.read_until().decode().strip() != "OK": - raise ReadWriteError - - def read(self, size: int) -> bytes: - self.conn.write(f"f_read {size}\n".encode()) - return self.conn.read(size) - - def _close(self): - self.conn.write(b"f_close\n") - - def close(self): - self._close() - # TODO: Add termination of remote file process. - del self - - def read_all(self, block_size=128) -> bytes: - """ - Function to simplify reading of file over serial. - - :return: content of file represented in `bytes` - """ - size = self.size() - a = bytearray() - seek = 0 - # Reading in blocks of block_size - while seek < block_size * (size // block_size - 1): - seek += block_size - self.lseek(seek) - a.extend(self.read(block_size)) - - seek += block_size - self.lseek(seek) - a.extend(self.read(size - seek)) # Appending mod - - self.lseek(0) # Resetting seek to default-position - - return bytes(a) - - -def push(ser: serial.Serial, local_path, remote_path): - with open(local_path, "rb") as local_f: # Reading local file - a = local_f.read() - - remote_f = File(ser, remote_path, FileMode.WRITE) - remote_f.write(a) - remote_f.close() - - -def pull(ser: serial.Serial, remote_path, local_path): - remote_f = File(ser, remote_path, FileMode.READ) - - with open(local_path, "wb") as f: - f.write(remote_f.read_all()) - - remote_f.close() diff --git a/flp/flp.py b/flp/flp.py deleted file mode 100644 index 0ef5a870..00000000 --- a/flp/flp.py +++ /dev/null @@ -1,39 +0,0 @@ -import flipper -import serial -import click - -DEFAULT_TTY = "/dev/ttyUSB0" - - -@click.group() -def cli(): - pass - - -@cli.group() -def fs(): - pass - - -@fs.command() -@click.argument("file_in", type=click.Path(exists=True)) -@click.argument("file_out") -@click.option("--port", default=DEFAULT_TTY) -def push(file_in, file_out, port): - with serial.Serial(port, 115200, timeout=10) as p: - flipper.file.push(p, file_in, file_out) - print("OK.") - - -@fs.command() -@click.argument("file_in") -@click.argument("file_out", type=click.Path()) -@click.option("--port", default=DEFAULT_TTY) -def pull(file_in, file_out, port): - with serial.Serial(port, 115200, timeout=10) as p: - flipper.file.pull(p, file_in, file_out) - print("OK.") - - -if __name__ == "__main__": - cli() diff --git a/lib/ui/ui.cpp b/lib/ui/ui.cpp deleted file mode 100644 index 61f73dae..00000000 --- a/lib/ui/ui.cpp +++ /dev/null @@ -1,589 +0,0 @@ -#include - -extern "C" { - #include "main.h" - #include "cmsis_os.h" - #include "u8g2_support.h" - #include "u8g2/u8g2.h" -} - -#include "ui.h" -#include "events.h" - -// function draw basic layout -- single bmp -void draw_bitmap(const char* bitmap, u8g2_t* u8g2, ScreenArea area) { - if(bitmap == NULL) { - printf("[basic layout] no content\n"); - u8g2_SetFont(u8g2, u8g2_font_6x10_mf); - u8g2_SetDrawColor(u8g2, 1); - u8g2_SetFontMode(u8g2, 1); - u8g2_DrawStr(u8g2, 2, 12, "no content"); - } else { - u8g2_SetDrawColor(u8g2, 1); - u8g2_DrawXBM(u8g2, 0, 0, area.x + area.width, area.y + area.height, (unsigned char*)bitmap); - } -} - -void draw_text(const char* text, u8g2_t* u8g2, ScreenArea area) { - // TODO proper cleanup statusbar - u8g2_SetDrawColor(u8g2, 0); - u8g2_DrawBox(u8g2, 0, 0, area.x + area.width, area.y + area.height); - - Block text_block = Block { - width: area.width, - height: area.height, - margin_left: 0, - margin_top: 0, - padding_left: 3, - padding_top: 7, - background: 0, - color: 1, - font: (uint8_t*)u8g2_font_6x10_mf, - }; - - draw_block(u8g2, text, text_block, area.x, area.y); -} - -// draw layout and switch between ui item by button and timer -void LayoutComponent::handle(Event* event, Store* store, u8g2_t* u8g2, ScreenArea area) { - switch(event->type) { - // get button event - case EventTypeButton: - if(event->value.button.state) { - for(size_t i = 0; i < this->actions_size; i++) { - FlipperComponent* next = NULL; - - switch(this->actions[i].action) { - case LayoutActionUp: - if(event->value.button.id == ButtonsUp) { - next = this->actions[i].item; - } - break; - case LayoutActionDown: - if(event->value.button.id == ButtonsDown) { - next = this->actions[i].item; - } - break; - case LayoutActionLeft: - if(event->value.button.id == ButtonsLeft) { - next = this->actions[i].item; - } - break; - case LayoutActionRight: - if(event->value.button.id == ButtonsRight) { - next = this->actions[i].item; - } - break; - case LayoutActionOk: - if(event->value.button.id == ButtonsOk) { - next = this->actions[i].item; - } - break; - case LayoutActionBack: - if(event->value.button.id == ButtonsBack) { - next = this->actions[i].item; - } - break; - - // stub action - case LayoutActionUsbDisconnect: - if(event->value.button.id == ButtonsLeft) { - next = this->actions[i].item; - } - break; - - case LayoutActionUsbConnect: - if(event->value.button.id == ButtonsRight) { - next = this->actions[i].item; - } - break; - - default: break; - } - - if(next) { - printf("[layout view] go to next item\n"); - Event send_event; - send_event.type = EventTypeUiNext; - next->handle( - &send_event, - store, - u8g2, - area - ); - } - } - } - break; - - case EventTypeUsb: { - printf("get usb event\n"); - - FlipperComponent* next = NULL; - - if(event->value.usb == UsbEventConnect) { - for(size_t i = 0; i < this->actions_size; i++) { - if(this->actions[i].action == LayoutActionUsbConnect) { - next = this->actions[i].item; - } - } - } - - if(event->value.usb == UsbEventDisconnect) { - for(size_t i = 0; i < this->actions_size; i++) { - if(this->actions[i].action == LayoutActionUsbDisconnect) { - next = this->actions[i].item; - } - } - } - - if(next) { - printf("[layout view] go to next item\n"); - Event send_event; - send_event.type = EventTypeUiNext; - next->handle( - &send_event, - store, - u8g2, - area - ); - } - } break; - - // start component from prev - case EventTypeUiNext: - printf("[layout view] start component %lX\n", (uint32_t)this); - - if(this->timeout > 0) { - // TODO start timer - } - - // set current item to self - store->current_component = this; - - this->wait_time = 0; - - // render layout - this->dirty = true; - break; - - case EventTypeTick: - this->wait_time += event->value.tick_delta; - - if(this->wait_time > this->timeout) { - for(size_t i = 0; i < this->actions_size; i++) { - if(this->actions[i].action == LayoutActionTimeout || - this->actions[i].action == LayoutActionEndOfCycle - ) { - if(this->actions[i].item != NULL) { - printf("[layout view] go to next item\n"); - Event send_event; - send_event.type = EventTypeUiNext; - this->actions[i].item->handle( - &send_event, - store, - u8g2, - area - ); - - return; - } - } - } - } - - if(this->dirty) { - this->draw_fn(this->data, u8g2, area); - - store->dirty_screen = true; - - this->dirty = false; - } - break; - - default: break; - } -} - -void BlinkerComponent::handle(Event* event, Store* store, u8g2_t* u8g2, ScreenArea area) { - switch(event->type) { - // get button event - case EventTypeButton: - if(event->value.button.state && event->value.button.id == ButtonsBack) { - if(this->prev && this->prev != this) { - printf("[blinker view] go back\n"); - - Event send_event; - send_event.type = EventTypeUiNext; - this->prev->handle( - &send_event, - store, - u8g2, - area - ); - - this->prev = NULL; - - store->led = ColorBlack; - this->wait_time = 0; - this->is_on = true; - this->active = false; - } else { - printf("[blinker view] no back/loop\n"); - } - } - - if(event->value.button.state && event->value.button.id != ButtonsBack) { - this->active = false; - } - - if(!event->value.button.state && event->value.button.id != ButtonsBack) { - this->active = true; - } - break; - - // start component from prev - case EventTypeUiNext: - printf("[blinker view] start component %lX\n", (uint32_t)this); - - if(this->prev == NULL) { - this->prev = store->current_component; - } - - // set current item to self - store->current_component = this; - - this->dirty = true; - this->wait_time = 0; - this->is_on = true; - this->active = false; - break; - - case EventTypeTick: - if(this->active) { - this->wait_time += event->value.tick_delta; - - if(this->is_on) { - if(this->wait_time > this->config.on_time) { - this->wait_time = 0; - this->is_on = false; - } - } else { - if(this->wait_time > this->config.off_time) { - this->wait_time = 0; - this->is_on = true; - } - } - - store->led = this->is_on ? this->config.on_color : this->config.off_color; - } else { - store->led = ColorBlack; - this->wait_time = 0; - this->is_on = true; - } - - if(this->dirty) { - this->draw_fn(this->data, u8g2, area); - - store->dirty_screen = true; - - this->dirty = false; - } - break; - - default: break; - } -} -void BlinkerComponentOnBtn::handle(Event* event, Store* store, u8g2_t* u8g2, ScreenArea area) { - switch(event->type) { - // get button event - case EventTypeButton: - if(event->value.button.state && event->value.button.id == ButtonsBack) { - if(this->prev && this->prev != this) { - printf("[blinker view] go back\n"); - - Event send_event; - send_event.type = EventTypeUiNext; - this->prev->handle( - &send_event, - store, - u8g2, - area - ); - - this->prev = NULL; - - store->led = ColorBlack; - this->wait_time = 0; - this->is_on = true; - this->active = false; - } else { - printf("[blinker view] no back/loop\n"); - } - } - - if(event->value.button.state && event->value.button.id != ButtonsBack) { - this->active = true; - } - - if(!event->value.button.state && event->value.button.id != ButtonsBack) { - this->active = false; - } - break; - - // start component from prev - case EventTypeUiNext: - printf("[blinker view] start component %lX\n", (uint32_t)this); - - if(this->prev == NULL) { - this->prev = store->current_component; - } - - // set current item to self - store->current_component = this; - - this->dirty = true; - this->wait_time = 0; - this->is_on = true; - this->active = false; - break; - - case EventTypeTick: - if(this->active) { - this->wait_time += event->value.tick_delta; - - if(this->is_on) { - if(this->wait_time > this->config.on_time) { - this->wait_time = 0; - this->is_on = false; - } - } else { - if(this->wait_time > this->config.off_time) { - this->wait_time = 0; - this->is_on = true; - } - } - - store->led = this->is_on ? this->config.on_color : this->config.off_color; - } else { - store->led = ColorBlack; - this->wait_time = 0; - this->is_on = true; - } - - if(this->dirty) { - this->draw_fn(this->data, u8g2, area); - - store->dirty_screen = true; - - this->dirty = false; - } - break; - - default: break; - } -} - -#define MENU_DRAW_LINES 4 - -Point draw_block(u8g2_t* u8g2, const char* text, Block layout, uint8_t x, uint8_t y) { - u8g2_SetDrawColor(u8g2, layout.background); - u8g2_DrawBox(u8g2, - x + layout.margin_left, - y + layout.margin_top, - layout.width, layout.height - ); - - u8g2_SetDrawColor(u8g2, layout.color); - u8g2_SetFont(u8g2, layout.font); - if(text != NULL) { - u8g2_DrawStr(u8g2, - x + layout.margin_left + layout.padding_left, - y + layout.margin_top + layout.padding_top, - text - ); - } - - return { - x: x + layout.margin_left + layout.width, - y: y + layout.margin_top + layout.height - }; -} - -void draw_menu(MenuCtx* ctx, u8g2_t* u8g2, ScreenArea area) { - // u8g2_ClearBuffer(u8g2); - // clear area - u8g2_SetDrawColor(u8g2, 0); - u8g2_DrawBox(u8g2, area.x, area.y, area.width, area.height); - - u8g2_SetFontMode(u8g2, 1); - - uint8_t list_start = ctx->current - ctx->cursor; - uint8_t list_size = ctx->size > MENU_DRAW_LINES ? MENU_DRAW_LINES : ctx->size; - - // draw header - /* - Point next = draw_block(u8g2, (const char*)data->name, Block { - width: 128, - height: 14, - margin_left: 0, - margin_top: 0, - padding_left: 4, - padding_top: 13, - background: 1, - color: 0, - font: (uint8_t*)u8g2_font_helvB14_tf, - }, area.x, area.y); - */ - - Point next = {area.x, area.y}; - - for(size_t i = 0; i < list_size; i++) { - next = draw_block(u8g2, (const char*)ctx->list[list_start + i].name, Block { - width: 128, - height: 15, - margin_left: 0, - margin_top: i == 0 ? 2 : 0, - padding_left: 2, - padding_top: 12, - background: i == ctx->cursor ? 1 : 0, - color: i == ctx->cursor ? 0 : 1, - font: (uint8_t*)u8g2_font_7x14_tf, - }, area.x, next.y); - } - - // u8g2_font_7x14_tf - // u8g2_font_profont12_tf smallerbut cute - // u8g2_font_samim_12_t_all орочий -} - -void MenuCtx::handle(MenuEvent event) { - uint8_t menu_size = this->size > MENU_DRAW_LINES ? MENU_DRAW_LINES : this->size; - - switch(event) { - case MenuEventDown: { - if(this->current < (this->size - 1)) { - this->current++; - - if(this->cursor < menu_size - 2 || this->current == this->size - 1) { - this->cursor++; - } - } else { - this->current = 0; - this->cursor = 0; - } - } break; - - case MenuEventUp: { - if(this->current > 0) { - this->current--; - - if(this->cursor > 1 || this->current == 0) { - this->cursor--; - } - - } else { - this->current = this->size - 1; - this->cursor = menu_size - 1; - } - } break; - } -} - -void MenuCtx::reset() { - this->current = 0; - this->cursor = 0; -} - -// draw numenu and handle navigation -void MenuComponent::handle(Event* event, Store* store, u8g2_t* u8g2, ScreenArea area) { - switch(event->type) { - // get button event - case EventTypeButton: { - if(event->value.button.id == ButtonsOk && event->value.button.state) { - if(this->ctx.current < this->ctx.size) { - FlipperComponent* next_item = (FlipperComponent*)this->ctx.list[this->ctx.current].item; - - if(next_item) { - store->is_fullscreen = false; - - printf("[layout view] go to %d item\n", this->ctx.current); - Event send_event; - send_event.type = EventTypeUiNext; - - next_item->handle( - &send_event, - store, - u8g2, - area - ); - } else { - printf("[menu view] no item at %d\n", this->ctx.current); - } - } - } - - if(event->value.button.id == ButtonsDown && event->value.button.state) { - this->ctx.handle(MenuEventDown); - this->dirty = true; - } - - if(event->value.button.id == ButtonsUp && event->value.button.state) { - this->ctx.handle(MenuEventUp); - this->dirty = true; - } - - // go back item - if(event->value.button.id == ButtonsBack && event->value.button.state) { - if(this->prev && this->prev != this) { - store->is_fullscreen = false; - - printf("[menu view] go back\n"); - - this->ctx.reset(); - - Event send_event; - send_event.type = EventTypeUiNext; - this->prev->handle( - &send_event, - store, - u8g2, - area - ); - - this->prev = NULL; - } else { - printf("[menu view] no back/loop\n"); - } - } - } break; - - // start component from prev - case EventTypeUiNext: - printf("[menu view] start component %lX (size %d)\n", (uint32_t)this, this->ctx.size); - - // set prev item - if(this->prev == NULL) { - printf("[menu view] set prev element to %lX\n", (uint32_t)store->current_component); - this->prev = store->current_component; - } - // set current item to self - store->current_component = this; - - store->is_fullscreen = true; - - // render menu - this->dirty = true; - break; - - case EventTypeTick: - if(this->dirty) { - draw_menu(&this->ctx, u8g2, area); - store->dirty_screen = true; - this->dirty = false; - } - break; - - default: break; - } -} diff --git a/lib/ui/ui.h b/lib/ui/ui.h deleted file mode 100644 index 0eb89bb6..00000000 --- a/lib/ui/ui.h +++ /dev/null @@ -1,218 +0,0 @@ -#pragma once - -extern "C" { - #include "main.h" - #include "cmsis_os.h" - #include "u8g2_support.h" - #include "u8g2/u8g2.h" -} - -#include "events.h" - -typedef struct { - void* item; - const char* name; -} MenuItem; - -#include "vendor.h" - -typedef enum { - LayoutActionUp, - LayoutActionDown, - LayoutActionLeft, - LayoutActionRight, - LayoutActionOk, - LayoutActionBack, - LayoutActionTimeout, - LayoutActionUsbConnect, - LayoutActionUsbDisconnect, - LayoutActionEndOfCycle -} LayoutAction; - -typedef struct { - FlipperComponent* item; - LayoutAction action; -} ActionItem; - -void draw_text(const char* text, u8g2_t* u8g2, ScreenArea area); -void draw_bitmap(const char* bitmap, u8g2_t* u8g2, ScreenArea area); - -class LayoutComponent: FlipperComponent { -public: - LayoutComponent(void (*draw_fn)(const char* text, u8g2_t* u8g2, ScreenArea area), ActionItem* actions, size_t actions_size, uint32_t timeout, const char* data) { - this->data = data; - this->actions = actions; - this->actions_size = actions_size; - this->timeout = timeout; - this->draw_fn = draw_fn; - - this->dirty = true; - - this->wait_time = 0; - } - - virtual void handle(Event* event, struct _Store* store, u8g2_t* u8g2, ScreenArea area); - -private: - const char* data; - ActionItem* actions; - size_t actions_size; - uint32_t timeout; - - void (*draw_fn)(const char* text, u8g2_t* u8g2, ScreenArea area); - - uint32_t wait_time; - - bool dirty; -}; - -typedef struct { - uint32_t on_time; - Color on_color; - uint32_t off_time; - Color off_color; -} BlinkerComponentConfig; - -class BlinkerComponent: FlipperComponent { -public: - BlinkerComponent( - void (*draw_fn)(const char* text, u8g2_t* u8g2, ScreenArea area), - BlinkerComponentConfig config, - const char* data - ) { - this->data = data; - this->draw_fn = draw_fn; - this->config = config; - - this->dirty = true; - - this->wait_time = 0; - this->is_on = true; - this->active = false; - this->prev = NULL; - } - - virtual void handle(Event* event, struct _Store* store, u8g2_t* u8g2, ScreenArea area); - -private: - const char* data; - BlinkerComponentConfig config; - - void (*draw_fn)(const char* text, u8g2_t* u8g2, ScreenArea area); - - uint32_t wait_time; - - bool is_on; - bool active; - - bool dirty; - FlipperComponent* prev; -}; - -typedef struct { - uint32_t on_time; - Color on_color; - uint32_t off_time; - Color off_color; -} BlinkerComponentOnBtnConfig; - -class BlinkerComponentOnBtn: FlipperComponent { -public: - BlinkerComponentOnBtn( - void (*draw_fn)(const char* text, u8g2_t* u8g2, ScreenArea area), - BlinkerComponentOnBtnConfig config, - const char* data - ) { - this->data = data; - this->draw_fn = draw_fn; - this->config = config; - - this->dirty = true; - - this->wait_time = 0; - this->is_on = true; - this->active = false; - this->prev = NULL; - } - - virtual void handle(Event* event, struct _Store* store, u8g2_t* u8g2, ScreenArea area); - -private: - const char* data; - BlinkerComponentOnBtnConfig config; - - void (*draw_fn)(const char* text, u8g2_t* u8g2, ScreenArea area); - - uint32_t wait_time; - - bool is_on; - bool active; - - bool dirty; - FlipperComponent* prev; -}; - - - -typedef enum { - MenuEventUp, - MenuEventDown -} MenuEvent; - -class MenuCtx { -public: - size_t size; - size_t current; - uint8_t cursor; - MenuItem* list; - - void handle(MenuEvent event); - void reset(); -}; - -void draw_menu(MenuCtx* ctx, u8g2_t* u8g2, ScreenArea area); - -class MenuComponent: FlipperComponent { -public: - MenuComponent(MenuItem* list, size_t size, const char* name) { - this->ctx.size = size; - this->ctx.current = 0; - this->ctx.cursor = 0; - - this->ctx.list = list; - - this->name = name; - this->prev = NULL; - - this->dirty = true; - } - - - const char* name; - FlipperComponent* prev; - MenuCtx ctx; - - - bool dirty; - - virtual void handle(Event* event, struct _Store* store, u8g2_t* u8g2, ScreenArea area); -}; - -typedef struct { - uint8_t x; - uint8_t y; -} Point; - -typedef struct { - uint8_t width; - uint8_t height; - uint8_t margin_left; - uint8_t margin_top; - uint8_t padding_left; - uint8_t padding_top; - uint8_t background; - uint8_t color; - uint8_t* font; -} Block; - -Point draw_block(u8g2_t* u8g2, const char* text, Block layout, uint8_t x, uint8_t y);