mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 04:34:43 +04:00
Merge remote-tracking branch 'OFW/dev' into dev
This commit is contained in:
9
applications/examples/example_adc/application.fam
Normal file
9
applications/examples/example_adc/application.fam
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
App(
|
||||||
|
appid="example_adc",
|
||||||
|
name="Example: ADC",
|
||||||
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
entry_point="example_adc_main",
|
||||||
|
requires=["gui"],
|
||||||
|
stack_size=1 * 1024,
|
||||||
|
fap_category="Examples",
|
||||||
|
)
|
||||||
176
applications/examples/example_adc/example_adc.c
Normal file
176
applications/examples/example_adc/example_adc.c
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
/**
|
||||||
|
* @file example_adc.c
|
||||||
|
* @brief ADC example.
|
||||||
|
*/
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include <gui/elements.h>
|
||||||
|
#include <input/input.h>
|
||||||
|
|
||||||
|
const uint8_t font[] =
|
||||||
|
"`\2\3\2\3\4\1\2\4\5\11\0\376\6\376\7\377\1M\2\263\3\370 \6\315\364\371\6!\12\315"
|
||||||
|
"\364\201\260\35\312Q\0\42\11\315tJI\316\13\0#\14\315\264\223dP*\203R'\1$\15\315\264"
|
||||||
|
"\262A\311\266D\251l\71\0%\15\315\264\7%\61)J\42\345 \0&\14\315\264\263$\13\223\266$"
|
||||||
|
"\7\1'\10\315\364\201\60\347\10(\10\315\364\32[\313\0)\11\315\64\322b[\35\2*\12\315\264\263"
|
||||||
|
"(\222j\71\15+\11\315\364I\331\226\23\1,\10\315\364\271\205Y\10-\10\315\364\31t\26\0.\10"
|
||||||
|
"\315\364\71\346(\0/\14\315\364\221\60\13\263\60\13C\0\60\13\315\264\245Jb)E:\12\61\12\315"
|
||||||
|
"\364\201Ll\333A\0\62\12\315\264\245bV\33r\20\63\13\315\264\245Z\232D\221\216\2\64\14\315\364"
|
||||||
|
"\201LJ\242!\313v\20\65\14\315t\207$\134\223(\322Q\0\66\13\315\264\245p\252D\221\216\2\67"
|
||||||
|
"\12\315t\207\60+\326a\0\70\13\315\264\245\222T\211\42\35\5\71\13\315\264\245J\24\215\221\216\2:"
|
||||||
|
"\11\315\364i\71!G\1;\12\315\364I\71!\314B\0<\11\315\364\341\254Z\7\1=\12\315\364)"
|
||||||
|
"C<\344$\0>\11\315\364\301\264V\207\1\77\12\315\264\245Z\35\312a\0@\14\315\264\245J\242$"
|
||||||
|
"J\272\203\0A\15\315\264\245J\224\14I\224D\71\10B\13\315t\247\312T\211\222\35\5C\12\315\264"
|
||||||
|
"\245JX\212t\24D\15\315t\247J\224DI\224\354(\0E\14\315t\207$\234\302p\310A\0F"
|
||||||
|
"\12\315t\207$\234\302:\1G\14\315\264\245J\230(Q\244\243\0H\17\315t\243$J\206$J\242"
|
||||||
|
"$\312A\0I\11\315\264\267\260m\7\1J\12\315\364\221\260%\212t\24K\14\315t\243\244\244iI"
|
||||||
|
"T\7\1L\11\315t\303\216C\16\2M\17\315t\243dH\206$J\242$\312A\0N\16\315t\243"
|
||||||
|
"D\251(Q\22%Q\16\2O\15\315\264\245J\224DI\24\351(\0P\12\315t\247J\224LaN"
|
||||||
|
"Q\15\315\264\245J\224DI\42\251\61\0R\14\315t\247J\224L\225(\7\1S\13\315\264\245\222\232"
|
||||||
|
"D\221\216\2T\10\315\264\267\260;\12U\16\315t\243$J\242$J\242HG\1V\15\315t\243$"
|
||||||
|
"J\242$Jj\71\14W\17\315t\243$J\242dH\206$\312A\0X\15\315t\243$\212\64\251\22"
|
||||||
|
"\345 \0Y\13\315t\243$Jja\35\6Z\12\315t\207\60k\34r\20[\10\315\264\264\260G\31"
|
||||||
|
"\134\12\315\264\303\64L\303\64\14]\10\315t\304\276\351\0^\11\315\364\201,\311\271\1_\7\315\364y"
|
||||||
|
"\35\4`\10\315t\322\234'\0a\14\315\364IK\224$R\222\203\0b\13\315t\303p\252D\311\216"
|
||||||
|
"\2c\12\315\364IR%\335A\0d\14\315\364\221\60Z\242$\212v\20e\12\315\364I\322\220\244;"
|
||||||
|
"\10f\12\315\364\221,\333\302:\12g\14\315\364IK\224D\321\30I\0h\14\315t\303p\252DI"
|
||||||
|
"\224\203\0i\12\315\364\201\34\21k;\10j\12\315\364\201\34\21\273e\0k\13\315t\303J\244%Q"
|
||||||
|
"\35\4l\10\315\264\305n;\10m\14\315\364)CRQ\22\245\216\1n\13\315\364)%\245\224D\71"
|
||||||
|
"\10o\12\315\364IR%\212t\24p\13\315\364)S%J\246\60\4q\13\315\364IK\224D\321X"
|
||||||
|
"\1r\11\315\364)%\245\230\23s\12\315\364I\313\232\354(\0t\13\315\364\201\60\333\302\64\7\1u"
|
||||||
|
"\15\315\364)Q\22%\211\224\344 \0v\13\315\364)Q\22%\265\34\6w\13\315\364)\25%Q\272"
|
||||||
|
"\203\0x\12\315\364)Q\244Iu\20y\15\315\364)Q\22%Q\64F\22\0z\12\315\364)CV"
|
||||||
|
"\33r\20{\12\315\364\212\265\64\254&\0|\7\315\264\302~\7}\12\315t\322\260\232\205\265\14~\11"
|
||||||
|
"\315\364II;\13\0\177\6\315\364\371\6\0\0\0\4\377\377\0";
|
||||||
|
|
||||||
|
#define FONT_HEIGHT (8u)
|
||||||
|
|
||||||
|
typedef float (*ValueConverter)(FuriHalAdcHandle* handle, uint16_t value);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const GpioPinRecord* pin;
|
||||||
|
float value;
|
||||||
|
ValueConverter converter;
|
||||||
|
const char* suffix;
|
||||||
|
} DataItem;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t count;
|
||||||
|
DataItem* items;
|
||||||
|
} Data;
|
||||||
|
|
||||||
|
const GpioPinRecord item_vref = {.name = "VREF", .channel = FuriHalAdcChannelVREFINT};
|
||||||
|
const GpioPinRecord item_temp = {.name = "TEMP", .channel = FuriHalAdcChannelTEMPSENSOR};
|
||||||
|
const GpioPinRecord item_vbat = {.name = "VBAT", .channel = FuriHalAdcChannelVBAT};
|
||||||
|
|
||||||
|
static void app_draw_callback(Canvas* canvas, void* ctx) {
|
||||||
|
furi_assert(ctx);
|
||||||
|
Data* data = ctx;
|
||||||
|
|
||||||
|
canvas_set_custom_u8g2_font(canvas, font);
|
||||||
|
char buffer[64];
|
||||||
|
int32_t x = 0, y = FONT_HEIGHT;
|
||||||
|
for(size_t i = 0; i < data->count; i++) {
|
||||||
|
if(i == canvas_height(canvas) / FONT_HEIGHT) {
|
||||||
|
x = 64;
|
||||||
|
y = FONT_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(
|
||||||
|
buffer,
|
||||||
|
sizeof(buffer),
|
||||||
|
"%4s: %4.0f%s\n",
|
||||||
|
data->items[i].pin->name,
|
||||||
|
(double)data->items[i].value,
|
||||||
|
data->items[i].suffix);
|
||||||
|
canvas_draw_str(canvas, x, y, buffer);
|
||||||
|
y += FONT_HEIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void app_input_callback(InputEvent* input_event, void* ctx) {
|
||||||
|
furi_assert(ctx);
|
||||||
|
FuriMessageQueue* event_queue = ctx;
|
||||||
|
furi_message_queue_put(event_queue, input_event, FuriWaitForever);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t example_adc_main(void* p) {
|
||||||
|
UNUSED(p);
|
||||||
|
|
||||||
|
// Data
|
||||||
|
Data data = {};
|
||||||
|
for(size_t i = 0; i < gpio_pins_count; i++) {
|
||||||
|
if(gpio_pins[i].channel != FuriHalAdcChannelNone) {
|
||||||
|
data.count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.count += 3; // Special channels
|
||||||
|
data.items = malloc(data.count * sizeof(DataItem));
|
||||||
|
size_t item_pos = 0;
|
||||||
|
for(size_t i = 0; i < gpio_pins_count; i++) {
|
||||||
|
if(gpio_pins[i].channel != FuriHalAdcChannelNone) {
|
||||||
|
furi_hal_gpio_init(gpio_pins[i].pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
data.items[item_pos].pin = &gpio_pins[i];
|
||||||
|
data.items[item_pos].converter = furi_hal_adc_convert_to_voltage;
|
||||||
|
data.items[item_pos].suffix = "mV";
|
||||||
|
item_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.items[item_pos].pin = &item_vref;
|
||||||
|
data.items[item_pos].converter = furi_hal_adc_convert_vref;
|
||||||
|
data.items[item_pos].suffix = "mV";
|
||||||
|
item_pos++;
|
||||||
|
data.items[item_pos].pin = &item_temp;
|
||||||
|
data.items[item_pos].converter = furi_hal_adc_convert_temp;
|
||||||
|
data.items[item_pos].suffix = "C";
|
||||||
|
item_pos++;
|
||||||
|
data.items[item_pos].pin = &item_vbat;
|
||||||
|
data.items[item_pos].converter = furi_hal_adc_convert_vbat;
|
||||||
|
data.items[item_pos].suffix = "mV";
|
||||||
|
item_pos++;
|
||||||
|
furi_assert(item_pos == data.count);
|
||||||
|
|
||||||
|
// Alloc message queue
|
||||||
|
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
|
||||||
|
|
||||||
|
// Configure view port
|
||||||
|
ViewPort* view_port = view_port_alloc();
|
||||||
|
view_port_draw_callback_set(view_port, app_draw_callback, &data);
|
||||||
|
view_port_input_callback_set(view_port, app_input_callback, event_queue);
|
||||||
|
|
||||||
|
// Register view port in GUI
|
||||||
|
Gui* gui = furi_record_open(RECORD_GUI);
|
||||||
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
|
// Initialize ADC
|
||||||
|
FuriHalAdcHandle* adc_handle = furi_hal_adc_acquire();
|
||||||
|
furi_hal_adc_configure(adc_handle);
|
||||||
|
|
||||||
|
// Process events
|
||||||
|
InputEvent event;
|
||||||
|
bool running = true;
|
||||||
|
while(running) {
|
||||||
|
if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) {
|
||||||
|
if(event.type == InputTypePress && event.key == InputKeyBack) {
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(size_t i = 0; i < data.count; i++) {
|
||||||
|
data.items[i].value = data.items[i].converter(
|
||||||
|
adc_handle, furi_hal_adc_read(adc_handle, data.items[i].pin->channel));
|
||||||
|
}
|
||||||
|
view_port_update(view_port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_hal_adc_release(adc_handle);
|
||||||
|
view_port_enabled_set(view_port, false);
|
||||||
|
gui_remove_view_port(gui, view_port);
|
||||||
|
view_port_free(view_port);
|
||||||
|
furi_message_queue_free(event_queue);
|
||||||
|
furi_record_close(RECORD_GUI);
|
||||||
|
free(data.items);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -94,7 +94,7 @@ int32_t example_custom_font_main(void* p) {
|
|||||||
|
|
||||||
// Configure view port
|
// Configure view port
|
||||||
ViewPort* view_port = view_port_alloc();
|
ViewPort* view_port = view_port_alloc();
|
||||||
view_port_draw_callback_set(view_port, app_draw_callback, view_port);
|
view_port_draw_callback_set(view_port, app_draw_callback, NULL);
|
||||||
view_port_input_callback_set(view_port, app_input_callback, event_queue);
|
view_port_input_callback_set(view_port, app_input_callback, event_queue);
|
||||||
|
|
||||||
// Register view port in GUI
|
// Register view port in GUI
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ int32_t example_images_main(void* p) {
|
|||||||
|
|
||||||
// Configure view port
|
// Configure view port
|
||||||
ViewPort* view_port = view_port_alloc();
|
ViewPort* view_port = view_port_alloc();
|
||||||
view_port_draw_callback_set(view_port, app_draw_callback, view_port);
|
view_port_draw_callback_set(view_port, app_draw_callback, NULL);
|
||||||
view_port_input_callback_set(view_port, app_input_callback, event_queue);
|
view_port_input_callback_set(view_port, app_input_callback, event_queue);
|
||||||
|
|
||||||
// Register view port in GUI
|
// Register view port in GUI
|
||||||
|
|||||||
@@ -17,5 +17,6 @@ ADD_SCENE(ibutton, delete_confirm, DeleteConfirm)
|
|||||||
ADD_SCENE(ibutton, delete_success, DeleteSuccess)
|
ADD_SCENE(ibutton, delete_success, DeleteSuccess)
|
||||||
ADD_SCENE(ibutton, retry_confirm, RetryConfirm)
|
ADD_SCENE(ibutton, retry_confirm, RetryConfirm)
|
||||||
ADD_SCENE(ibutton, exit_confirm, ExitConfirm)
|
ADD_SCENE(ibutton, exit_confirm, ExitConfirm)
|
||||||
|
ADD_SCENE(ibutton, read_exit_confirm, ReadExitConfirm)
|
||||||
ADD_SCENE(ibutton, view_data, ViewData)
|
ADD_SCENE(ibutton, view_data, ViewData)
|
||||||
ADD_SCENE(ibutton, rpc, Rpc)
|
ADD_SCENE(ibutton, rpc, Rpc)
|
||||||
|
|||||||
@@ -7,23 +7,33 @@ void ibutton_scene_delete_confirm_on_enter(void* context) {
|
|||||||
Widget* widget = ibutton->widget;
|
Widget* widget = ibutton->widget;
|
||||||
|
|
||||||
FuriString* tmp = furi_string_alloc();
|
FuriString* tmp = furi_string_alloc();
|
||||||
|
FuriString* uid = furi_string_alloc();
|
||||||
|
|
||||||
widget_add_button_element(widget, GuiButtonTypeLeft, "Back", ibutton_widget_callback, context);
|
widget_add_button_element(widget, GuiButtonTypeLeft, "Back", ibutton_widget_callback, context);
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
widget, GuiButtonTypeRight, "Delete", ibutton_widget_callback, context);
|
widget, GuiButtonTypeRight, "Delete", ibutton_widget_callback, context);
|
||||||
|
|
||||||
furi_string_printf(tmp, "\e#Delete %s?\e#", ibutton->key_name);
|
furi_string_printf(tmp, "\e#Delete %s?\e#\n", ibutton->key_name);
|
||||||
|
|
||||||
|
ibutton_protocols_render_uid(ibutton->protocols, key, uid);
|
||||||
|
|
||||||
|
furi_string_cat_printf(
|
||||||
|
uid,
|
||||||
|
"\n%s %s",
|
||||||
|
ibutton_protocols_get_manufacturer(ibutton->protocols, ibutton_key_get_protocol_id(key)),
|
||||||
|
ibutton_protocols_get_name(ibutton->protocols, ibutton_key_get_protocol_id(key)));
|
||||||
|
|
||||||
|
furi_string_cat(tmp, uid);
|
||||||
|
|
||||||
widget_add_text_box_element(
|
widget_add_text_box_element(
|
||||||
widget, 0, 0, 128, 23, AlignCenter, AlignCenter, furi_string_get_cstr(tmp), false);
|
widget, 0, 0, 128, 64, AlignCenter, AlignTop, furi_string_get_cstr(tmp), false);
|
||||||
|
|
||||||
furi_string_reset(tmp);
|
furi_string_reset(tmp);
|
||||||
ibutton_protocols_render_brief_data(ibutton->protocols, key, tmp);
|
furi_string_reset(uid);
|
||||||
|
|
||||||
widget_add_string_multiline_element(
|
|
||||||
widget, 128 / 2, 24, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp));
|
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||||
furi_string_free(tmp);
|
furi_string_free(tmp);
|
||||||
|
furi_string_free(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) {
|
bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
|||||||
@@ -21,17 +21,20 @@ void ibutton_scene_emulate_on_enter(void* context) {
|
|||||||
|
|
||||||
widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44);
|
widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44);
|
||||||
|
|
||||||
furi_string_printf(
|
if(furi_string_empty(ibutton->file_path)) {
|
||||||
tmp,
|
furi_string_printf(
|
||||||
"[%s]\n%s",
|
tmp,
|
||||||
ibutton_protocols_get_name(ibutton->protocols, ibutton_key_get_protocol_id(key)),
|
"Unsaved\n%s",
|
||||||
furi_string_empty(ibutton->file_path) ? "Unsaved Key" : ibutton->key_name);
|
ibutton_protocols_get_name(ibutton->protocols, ibutton_key_get_protocol_id(key)));
|
||||||
|
} else {
|
||||||
|
furi_string_printf(tmp, "%s", ibutton->key_name);
|
||||||
|
}
|
||||||
|
|
||||||
widget_add_text_box_element(
|
widget_add_text_box_element(
|
||||||
widget, 52, 30, 75, 40, AlignCenter, AlignCenter, furi_string_get_cstr(tmp), true);
|
widget, 52, 23, 75, 26, AlignCenter, AlignTop, furi_string_get_cstr(tmp), false);
|
||||||
|
|
||||||
widget_add_string_multiline_element(
|
widget_add_string_multiline_element(
|
||||||
widget, 88, 5, AlignCenter, AlignTop, FontPrimary, "iButton\nemulating");
|
widget, 88, 10, AlignCenter, AlignTop, FontPrimary, "Emulating");
|
||||||
|
|
||||||
ibutton_worker_emulate_set_callback(ibutton->worker, ibutton_scene_emulate_callback, ibutton);
|
ibutton_worker_emulate_set_callback(ibutton->worker, ibutton_scene_emulate_callback, ibutton);
|
||||||
ibutton_worker_emulate_start(ibutton->worker, key);
|
ibutton_worker_emulate_start(ibutton->worker, key);
|
||||||
|
|||||||
@@ -8,19 +8,24 @@ void ibutton_scene_info_on_enter(void* context) {
|
|||||||
const iButtonProtocolId protocol_id = ibutton_key_get_protocol_id(key);
|
const iButtonProtocolId protocol_id = ibutton_key_get_protocol_id(key);
|
||||||
|
|
||||||
FuriString* tmp = furi_string_alloc();
|
FuriString* tmp = furi_string_alloc();
|
||||||
FuriString* keynumber = furi_string_alloc();
|
FuriString* brief_data = furi_string_alloc();
|
||||||
|
|
||||||
ibutton_protocols_render_brief_data(ibutton->protocols, key, keynumber);
|
|
||||||
|
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
tmp,
|
tmp,
|
||||||
"\e#%s\n[%s]\e#\n%s",
|
"Name:%s\n\e#%s %s\e#\n",
|
||||||
ibutton->key_name,
|
ibutton->key_name,
|
||||||
ibutton_protocols_get_name(ibutton->protocols, protocol_id),
|
ibutton_protocols_get_manufacturer(ibutton->protocols, protocol_id),
|
||||||
furi_string_get_cstr(keynumber));
|
ibutton_protocols_get_name(ibutton->protocols, protocol_id));
|
||||||
|
|
||||||
|
ibutton_protocols_render_brief_data(ibutton->protocols, key, brief_data);
|
||||||
|
|
||||||
|
furi_string_cat(tmp, brief_data);
|
||||||
|
|
||||||
widget_add_text_box_element(
|
widget_add_text_box_element(
|
||||||
widget, 0, 2, 128, 64, AlignLeft, AlignTop, furi_string_get_cstr(tmp), true);
|
widget, 0, 0, 128, 64, AlignLeft, AlignTop, furi_string_get_cstr(tmp), false);
|
||||||
|
|
||||||
|
furi_string_reset(tmp);
|
||||||
|
furi_string_reset(brief_data);
|
||||||
|
|
||||||
if(ibutton_protocols_get_features(ibutton->protocols, protocol_id) &
|
if(ibutton_protocols_get_features(ibutton->protocols, protocol_id) &
|
||||||
iButtonProtocolFeatureExtData) {
|
iButtonProtocolFeatureExtData) {
|
||||||
@@ -30,7 +35,7 @@ void ibutton_scene_info_on_enter(void* context) {
|
|||||||
|
|
||||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||||
furi_string_free(tmp);
|
furi_string_free(tmp);
|
||||||
furi_string_free(keynumber);
|
furi_string_free(brief_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) {
|
bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ void ibutton_scene_read_on_enter(void* context) {
|
|||||||
iButtonKey* key = ibutton->key;
|
iButtonKey* key = ibutton->key;
|
||||||
iButtonWorker* worker = ibutton->worker;
|
iButtonWorker* worker = ibutton->worker;
|
||||||
|
|
||||||
popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom);
|
popup_set_header(popup, "Reading", 95, 26, AlignCenter, AlignBottom);
|
||||||
popup_set_text(popup, "Apply key to\nFlipper's back", 95, 30, AlignCenter, AlignTop);
|
popup_set_text(popup, "Connect key\nwith pogo pins", 95, 30, AlignCenter, AlignTop);
|
||||||
popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59);
|
popup_set_icon(popup, 0, 10, &I_DolphinWait_59x54);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
|
||||||
|
|
||||||
|
|||||||
@@ -14,13 +14,10 @@ void ibutton_scene_read_error_on_enter(void* context) {
|
|||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
widget, GuiButtonTypeRight, "More", ibutton_widget_callback, context);
|
widget, GuiButtonTypeRight, "More", ibutton_widget_callback, context);
|
||||||
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 128 / 2, 2, AlignCenter, AlignTop, FontPrimary, "Read Error");
|
|
||||||
|
|
||||||
ibutton_protocols_render_error(ibutton->protocols, key, tmp);
|
ibutton_protocols_render_error(ibutton->protocols, key, tmp);
|
||||||
|
|
||||||
widget_add_string_multiline_element(
|
widget_add_text_box_element(
|
||||||
widget, 128 / 2, 16, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp));
|
widget, 0, 0, 128, 48, AlignCenter, AlignTop, furi_string_get_cstr(tmp), false);
|
||||||
|
|
||||||
ibutton_notification_message(ibutton, iButtonNotificationMessageError);
|
ibutton_notification_message(ibutton, iButtonNotificationMessageError);
|
||||||
ibutton_notification_message(ibutton, iButtonNotificationMessageRedOn);
|
ibutton_notification_message(ibutton, iButtonNotificationMessageRedOn);
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
static void ibutton_scene_read_exit_confirm_widget_callback(
|
||||||
|
GuiButtonType result,
|
||||||
|
InputType type,
|
||||||
|
void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
if(type == InputTypeShort) {
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_exit_confirm_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Widget* widget = ibutton->widget;
|
||||||
|
|
||||||
|
widget_add_button_element(
|
||||||
|
widget,
|
||||||
|
GuiButtonTypeLeft,
|
||||||
|
"Exit",
|
||||||
|
ibutton_scene_read_exit_confirm_widget_callback,
|
||||||
|
ibutton);
|
||||||
|
widget_add_button_element(
|
||||||
|
widget,
|
||||||
|
GuiButtonTypeRight,
|
||||||
|
"Stay",
|
||||||
|
ibutton_scene_read_exit_confirm_widget_callback,
|
||||||
|
ibutton);
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Retry Reading?");
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_read_exit_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeBack) {
|
||||||
|
consumed = true; // Ignore Back button presses
|
||||||
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == GuiButtonTypeLeft) {
|
||||||
|
scene_manager_search_and_switch_to_previous_scene(scene_manager, iButtonSceneRead);
|
||||||
|
} else if(event.event == GuiButtonTypeRight) {
|
||||||
|
scene_manager_previous_scene(scene_manager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_exit_confirm_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
widget_reset(ibutton->widget);
|
||||||
|
}
|
||||||
@@ -30,19 +30,10 @@ void ibutton_scene_read_key_menu_on_enter(void* context) {
|
|||||||
ibutton_scene_read_key_menu_submenu_callback,
|
ibutton_scene_read_key_menu_submenu_callback,
|
||||||
ibutton);
|
ibutton);
|
||||||
|
|
||||||
if(features & iButtonProtocolFeatureExtData) {
|
|
||||||
submenu_add_item(
|
|
||||||
submenu,
|
|
||||||
"View Data",
|
|
||||||
SubmenuIndexViewData,
|
|
||||||
ibutton_scene_read_key_menu_submenu_callback,
|
|
||||||
ibutton);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(features & iButtonProtocolFeatureWriteBlank) {
|
if(features & iButtonProtocolFeatureWriteBlank) {
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
"Write Blank",
|
"Write ID",
|
||||||
SubmenuIndexWriteBlank,
|
SubmenuIndexWriteBlank,
|
||||||
ibutton_scene_read_key_menu_submenu_callback,
|
ibutton_scene_read_key_menu_submenu_callback,
|
||||||
ibutton);
|
ibutton);
|
||||||
@@ -51,12 +42,21 @@ void ibutton_scene_read_key_menu_on_enter(void* context) {
|
|||||||
if(features & iButtonProtocolFeatureWriteCopy) {
|
if(features & iButtonProtocolFeatureWriteCopy) {
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
"Write Copy",
|
"Full Write on Same Type",
|
||||||
SubmenuIndexWriteCopy,
|
SubmenuIndexWriteCopy,
|
||||||
ibutton_scene_read_key_menu_submenu_callback,
|
ibutton_scene_read_key_menu_submenu_callback,
|
||||||
ibutton);
|
ibutton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(features & iButtonProtocolFeatureExtData) {
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Data Info",
|
||||||
|
SubmenuIndexViewData,
|
||||||
|
ibutton_scene_read_key_menu_submenu_callback,
|
||||||
|
ibutton);
|
||||||
|
}
|
||||||
|
|
||||||
submenu_set_selected_item(
|
submenu_set_selected_item(
|
||||||
submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneReadKeyMenu));
|
submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneReadKeyMenu));
|
||||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ void ibutton_scene_read_success_on_enter(void* context) {
|
|||||||
|
|
||||||
furi_string_printf(
|
furi_string_printf(
|
||||||
tmp,
|
tmp,
|
||||||
"%s[%s]",
|
"%s %s",
|
||||||
ibutton_protocols_get_name(ibutton->protocols, protocol_id),
|
ibutton_protocols_get_manufacturer(ibutton->protocols, protocol_id),
|
||||||
ibutton_protocols_get_manufacturer(ibutton->protocols, protocol_id));
|
ibutton_protocols_get_name(ibutton->protocols, protocol_id));
|
||||||
|
|
||||||
widget_add_string_element(
|
widget_add_string_element(
|
||||||
widget, 0, 2, AlignLeft, AlignTop, FontPrimary, furi_string_get_cstr(tmp));
|
widget, 0, 2, AlignLeft, AlignTop, FontPrimary, furi_string_get_cstr(tmp));
|
||||||
@@ -44,7 +44,7 @@ bool ibutton_scene_read_success_on_event(void* context, SceneManagerEvent event)
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeBack) {
|
if(event.type == SceneManagerEventTypeBack) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
scene_manager_next_scene(scene_manager, iButtonSceneExitConfirm);
|
scene_manager_next_scene(scene_manager, iButtonSceneReadExitConfirm);
|
||||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == GuiButtonTypeRight) {
|
if(event.event == GuiButtonTypeRight) {
|
||||||
|
|||||||
@@ -21,12 +21,16 @@ void ibutton_scene_saved_key_menu_on_enter(void* context) {
|
|||||||
|
|
||||||
if(features & iButtonProtocolFeatureWriteBlank) {
|
if(features & iButtonProtocolFeatureWriteBlank) {
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu, "Write Blank", SubmenuIndexWriteBlank, ibutton_submenu_callback, ibutton);
|
submenu, "Write ID", SubmenuIndexWriteBlank, ibutton_submenu_callback, ibutton);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(features & iButtonProtocolFeatureWriteCopy) {
|
if(features & iButtonProtocolFeatureWriteCopy) {
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu, "Write Copy", SubmenuIndexWriteCopy, ibutton_submenu_callback, ibutton);
|
submenu,
|
||||||
|
"Full Write on Same Type",
|
||||||
|
SubmenuIndexWriteCopy,
|
||||||
|
ibutton_submenu_callback,
|
||||||
|
ibutton);
|
||||||
}
|
}
|
||||||
|
|
||||||
submenu_add_item(submenu, "Edit", SubmenuIndexEdit, ibutton_submenu_callback, ibutton);
|
submenu_add_item(submenu, "Edit", SubmenuIndexEdit, ibutton_submenu_callback, ibutton);
|
||||||
|
|||||||
@@ -40,25 +40,24 @@ void ibutton_scene_write_on_enter(void* context) {
|
|||||||
|
|
||||||
widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44);
|
widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44);
|
||||||
|
|
||||||
furi_string_printf(
|
if(furi_string_empty(ibutton->file_path)) {
|
||||||
tmp,
|
furi_string_printf(
|
||||||
"[%s]\n%s ",
|
tmp, "Unsaved\n%s", ibutton_protocols_get_name(ibutton->protocols, protocol_id));
|
||||||
ibutton_protocols_get_name(ibutton->protocols, protocol_id),
|
} else {
|
||||||
ibutton->key_name);
|
furi_string_printf(tmp, "%s", ibutton->key_name);
|
||||||
|
}
|
||||||
|
|
||||||
widget_add_text_box_element(
|
widget_add_text_box_element(
|
||||||
widget, 52, 30, 75, 40, AlignCenter, AlignCenter, furi_string_get_cstr(tmp), true);
|
widget, 52, 23, 75, 26, AlignCenter, AlignTop, furi_string_get_cstr(tmp), false);
|
||||||
|
|
||||||
ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton);
|
ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton);
|
||||||
|
|
||||||
furi_string_set(tmp, "iButton\nwriting ");
|
|
||||||
|
|
||||||
if(ibutton->write_mode == iButtonWriteModeBlank) {
|
if(ibutton->write_mode == iButtonWriteModeBlank) {
|
||||||
furi_string_cat(tmp, "Blank");
|
furi_string_set(tmp, "Writing ID");
|
||||||
ibutton_worker_write_blank_start(worker, key);
|
ibutton_worker_write_blank_start(worker, key);
|
||||||
|
|
||||||
} else if(ibutton->write_mode == iButtonWriteModeCopy) {
|
} else if(ibutton->write_mode == iButtonWriteModeCopy) {
|
||||||
furi_string_cat(tmp, "Copy");
|
furi_string_set(tmp, "Full Writing");
|
||||||
ibutton_worker_write_copy_start(worker, key);
|
ibutton_worker_write_copy_start(worker, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,10 @@ static bool bip_read(Nfc* nfc, NfcDevice* device) {
|
|||||||
MfClassicType type = MfClassicTypeMini;
|
MfClassicType type = MfClassicTypeMini;
|
||||||
MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type);
|
MfClassicError error = mf_classic_poller_sync_detect_type(nfc, &type);
|
||||||
if(error != MfClassicErrorNone) break;
|
if(error != MfClassicErrorNone) break;
|
||||||
|
if(type != MfClassicType1k) {
|
||||||
|
FURI_LOG_W(TAG, "Card not MIFARE Classic 1k");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
data->type = type;
|
data->type = type;
|
||||||
if(type != MfClassicType1k) break;
|
if(type != MfClassicType1k) break;
|
||||||
|
|||||||
BIN
assets/icons/Dolphin/DolphinWait_59x54.png
Normal file
BIN
assets/icons/Dolphin/DolphinWait_59x54.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -287,6 +287,17 @@ bool ibutton_protocols_load(iButtonProtocols* protocols, iButtonKey* key, const
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ibutton_protocols_render_uid(
|
||||||
|
iButtonProtocols* protocols,
|
||||||
|
const iButtonKey* key,
|
||||||
|
FuriString* result) {
|
||||||
|
const iButtonProtocolId id = ibutton_key_get_protocol_id(key);
|
||||||
|
const iButtonProtocolData* data = ibutton_key_get_protocol_data(key);
|
||||||
|
|
||||||
|
GET_PROTOCOL_GROUP(id);
|
||||||
|
GROUP_BASE->render_uid(GROUP_DATA, data, PROTOCOL_ID, result);
|
||||||
|
}
|
||||||
|
|
||||||
void ibutton_protocols_render_data(
|
void ibutton_protocols_render_data(
|
||||||
iButtonProtocols* protocols,
|
iButtonProtocols* protocols,
|
||||||
const iButtonKey* key,
|
const iButtonKey* key,
|
||||||
|
|||||||
@@ -133,6 +133,17 @@ bool ibutton_protocols_save(
|
|||||||
*/
|
*/
|
||||||
bool ibutton_protocols_load(iButtonProtocols* protocols, iButtonKey* key, const char* file_name);
|
bool ibutton_protocols_load(iButtonProtocols* protocols, iButtonKey* key, const char* file_name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a string containing defice UID
|
||||||
|
* @param [in] protocols pointer to an iButtonProtocols object
|
||||||
|
* @param [in] key pointer to the key to be rendered
|
||||||
|
* @param [out] result pointer to the FuriString instance (must be initialized)
|
||||||
|
*/
|
||||||
|
void ibutton_protocols_render_uid(
|
||||||
|
iButtonProtocols* protocols,
|
||||||
|
const iButtonKey* key,
|
||||||
|
FuriString* result);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format a string containing device full data
|
* Format a string containing device full data
|
||||||
* @param [in] protocols pointer to an iButtonProtocols object
|
* @param [in] protocols pointer to an iButtonProtocols object
|
||||||
|
|||||||
@@ -208,15 +208,26 @@ bool dallas_common_is_valid_crc(const DallasCommonRomData* rom_data) {
|
|||||||
return crc_calculated == crc_received;
|
return crc_calculated == crc_received;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dallas_common_render_uid(FuriString* result, const DallasCommonRomData* rom_data) {
|
||||||
|
furi_string_cat_printf(result, "ID: ");
|
||||||
|
for(size_t i = 0; i < sizeof(DallasCommonRomData); ++i) {
|
||||||
|
furi_string_cat_printf(result, "%02X ", rom_data->bytes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void dallas_common_render_brief_data(
|
void dallas_common_render_brief_data(
|
||||||
FuriString* result,
|
FuriString* result,
|
||||||
const DallasCommonRomData* rom_data,
|
const DallasCommonRomData* rom_data,
|
||||||
const uint8_t* mem_data,
|
const uint8_t* mem_data,
|
||||||
size_t mem_size,
|
size_t mem_size,
|
||||||
const char* mem_name) {
|
const char* mem_name) {
|
||||||
|
UNUSED(mem_data);
|
||||||
|
|
||||||
|
furi_string_cat_printf(result, "ID: ");
|
||||||
for(size_t i = 0; i < sizeof(rom_data->bytes); ++i) {
|
for(size_t i = 0; i < sizeof(rom_data->bytes); ++i) {
|
||||||
furi_string_cat_printf(result, "%02X ", rom_data->bytes[i]);
|
furi_string_cat_printf(result, "%02X ", rom_data->bytes[i]);
|
||||||
}
|
}
|
||||||
|
furi_string_cat_printf(result, "\nFamily Code: %02X\n", rom_data->bytes[0]);
|
||||||
|
|
||||||
const char* size_prefix = "";
|
const char* size_prefix = "";
|
||||||
size_t mem_size_bits = mem_size * BITS_IN_BYTE;
|
size_t mem_size_bits = mem_size * BITS_IN_BYTE;
|
||||||
@@ -229,28 +240,23 @@ void dallas_common_render_brief_data(
|
|||||||
mem_size_bits /= BITS_IN_KBIT;
|
mem_size_bits /= BITS_IN_KBIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(result, "%s: %zu %sbit\n", mem_name, mem_size_bits, size_prefix);
|
||||||
result, "\nInternal %s: %zu %sbit\n", mem_name, mem_size_bits, size_prefix);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < DALLAS_COMMON_BRIEF_HEAD_COUNT; ++i) {
|
|
||||||
furi_string_cat_printf(result, "%02X ", mem_data[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
furi_string_cat_printf(result, "[ . . . ]");
|
|
||||||
|
|
||||||
for(size_t i = mem_size - DALLAS_COMMON_BRIEF_TAIL_COUNT; i < mem_size; ++i) {
|
|
||||||
furi_string_cat_printf(result, " %02X", mem_data[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dallas_common_render_crc_error(FuriString* result, const DallasCommonRomData* rom_data) {
|
void dallas_common_render_crc_error(FuriString* result, const DallasCommonRomData* rom_data) {
|
||||||
furi_string_set(result, "CRC Error\n");
|
furi_string_set(result, "\e#CRC Error\e#\n");
|
||||||
|
|
||||||
const size_t data_size = sizeof(DallasCommonRomData);
|
const size_t data_size = sizeof(DallasCommonRomData);
|
||||||
|
|
||||||
for(size_t i = 0; i < data_size; ++i) {
|
for(size_t i = 0; i < data_size; ++i) {
|
||||||
furi_string_cat_printf(result, (i < data_size - 1) ? "%02X " : "%02X", rom_data->bytes[i]);
|
furi_string_cat_printf(
|
||||||
|
result, (i < data_size - 1) ? "%02X " : "\e!%02X\e!", rom_data->bytes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
furi_string_cat_printf(
|
||||||
|
result,
|
||||||
|
"\nExpected CRC: \e!%02X\e!",
|
||||||
|
maxim_crc8(rom_data->bytes, sizeof(DallasCommonRomData) - 1, MAXIM_CRC8_INIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
void dallas_common_apply_edits(DallasCommonRomData* rom_data, uint8_t family_code) {
|
void dallas_common_apply_edits(DallasCommonRomData* rom_data, uint8_t family_code) {
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ bool dallas_common_load_rom_data(
|
|||||||
/* Miscellaneous */
|
/* Miscellaneous */
|
||||||
bool dallas_common_is_valid_crc(const DallasCommonRomData* rom_data);
|
bool dallas_common_is_valid_crc(const DallasCommonRomData* rom_data);
|
||||||
|
|
||||||
|
void dallas_common_render_uid(FuriString* result, const DallasCommonRomData* rom_data);
|
||||||
|
|
||||||
void dallas_common_render_brief_data(
|
void dallas_common_render_brief_data(
|
||||||
FuriString* result,
|
FuriString* result,
|
||||||
const DallasCommonRomData* rom_data,
|
const DallasCommonRomData* rom_data,
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ typedef struct {
|
|||||||
iButtonProtocolDallasEmulateFunc emulate;
|
iButtonProtocolDallasEmulateFunc emulate;
|
||||||
iButtonProtocolDallasSaveFunc save;
|
iButtonProtocolDallasSaveFunc save;
|
||||||
iButtonProtocolDallasLoadFunc load;
|
iButtonProtocolDallasLoadFunc load;
|
||||||
|
iButtonProtocolDallasRenderDataFunc render_uid;
|
||||||
iButtonProtocolDallasRenderDataFunc render_data;
|
iButtonProtocolDallasRenderDataFunc render_data;
|
||||||
iButtonProtocolDallasRenderDataFunc render_brief_data;
|
iButtonProtocolDallasRenderDataFunc render_brief_data;
|
||||||
iButtonProtocolDallasRenderDataFunc render_error;
|
iButtonProtocolDallasRenderDataFunc render_error;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ static bool dallas_ds1971_write_copy(OneWireHost*, iButtonProtocolData*);
|
|||||||
static void dallas_ds1971_emulate(OneWireSlave*, iButtonProtocolData*);
|
static void dallas_ds1971_emulate(OneWireSlave*, iButtonProtocolData*);
|
||||||
static bool dallas_ds1971_load(FlipperFormat*, uint32_t, iButtonProtocolData*);
|
static bool dallas_ds1971_load(FlipperFormat*, uint32_t, iButtonProtocolData*);
|
||||||
static bool dallas_ds1971_save(FlipperFormat*, const iButtonProtocolData*);
|
static bool dallas_ds1971_save(FlipperFormat*, const iButtonProtocolData*);
|
||||||
|
static void dallas_ds1971_render_uid(FuriString*, const iButtonProtocolData*);
|
||||||
static void dallas_ds1971_render_data(FuriString*, const iButtonProtocolData*);
|
static void dallas_ds1971_render_data(FuriString*, const iButtonProtocolData*);
|
||||||
static void dallas_ds1971_render_brief_data(FuriString*, const iButtonProtocolData*);
|
static void dallas_ds1971_render_brief_data(FuriString*, const iButtonProtocolData*);
|
||||||
static void dallas_ds1971_render_error(FuriString*, const iButtonProtocolData*);
|
static void dallas_ds1971_render_error(FuriString*, const iButtonProtocolData*);
|
||||||
@@ -58,6 +59,7 @@ const iButtonProtocolDallasBase ibutton_protocol_ds1971 = {
|
|||||||
.emulate = dallas_ds1971_emulate,
|
.emulate = dallas_ds1971_emulate,
|
||||||
.save = dallas_ds1971_save,
|
.save = dallas_ds1971_save,
|
||||||
.load = dallas_ds1971_load,
|
.load = dallas_ds1971_load,
|
||||||
|
.render_uid = dallas_ds1971_render_uid,
|
||||||
.render_data = dallas_ds1971_render_data,
|
.render_data = dallas_ds1971_render_data,
|
||||||
.render_brief_data = dallas_ds1971_render_brief_data,
|
.render_brief_data = dallas_ds1971_render_brief_data,
|
||||||
.render_error = dallas_ds1971_render_error,
|
.render_error = dallas_ds1971_render_error,
|
||||||
@@ -209,14 +211,26 @@ bool dallas_ds1971_save(FlipperFormat* ff, const iButtonProtocolData* protocol_d
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dallas_ds1971_render_uid(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
|
const DS1971ProtocolData* data = protocol_data;
|
||||||
|
dallas_common_render_uid(result, &data->rom_data);
|
||||||
|
}
|
||||||
|
|
||||||
void dallas_ds1971_render_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
void dallas_ds1971_render_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
const DS1971ProtocolData* data = protocol_data;
|
const DS1971ProtocolData* data = protocol_data;
|
||||||
|
FuriString* data_string = furi_string_alloc();
|
||||||
|
|
||||||
pretty_format_bytes_hex_canonical(
|
pretty_format_bytes_hex_canonical(
|
||||||
result,
|
data_string,
|
||||||
DS1971_DATA_BYTE_COUNT,
|
DS1971_DATA_BYTE_COUNT,
|
||||||
PRETTY_FORMAT_FONT_MONOSPACE,
|
PRETTY_FORMAT_FONT_MONOSPACE,
|
||||||
data->eeprom_data,
|
data->eeprom_data,
|
||||||
DS1971_EEPROM_DATA_SIZE);
|
DS1971_EEPROM_DATA_SIZE);
|
||||||
|
|
||||||
|
furi_string_cat_printf(result, "\e#Memory Data\n--------------------\n");
|
||||||
|
furi_string_cat_printf(result, "%s", furi_string_get_cstr(data_string));
|
||||||
|
|
||||||
|
furi_string_free(data_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dallas_ds1971_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
void dallas_ds1971_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ static bool dallas_ds1990_write_blank(OneWireHost*, iButtonProtocolData*);
|
|||||||
static void dallas_ds1990_emulate(OneWireSlave*, iButtonProtocolData*);
|
static void dallas_ds1990_emulate(OneWireSlave*, iButtonProtocolData*);
|
||||||
static bool dallas_ds1990_load(FlipperFormat*, uint32_t, iButtonProtocolData*);
|
static bool dallas_ds1990_load(FlipperFormat*, uint32_t, iButtonProtocolData*);
|
||||||
static bool dallas_ds1990_save(FlipperFormat*, const iButtonProtocolData*);
|
static bool dallas_ds1990_save(FlipperFormat*, const iButtonProtocolData*);
|
||||||
|
static void dallas_ds1990_render_uid(FuriString*, const iButtonProtocolData*);
|
||||||
static void dallas_ds1990_render_brief_data(FuriString*, const iButtonProtocolData*);
|
static void dallas_ds1990_render_brief_data(FuriString*, const iButtonProtocolData*);
|
||||||
static void dallas_ds1990_render_error(FuriString*, const iButtonProtocolData*);
|
static void dallas_ds1990_render_error(FuriString*, const iButtonProtocolData*);
|
||||||
static bool dallas_ds1990_is_data_valid(const iButtonProtocolData*);
|
static bool dallas_ds1990_is_data_valid(const iButtonProtocolData*);
|
||||||
@@ -46,6 +47,7 @@ const iButtonProtocolDallasBase ibutton_protocol_ds1990 = {
|
|||||||
.emulate = dallas_ds1990_emulate,
|
.emulate = dallas_ds1990_emulate,
|
||||||
.save = dallas_ds1990_save,
|
.save = dallas_ds1990_save,
|
||||||
.load = dallas_ds1990_load,
|
.load = dallas_ds1990_load,
|
||||||
|
.render_uid = dallas_ds1990_render_uid,
|
||||||
.render_data = NULL, /* No data to render */
|
.render_data = NULL, /* No data to render */
|
||||||
.render_brief_data = dallas_ds1990_render_brief_data,
|
.render_brief_data = dallas_ds1990_render_brief_data,
|
||||||
.render_error = dallas_ds1990_render_error,
|
.render_error = dallas_ds1990_render_error,
|
||||||
@@ -117,12 +119,20 @@ bool dallas_ds1990_load(
|
|||||||
return dallas_common_load_rom_data(ff, format_version, &data->rom_data);
|
return dallas_common_load_rom_data(ff, format_version, &data->rom_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dallas_ds1990_render_uid(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
|
const DS1990ProtocolData* data = protocol_data;
|
||||||
|
|
||||||
|
dallas_common_render_uid(result, &data->rom_data);
|
||||||
|
}
|
||||||
|
|
||||||
void dallas_ds1990_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
void dallas_ds1990_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
const DS1990ProtocolData* data = protocol_data;
|
const DS1990ProtocolData* data = protocol_data;
|
||||||
|
|
||||||
|
furi_string_cat_printf(result, "ID: ");
|
||||||
for(size_t i = 0; i < sizeof(DallasCommonRomData); ++i) {
|
for(size_t i = 0; i < sizeof(DallasCommonRomData); ++i) {
|
||||||
furi_string_cat_printf(result, "%02X ", data->rom_data.bytes[i]);
|
furi_string_cat_printf(result, "%02X ", data->rom_data.bytes[i]);
|
||||||
}
|
}
|
||||||
|
furi_string_cat_printf(result, "\nFamily Code: %02X\n", data->rom_data.bytes[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dallas_ds1990_render_error(FuriString* result, const iButtonProtocolData* protocol_data) {
|
void dallas_ds1990_render_error(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ static bool dallas_ds1992_write_copy(OneWireHost*, iButtonProtocolData*);
|
|||||||
static void dallas_ds1992_emulate(OneWireSlave*, iButtonProtocolData*);
|
static void dallas_ds1992_emulate(OneWireSlave*, iButtonProtocolData*);
|
||||||
static bool dallas_ds1992_load(FlipperFormat*, uint32_t, iButtonProtocolData*);
|
static bool dallas_ds1992_load(FlipperFormat*, uint32_t, iButtonProtocolData*);
|
||||||
static bool dallas_ds1992_save(FlipperFormat*, const iButtonProtocolData*);
|
static bool dallas_ds1992_save(FlipperFormat*, const iButtonProtocolData*);
|
||||||
|
static void dallas_ds1992_render_uid(FuriString*, const iButtonProtocolData*);
|
||||||
static void dallas_ds1992_render_data(FuriString*, const iButtonProtocolData*);
|
static void dallas_ds1992_render_data(FuriString*, const iButtonProtocolData*);
|
||||||
static void dallas_ds1992_render_brief_data(FuriString*, const iButtonProtocolData*);
|
static void dallas_ds1992_render_brief_data(FuriString*, const iButtonProtocolData*);
|
||||||
static void dallas_ds1992_render_error(FuriString*, const iButtonProtocolData*);
|
static void dallas_ds1992_render_error(FuriString*, const iButtonProtocolData*);
|
||||||
@@ -57,6 +58,7 @@ const iButtonProtocolDallasBase ibutton_protocol_ds1992 = {
|
|||||||
.emulate = dallas_ds1992_emulate,
|
.emulate = dallas_ds1992_emulate,
|
||||||
.save = dallas_ds1992_save,
|
.save = dallas_ds1992_save,
|
||||||
.load = dallas_ds1992_load,
|
.load = dallas_ds1992_load,
|
||||||
|
.render_uid = dallas_ds1992_render_uid,
|
||||||
.render_data = dallas_ds1992_render_data,
|
.render_data = dallas_ds1992_render_data,
|
||||||
.render_brief_data = dallas_ds1992_render_brief_data,
|
.render_brief_data = dallas_ds1992_render_brief_data,
|
||||||
.render_error = dallas_ds1992_render_error,
|
.render_error = dallas_ds1992_render_error,
|
||||||
@@ -182,14 +184,26 @@ bool dallas_ds1992_save(FlipperFormat* ff, const iButtonProtocolData* protocol_d
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dallas_ds1992_render_uid(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
|
const DS1992ProtocolData* data = protocol_data;
|
||||||
|
dallas_common_render_uid(result, &data->rom_data);
|
||||||
|
}
|
||||||
|
|
||||||
void dallas_ds1992_render_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
void dallas_ds1992_render_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
const DS1992ProtocolData* data = protocol_data;
|
const DS1992ProtocolData* data = protocol_data;
|
||||||
|
FuriString* data_string = furi_string_alloc();
|
||||||
|
|
||||||
pretty_format_bytes_hex_canonical(
|
pretty_format_bytes_hex_canonical(
|
||||||
result,
|
data_string,
|
||||||
DS1992_DATA_BYTE_COUNT,
|
DS1992_DATA_BYTE_COUNT,
|
||||||
PRETTY_FORMAT_FONT_MONOSPACE,
|
PRETTY_FORMAT_FONT_MONOSPACE,
|
||||||
data->sram_data,
|
data->sram_data,
|
||||||
DS1992_SRAM_DATA_SIZE);
|
DS1992_SRAM_DATA_SIZE);
|
||||||
|
|
||||||
|
furi_string_cat_printf(result, "\e#Memory Data\n--------------------\n");
|
||||||
|
furi_string_cat_printf(result, "%s", furi_string_get_cstr(data_string));
|
||||||
|
|
||||||
|
furi_string_free(data_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dallas_ds1992_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
void dallas_ds1992_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ static bool dallas_ds1996_write_copy(OneWireHost*, iButtonProtocolData*);
|
|||||||
static void dallas_ds1996_emulate(OneWireSlave*, iButtonProtocolData*);
|
static void dallas_ds1996_emulate(OneWireSlave*, iButtonProtocolData*);
|
||||||
static bool dallas_ds1996_load(FlipperFormat*, uint32_t, iButtonProtocolData*);
|
static bool dallas_ds1996_load(FlipperFormat*, uint32_t, iButtonProtocolData*);
|
||||||
static bool dallas_ds1996_save(FlipperFormat*, const iButtonProtocolData*);
|
static bool dallas_ds1996_save(FlipperFormat*, const iButtonProtocolData*);
|
||||||
|
static void dallas_ds1996_render_uid(FuriString*, const iButtonProtocolData*);
|
||||||
static void dallas_ds1996_render_data(FuriString*, const iButtonProtocolData*);
|
static void dallas_ds1996_render_data(FuriString*, const iButtonProtocolData*);
|
||||||
static void dallas_ds1996_render_brief_data(FuriString*, const iButtonProtocolData*);
|
static void dallas_ds1996_render_brief_data(FuriString*, const iButtonProtocolData*);
|
||||||
static void dallas_ds1996_render_error(FuriString*, const iButtonProtocolData*);
|
static void dallas_ds1996_render_error(FuriString*, const iButtonProtocolData*);
|
||||||
@@ -53,6 +54,7 @@ const iButtonProtocolDallasBase ibutton_protocol_ds1996 = {
|
|||||||
.emulate = dallas_ds1996_emulate,
|
.emulate = dallas_ds1996_emulate,
|
||||||
.save = dallas_ds1996_save,
|
.save = dallas_ds1996_save,
|
||||||
.load = dallas_ds1996_load,
|
.load = dallas_ds1996_load,
|
||||||
|
.render_uid = dallas_ds1996_render_uid,
|
||||||
.render_data = dallas_ds1996_render_data,
|
.render_data = dallas_ds1996_render_data,
|
||||||
.render_brief_data = dallas_ds1996_render_brief_data,
|
.render_brief_data = dallas_ds1996_render_brief_data,
|
||||||
.render_error = dallas_ds1996_render_error,
|
.render_error = dallas_ds1996_render_error,
|
||||||
@@ -207,15 +209,27 @@ bool dallas_ds1996_save(FlipperFormat* ff, const iButtonProtocolData* protocol_d
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dallas_ds1996_render_uid(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
|
const DS1996ProtocolData* data = protocol_data;
|
||||||
|
dallas_common_render_uid(result, &data->rom_data);
|
||||||
|
}
|
||||||
|
|
||||||
void dallas_ds1996_render_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
void dallas_ds1996_render_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
const DS1996ProtocolData* data = protocol_data;
|
const DS1996ProtocolData* data = protocol_data;
|
||||||
|
|
||||||
|
FuriString* data_string = furi_string_alloc();
|
||||||
|
|
||||||
pretty_format_bytes_hex_canonical(
|
pretty_format_bytes_hex_canonical(
|
||||||
result,
|
data_string,
|
||||||
DS1996_DATA_BYTE_COUNT,
|
DS1996_DATA_BYTE_COUNT,
|
||||||
PRETTY_FORMAT_FONT_MONOSPACE,
|
PRETTY_FORMAT_FONT_MONOSPACE,
|
||||||
data->sram_data,
|
data->sram_data,
|
||||||
DS1996_SRAM_DATA_SIZE);
|
DS1996_SRAM_DATA_SIZE);
|
||||||
|
|
||||||
|
furi_string_cat_printf(result, "\e#Memory Data\n--------------------\n");
|
||||||
|
furi_string_cat_printf(result, "%s", furi_string_get_cstr(data_string));
|
||||||
|
|
||||||
|
furi_string_free(data_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dallas_ds1996_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
void dallas_ds1996_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "../blanks/tm2004.h"
|
#include "../blanks/tm2004.h"
|
||||||
|
|
||||||
#define DALLAS_GENERIC_FAMILY_CODE 0x00U
|
#define DALLAS_GENERIC_FAMILY_CODE 0x00U
|
||||||
#define DALLAS_GENERIC_FAMILY_NAME "DSGeneric"
|
#define DALLAS_GENERIC_FAMILY_NAME "(non-specific)"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
OneWireSlave* bus;
|
OneWireSlave* bus;
|
||||||
@@ -24,6 +24,7 @@ static bool ds_generic_write_blank(OneWireHost*, iButtonProtocolData*);
|
|||||||
static void ds_generic_emulate(OneWireSlave*, iButtonProtocolData*);
|
static void ds_generic_emulate(OneWireSlave*, iButtonProtocolData*);
|
||||||
static bool ds_generic_load(FlipperFormat*, uint32_t, iButtonProtocolData*);
|
static bool ds_generic_load(FlipperFormat*, uint32_t, iButtonProtocolData*);
|
||||||
static bool ds_generic_save(FlipperFormat*, const iButtonProtocolData*);
|
static bool ds_generic_save(FlipperFormat*, const iButtonProtocolData*);
|
||||||
|
static void ds_generic_render_uid(FuriString*, const iButtonProtocolData*);
|
||||||
static void ds_generic_render_brief_data(FuriString*, const iButtonProtocolData*);
|
static void ds_generic_render_brief_data(FuriString*, const iButtonProtocolData*);
|
||||||
static void ds_generic_render_error(FuriString*, const iButtonProtocolData*);
|
static void ds_generic_render_error(FuriString*, const iButtonProtocolData*);
|
||||||
static bool ds_generic_is_data_valid(const iButtonProtocolData*);
|
static bool ds_generic_is_data_valid(const iButtonProtocolData*);
|
||||||
@@ -44,6 +45,7 @@ const iButtonProtocolDallasBase ibutton_protocol_ds_generic = {
|
|||||||
.save = ds_generic_save,
|
.save = ds_generic_save,
|
||||||
.load = ds_generic_load,
|
.load = ds_generic_load,
|
||||||
.render_data = NULL, /* No data to render */
|
.render_data = NULL, /* No data to render */
|
||||||
|
.render_uid = ds_generic_render_uid,
|
||||||
.render_brief_data = ds_generic_render_brief_data,
|
.render_brief_data = ds_generic_render_brief_data,
|
||||||
.render_error = ds_generic_render_error,
|
.render_error = ds_generic_render_error,
|
||||||
.is_valid = ds_generic_is_data_valid,
|
.is_valid = ds_generic_is_data_valid,
|
||||||
@@ -111,9 +113,15 @@ bool ds_generic_load(
|
|||||||
return dallas_common_load_rom_data(ff, format_version, &data->rom_data);
|
return dallas_common_load_rom_data(ff, format_version, &data->rom_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ds_generic_render_uid(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
|
const DallasGenericProtocolData* data = protocol_data;
|
||||||
|
dallas_common_render_uid(result, &data->rom_data);
|
||||||
|
}
|
||||||
|
|
||||||
void ds_generic_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
void ds_generic_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) {
|
||||||
const DallasGenericProtocolData* data = protocol_data;
|
const DallasGenericProtocolData* data = protocol_data;
|
||||||
|
|
||||||
|
furi_string_cat_printf(result, "ID: ");
|
||||||
for(size_t i = 0; i < sizeof(DallasCommonRomData); ++i) {
|
for(size_t i = 0; i < sizeof(DallasCommonRomData); ++i) {
|
||||||
furi_string_cat_printf(result, "%02X ", data->rom_data.bytes[i]);
|
furi_string_cat_printf(result, "%02X ", data->rom_data.bytes[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ static bool ibutton_protocol_group_dallas_get_id_by_name(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle files that refer to Dallas "Raw Data" as DSGeneric
|
||||||
|
if(strcmp(name, "DSGeneric") == 0) {
|
||||||
|
*id = iButtonProtocolDSGeneric;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
for(iButtonProtocolLocalId i = 0; i < iButtonProtocolDSMax; ++i) {
|
for(iButtonProtocolLocalId i = 0; i < iButtonProtocolDSMax; ++i) {
|
||||||
if(strcmp(ibutton_protocols_dallas[i]->name, name) == 0) {
|
if(strcmp(ibutton_protocols_dallas[i]->name, name) == 0) {
|
||||||
*id = i;
|
*id = i;
|
||||||
@@ -212,6 +218,18 @@ static bool ibutton_protocol_group_dallas_load(
|
|||||||
return ibutton_protocols_dallas[id]->load(ff, version, data);
|
return ibutton_protocols_dallas[id]->load(ff, version, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ibutton_protocol_group_dallas_render_uid(
|
||||||
|
iButtonProtocolGroupDallas* group,
|
||||||
|
const iButtonProtocolData* data,
|
||||||
|
iButtonProtocolLocalId id,
|
||||||
|
FuriString* result) {
|
||||||
|
UNUSED(group);
|
||||||
|
furi_assert(id < iButtonProtocolDSMax);
|
||||||
|
const iButtonProtocolDallasBase* protocol = ibutton_protocols_dallas[id];
|
||||||
|
furi_assert(protocol->render_uid);
|
||||||
|
protocol->render_uid(result, data);
|
||||||
|
}
|
||||||
|
|
||||||
static void ibutton_protocol_group_dallas_render_data(
|
static void ibutton_protocol_group_dallas_render_data(
|
||||||
iButtonProtocolGroupDallas* group,
|
iButtonProtocolGroupDallas* group,
|
||||||
const iButtonProtocolData* data,
|
const iButtonProtocolData* data,
|
||||||
@@ -298,6 +316,7 @@ const iButtonProtocolGroupBase ibutton_protocol_group_dallas = {
|
|||||||
.save = (iButtonProtocolGroupSaveFunc)ibutton_protocol_group_dallas_save,
|
.save = (iButtonProtocolGroupSaveFunc)ibutton_protocol_group_dallas_save,
|
||||||
.load = (iButtonProtocolGroupLoadFunc)ibutton_protocol_group_dallas_load,
|
.load = (iButtonProtocolGroupLoadFunc)ibutton_protocol_group_dallas_load,
|
||||||
|
|
||||||
|
.render_uid = (iButtonProtocolGroupRenderFunc)ibutton_protocol_group_dallas_render_uid,
|
||||||
.render_data = (iButtonProtocolGroupRenderFunc)ibutton_protocol_group_dallas_render_data,
|
.render_data = (iButtonProtocolGroupRenderFunc)ibutton_protocol_group_dallas_render_data,
|
||||||
.render_brief_data =
|
.render_brief_data =
|
||||||
(iButtonProtocolGroupRenderFunc)ibutton_protocol_group_dallas_render_brief_data,
|
(iButtonProtocolGroupRenderFunc)ibutton_protocol_group_dallas_render_brief_data,
|
||||||
|
|||||||
@@ -325,7 +325,15 @@ static LevelDuration protocol_cyfral_encoder_yield(ProtocolCyfral* proto) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void protocol_cyfral_render_uid(FuriString* result, ProtocolCyfral* proto) {
|
||||||
|
furi_string_cat_printf(result, "ID: ");
|
||||||
|
for(size_t i = 0; i < CYFRAL_DATA_SIZE; ++i) {
|
||||||
|
furi_string_cat_printf(result, "%02X ", ((uint8_t*)&proto->data)[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void protocol_cyfral_render_brief_data(ProtocolCyfral* proto, FuriString* result) {
|
static void protocol_cyfral_render_brief_data(ProtocolCyfral* proto, FuriString* result) {
|
||||||
|
furi_string_cat_printf(result, "ID: ");
|
||||||
for(size_t i = 0; i < CYFRAL_DATA_SIZE; ++i) {
|
for(size_t i = 0; i < CYFRAL_DATA_SIZE; ++i) {
|
||||||
furi_string_cat_printf(result, "%02X ", ((uint8_t*)&proto->data)[i]);
|
furi_string_cat_printf(result, "%02X ", ((uint8_t*)&proto->data)[i]);
|
||||||
}
|
}
|
||||||
@@ -348,5 +356,6 @@ const ProtocolBase ibutton_protocol_misc_cyfral = {
|
|||||||
.start = (ProtocolEncoderStart)protocol_cyfral_encoder_start,
|
.start = (ProtocolEncoderStart)protocol_cyfral_encoder_start,
|
||||||
.yield = (ProtocolEncoderYield)protocol_cyfral_encoder_yield,
|
.yield = (ProtocolEncoderYield)protocol_cyfral_encoder_yield,
|
||||||
},
|
},
|
||||||
|
.render_uid = (ProtocolRenderData)protocol_cyfral_render_uid,
|
||||||
.render_brief_data = (ProtocolRenderData)protocol_cyfral_render_brief_data,
|
.render_brief_data = (ProtocolRenderData)protocol_cyfral_render_brief_data,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -301,12 +301,17 @@ static LevelDuration protocol_metakom_encoder_yield(ProtocolMetakom* proto) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void protocol_metakom_render_brief_data(ProtocolMetakom* proto, FuriString* result) {
|
static void protocol_metakom_render_uid(ProtocolMetakom* proto, FuriString* result) {
|
||||||
|
furi_string_cat_printf(result, "ID: ");
|
||||||
for(size_t i = 0; i < METAKOM_DATA_SIZE; ++i) {
|
for(size_t i = 0; i < METAKOM_DATA_SIZE; ++i) {
|
||||||
furi_string_cat_printf(result, "%02X ", ((uint8_t*)&proto->data)[i]);
|
furi_string_cat_printf(result, "%02X ", ((uint8_t*)&proto->data)[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void protocol_metakom_render_brief_data(ProtocolMetakom* proto, FuriString* result) {
|
||||||
|
protocol_metakom_render_uid(proto, result);
|
||||||
|
}
|
||||||
|
|
||||||
const ProtocolBase ibutton_protocol_misc_metakom = {
|
const ProtocolBase ibutton_protocol_misc_metakom = {
|
||||||
.name = "Metakom",
|
.name = "Metakom",
|
||||||
.manufacturer = "Metakom",
|
.manufacturer = "Metakom",
|
||||||
@@ -324,5 +329,6 @@ const ProtocolBase ibutton_protocol_misc_metakom = {
|
|||||||
.start = (ProtocolEncoderStart)protocol_metakom_encoder_start,
|
.start = (ProtocolEncoderStart)protocol_metakom_encoder_start,
|
||||||
.yield = (ProtocolEncoderYield)protocol_metakom_encoder_yield,
|
.yield = (ProtocolEncoderYield)protocol_metakom_encoder_yield,
|
||||||
},
|
},
|
||||||
|
.render_uid = (ProtocolRenderData)protocol_metakom_render_uid,
|
||||||
.render_brief_data = (ProtocolRenderData)protocol_metakom_render_brief_data,
|
.render_brief_data = (ProtocolRenderData)protocol_metakom_render_brief_data,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ typedef struct {
|
|||||||
iButtonProtocolGroupSaveFunc save;
|
iButtonProtocolGroupSaveFunc save;
|
||||||
iButtonProtocolGroupLoadFunc load;
|
iButtonProtocolGroupLoadFunc load;
|
||||||
|
|
||||||
|
iButtonProtocolGroupRenderFunc render_uid;
|
||||||
iButtonProtocolGroupRenderFunc render_data;
|
iButtonProtocolGroupRenderFunc render_data;
|
||||||
iButtonProtocolGroupRenderFunc render_brief_data;
|
iButtonProtocolGroupRenderFunc render_brief_data;
|
||||||
iButtonProtocolGroupRenderFunc render_error;
|
iButtonProtocolGroupRenderFunc render_error;
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ typedef struct {
|
|||||||
ProtocolGetData get_data;
|
ProtocolGetData get_data;
|
||||||
ProtocolDecoder decoder;
|
ProtocolDecoder decoder;
|
||||||
ProtocolEncoder encoder;
|
ProtocolEncoder encoder;
|
||||||
|
ProtocolRenderData render_uid;
|
||||||
ProtocolRenderData render_data;
|
ProtocolRenderData render_data;
|
||||||
ProtocolRenderData render_brief_data;
|
ProtocolRenderData render_brief_data;
|
||||||
ProtocolWriteData write_data;
|
ProtocolWriteData write_data;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,60.8,,
|
Version,+,61.1,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
Header,+,applications/services/cli/cli_vcp.h,,
|
Header,+,applications/services/cli/cli_vcp.h,,
|
||||||
@@ -199,6 +199,7 @@ Header,+,targets/f7/platform_specific/cxx_virtual_stub.h,,
|
|||||||
Header,+,targets/f7/platform_specific/intrinsic_export.h,,
|
Header,+,targets/f7/platform_specific/intrinsic_export.h,,
|
||||||
Header,+,targets/f7/platform_specific/math_wrapper.h,,
|
Header,+,targets/f7/platform_specific/math_wrapper.h,,
|
||||||
Header,+,targets/furi_hal_include/furi_hal.h,,
|
Header,+,targets/furi_hal_include/furi_hal.h,,
|
||||||
|
Header,+,targets/furi_hal_include/furi_hal_adc.h,,
|
||||||
Header,+,targets/furi_hal_include/furi_hal_bt.h,,
|
Header,+,targets/furi_hal_include/furi_hal_bt.h,,
|
||||||
Header,+,targets/furi_hal_include/furi_hal_cortex.h,,
|
Header,+,targets/furi_hal_include/furi_hal_cortex.h,,
|
||||||
Header,+,targets/furi_hal_include/furi_hal_crypto.h,,
|
Header,+,targets/furi_hal_include/furi_hal_crypto.h,,
|
||||||
@@ -1086,6 +1087,16 @@ Function,+,furi_event_flag_get,uint32_t,FuriEventFlag*
|
|||||||
Function,+,furi_event_flag_set,uint32_t,"FuriEventFlag*, uint32_t"
|
Function,+,furi_event_flag_set,uint32_t,"FuriEventFlag*, uint32_t"
|
||||||
Function,+,furi_event_flag_wait,uint32_t,"FuriEventFlag*, uint32_t, uint32_t, uint32_t"
|
Function,+,furi_event_flag_wait,uint32_t,"FuriEventFlag*, uint32_t, uint32_t, uint32_t"
|
||||||
Function,+,furi_get_tick,uint32_t,
|
Function,+,furi_get_tick,uint32_t,
|
||||||
|
Function,+,furi_hal_adc_acquire,FuriHalAdcHandle*,
|
||||||
|
Function,+,furi_hal_adc_configure,void,FuriHalAdcHandle*
|
||||||
|
Function,+,furi_hal_adc_configure_ex,void,"FuriHalAdcHandle*, FuriHalAdcScale, FuriHalAdcClock, FuriHalAdcOversample, FuriHalAdcSamplingTime"
|
||||||
|
Function,+,furi_hal_adc_convert_temp,float,"FuriHalAdcHandle*, uint16_t"
|
||||||
|
Function,+,furi_hal_adc_convert_to_voltage,float,"FuriHalAdcHandle*, uint16_t"
|
||||||
|
Function,+,furi_hal_adc_convert_vbat,float,"FuriHalAdcHandle*, uint16_t"
|
||||||
|
Function,+,furi_hal_adc_convert_vref,float,"FuriHalAdcHandle*, uint16_t"
|
||||||
|
Function,+,furi_hal_adc_init,void,
|
||||||
|
Function,+,furi_hal_adc_read,uint16_t,"FuriHalAdcHandle*, FuriHalAdcChannel"
|
||||||
|
Function,+,furi_hal_adc_release,void,FuriHalAdcHandle*
|
||||||
Function,+,furi_hal_bt_change_app,FuriHalBleProfileBase*,"const FuriHalBleProfileTemplate*, FuriHalBleProfileParams, GapEventCallback, void*"
|
Function,+,furi_hal_bt_change_app,FuriHalBleProfileBase*,"const FuriHalBleProfileTemplate*, FuriHalBleProfileParams, GapEventCallback, void*"
|
||||||
Function,+,furi_hal_bt_check_profile_type,_Bool,"FuriHalBleProfileBase*, const FuriHalBleProfileTemplate*"
|
Function,+,furi_hal_bt_check_profile_type,_Bool,"FuriHalBleProfileBase*, const FuriHalBleProfileTemplate*"
|
||||||
Function,+,furi_hal_bt_clear_white_list,_Bool,
|
Function,+,furi_hal_bt_clear_white_list,_Bool,
|
||||||
|
|||||||
|
@@ -31,6 +31,7 @@ void furi_hal_deinit_early(void) {
|
|||||||
|
|
||||||
void furi_hal_init(void) {
|
void furi_hal_init(void) {
|
||||||
furi_hal_mpu_init();
|
furi_hal_mpu_init();
|
||||||
|
furi_hal_adc_init();
|
||||||
furi_hal_clock_init();
|
furi_hal_clock_init();
|
||||||
furi_hal_random_init();
|
furi_hal_random_init();
|
||||||
furi_hal_serial_control_init();
|
furi_hal_serial_control_init();
|
||||||
|
|||||||
@@ -68,49 +68,161 @@ const GpioPin gpio_usb_dp = {.port = GPIOA, .pin = LL_GPIO_PIN_12};
|
|||||||
|
|
||||||
const GpioPinRecord gpio_pins[] = {
|
const GpioPinRecord gpio_pins[] = {
|
||||||
// 5V: 1
|
// 5V: 1
|
||||||
{.pin = &gpio_ext_pa7, .name = "PA7", .number = 2, .debug = false},
|
{.pin = &gpio_ext_pa7,
|
||||||
{.pin = &gpio_ext_pa6, .name = "PA6", .number = 3, .debug = false},
|
.name = "PA7",
|
||||||
{.pin = &gpio_ext_pa4, .name = "PA4", .number = 4, .debug = false},
|
.channel = FuriHalAdcChannel12,
|
||||||
{.pin = &gpio_ext_pb3, .name = "PB3", .number = 5, .debug = false},
|
.number = 2,
|
||||||
{.pin = &gpio_ext_pb2, .name = "PB2", .number = 6, .debug = false},
|
.debug = false},
|
||||||
{.pin = &gpio_ext_pc3, .name = "PC3", .number = 7, .debug = false},
|
{.pin = &gpio_ext_pa6,
|
||||||
|
.name = "PA6",
|
||||||
|
.channel = FuriHalAdcChannel11,
|
||||||
|
.number = 3,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pa4,
|
||||||
|
.name = "PA4",
|
||||||
|
.channel = FuriHalAdcChannel9,
|
||||||
|
.number = 4,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pb3,
|
||||||
|
.name = "PB3",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 5,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pb2,
|
||||||
|
.name = "PB2",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 6,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pc3,
|
||||||
|
.name = "PC3",
|
||||||
|
.channel = FuriHalAdcChannel4,
|
||||||
|
.number = 7,
|
||||||
|
.debug = false},
|
||||||
// GND: 8
|
// GND: 8
|
||||||
// Space
|
// Space
|
||||||
// 3v3: 9
|
// 3v3: 9
|
||||||
{.pin = &gpio_swclk, .name = "PA14", .number = 10, .debug = true},
|
{.pin = &gpio_swclk,
|
||||||
|
.name = "PA14",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 10,
|
||||||
|
.debug = true},
|
||||||
// GND: 11
|
// GND: 11
|
||||||
{.pin = &gpio_swdio, .name = "PA13", .number = 12, .debug = true},
|
{.pin = &gpio_swdio,
|
||||||
{.pin = &gpio_usart_tx, .name = "PB6", .number = 13, .debug = true},
|
.name = "PA13",
|
||||||
{.pin = &gpio_usart_rx, .name = "PB7", .number = 14, .debug = true},
|
.channel = FuriHalAdcChannelNone,
|
||||||
{.pin = &gpio_ext_pc1, .name = "PC1", .number = 15, .debug = false},
|
.number = 12,
|
||||||
{.pin = &gpio_ext_pc0, .name = "PC0", .number = 16, .debug = false},
|
.debug = true},
|
||||||
{.pin = &gpio_ibutton, .name = "PB14", .number = 17, .debug = true},
|
{.pin = &gpio_usart_tx,
|
||||||
|
.name = "PB6",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 13,
|
||||||
|
.debug = true},
|
||||||
|
{.pin = &gpio_usart_rx,
|
||||||
|
.name = "PB7",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 14,
|
||||||
|
.debug = true},
|
||||||
|
{.pin = &gpio_ext_pc1,
|
||||||
|
.name = "PC1",
|
||||||
|
.channel = FuriHalAdcChannel2,
|
||||||
|
.number = 15,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pc0,
|
||||||
|
.name = "PC0",
|
||||||
|
.channel = FuriHalAdcChannel1,
|
||||||
|
.number = 16,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ibutton,
|
||||||
|
.name = "PB14",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 17,
|
||||||
|
.debug = true},
|
||||||
// GND: 18
|
// GND: 18
|
||||||
|
|
||||||
// 2nd column
|
// 2nd column
|
||||||
// 5V: 19
|
// 5V: 19
|
||||||
{.pin = &gpio_ext_pc5, .name = "PC5", .number = 20, .debug = false},
|
{.pin = &gpio_ext_pc5,
|
||||||
{.pin = &gpio_ext_pc4, .name = "PC4", .number = 21, .debug = false},
|
.name = "PC5",
|
||||||
{.pin = &gpio_ext_pa5, .name = "PA5", .number = 22, .debug = false},
|
.channel = FuriHalAdcChannel14,
|
||||||
{.pin = &gpio_ext_pb9, .name = "PB9", .number = 23, .debug = false},
|
.number = 20,
|
||||||
{.pin = &gpio_ext_pa0, .name = "PA0", .number = 24, .debug = false},
|
.debug = false},
|
||||||
{.pin = &gpio_ext_pa1, .name = "PA1", .number = 25, .debug = false},
|
{.pin = &gpio_ext_pc4,
|
||||||
|
.name = "PC4",
|
||||||
|
.channel = FuriHalAdcChannel13,
|
||||||
|
.number = 21,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pa5,
|
||||||
|
.name = "PA5",
|
||||||
|
.channel = FuriHalAdcChannel10,
|
||||||
|
.number = 22,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pb9,
|
||||||
|
.name = "PB9",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 23,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pa0,
|
||||||
|
.name = "PA0",
|
||||||
|
.channel = FuriHalAdcChannel5,
|
||||||
|
.number = 24,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pa1,
|
||||||
|
.name = "PA1",
|
||||||
|
.channel = FuriHalAdcChannel6,
|
||||||
|
.number = 25,
|
||||||
|
.debug = false},
|
||||||
// KEY: 26
|
// KEY: 26
|
||||||
// Space
|
// Space
|
||||||
// 3v3: 27
|
// 3v3: 27
|
||||||
{.pin = &gpio_ext_pa15, .name = "PA15", .number = 28, .debug = false},
|
{.pin = &gpio_ext_pa15,
|
||||||
|
.name = "PA15",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 28,
|
||||||
|
.debug = false},
|
||||||
// GND: 29
|
// GND: 29
|
||||||
{.pin = &gpio_ext_pe4, .name = "PE4", .number = 30, .debug = false},
|
{.pin = &gpio_ext_pe4,
|
||||||
{.pin = &gpio_ext_pa2, .name = "PA2", .number = 31, .debug = false},
|
.name = "PE4",
|
||||||
{.pin = &gpio_ext_pb4, .name = "PB4", .number = 32, .debug = false},
|
.channel = FuriHalAdcChannelNone,
|
||||||
{.pin = &gpio_ext_pb5, .name = "PB5", .number = 33, .debug = false},
|
.number = 30,
|
||||||
{.pin = &gpio_ext_pd0, .name = "PD0", .number = 34, .debug = false},
|
.debug = false},
|
||||||
{.pin = &gpio_ext_pb13, .name = "PB13", .number = 35, .debug = false},
|
{.pin = &gpio_ext_pa2,
|
||||||
|
.name = "PA2",
|
||||||
|
.channel = FuriHalAdcChannel7,
|
||||||
|
.number = 31,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pb4,
|
||||||
|
.name = "PB4",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 32,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pb5,
|
||||||
|
.name = "PB5",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 33,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pd0,
|
||||||
|
.name = "PD0",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 34,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pb13,
|
||||||
|
.name = "PB13",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 35,
|
||||||
|
.debug = false},
|
||||||
// GND: 36
|
// GND: 36
|
||||||
|
|
||||||
/* Dangerous pins, may damage hardware */
|
/* Dangerous pins, may damage hardware */
|
||||||
{.pin = &gpio_usart_rx, .name = "PB7", .number = 0, .debug = true},
|
{.pin = &gpio_usart_rx,
|
||||||
{.pin = &gpio_speaker, .name = "PB8", .number = 0, .debug = true},
|
.name = "PB7",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 0,
|
||||||
|
.debug = true},
|
||||||
|
{.pin = &gpio_speaker,
|
||||||
|
.name = "PB8",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 0,
|
||||||
|
.debug = true},
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t gpio_pins_count = COUNT_OF(gpio_pins);
|
const size_t gpio_pins_count = COUNT_OF(gpio_pins);
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
#include <furi_hal_adc.h>
|
||||||
#include <stm32wbxx.h>
|
|
||||||
#include <stm32wbxx_ll_gpio.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -41,6 +39,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
const GpioPin* pin;
|
const GpioPin* pin;
|
||||||
const char* name;
|
const char* name;
|
||||||
|
const FuriHalAdcChannel channel;
|
||||||
const uint8_t number;
|
const uint8_t number;
|
||||||
const bool debug;
|
const bool debug;
|
||||||
} GpioPinRecord;
|
} GpioPinRecord;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,60.8,,
|
Version,+,61.1,,
|
||||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
@@ -272,6 +272,7 @@ Header,+,targets/f7/platform_specific/cxx_virtual_stub.h,,
|
|||||||
Header,+,targets/f7/platform_specific/intrinsic_export.h,,
|
Header,+,targets/f7/platform_specific/intrinsic_export.h,,
|
||||||
Header,+,targets/f7/platform_specific/math_wrapper.h,,
|
Header,+,targets/f7/platform_specific/math_wrapper.h,,
|
||||||
Header,+,targets/furi_hal_include/furi_hal.h,,
|
Header,+,targets/furi_hal_include/furi_hal.h,,
|
||||||
|
Header,+,targets/furi_hal_include/furi_hal_adc.h,,
|
||||||
Header,+,targets/furi_hal_include/furi_hal_bt.h,,
|
Header,+,targets/furi_hal_include/furi_hal_bt.h,,
|
||||||
Header,+,targets/furi_hal_include/furi_hal_cortex.h,,
|
Header,+,targets/furi_hal_include/furi_hal_cortex.h,,
|
||||||
Header,+,targets/furi_hal_include/furi_hal_crypto.h,,
|
Header,+,targets/furi_hal_include/furi_hal_crypto.h,,
|
||||||
@@ -1215,6 +1216,16 @@ Function,+,furi_event_flag_get,uint32_t,FuriEventFlag*
|
|||||||
Function,+,furi_event_flag_set,uint32_t,"FuriEventFlag*, uint32_t"
|
Function,+,furi_event_flag_set,uint32_t,"FuriEventFlag*, uint32_t"
|
||||||
Function,+,furi_event_flag_wait,uint32_t,"FuriEventFlag*, uint32_t, uint32_t, uint32_t"
|
Function,+,furi_event_flag_wait,uint32_t,"FuriEventFlag*, uint32_t, uint32_t, uint32_t"
|
||||||
Function,+,furi_get_tick,uint32_t,
|
Function,+,furi_get_tick,uint32_t,
|
||||||
|
Function,+,furi_hal_adc_acquire,FuriHalAdcHandle*,
|
||||||
|
Function,+,furi_hal_adc_configure,void,FuriHalAdcHandle*
|
||||||
|
Function,+,furi_hal_adc_configure_ex,void,"FuriHalAdcHandle*, FuriHalAdcScale, FuriHalAdcClock, FuriHalAdcOversample, FuriHalAdcSamplingTime"
|
||||||
|
Function,+,furi_hal_adc_convert_temp,float,"FuriHalAdcHandle*, uint16_t"
|
||||||
|
Function,+,furi_hal_adc_convert_to_voltage,float,"FuriHalAdcHandle*, uint16_t"
|
||||||
|
Function,+,furi_hal_adc_convert_vbat,float,"FuriHalAdcHandle*, uint16_t"
|
||||||
|
Function,+,furi_hal_adc_convert_vref,float,"FuriHalAdcHandle*, uint16_t"
|
||||||
|
Function,+,furi_hal_adc_init,void,
|
||||||
|
Function,+,furi_hal_adc_read,uint16_t,"FuriHalAdcHandle*, FuriHalAdcChannel"
|
||||||
|
Function,+,furi_hal_adc_release,void,FuriHalAdcHandle*
|
||||||
Function,+,furi_hal_bt_change_app,FuriHalBleProfileBase*,"const FuriHalBleProfileTemplate*, FuriHalBleProfileParams, GapEventCallback, void*"
|
Function,+,furi_hal_bt_change_app,FuriHalBleProfileBase*,"const FuriHalBleProfileTemplate*, FuriHalBleProfileParams, GapEventCallback, void*"
|
||||||
Function,+,furi_hal_bt_check_profile_type,_Bool,"FuriHalBleProfileBase*, const FuriHalBleProfileTemplate*"
|
Function,+,furi_hal_bt_check_profile_type,_Bool,"FuriHalBleProfileBase*, const FuriHalBleProfileTemplate*"
|
||||||
Function,+,furi_hal_bt_clear_white_list,_Bool,
|
Function,+,furi_hal_bt_clear_white_list,_Bool,
|
||||||
@@ -1925,6 +1936,7 @@ Function,+,ibutton_protocols_read,_Bool,"iButtonProtocols*, iButtonKey*"
|
|||||||
Function,+,ibutton_protocols_render_brief_data,void,"iButtonProtocols*, const iButtonKey*, FuriString*"
|
Function,+,ibutton_protocols_render_brief_data,void,"iButtonProtocols*, const iButtonKey*, FuriString*"
|
||||||
Function,+,ibutton_protocols_render_data,void,"iButtonProtocols*, const iButtonKey*, FuriString*"
|
Function,+,ibutton_protocols_render_data,void,"iButtonProtocols*, const iButtonKey*, FuriString*"
|
||||||
Function,+,ibutton_protocols_render_error,void,"iButtonProtocols*, const iButtonKey*, FuriString*"
|
Function,+,ibutton_protocols_render_error,void,"iButtonProtocols*, const iButtonKey*, FuriString*"
|
||||||
|
Function,+,ibutton_protocols_render_uid,void,"iButtonProtocols*, const iButtonKey*, FuriString*"
|
||||||
Function,+,ibutton_protocols_save,_Bool,"iButtonProtocols*, const iButtonKey*, const char*"
|
Function,+,ibutton_protocols_save,_Bool,"iButtonProtocols*, const iButtonKey*, const char*"
|
||||||
Function,+,ibutton_protocols_write_blank,_Bool,"iButtonProtocols*, iButtonKey*"
|
Function,+,ibutton_protocols_write_blank,_Bool,"iButtonProtocols*, iButtonKey*"
|
||||||
Function,+,ibutton_protocols_write_copy,_Bool,"iButtonProtocols*, iButtonKey*"
|
Function,+,ibutton_protocols_write_copy,_Bool,"iButtonProtocols*, iButtonKey*"
|
||||||
|
|||||||
|
@@ -9,7 +9,6 @@
|
|||||||
/**
|
/**
|
||||||
* Define IO Authentication
|
* Define IO Authentication
|
||||||
*/
|
*/
|
||||||
#define CFG_USED_FIXED_PIN USE_FIXED_PIN_FOR_PAIRING_FORBIDDEN
|
|
||||||
#define CFG_ENCRYPTION_KEY_SIZE_MAX (16)
|
#define CFG_ENCRYPTION_KEY_SIZE_MAX (16)
|
||||||
#define CFG_ENCRYPTION_KEY_SIZE_MIN (8)
|
#define CFG_ENCRYPTION_KEY_SIZE_MIN (8)
|
||||||
|
|
||||||
@@ -18,11 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
#define CFG_IO_CAPABILITY IO_CAP_DISPLAY_YES_NO
|
#define CFG_IO_CAPABILITY IO_CAP_DISPLAY_YES_NO
|
||||||
|
|
||||||
/**
|
|
||||||
* Define MITM modes
|
|
||||||
*/
|
|
||||||
#define CFG_MITM_PROTECTION MITM_PROTECTION_REQUIRED
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define Secure Connections Support
|
* Define Secure Connections Support
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ static int32_t gap_app(void* context);
|
|||||||
/** function for updating rssi informations in global Gap object
|
/** function for updating rssi informations in global Gap object
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static inline void fetch_rssi() {
|
static inline void fetch_rssi(void) {
|
||||||
uint8_t ret_rssi = 127;
|
uint8_t ret_rssi = 127;
|
||||||
if(hci_read_rssi(gap->service.connection_handle, &ret_rssi) == BLE_STATUS_SUCCESS) {
|
if(hci_read_rssi(gap->service.connection_handle, &ret_rssi) == BLE_STATUS_SUCCESS) {
|
||||||
gap->conn_rssi = (int8_t)ret_rssi;
|
gap->conn_rssi = (int8_t)ret_rssi;
|
||||||
@@ -372,9 +372,8 @@ static void gap_init_svc(Gap* gap) {
|
|||||||
// Set default PHY
|
// Set default PHY
|
||||||
hci_le_set_default_phy(ALL_PHYS_PREFERENCE, TX_2M_PREFERRED, RX_2M_PREFERRED);
|
hci_le_set_default_phy(ALL_PHYS_PREFERENCE, TX_2M_PREFERRED, RX_2M_PREFERRED);
|
||||||
// Set I/O capability
|
// Set I/O capability
|
||||||
bool bonding_mode = gap->config->bonding_mode;
|
uint8_t auth_req_mitm_mode = MITM_PROTECTION_REQUIRED;
|
||||||
uint8_t cfg_mitm_protection = CFG_MITM_PROTECTION;
|
uint8_t auth_req_use_fixed_pin = USE_FIXED_PIN_FOR_PAIRING_FORBIDDEN;
|
||||||
uint8_t cfg_used_fixed_pin = CFG_USED_FIXED_PIN;
|
|
||||||
bool keypress_supported = false;
|
bool keypress_supported = false;
|
||||||
if(gap->config->pairing_method == GapPairingPinCodeShow) {
|
if(gap->config->pairing_method == GapPairingPinCodeShow) {
|
||||||
aci_gap_set_io_capability(IO_CAP_DISPLAY_ONLY);
|
aci_gap_set_io_capability(IO_CAP_DISPLAY_ONLY);
|
||||||
@@ -383,22 +382,21 @@ static void gap_init_svc(Gap* gap) {
|
|||||||
keypress_supported = true;
|
keypress_supported = true;
|
||||||
} else if(gap->config->pairing_method == GapPairingNone) {
|
} else if(gap->config->pairing_method == GapPairingNone) {
|
||||||
// "Just works" pairing method (iOS accepts it, it seems Android and Linux don't)
|
// "Just works" pairing method (iOS accepts it, it seems Android and Linux don't)
|
||||||
bonding_mode = false;
|
auth_req_mitm_mode = MITM_PROTECTION_NOT_REQUIRED;
|
||||||
cfg_mitm_protection = MITM_PROTECTION_NOT_REQUIRED;
|
auth_req_use_fixed_pin = USE_FIXED_PIN_FOR_PAIRING_ALLOWED;
|
||||||
cfg_used_fixed_pin = USE_FIXED_PIN_FOR_PAIRING_ALLOWED;
|
|
||||||
// If "just works" isn't supported, we want the numeric comparaison method
|
// If "just works" isn't supported, we want the numeric comparaison method
|
||||||
aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO);
|
aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO);
|
||||||
keypress_supported = true;
|
keypress_supported = true;
|
||||||
}
|
}
|
||||||
// Setup authentication
|
// Setup authentication
|
||||||
aci_gap_set_authentication_requirement(
|
aci_gap_set_authentication_requirement(
|
||||||
bonding_mode,
|
gap->config->bonding_mode,
|
||||||
cfg_mitm_protection,
|
auth_req_mitm_mode,
|
||||||
CFG_SC_SUPPORT,
|
CFG_SC_SUPPORT,
|
||||||
keypress_supported,
|
keypress_supported,
|
||||||
CFG_ENCRYPTION_KEY_SIZE_MIN,
|
CFG_ENCRYPTION_KEY_SIZE_MIN,
|
||||||
CFG_ENCRYPTION_KEY_SIZE_MAX,
|
CFG_ENCRYPTION_KEY_SIZE_MAX,
|
||||||
cfg_used_fixed_pin,
|
auth_req_use_fixed_pin,
|
||||||
0,
|
0,
|
||||||
CFG_IDENTITY_ADDRESS);
|
CFG_IDENTITY_ADDRESS);
|
||||||
// Configure whitelist
|
// Configure whitelist
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ typedef enum {
|
|||||||
GapPairingNone,
|
GapPairingNone,
|
||||||
GapPairingPinCodeShow,
|
GapPairingPinCodeShow,
|
||||||
GapPairingPinCodeVerifyYesNo,
|
GapPairingPinCodeVerifyYesNo,
|
||||||
|
GapPairingCount,
|
||||||
} GapPairing;
|
} GapPairing;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ void furi_hal_deinit_early(void) {
|
|||||||
|
|
||||||
void furi_hal_init(void) {
|
void furi_hal_init(void) {
|
||||||
furi_hal_mpu_init();
|
furi_hal_mpu_init();
|
||||||
|
furi_hal_adc_init();
|
||||||
furi_hal_clock_init();
|
furi_hal_clock_init();
|
||||||
furi_hal_random_init();
|
furi_hal_random_init();
|
||||||
furi_hal_serial_control_init();
|
furi_hal_serial_control_init();
|
||||||
|
|||||||
281
targets/f7/furi_hal/furi_hal_adc.c
Normal file
281
targets/f7/furi_hal/furi_hal_adc.c
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
#include <furi_hal_adc.h>
|
||||||
|
#include <furi_hal_bus.h>
|
||||||
|
#include <furi_hal_cortex.h>
|
||||||
|
#include <furi_hal_power.h>
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
|
#include <stm32wbxx_ll_adc.h>
|
||||||
|
#include <stm32wbxx_ll_system.h>
|
||||||
|
|
||||||
|
struct FuriHalAdcHandle {
|
||||||
|
ADC_TypeDef* adc;
|
||||||
|
FuriMutex* mutex;
|
||||||
|
uint32_t full_scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32_t furi_hal_adc_clock[] = {
|
||||||
|
[FuriHalAdcClockSync16] = LL_ADC_CLOCK_SYNC_PCLK_DIV4,
|
||||||
|
[FuriHalAdcClockSync32] = LL_ADC_CLOCK_SYNC_PCLK_DIV2,
|
||||||
|
[FuriHalAdcClockSync64] = LL_ADC_CLOCK_SYNC_PCLK_DIV1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t furi_hal_adc_clock_div[] = {
|
||||||
|
[FuriHalAdcClockSync16] = 4,
|
||||||
|
[FuriHalAdcClockSync32] = 2,
|
||||||
|
[FuriHalAdcClockSync64] = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32_t furi_hal_adc_oversample_ratio[] = {
|
||||||
|
[FuriHalAdcOversample2] = LL_ADC_OVS_RATIO_2,
|
||||||
|
[FuriHalAdcOversample4] = LL_ADC_OVS_RATIO_4,
|
||||||
|
[FuriHalAdcOversample8] = LL_ADC_OVS_RATIO_8,
|
||||||
|
[FuriHalAdcOversample16] = LL_ADC_OVS_RATIO_16,
|
||||||
|
[FuriHalAdcOversample32] = LL_ADC_OVS_RATIO_32,
|
||||||
|
[FuriHalAdcOversample64] = LL_ADC_OVS_RATIO_64,
|
||||||
|
[FuriHalAdcOversample128] = LL_ADC_OVS_RATIO_128,
|
||||||
|
[FuriHalAdcOversample256] = LL_ADC_OVS_RATIO_256,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32_t furi_hal_adc_oversample_shift[] = {
|
||||||
|
[FuriHalAdcOversample2] = LL_ADC_OVS_SHIFT_RIGHT_1,
|
||||||
|
[FuriHalAdcOversample4] = LL_ADC_OVS_SHIFT_RIGHT_2,
|
||||||
|
[FuriHalAdcOversample8] = LL_ADC_OVS_SHIFT_RIGHT_3,
|
||||||
|
[FuriHalAdcOversample16] = LL_ADC_OVS_SHIFT_RIGHT_4,
|
||||||
|
[FuriHalAdcOversample32] = LL_ADC_OVS_SHIFT_RIGHT_5,
|
||||||
|
[FuriHalAdcOversample64] = LL_ADC_OVS_SHIFT_RIGHT_6,
|
||||||
|
[FuriHalAdcOversample128] = LL_ADC_OVS_SHIFT_RIGHT_7,
|
||||||
|
[FuriHalAdcOversample256] = LL_ADC_OVS_SHIFT_RIGHT_8,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32_t furi_hal_adc_sampling_time[] = {
|
||||||
|
[FuriHalAdcSamplingtime2_5] = LL_ADC_SAMPLINGTIME_2CYCLES_5,
|
||||||
|
[FuriHalAdcSamplingtime6_5] = LL_ADC_SAMPLINGTIME_6CYCLES_5,
|
||||||
|
[FuriHalAdcSamplingtime12_5] = LL_ADC_SAMPLINGTIME_12CYCLES_5,
|
||||||
|
[FuriHalAdcSamplingtime24_5] = LL_ADC_SAMPLINGTIME_24CYCLES_5,
|
||||||
|
[FuriHalAdcSamplingtime47_5] = LL_ADC_SAMPLINGTIME_47CYCLES_5,
|
||||||
|
[FuriHalAdcSamplingtime92_5] = LL_ADC_SAMPLINGTIME_92CYCLES_5,
|
||||||
|
[FuriHalAdcSamplingtime247_5] = LL_ADC_SAMPLINGTIME_247CYCLES_5,
|
||||||
|
[FuriHalAdcSamplingtime640_5] = LL_ADC_SAMPLINGTIME_640CYCLES_5,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32_t furi_hal_adc_channel_map[] = {
|
||||||
|
[FuriHalAdcChannel0] = LL_ADC_CHANNEL_0,
|
||||||
|
[FuriHalAdcChannel1] = LL_ADC_CHANNEL_1,
|
||||||
|
[FuriHalAdcChannel2] = LL_ADC_CHANNEL_2,
|
||||||
|
[FuriHalAdcChannel3] = LL_ADC_CHANNEL_3,
|
||||||
|
[FuriHalAdcChannel4] = LL_ADC_CHANNEL_4,
|
||||||
|
[FuriHalAdcChannel5] = LL_ADC_CHANNEL_5,
|
||||||
|
[FuriHalAdcChannel6] = LL_ADC_CHANNEL_6,
|
||||||
|
[FuriHalAdcChannel7] = LL_ADC_CHANNEL_7,
|
||||||
|
[FuriHalAdcChannel8] = LL_ADC_CHANNEL_8,
|
||||||
|
[FuriHalAdcChannel9] = LL_ADC_CHANNEL_9,
|
||||||
|
[FuriHalAdcChannel10] = LL_ADC_CHANNEL_10,
|
||||||
|
[FuriHalAdcChannel11] = LL_ADC_CHANNEL_11,
|
||||||
|
[FuriHalAdcChannel12] = LL_ADC_CHANNEL_12,
|
||||||
|
[FuriHalAdcChannel13] = LL_ADC_CHANNEL_13,
|
||||||
|
[FuriHalAdcChannel14] = LL_ADC_CHANNEL_14,
|
||||||
|
[FuriHalAdcChannel15] = LL_ADC_CHANNEL_15,
|
||||||
|
[FuriHalAdcChannel16] = LL_ADC_CHANNEL_16,
|
||||||
|
[FuriHalAdcChannel17] = LL_ADC_CHANNEL_17,
|
||||||
|
[FuriHalAdcChannel18] = LL_ADC_CHANNEL_18,
|
||||||
|
[FuriHalAdcChannelVREFINT] = LL_ADC_CHANNEL_VREFINT,
|
||||||
|
[FuriHalAdcChannelTEMPSENSOR] = LL_ADC_CHANNEL_TEMPSENSOR,
|
||||||
|
[FuriHalAdcChannelVBAT] = LL_ADC_CHANNEL_VBAT,
|
||||||
|
};
|
||||||
|
|
||||||
|
static FuriHalAdcHandle* furi_hal_adc_handle = NULL;
|
||||||
|
|
||||||
|
void furi_hal_adc_init(void) {
|
||||||
|
furi_hal_adc_handle = malloc(sizeof(FuriHalAdcHandle));
|
||||||
|
furi_hal_adc_handle->adc = ADC1;
|
||||||
|
furi_hal_adc_handle->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
FuriHalAdcHandle* furi_hal_adc_acquire(void) {
|
||||||
|
furi_check(furi_mutex_acquire(furi_hal_adc_handle->mutex, FuriWaitForever) == FuriStatusOk);
|
||||||
|
|
||||||
|
furi_hal_power_insomnia_enter();
|
||||||
|
|
||||||
|
furi_hal_bus_enable(FuriHalBusADC);
|
||||||
|
|
||||||
|
return furi_hal_adc_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void furi_hal_adc_release(FuriHalAdcHandle* handle) {
|
||||||
|
furi_check(handle);
|
||||||
|
|
||||||
|
if(furi_hal_bus_is_enabled(FuriHalBusADC)) furi_hal_bus_disable(FuriHalBusADC);
|
||||||
|
|
||||||
|
LL_VREFBUF_Disable();
|
||||||
|
LL_VREFBUF_EnableHIZ();
|
||||||
|
|
||||||
|
furi_hal_power_insomnia_exit();
|
||||||
|
|
||||||
|
furi_check(furi_mutex_release(furi_hal_adc_handle->mutex) == FuriStatusOk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void furi_hal_adc_configure(FuriHalAdcHandle* handle) {
|
||||||
|
furi_hal_adc_configure_ex(
|
||||||
|
handle,
|
||||||
|
FuriHalAdcScale2048,
|
||||||
|
FuriHalAdcClockSync64,
|
||||||
|
FuriHalAdcOversample64,
|
||||||
|
FuriHalAdcSamplingtime247_5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void furi_hal_adc_configure_ex(
|
||||||
|
FuriHalAdcHandle* handle,
|
||||||
|
FuriHalAdcScale scale,
|
||||||
|
FuriHalAdcClock clock,
|
||||||
|
FuriHalAdcOversample oversample,
|
||||||
|
FuriHalAdcSamplingTime sampling_time) {
|
||||||
|
furi_check(handle);
|
||||||
|
furi_check(scale == FuriHalAdcScale2048 || scale == FuriHalAdcScale2500);
|
||||||
|
furi_check(clock <= FuriHalAdcClockSync64);
|
||||||
|
furi_check(oversample <= FuriHalAdcOversampleNone);
|
||||||
|
furi_check(sampling_time <= FuriHalAdcSamplingtime640_5);
|
||||||
|
|
||||||
|
FuriHalCortexTimer timer;
|
||||||
|
|
||||||
|
if(furi_hal_bus_is_enabled(FuriHalBusADC)) furi_hal_bus_disable(FuriHalBusADC);
|
||||||
|
|
||||||
|
uint32_t trim_value = 0;
|
||||||
|
switch(scale) {
|
||||||
|
case FuriHalAdcScale2048:
|
||||||
|
LL_VREFBUF_SetVoltageScaling(LL_VREFBUF_VOLTAGE_SCALE0);
|
||||||
|
trim_value = LL_VREFBUF_SC0_GetCalibration() & 0x3FU;
|
||||||
|
handle->full_scale = 2048;
|
||||||
|
break;
|
||||||
|
case FuriHalAdcScale2500:
|
||||||
|
LL_VREFBUF_SetVoltageScaling(LL_VREFBUF_VOLTAGE_SCALE1);
|
||||||
|
trim_value = LL_VREFBUF_SC1_GetCalibration() & 0x3FU;
|
||||||
|
handle->full_scale = 2500;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
furi_crash();
|
||||||
|
}
|
||||||
|
LL_VREFBUF_SetTrimming(trim_value);
|
||||||
|
LL_VREFBUF_Enable();
|
||||||
|
LL_VREFBUF_DisableHIZ();
|
||||||
|
|
||||||
|
timer = furi_hal_cortex_timer_get(500000); // 500ms to stabilize VREF
|
||||||
|
while(!LL_VREFBUF_IsVREFReady()) {
|
||||||
|
furi_check(!furi_hal_cortex_timer_is_expired(timer), "VREF fail");
|
||||||
|
};
|
||||||
|
|
||||||
|
furi_hal_bus_enable(FuriHalBusADC);
|
||||||
|
|
||||||
|
// ADC Common config
|
||||||
|
LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0};
|
||||||
|
ADC_CommonInitStruct.CommonClock = furi_hal_adc_clock[clock];
|
||||||
|
furi_check(
|
||||||
|
LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(handle->adc), &ADC_CommonInitStruct) ==
|
||||||
|
SUCCESS);
|
||||||
|
LL_ADC_SetCommonPathInternalCh(
|
||||||
|
__LL_ADC_COMMON_INSTANCE(handle->adc),
|
||||||
|
LL_ADC_PATH_INTERNAL_VREFINT | LL_ADC_PATH_INTERNAL_TEMPSENSOR |
|
||||||
|
LL_ADC_PATH_INTERNAL_VBAT);
|
||||||
|
|
||||||
|
// ADC config part 1
|
||||||
|
LL_ADC_InitTypeDef ADC_InitStruct = {0};
|
||||||
|
ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B; //-V1048
|
||||||
|
ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
|
||||||
|
ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;
|
||||||
|
furi_check(LL_ADC_Init(handle->adc, &ADC_InitStruct) == SUCCESS);
|
||||||
|
|
||||||
|
// ADC config part 2: groups parameters
|
||||||
|
LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
|
||||||
|
ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE; //-V1048
|
||||||
|
ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;
|
||||||
|
ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
|
||||||
|
ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;
|
||||||
|
ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;
|
||||||
|
ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN;
|
||||||
|
furi_check(LL_ADC_REG_Init(handle->adc, &ADC_REG_InitStruct) == SUCCESS);
|
||||||
|
|
||||||
|
// ADC config part 3: sequencer and channels
|
||||||
|
if(oversample == FuriHalAdcOversampleNone) {
|
||||||
|
LL_ADC_SetOverSamplingScope(handle->adc, LL_ADC_OVS_DISABLE);
|
||||||
|
} else {
|
||||||
|
LL_ADC_SetOverSamplingScope(handle->adc, LL_ADC_OVS_GRP_REGULAR_CONTINUED);
|
||||||
|
LL_ADC_ConfigOverSamplingRatioShift(
|
||||||
|
handle->adc,
|
||||||
|
furi_hal_adc_oversample_ratio[oversample],
|
||||||
|
furi_hal_adc_oversample_shift[oversample]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(FuriHalAdcChannel channel = FuriHalAdcChannel0; channel < FuriHalAdcChannelNone;
|
||||||
|
channel++) {
|
||||||
|
// 47.5 cycles on 64MHz is first meaningful value for internal sources sampling
|
||||||
|
LL_ADC_SetChannelSamplingTime(
|
||||||
|
handle->adc,
|
||||||
|
furi_hal_adc_channel_map[channel],
|
||||||
|
furi_hal_adc_sampling_time[sampling_time]);
|
||||||
|
LL_ADC_SetChannelSingleDiff(
|
||||||
|
handle->adc, furi_hal_adc_channel_map[channel], LL_ADC_SINGLE_ENDED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable ADC deep power down (enabled by default after reset state)
|
||||||
|
LL_ADC_DisableDeepPowerDown(handle->adc);
|
||||||
|
|
||||||
|
// Enable ADC internal voltage regulator
|
||||||
|
LL_ADC_EnableInternalRegulator(handle->adc);
|
||||||
|
// Delay for ADC internal voltage regulator stabilization.
|
||||||
|
timer = furi_hal_cortex_timer_get(LL_ADC_DELAY_INTERNAL_REGUL_STAB_US);
|
||||||
|
while(!furi_hal_cortex_timer_is_expired(timer))
|
||||||
|
;
|
||||||
|
|
||||||
|
// Run ADC self calibration
|
||||||
|
LL_ADC_StartCalibration(handle->adc, LL_ADC_SINGLE_ENDED);
|
||||||
|
// Poll for ADC effectively calibrated
|
||||||
|
while(LL_ADC_IsCalibrationOnGoing(handle->adc) != 0)
|
||||||
|
;
|
||||||
|
// Delay between ADC end of calibration and ADC enable
|
||||||
|
size_t end =
|
||||||
|
DWT->CYCCNT + (LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES * furi_hal_adc_clock_div[clock]);
|
||||||
|
while(DWT->CYCCNT < end)
|
||||||
|
;
|
||||||
|
|
||||||
|
// Enable ADC
|
||||||
|
LL_ADC_ClearFlag_ADRDY(handle->adc);
|
||||||
|
LL_ADC_Enable(handle->adc);
|
||||||
|
while(LL_ADC_IsActiveFlag_ADRDY(handle->adc) == 0)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t furi_hal_adc_read(FuriHalAdcHandle* handle, FuriHalAdcChannel channel) {
|
||||||
|
furi_check(handle);
|
||||||
|
furi_check(channel <= FuriHalAdcChannelVBAT);
|
||||||
|
furi_check(LL_ADC_IsEnabled(handle->adc) == 1);
|
||||||
|
furi_check(LL_ADC_IsDisableOngoing(handle->adc) == 0);
|
||||||
|
furi_check(LL_ADC_REG_IsConversionOngoing(handle->adc) == 0);
|
||||||
|
|
||||||
|
LL_ADC_REG_SetSequencerRanks(
|
||||||
|
handle->adc, LL_ADC_REG_RANK_1, furi_hal_adc_channel_map[channel]);
|
||||||
|
|
||||||
|
LL_ADC_REG_StartConversion(handle->adc);
|
||||||
|
|
||||||
|
while(LL_ADC_IsActiveFlag_EOC(handle->adc) == 0)
|
||||||
|
;
|
||||||
|
uint16_t value = LL_ADC_REG_ReadConversionData12(handle->adc);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
float furi_hal_adc_convert_to_voltage(FuriHalAdcHandle* handle, uint16_t value) {
|
||||||
|
return (float)__LL_ADC_CALC_DATA_TO_VOLTAGE(handle->full_scale, value, LL_ADC_RESOLUTION_12B);
|
||||||
|
}
|
||||||
|
|
||||||
|
float furi_hal_adc_convert_vref(FuriHalAdcHandle* handle, uint16_t value) {
|
||||||
|
UNUSED(handle);
|
||||||
|
return (float)__LL_ADC_CALC_VREFANALOG_VOLTAGE(value, LL_ADC_RESOLUTION_12B);
|
||||||
|
}
|
||||||
|
|
||||||
|
float furi_hal_adc_convert_temp(FuriHalAdcHandle* handle, uint16_t value) {
|
||||||
|
return (float)__LL_ADC_CALC_TEMPERATURE(handle->full_scale, value, LL_ADC_RESOLUTION_12B);
|
||||||
|
}
|
||||||
|
|
||||||
|
float furi_hal_adc_convert_vbat(FuriHalAdcHandle* handle, uint16_t value) {
|
||||||
|
return furi_hal_adc_convert_to_voltage(handle, value) * 3;
|
||||||
|
}
|
||||||
@@ -121,6 +121,7 @@ void furi_hal_clock_init(void) {
|
|||||||
LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSI);
|
LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSI);
|
||||||
LL_RCC_SetSMPSPrescaler(LL_RCC_SMPS_DIV_1);
|
LL_RCC_SetSMPSPrescaler(LL_RCC_SMPS_DIV_1);
|
||||||
LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE);
|
LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE);
|
||||||
|
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_SYSCLK);
|
||||||
|
|
||||||
FURI_LOG_I(TAG, "Init OK");
|
FURI_LOG_I(TAG, "Init OK");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,28 +70,88 @@ const GpioPin gpio_usb_dp = {.port = GPIOA, .pin = LL_GPIO_PIN_12};
|
|||||||
|
|
||||||
const GpioPinRecord gpio_pins[] = {
|
const GpioPinRecord gpio_pins[] = {
|
||||||
// 5V: 1
|
// 5V: 1
|
||||||
{.pin = &gpio_ext_pa7, .name = "PA7", .number = 2, .debug = false},
|
{.pin = &gpio_ext_pa7,
|
||||||
{.pin = &gpio_ext_pa6, .name = "PA6", .number = 3, .debug = false},
|
.name = "PA7",
|
||||||
{.pin = &gpio_ext_pa4, .name = "PA4", .number = 4, .debug = false},
|
.channel = FuriHalAdcChannel12,
|
||||||
{.pin = &gpio_ext_pb3, .name = "PB3", .number = 5, .debug = false},
|
.number = 2,
|
||||||
{.pin = &gpio_ext_pb2, .name = "PB2", .number = 6, .debug = false},
|
.debug = false},
|
||||||
{.pin = &gpio_ext_pc3, .name = "PC3", .number = 7, .debug = false},
|
{.pin = &gpio_ext_pa6,
|
||||||
|
.name = "PA6",
|
||||||
|
.channel = FuriHalAdcChannel11,
|
||||||
|
.number = 3,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pa4,
|
||||||
|
.name = "PA4",
|
||||||
|
.channel = FuriHalAdcChannel9,
|
||||||
|
.number = 4,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pb3,
|
||||||
|
.name = "PB3",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 5,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pb2,
|
||||||
|
.name = "PB2",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 6,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pc3,
|
||||||
|
.name = "PC3",
|
||||||
|
.channel = FuriHalAdcChannel4,
|
||||||
|
.number = 7,
|
||||||
|
.debug = false},
|
||||||
// GND: 8
|
// GND: 8
|
||||||
// Space
|
// Space
|
||||||
// 3v3: 9
|
// 3v3: 9
|
||||||
{.pin = &gpio_swclk, .name = "PA14", .number = 10, .debug = true},
|
{.pin = &gpio_swclk,
|
||||||
|
.name = "PA14",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 10,
|
||||||
|
.debug = true},
|
||||||
// GND: 11
|
// GND: 11
|
||||||
{.pin = &gpio_swdio, .name = "PA13", .number = 12, .debug = true},
|
{.pin = &gpio_swdio,
|
||||||
{.pin = &gpio_usart_tx, .name = "PB6", .number = 13, .debug = true},
|
.name = "PA13",
|
||||||
{.pin = &gpio_usart_rx, .name = "PB7", .number = 14, .debug = true},
|
.channel = FuriHalAdcChannelNone,
|
||||||
{.pin = &gpio_ext_pc1, .name = "PC1", .number = 15, .debug = false},
|
.number = 12,
|
||||||
{.pin = &gpio_ext_pc0, .name = "PC0", .number = 16, .debug = false},
|
.debug = true},
|
||||||
{.pin = &gpio_ibutton, .name = "PB14", .number = 17, .debug = true},
|
{.pin = &gpio_usart_tx,
|
||||||
|
.name = "PB6",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 13,
|
||||||
|
.debug = true},
|
||||||
|
{.pin = &gpio_usart_rx,
|
||||||
|
.name = "PB7",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 14,
|
||||||
|
.debug = true},
|
||||||
|
{.pin = &gpio_ext_pc1,
|
||||||
|
.name = "PC1",
|
||||||
|
.channel = FuriHalAdcChannel2,
|
||||||
|
.number = 15,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ext_pc0,
|
||||||
|
.name = "PC0",
|
||||||
|
.channel = FuriHalAdcChannel1,
|
||||||
|
.number = 16,
|
||||||
|
.debug = false},
|
||||||
|
{.pin = &gpio_ibutton,
|
||||||
|
.name = "PB14",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 17,
|
||||||
|
.debug = true},
|
||||||
// GND: 18
|
// GND: 18
|
||||||
|
|
||||||
/* Dangerous pins, may damage hardware */
|
/* Dangerous pins, may damage hardware */
|
||||||
{.pin = &gpio_speaker, .name = "PB8", .debug = true},
|
{.pin = &gpio_speaker,
|
||||||
{.pin = &gpio_infrared_tx, .name = "PB9", .debug = true},
|
.name = "PB8",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 0,
|
||||||
|
.debug = true},
|
||||||
|
{.pin = &gpio_infrared_tx,
|
||||||
|
.name = "PB9",
|
||||||
|
.channel = FuriHalAdcChannelNone,
|
||||||
|
.number = 0,
|
||||||
|
.debug = true},
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t gpio_pins_count = COUNT_OF(gpio_pins);
|
const size_t gpio_pins_count = COUNT_OF(gpio_pins);
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
#include <furi_hal_adc.h>
|
||||||
#include <stm32wbxx.h>
|
|
||||||
#include <stm32wbxx_ll_gpio.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -41,6 +39,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
const GpioPin* pin;
|
const GpioPin* pin;
|
||||||
const char* name;
|
const char* name;
|
||||||
|
const FuriHalAdcChannel channel;
|
||||||
const uint8_t number;
|
const uint8_t number;
|
||||||
const bool debug;
|
const bool debug;
|
||||||
} GpioPinRecord;
|
} GpioPinRecord;
|
||||||
@@ -220,10 +219,11 @@ void furi_hal_resources_deinit_early(void);
|
|||||||
|
|
||||||
void furi_hal_resources_init(void);
|
void furi_hal_resources_init(void);
|
||||||
|
|
||||||
/**
|
/** Get a corresponding external connector pin number for a gpio
|
||||||
* Get a corresponding external connector pin number for a gpio
|
*
|
||||||
* @param gpio GpioPin
|
* @param gpio GpioPin
|
||||||
* @return pin number or -1 if gpio is not on the external connector
|
*
|
||||||
|
* @return pin number or -1 if gpio is not on the external connector
|
||||||
*/
|
*/
|
||||||
int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio);
|
int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio);
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ struct STOP_EXTERNING_ME {};
|
|||||||
|
|
||||||
#include <furi_hal_cortex.h>
|
#include <furi_hal_cortex.h>
|
||||||
#include <furi_hal_clock.h>
|
#include <furi_hal_clock.h>
|
||||||
|
#include <furi_hal_adc.h>
|
||||||
#include <furi_hal_bus.h>
|
#include <furi_hal_bus.h>
|
||||||
#include <furi_hal_crypto.h>
|
#include <furi_hal_crypto.h>
|
||||||
#include <furi_hal_debug.h>
|
#include <furi_hal_debug.h>
|
||||||
|
|||||||
229
targets/furi_hal_include/furi_hal_adc.h
Normal file
229
targets/furi_hal_include/furi_hal_adc.h
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
/**
|
||||||
|
* @file furi_hal_adc.h
|
||||||
|
* @brief ADC HAL API
|
||||||
|
*
|
||||||
|
* For the sake of simplicity this API implements only small subset
|
||||||
|
* of what ADC is actually capable of. Feel free to visit Reference
|
||||||
|
* Manual for STM32WB series and implement any other modes by your
|
||||||
|
* self.
|
||||||
|
*
|
||||||
|
* Couple things to keep in mind:
|
||||||
|
*
|
||||||
|
* - ADC resolution is 12 bits, but effective number of bits is ~10 at the best
|
||||||
|
* and further depends on how you use and configure it.
|
||||||
|
* - Analog domain is fed from SMPS which is quite noisy.
|
||||||
|
* - Because of that we use internal on-chip voltage reference for ADC.
|
||||||
|
* - It's capable of producing 2 voltages: 2.5V and 2.048V. This is the scale
|
||||||
|
* for your signal.
|
||||||
|
* - Only single ended mode is available. But you can implement differential one
|
||||||
|
* by using low level controls directly.
|
||||||
|
* - No DMA or interrupt API available at this point. But can be implemented
|
||||||
|
* with low level controls.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* How to use:
|
||||||
|
*
|
||||||
|
* - furi_hal_gpio_init - Configure your pins in `GpioModeAnalog`
|
||||||
|
* - furi_hal_adc_acquire - acquire ADC handle to work with
|
||||||
|
* - furi_hal_adc_configure - configure ADC block
|
||||||
|
* - furi_hal_adc_read - read value
|
||||||
|
* - furi_hal_adc_release - release ADC handle
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct FuriHalAdcHandle FuriHalAdcHandle;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FuriHalAdcScale2048, /**< 2.048V scale */
|
||||||
|
FuriHalAdcScale2500, /**< 2.5V scale */
|
||||||
|
} FuriHalAdcScale;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FuriHalAdcClockSync16, /**< 16MHZ, synchronous */
|
||||||
|
FuriHalAdcClockSync32, /**< 32MHZ, synchronous */
|
||||||
|
FuriHalAdcClockSync64, /**< 64MHz, synchronous */
|
||||||
|
} FuriHalAdcClock;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FuriHalAdcOversample2, /**< ADC will take 2 samples per each value */
|
||||||
|
FuriHalAdcOversample4, /**< ADC will take 4 samples per each value */
|
||||||
|
FuriHalAdcOversample8, /**< ADC will take 8 samples per each value */
|
||||||
|
FuriHalAdcOversample16, /**< ADC will take 16 samples per each value */
|
||||||
|
FuriHalAdcOversample32, /**< ADC will take 32 samples per each value */
|
||||||
|
FuriHalAdcOversample64, /**< ADC will take 64 samples per each value */
|
||||||
|
FuriHalAdcOversample128, /**< ADC will take 128 samples per each value */
|
||||||
|
FuriHalAdcOversample256, /**< ADC will take 256 samples per each value */
|
||||||
|
FuriHalAdcOversampleNone, /**< disable oversampling */
|
||||||
|
} FuriHalAdcOversample;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FuriHalAdcSamplingtime2_5, /**< Sampling time 2.5 ADC clock */
|
||||||
|
FuriHalAdcSamplingtime6_5, /**< Sampling time 6.5 ADC clock */
|
||||||
|
FuriHalAdcSamplingtime12_5, /**< Sampling time 12.5 ADC clock */
|
||||||
|
FuriHalAdcSamplingtime24_5, /**< Sampling time 24.5 ADC clock */
|
||||||
|
FuriHalAdcSamplingtime47_5, /**< Sampling time 47.5 ADC clock */
|
||||||
|
FuriHalAdcSamplingtime92_5, /**< Sampling time 92.5 ADC clock */
|
||||||
|
FuriHalAdcSamplingtime247_5, /**< Sampling time 247.5 ADC clock */
|
||||||
|
FuriHalAdcSamplingtime640_5, /**< Sampling time 640.5 ADC clock */
|
||||||
|
} FuriHalAdcSamplingTime;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* Channels 0 - 5 are fast channels */
|
||||||
|
FuriHalAdcChannel0, /**< Internal channel, see `FuriHalAdcChannelVREFINT`. */
|
||||||
|
FuriHalAdcChannel1, /**< Channel 1p */
|
||||||
|
FuriHalAdcChannel2, /**< Channel 2p or 1n */
|
||||||
|
FuriHalAdcChannel3, /**< Channel 3p or 2n */
|
||||||
|
FuriHalAdcChannel4, /**< Channel 4p or 3n */
|
||||||
|
FuriHalAdcChannel5, /**< Channel 5p or 4n */
|
||||||
|
/* Channels 6 - 18 are slow channels */
|
||||||
|
FuriHalAdcChannel6, /**< Channel 6p or 5n */
|
||||||
|
FuriHalAdcChannel7, /**< Channel 7p or 6n */
|
||||||
|
FuriHalAdcChannel8, /**< Channel 8p or 7n */
|
||||||
|
FuriHalAdcChannel9, /**< Channel 9p or 8n */
|
||||||
|
FuriHalAdcChannel10, /**< Channel 10p or 9n */
|
||||||
|
FuriHalAdcChannel11, /**< Channel 11p or 10n */
|
||||||
|
FuriHalAdcChannel12, /**< Channel 12p or 11n */
|
||||||
|
FuriHalAdcChannel13, /**< Channel 13p or 12n */
|
||||||
|
FuriHalAdcChannel14, /**< Channel 14p or 13n */
|
||||||
|
FuriHalAdcChannel15, /**< Channel 15p or 14n */
|
||||||
|
FuriHalAdcChannel16, /**< Channel 16p or 15n */
|
||||||
|
FuriHalAdcChannel17, /**< Internal channel, see `FuriHalAdcChannelTEMPSENSOR`. */
|
||||||
|
FuriHalAdcChannel18, /**< Internal channel, see `FuriHalAdcChannelVBAT`. */
|
||||||
|
/* Special Channels: combines one of the 0-18 channel and additional internal peripherals */
|
||||||
|
FuriHalAdcChannelVREFINT, /**< Special channel for VREFINT, used for calibration and self test */
|
||||||
|
FuriHalAdcChannelTEMPSENSOR, /**< Special channel for on-die temperature sensor, requires at least 5us of sampling time */
|
||||||
|
FuriHalAdcChannelVBAT, /**< Special channel for VBAT/3 voltage, requires at least 12us of sampling time */
|
||||||
|
/* Special value to indicate that pin is not connected to ADC */
|
||||||
|
FuriHalAdcChannelNone, /**< No channel */
|
||||||
|
} FuriHalAdcChannel;
|
||||||
|
|
||||||
|
/** Initialize ADC subsystem */
|
||||||
|
void furi_hal_adc_init(void);
|
||||||
|
|
||||||
|
/** Acquire ADC handle
|
||||||
|
*
|
||||||
|
* Enables appropriate power and clocking domains
|
||||||
|
*
|
||||||
|
* @return FuriHalAdcHandle pointer
|
||||||
|
*/
|
||||||
|
FuriHalAdcHandle* furi_hal_adc_acquire(void);
|
||||||
|
|
||||||
|
/** Release ADC handle
|
||||||
|
*
|
||||||
|
* @param handle The ADC handle
|
||||||
|
*/
|
||||||
|
void furi_hal_adc_release(FuriHalAdcHandle* handle);
|
||||||
|
|
||||||
|
/** Configure with default parameters and enable ADC
|
||||||
|
*
|
||||||
|
* Parameters used:
|
||||||
|
* - FuriHalAdcScale2048 - 2.048V VREF Scale. Your signal should be in 0 -
|
||||||
|
* 2.048V range.
|
||||||
|
* - FuriHalAdcClockSync64 - Clocked from sysclk bus at 64MHz in synchronous
|
||||||
|
* mode. Fast, no delay on data bus access.
|
||||||
|
* - FuriHalAdcOversample64 - Going to acquire and average 64 samples. For
|
||||||
|
* circuits with slowly or not changing signal. Total time per one read:
|
||||||
|
* (1/64)*(12.5+247.5)*64 = 260us. The best results you'll get if your signal
|
||||||
|
* will stay on the same level all this time.
|
||||||
|
* - FuriHalAdcSamplingtime247_5 - Sampling(transfer from source to internal
|
||||||
|
* sampling capacitor) time is 247.5 ADC clocks: (1/64)*247.5 = 3.8671875us.
|
||||||
|
* For relatively high impedance circuits.
|
||||||
|
*
|
||||||
|
* Also keep your measurement circuit impedance under 10KOhm or oversampling
|
||||||
|
* results will be compromised. Verify your signal with oscilloscope(you may
|
||||||
|
* need fast oscilloscope: 200MHz bandwidth, 125MS/s), ensure that signal is not
|
||||||
|
* distorted by sampling.
|
||||||
|
*
|
||||||
|
* Those parameters were optimized for 0 - 2.048 voltage measurement with ~0.1%
|
||||||
|
* precision. You can get more, but it will require some magic.
|
||||||
|
*
|
||||||
|
* @param handle The ADC handle
|
||||||
|
*/
|
||||||
|
void furi_hal_adc_configure(FuriHalAdcHandle* handle);
|
||||||
|
|
||||||
|
/** Configure with extended parameters and enable ADC
|
||||||
|
*
|
||||||
|
* General advice is to start with default parameters, figure out what exactly
|
||||||
|
* is not working for you and then tune it. Also in some cases changing
|
||||||
|
* circuit(adding caps, lowering impedance, adding opamp) may be better than changing
|
||||||
|
* parameters.
|
||||||
|
*
|
||||||
|
* @warning In general ADC is a world of magic: make sure that you understand
|
||||||
|
* how your circuit and ADC works. Then carefully read STM32WB
|
||||||
|
* series reference manual. Setting incorrect parameters leads to
|
||||||
|
* very poor results. Also internal channels require special
|
||||||
|
* settings.
|
||||||
|
*
|
||||||
|
* @param handle The ADC handle
|
||||||
|
* @param[in] scale The ADC voltage scale
|
||||||
|
* @param[in] clock The ADC clock
|
||||||
|
* @param[in] oversample The ADC oversample mode
|
||||||
|
* @param[in] sampling_time The ADC sampling time
|
||||||
|
*/
|
||||||
|
void furi_hal_adc_configure_ex(
|
||||||
|
FuriHalAdcHandle* handle,
|
||||||
|
FuriHalAdcScale scale,
|
||||||
|
FuriHalAdcClock clock,
|
||||||
|
FuriHalAdcOversample oversample,
|
||||||
|
FuriHalAdcSamplingTime sampling_time);
|
||||||
|
|
||||||
|
/** Read single ADC value
|
||||||
|
*
|
||||||
|
* @param handle The ADC handle
|
||||||
|
* @param[in] channel The channel to sample
|
||||||
|
*
|
||||||
|
* @return value, 12 bits
|
||||||
|
*/
|
||||||
|
uint16_t furi_hal_adc_read(FuriHalAdcHandle* handle, FuriHalAdcChannel channel);
|
||||||
|
|
||||||
|
/** Convert sampled value to voltage
|
||||||
|
*
|
||||||
|
* @param handle The ADC handle
|
||||||
|
* @param[in] value The value acquired with `furi_hal_adc_read`
|
||||||
|
*
|
||||||
|
* @return Voltage in mV
|
||||||
|
*/
|
||||||
|
float furi_hal_adc_convert_to_voltage(FuriHalAdcHandle* handle, uint16_t value);
|
||||||
|
|
||||||
|
/** Convert sampled VREFINT value to voltage
|
||||||
|
*
|
||||||
|
* @param handle The ADC handle
|
||||||
|
* @param[in] value The value acquired with `furi_hal_adc_read` for
|
||||||
|
* `FuriHalAdcChannelVREFINT` channel
|
||||||
|
*
|
||||||
|
* @return Voltage in mV
|
||||||
|
*/
|
||||||
|
float furi_hal_adc_convert_vref(FuriHalAdcHandle* handle, uint16_t value);
|
||||||
|
|
||||||
|
/** Convert sampled TEMPSENSOR value to temperature
|
||||||
|
*
|
||||||
|
* @param handle The ADC handle
|
||||||
|
* @param[in] value The value acquired with `furi_hal_adc_read` for
|
||||||
|
* `FuriHalAdcChannelTEMPSENSOR` channel
|
||||||
|
*
|
||||||
|
* @return temperature in degree C
|
||||||
|
*/
|
||||||
|
float furi_hal_adc_convert_temp(FuriHalAdcHandle* handle, uint16_t value);
|
||||||
|
|
||||||
|
/** Convert sampled VBAT value to voltage
|
||||||
|
*
|
||||||
|
* @param handle The ADC handle
|
||||||
|
* @param[in] value The value acquired with `furi_hal_adc_read` for
|
||||||
|
* `FuriHalAdcChannelVBAT` channel
|
||||||
|
*
|
||||||
|
* @return Voltage in mV
|
||||||
|
*/
|
||||||
|
float furi_hal_adc_convert_vbat(FuriHalAdcHandle* handle, uint16_t value);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user