Update code owners and remove obsolete code (#446)

This commit is contained in:
あく 2021-05-05 17:53:07 +03:00 committed by GitHub
parent 920b3c3dee
commit c880f90eb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 44 additions and 1330 deletions

144
.github/CODEOWNERS vendored
View File

@ -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

View File

@ -1,104 +0,0 @@
#include <furi.h>
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;
}

0
flp/.gitignore vendored
View File

View File

@ -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"

142
flp/Pipfile.lock generated
View File

@ -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"
}
}
}

View File

@ -1,2 +0,0 @@
from flipper import file
from flipper.file import File

View File

@ -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()

View File

@ -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()

View File

@ -1,589 +0,0 @@
#include <stdio.h>
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;
}
}

View File

@ -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);