[FL-3057] Allow use of any suitable pin for 1-Wire devices (#2350)
* Add 1-wire thermometer example app stub * Working 1-wire thermometer app * Refactor app to use threads * Clean up code, add comments * Add CRC checking * Increase update period * Fix error in fbt * Revert the old update period * Use settable pin in onewire_host * Use settable pin for onewire_slave * Clear EXTI flag after callback, make private methods static in onewire_slave * Do not hardcode GPIO pin number * Remove iButton hal from furi_hal_rfid * Remove most of furi_hal_ibutton * Add some of furi_hal_ibutton back * Slightly neater code * Fix formatting * Fix PVS-studio warnings * Update CODEOWNERS * Add furi_hal_gpio_get_ext_pin_number * Create README.md * FuriHal: move furi_hal_gpio_get_ext_pin_number to resources --------- Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
parent
e3d473bf42
commit
7a3a1aaf0d
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -42,6 +42,8 @@
|
|||||||
|
|
||||||
/applications/debug/unit_tests/ @skotopes @DrZlo13 @hedger @nminaylov @gornekich @Astrrra @gsurkov @Skorpionm
|
/applications/debug/unit_tests/ @skotopes @DrZlo13 @hedger @nminaylov @gornekich @Astrrra @gsurkov @Skorpionm
|
||||||
|
|
||||||
|
/applications/examples/example_thermo/ @skotopes @DrZlo13 @hedger @gsurkov
|
||||||
|
|
||||||
# Assets
|
# Assets
|
||||||
/assets/resources/infrared/ @skotopes @DrZlo13 @hedger @gsurkov
|
/assets/resources/infrared/ @skotopes @DrZlo13 @hedger @gsurkov
|
||||||
|
|
||||||
|
44
applications/examples/example_thermo/README.md
Normal file
44
applications/examples/example_thermo/README.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# 1-Wire Thermometer
|
||||||
|
This example application demonstrates the use of the 1-Wire library with a DS18B20 thermometer.
|
||||||
|
It also covers basic GUI, input handling, threads and localisation.
|
||||||
|
|
||||||
|
## Electrical connections
|
||||||
|
Before launching the application, connect the sensor to Flipper's external GPIO according to the table below:
|
||||||
|
| DS18B20 | Flipper |
|
||||||
|
| :-----: | :-----: |
|
||||||
|
| VDD | 9 |
|
||||||
|
| GND | 18 |
|
||||||
|
| DQ | 17 |
|
||||||
|
|
||||||
|
*NOTE 1*: GND is also available on pins 8 and 11.
|
||||||
|
|
||||||
|
*NOTE 2*: For any other pin than 17, connect an external 4.7k pull-up resistor to pin 9.
|
||||||
|
|
||||||
|
## Launching the application
|
||||||
|
In order to launch this demo, follow the steps below:
|
||||||
|
1. Make sure your Flipper has an SD card installed.
|
||||||
|
2. Connect your Flipper to the computer via a USB cable.
|
||||||
|
3. Run `./fbt launch_app APPSRC=example_thermo` in your terminal emulator of choice.
|
||||||
|
|
||||||
|
## Changing the data pin
|
||||||
|
It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/* Possible GPIO pin choices:
|
||||||
|
- gpio_ext_pc0
|
||||||
|
- gpio_ext_pc1
|
||||||
|
- gpio_ext_pc3
|
||||||
|
- gpio_ext_pb2
|
||||||
|
- gpio_ext_pb3
|
||||||
|
- gpio_ext_pa4
|
||||||
|
- gpio_ext_pa6
|
||||||
|
- gpio_ext_pa7
|
||||||
|
- ibutton_gpio
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define THERMO_GPIO_PIN (ibutton_gpio)
|
||||||
|
```
|
||||||
|
Do not forget about the external pull-up resistor as these pins do not have one built-in.
|
||||||
|
|
||||||
|
With the changes been made, recompile and launch the application again.
|
||||||
|
The on-screen text should reflect it by asking to connect the thermometer to another pin.
|
10
applications/examples/example_thermo/application.fam
Normal file
10
applications/examples/example_thermo/application.fam
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
App(
|
||||||
|
appid="example_thermo",
|
||||||
|
name="Example: Thermometer",
|
||||||
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
entry_point="example_thermo_main",
|
||||||
|
requires=["gui"],
|
||||||
|
stack_size=1 * 1024,
|
||||||
|
fap_icon="example_thermo_10px.png",
|
||||||
|
fap_category="Examples",
|
||||||
|
)
|
356
applications/examples/example_thermo/example_thermo.c
Normal file
356
applications/examples/example_thermo/example_thermo.c
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
/*
|
||||||
|
* This file contains an example application that reads and displays
|
||||||
|
* the temperature from a DS18B20 1-wire thermometer.
|
||||||
|
*
|
||||||
|
* It also covers basic GUI, input handling, threads and localisation.
|
||||||
|
*
|
||||||
|
* References:
|
||||||
|
* [1] DS18B20 Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/DS18B20.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include <gui/view_port.h>
|
||||||
|
|
||||||
|
#include <core/thread.h>
|
||||||
|
#include <core/kernel.h>
|
||||||
|
|
||||||
|
#include <locale/locale.h>
|
||||||
|
|
||||||
|
#include <one_wire/maxim_crc.h>
|
||||||
|
#include <one_wire/one_wire_host.h>
|
||||||
|
|
||||||
|
#define UPDATE_PERIOD_MS 1000UL
|
||||||
|
#define TEXT_STORE_SIZE 64U
|
||||||
|
|
||||||
|
#define DS18B20_CMD_CONVERT 0x44U
|
||||||
|
#define DS18B20_CMD_READ_SCRATCHPAD 0xbeU
|
||||||
|
|
||||||
|
#define DS18B20_CFG_RESOLUTION_POS 5U
|
||||||
|
#define DS18B20_CFG_RESOLUTION_MASK 0x03U
|
||||||
|
#define DS18B20_DECIMAL_PART_MASK 0x0fU
|
||||||
|
|
||||||
|
#define DS18B20_SIGN_MASK 0xf0U
|
||||||
|
|
||||||
|
/* Possible GPIO pin choices:
|
||||||
|
- gpio_ext_pc0
|
||||||
|
- gpio_ext_pc1
|
||||||
|
- gpio_ext_pc3
|
||||||
|
- gpio_ext_pb2
|
||||||
|
- gpio_ext_pb3
|
||||||
|
- gpio_ext_pa4
|
||||||
|
- gpio_ext_pa6
|
||||||
|
- gpio_ext_pa7
|
||||||
|
- ibutton_gpio
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define THERMO_GPIO_PIN (ibutton_gpio)
|
||||||
|
|
||||||
|
/* Flags which the reader thread responds to */
|
||||||
|
typedef enum {
|
||||||
|
ReaderThreadFlagExit = 1,
|
||||||
|
} ReaderThreadFlag;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
uint8_t temp_lsb; /* Least significant byte of the temperature */
|
||||||
|
uint8_t temp_msb; /* Most significant byte of the temperature */
|
||||||
|
uint8_t user_alarm_high; /* User register 1 (Temp high alarm) */
|
||||||
|
uint8_t user_alarm_low; /* User register 2 (Temp low alarm) */
|
||||||
|
uint8_t config; /* Configuration register */
|
||||||
|
uint8_t reserved[3]; /* Not used */
|
||||||
|
uint8_t crc; /* CRC checksum for error detection */
|
||||||
|
} fields;
|
||||||
|
uint8_t bytes[9];
|
||||||
|
} DS18B20Scratchpad;
|
||||||
|
|
||||||
|
/* Application context structure */
|
||||||
|
typedef struct {
|
||||||
|
Gui* gui;
|
||||||
|
ViewPort* view_port;
|
||||||
|
FuriThread* reader_thread;
|
||||||
|
FuriMessageQueue* event_queue;
|
||||||
|
OneWireHost* onewire;
|
||||||
|
float temp_celsius;
|
||||||
|
bool has_device;
|
||||||
|
} ExampleThermoContext;
|
||||||
|
|
||||||
|
/*************** 1-Wire Communication and Processing *****************/
|
||||||
|
|
||||||
|
/* Commands the thermometer to begin measuring the temperature. */
|
||||||
|
static void example_thermo_request_temperature(ExampleThermoContext* context) {
|
||||||
|
OneWireHost* onewire = context->onewire;
|
||||||
|
|
||||||
|
/* All 1-wire transactions must happen in a critical section, i.e
|
||||||
|
not interrupted by other threads. */
|
||||||
|
FURI_CRITICAL_ENTER();
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
do {
|
||||||
|
/* Each communication with a 1-wire device starts by a reset.
|
||||||
|
The functon will return true if a device responded with a presence pulse. */
|
||||||
|
if(!onewire_host_reset(onewire)) break;
|
||||||
|
/* After the reset, a ROM operation must follow.
|
||||||
|
If there is only one device connected, the "Skip ROM" command is most appropriate
|
||||||
|
(it can also be used to address all of the connected devices in some cases).*/
|
||||||
|
onewire_host_skip(onewire);
|
||||||
|
/* After the ROM operation, a device-specific command is issued.
|
||||||
|
In this case, it's a request to start measuring the temperature. */
|
||||||
|
onewire_host_write(onewire, DS18B20_CMD_CONVERT);
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
context->has_device = success;
|
||||||
|
|
||||||
|
FURI_CRITICAL_EXIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads the measured temperature from the thermometer. */
|
||||||
|
static void example_thermo_read_temperature(ExampleThermoContext* context) {
|
||||||
|
/* If there was no device detected, don't try to read the temperature */
|
||||||
|
if(!context->has_device) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OneWireHost* onewire = context->onewire;
|
||||||
|
|
||||||
|
/* All 1-wire transactions must happen in a critical section, i.e
|
||||||
|
not interrupted by other threads. */
|
||||||
|
FURI_CRITICAL_ENTER();
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
DS18B20Scratchpad buf;
|
||||||
|
|
||||||
|
/* Attempt reading the temperature 10 times before giving up */
|
||||||
|
size_t attempts_left = 10;
|
||||||
|
do {
|
||||||
|
/* Each communication with a 1-wire device starts by a reset.
|
||||||
|
The functon will return true if a device responded with a presence pulse. */
|
||||||
|
if(!onewire_host_reset(onewire)) continue;
|
||||||
|
|
||||||
|
/* After the reset, a ROM operation must follow.
|
||||||
|
If there is only one device connected, the "Skip ROM" command is most appropriate
|
||||||
|
(it can also be used to address all of the connected devices in some cases).*/
|
||||||
|
onewire_host_skip(onewire);
|
||||||
|
|
||||||
|
/* After the ROM operation, a device-specific command is issued.
|
||||||
|
This time, it will be the "Read Scratchpad" command which will
|
||||||
|
prepare the device's internal buffer memory for reading. */
|
||||||
|
onewire_host_write(onewire, DS18B20_CMD_READ_SCRATCHPAD);
|
||||||
|
|
||||||
|
/* The actual reading happens here. A total of 9 bytes is read. */
|
||||||
|
onewire_host_read_bytes(onewire, buf.bytes, sizeof(buf.bytes));
|
||||||
|
|
||||||
|
/* Calculate the checksum and compare it with one provided by the device. */
|
||||||
|
const uint8_t crc = maxim_crc8(buf.bytes, sizeof(buf.bytes) - 1, MAXIM_CRC8_INIT);
|
||||||
|
|
||||||
|
/* Checksums match, exit the loop */
|
||||||
|
if(crc == buf.fields.crc) break;
|
||||||
|
|
||||||
|
} while(--attempts_left);
|
||||||
|
|
||||||
|
if(attempts_left == 0) break;
|
||||||
|
|
||||||
|
/* Get the measurement resolution from the configuration register. (See [1] page 9) */
|
||||||
|
const uint8_t resolution_mode = (buf.fields.config >> DS18B20_CFG_RESOLUTION_POS) &
|
||||||
|
DS18B20_CFG_RESOLUTION_MASK;
|
||||||
|
|
||||||
|
/* Generate a mask for undefined bits in the decimal part. (See [1] page 6) */
|
||||||
|
const uint8_t decimal_mask =
|
||||||
|
(DS18B20_DECIMAL_PART_MASK << (DS18B20_CFG_RESOLUTION_MASK - resolution_mode)) &
|
||||||
|
DS18B20_DECIMAL_PART_MASK;
|
||||||
|
|
||||||
|
/* Get the integer and decimal part of the temperature (See [1] page 6) */
|
||||||
|
const uint8_t integer_part = (buf.fields.temp_msb << 4U) | (buf.fields.temp_lsb >> 4U);
|
||||||
|
const uint8_t decimal_part = buf.fields.temp_lsb & decimal_mask;
|
||||||
|
|
||||||
|
/* Calculate the sign of the temperature (See [1] page 6) */
|
||||||
|
const bool is_negative = (buf.fields.temp_msb & DS18B20_SIGN_MASK) != 0;
|
||||||
|
|
||||||
|
/* Combine the integer and decimal part together */
|
||||||
|
const float temp_celsius_abs = integer_part + decimal_part / 16.f;
|
||||||
|
|
||||||
|
/* Set the appropriate sign */
|
||||||
|
context->temp_celsius = is_negative ? -temp_celsius_abs : temp_celsius_abs;
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
context->has_device = success;
|
||||||
|
|
||||||
|
FURI_CRITICAL_EXIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Periodically requests measurements and reads temperature. This function runs in a separare thread. */
|
||||||
|
static int32_t example_thermo_reader_thread_callback(void* ctx) {
|
||||||
|
ExampleThermoContext* context = ctx;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
/* Tell the termometer to start measuring the temperature. The process may take up to 750ms. */
|
||||||
|
example_thermo_request_temperature(context);
|
||||||
|
|
||||||
|
/* Wait for the measurement to finish. At the same time wait for an exit signal. */
|
||||||
|
const uint32_t flags =
|
||||||
|
furi_thread_flags_wait(ReaderThreadFlagExit, FuriFlagWaitAny, UPDATE_PERIOD_MS);
|
||||||
|
|
||||||
|
/* If an exit signal was received, return from this thread. */
|
||||||
|
if(flags != (unsigned)FuriFlagErrorTimeout) break;
|
||||||
|
|
||||||
|
/* The measurement is now ready, read it from the termometer. */
|
||||||
|
example_thermo_read_temperature(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************** GUI, Input and Main Loop *****************/
|
||||||
|
|
||||||
|
/* Draw the GUI of the application. The screen is completely redrawn during each call. */
|
||||||
|
static void example_thermo_draw_callback(Canvas* canvas, void* ctx) {
|
||||||
|
ExampleThermoContext* context = ctx;
|
||||||
|
char text_store[TEXT_STORE_SIZE];
|
||||||
|
const size_t middle_x = canvas_width(canvas) / 2U;
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(canvas, middle_x, 12, AlignCenter, AlignBottom, "Thermometer Demo");
|
||||||
|
canvas_draw_line(canvas, 0, 16, 128, 16);
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
canvas_draw_str_aligned(
|
||||||
|
canvas, middle_x, 30, AlignCenter, AlignBottom, "Connnect thermometer");
|
||||||
|
|
||||||
|
snprintf(
|
||||||
|
text_store,
|
||||||
|
TEXT_STORE_SIZE,
|
||||||
|
"to GPIO pin %ld",
|
||||||
|
furi_hal_resources_get_ext_pin_number(&THERMO_GPIO_PIN));
|
||||||
|
canvas_draw_str_aligned(canvas, middle_x, 42, AlignCenter, AlignBottom, text_store);
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontKeyboard);
|
||||||
|
|
||||||
|
if(context->has_device) {
|
||||||
|
float temp;
|
||||||
|
char temp_units;
|
||||||
|
|
||||||
|
/* The applicaton is locale-aware.
|
||||||
|
Change Settings->System->Units to check it out. */
|
||||||
|
switch(locale_get_measurement_unit()) {
|
||||||
|
case LocaleMeasurementUnitsMetric:
|
||||||
|
temp = context->temp_celsius;
|
||||||
|
temp_units = 'C';
|
||||||
|
break;
|
||||||
|
case LocaleMeasurementUnitsImperial:
|
||||||
|
temp = locale_celsius_to_fahrenheit(context->temp_celsius);
|
||||||
|
temp_units = 'F';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
furi_crash("Illegal measurement units");
|
||||||
|
}
|
||||||
|
/* If a reading is available, display it */
|
||||||
|
snprintf(text_store, TEXT_STORE_SIZE, "Temperature: %+.1f%c", (double)temp, temp_units);
|
||||||
|
} else {
|
||||||
|
/* Or show a message that no data is available */
|
||||||
|
strncpy(text_store, "-- No data --", TEXT_STORE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas_draw_str_aligned(canvas, middle_x, 58, AlignCenter, AlignBottom, text_store);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function is called from the GUI thread. All it does is put the event
|
||||||
|
into the application's queue so it can be processed later. */
|
||||||
|
static void example_thermo_input_callback(InputEvent* event, void* ctx) {
|
||||||
|
ExampleThermoContext* context = ctx;
|
||||||
|
furi_message_queue_put(context->event_queue, event, FuriWaitForever);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Starts the reader thread and handles the input */
|
||||||
|
static void example_thermo_run(ExampleThermoContext* context) {
|
||||||
|
/* Configure the hardware in host mode */
|
||||||
|
onewire_host_start(context->onewire);
|
||||||
|
|
||||||
|
/* Start the reader thread. It will talk to the thermometer in the background. */
|
||||||
|
furi_thread_start(context->reader_thread);
|
||||||
|
|
||||||
|
/* An endless loop which handles the input*/
|
||||||
|
for(bool is_running = true; is_running;) {
|
||||||
|
InputEvent event;
|
||||||
|
/* Wait for an input event. Input events come from the GUI thread via a callback. */
|
||||||
|
const FuriStatus status =
|
||||||
|
furi_message_queue_get(context->event_queue, &event, FuriWaitForever);
|
||||||
|
|
||||||
|
/* This application is only interested in short button presses. */
|
||||||
|
if((status != FuriStatusOk) || (event.type != InputTypeShort)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the user presses the "Back" button, break the loop and exit the application. */
|
||||||
|
if(event.key == InputKeyBack) {
|
||||||
|
is_running = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signal the reader thread to cease operation and exit */
|
||||||
|
furi_thread_flags_set(furi_thread_get_id(context->reader_thread), ReaderThreadFlagExit);
|
||||||
|
|
||||||
|
/* Wait for the reader thread to finish */
|
||||||
|
furi_thread_join(context->reader_thread);
|
||||||
|
|
||||||
|
/* Reset the hardware */
|
||||||
|
onewire_host_stop(context->onewire);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************** Initialisation & startup *****************************/
|
||||||
|
|
||||||
|
/* Allocate the memory and initialise the variables */
|
||||||
|
static ExampleThermoContext* example_thermo_context_alloc() {
|
||||||
|
ExampleThermoContext* context = malloc(sizeof(ExampleThermoContext));
|
||||||
|
|
||||||
|
context->view_port = view_port_alloc();
|
||||||
|
view_port_draw_callback_set(context->view_port, example_thermo_draw_callback, context);
|
||||||
|
view_port_input_callback_set(context->view_port, example_thermo_input_callback, context);
|
||||||
|
|
||||||
|
context->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
|
||||||
|
|
||||||
|
context->reader_thread = furi_thread_alloc();
|
||||||
|
furi_thread_set_stack_size(context->reader_thread, 1024U);
|
||||||
|
furi_thread_set_context(context->reader_thread, context);
|
||||||
|
furi_thread_set_callback(context->reader_thread, example_thermo_reader_thread_callback);
|
||||||
|
|
||||||
|
context->gui = furi_record_open(RECORD_GUI);
|
||||||
|
gui_add_view_port(context->gui, context->view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
|
context->onewire = onewire_host_alloc(&THERMO_GPIO_PIN);
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the unused resources and deallocate memory */
|
||||||
|
static void example_thermo_context_free(ExampleThermoContext* context) {
|
||||||
|
view_port_enabled_set(context->view_port, false);
|
||||||
|
gui_remove_view_port(context->gui, context->view_port);
|
||||||
|
|
||||||
|
onewire_host_free(context->onewire);
|
||||||
|
furi_thread_free(context->reader_thread);
|
||||||
|
furi_message_queue_free(context->event_queue);
|
||||||
|
view_port_free(context->view_port);
|
||||||
|
|
||||||
|
furi_record_close(RECORD_GUI);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The application's entry point. Execution starts from here. */
|
||||||
|
int32_t example_thermo_main(void* p) {
|
||||||
|
UNUSED(p);
|
||||||
|
|
||||||
|
/* Allocate all of the necessary structures */
|
||||||
|
ExampleThermoContext* context = example_thermo_context_alloc();
|
||||||
|
|
||||||
|
/* Start the applicaton's main loop. It won't return until the application was requested to exit. */
|
||||||
|
example_thermo_run(context);
|
||||||
|
|
||||||
|
/* Release all unneeded resources */
|
||||||
|
example_thermo_context_free(context);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
applications/examples/example_thermo/example_thermo_10px.png
Normal file
BIN
applications/examples/example_thermo/example_thermo_10px.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.1 KiB |
@ -271,7 +271,7 @@ void onewire_cli_print_usage() {
|
|||||||
|
|
||||||
static void onewire_cli_search(Cli* cli) {
|
static void onewire_cli_search(Cli* cli) {
|
||||||
UNUSED(cli);
|
UNUSED(cli);
|
||||||
OneWireHost* onewire = onewire_host_alloc();
|
OneWireHost* onewire = onewire_host_alloc(&ibutton_gpio);
|
||||||
uint8_t address[8];
|
uint8_t address[8];
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,12.2,,
|
Version,+,13.0,,
|
||||||
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,,
|
||||||
@ -910,6 +910,7 @@ Function,-,furi_hal_flash_write_dword,void,"size_t, uint64_t"
|
|||||||
Function,+,furi_hal_gpio_add_int_callback,void,"const GpioPin*, GpioExtiCallback, void*"
|
Function,+,furi_hal_gpio_add_int_callback,void,"const GpioPin*, GpioExtiCallback, void*"
|
||||||
Function,+,furi_hal_gpio_disable_int_callback,void,const GpioPin*
|
Function,+,furi_hal_gpio_disable_int_callback,void,const GpioPin*
|
||||||
Function,+,furi_hal_gpio_enable_int_callback,void,const GpioPin*
|
Function,+,furi_hal_gpio_enable_int_callback,void,const GpioPin*
|
||||||
|
Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin*
|
||||||
Function,+,furi_hal_gpio_init,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed"
|
Function,+,furi_hal_gpio_init,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed"
|
||||||
Function,+,furi_hal_gpio_init_ex,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed, const GpioAltFn"
|
Function,+,furi_hal_gpio_init_ex,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed, const GpioAltFn"
|
||||||
Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode"
|
Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode"
|
||||||
|
|
@ -199,3 +199,27 @@ void furi_hal_resources_init() {
|
|||||||
NVIC_SetPriority(EXTI15_10_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
NVIC_SetPriority(EXTI15_10_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||||
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio) {
|
||||||
|
// TODO: describe second ROW
|
||||||
|
if(gpio == &gpio_ext_pa7)
|
||||||
|
return 2;
|
||||||
|
else if(gpio == &gpio_ext_pa6)
|
||||||
|
return 3;
|
||||||
|
else if(gpio == &gpio_ext_pa4)
|
||||||
|
return 4;
|
||||||
|
else if(gpio == &gpio_ext_pb3)
|
||||||
|
return 5;
|
||||||
|
else if(gpio == &gpio_ext_pb2)
|
||||||
|
return 6;
|
||||||
|
else if(gpio == &gpio_ext_pc3)
|
||||||
|
return 7;
|
||||||
|
else if(gpio == &gpio_ext_pc1)
|
||||||
|
return 15;
|
||||||
|
else if(gpio == &gpio_ext_pc0)
|
||||||
|
return 16;
|
||||||
|
else if(gpio == &ibutton_gpio)
|
||||||
|
return 17;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
@ -111,6 +111,13 @@ void furi_hal_resources_deinit_early();
|
|||||||
|
|
||||||
void furi_hal_resources_init();
|
void furi_hal_resources_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a corresponding external connector pin number for a gpio
|
||||||
|
* @param gpio GpioPin
|
||||||
|
* @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);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,12.2,,
|
Version,+,13.0,,
|
||||||
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,,
|
||||||
@ -1094,6 +1094,7 @@ Function,-,furi_hal_flash_write_dword,void,"size_t, uint64_t"
|
|||||||
Function,+,furi_hal_gpio_add_int_callback,void,"const GpioPin*, GpioExtiCallback, void*"
|
Function,+,furi_hal_gpio_add_int_callback,void,"const GpioPin*, GpioExtiCallback, void*"
|
||||||
Function,+,furi_hal_gpio_disable_int_callback,void,const GpioPin*
|
Function,+,furi_hal_gpio_disable_int_callback,void,const GpioPin*
|
||||||
Function,+,furi_hal_gpio_enable_int_callback,void,const GpioPin*
|
Function,+,furi_hal_gpio_enable_int_callback,void,const GpioPin*
|
||||||
|
Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin*
|
||||||
Function,+,furi_hal_gpio_init,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed"
|
Function,+,furi_hal_gpio_init,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed"
|
||||||
Function,+,furi_hal_gpio_init_ex,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed, const GpioAltFn"
|
Function,+,furi_hal_gpio_init_ex,void,"const GpioPin*, const GpioMode, const GpioPull, const GpioSpeed, const GpioAltFn"
|
||||||
Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode"
|
Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode"
|
||||||
@ -1129,20 +1130,13 @@ Function,+,furi_hal_i2c_tx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, const uin
|
|||||||
Function,+,furi_hal_i2c_write_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint8_t, uint32_t"
|
Function,+,furi_hal_i2c_write_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint8_t, uint32_t"
|
||||||
Function,+,furi_hal_i2c_write_reg_16,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint16_t, uint32_t"
|
Function,+,furi_hal_i2c_write_reg_16,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint16_t, uint32_t"
|
||||||
Function,+,furi_hal_i2c_write_reg_8,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t, uint32_t"
|
Function,+,furi_hal_i2c_write_reg_8,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t, uint32_t"
|
||||||
Function,+,furi_hal_ibutton_add_interrupt,void,"GpioExtiCallback, void*"
|
|
||||||
Function,+,furi_hal_ibutton_emulate_set_next,void,uint32_t
|
Function,+,furi_hal_ibutton_emulate_set_next,void,uint32_t
|
||||||
Function,+,furi_hal_ibutton_emulate_start,void,"uint32_t, FuriHalIbuttonEmulateCallback, void*"
|
Function,+,furi_hal_ibutton_emulate_start,void,"uint32_t, FuriHalIbuttonEmulateCallback, void*"
|
||||||
Function,+,furi_hal_ibutton_emulate_stop,void,
|
Function,+,furi_hal_ibutton_emulate_stop,void,
|
||||||
Function,-,furi_hal_ibutton_init,void,
|
Function,-,furi_hal_ibutton_init,void,
|
||||||
Function,+,furi_hal_ibutton_pin_get_level,_Bool,
|
Function,+,furi_hal_ibutton_pin_configure,void,
|
||||||
Function,+,furi_hal_ibutton_pin_high,void,
|
Function,+,furi_hal_ibutton_pin_reset,void,
|
||||||
Function,+,furi_hal_ibutton_pin_low,void,
|
Function,+,furi_hal_ibutton_pin_write,void,const _Bool
|
||||||
Function,+,furi_hal_ibutton_remove_interrupt,void,
|
|
||||||
Function,+,furi_hal_ibutton_start_drive,void,
|
|
||||||
Function,+,furi_hal_ibutton_start_drive_in_isr,void,
|
|
||||||
Function,+,furi_hal_ibutton_start_interrupt,void,
|
|
||||||
Function,+,furi_hal_ibutton_start_interrupt_in_isr,void,
|
|
||||||
Function,+,furi_hal_ibutton_stop,void,
|
|
||||||
Function,+,furi_hal_info_get,void,"PropertyValueCallback, char, void*"
|
Function,+,furi_hal_info_get,void,"PropertyValueCallback, char, void*"
|
||||||
Function,+,furi_hal_infrared_async_rx_set_capture_isr_callback,void,"FuriHalInfraredRxCaptureCallback, void*"
|
Function,+,furi_hal_infrared_async_rx_set_capture_isr_callback,void,"FuriHalInfraredRxCaptureCallback, void*"
|
||||||
Function,+,furi_hal_infrared_async_rx_set_timeout,void,uint32_t
|
Function,+,furi_hal_infrared_async_rx_set_timeout,void,uint32_t
|
||||||
@ -2040,7 +2034,7 @@ Function,+,onewire_device_detach,void,OneWireDevice*
|
|||||||
Function,+,onewire_device_free,void,OneWireDevice*
|
Function,+,onewire_device_free,void,OneWireDevice*
|
||||||
Function,+,onewire_device_get_id_p,uint8_t*,OneWireDevice*
|
Function,+,onewire_device_get_id_p,uint8_t*,OneWireDevice*
|
||||||
Function,+,onewire_device_send_id,void,OneWireDevice*
|
Function,+,onewire_device_send_id,void,OneWireDevice*
|
||||||
Function,+,onewire_host_alloc,OneWireHost*,
|
Function,+,onewire_host_alloc,OneWireHost*,const GpioPin*
|
||||||
Function,+,onewire_host_free,void,OneWireHost*
|
Function,+,onewire_host_free,void,OneWireHost*
|
||||||
Function,+,onewire_host_read,uint8_t,OneWireHost*
|
Function,+,onewire_host_read,uint8_t,OneWireHost*
|
||||||
Function,+,onewire_host_read_bit,_Bool,OneWireHost*
|
Function,+,onewire_host_read_bit,_Bool,OneWireHost*
|
||||||
@ -2054,7 +2048,7 @@ Function,+,onewire_host_stop,void,OneWireHost*
|
|||||||
Function,+,onewire_host_target_search,void,"OneWireHost*, uint8_t"
|
Function,+,onewire_host_target_search,void,"OneWireHost*, uint8_t"
|
||||||
Function,+,onewire_host_write,void,"OneWireHost*, uint8_t"
|
Function,+,onewire_host_write,void,"OneWireHost*, uint8_t"
|
||||||
Function,+,onewire_host_write_bit,void,"OneWireHost*, _Bool"
|
Function,+,onewire_host_write_bit,void,"OneWireHost*, _Bool"
|
||||||
Function,+,onewire_slave_alloc,OneWireSlave*,
|
Function,+,onewire_slave_alloc,OneWireSlave*,const GpioPin*
|
||||||
Function,+,onewire_slave_attach,void,"OneWireSlave*, OneWireDevice*"
|
Function,+,onewire_slave_attach,void,"OneWireSlave*, OneWireDevice*"
|
||||||
Function,+,onewire_slave_detach,void,OneWireSlave*
|
Function,+,onewire_slave_detach,void,OneWireSlave*
|
||||||
Function,+,onewire_slave_free,void,OneWireSlave*
|
Function,+,onewire_slave_free,void,OneWireSlave*
|
||||||
|
|
@ -1,6 +1,7 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal_gpio.h>
|
#include <furi_hal_gpio.h>
|
||||||
#include <furi_hal_version.h>
|
#include <furi_hal_version.h>
|
||||||
|
#include <furi_hal_resources.h>
|
||||||
#include <stm32wbxx_ll_comp.h>
|
#include <stm32wbxx_ll_comp.h>
|
||||||
|
|
||||||
#define GET_SYSCFG_EXTI_PORT(gpio) \
|
#define GET_SYSCFG_EXTI_PORT(gpio) \
|
||||||
@ -224,85 +225,85 @@ static void furi_hal_gpio_int_call(uint16_t pin_num) {
|
|||||||
/* Interrupt handlers */
|
/* Interrupt handlers */
|
||||||
void EXTI0_IRQHandler(void) {
|
void EXTI0_IRQHandler(void) {
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_0)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_0)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_0);
|
|
||||||
furi_hal_gpio_int_call(0);
|
furi_hal_gpio_int_call(0);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXTI1_IRQHandler(void) {
|
void EXTI1_IRQHandler(void) {
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_1)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_1)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_1);
|
|
||||||
furi_hal_gpio_int_call(1);
|
furi_hal_gpio_int_call(1);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXTI2_IRQHandler(void) {
|
void EXTI2_IRQHandler(void) {
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_2)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_2)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_2);
|
|
||||||
furi_hal_gpio_int_call(2);
|
furi_hal_gpio_int_call(2);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXTI3_IRQHandler(void) {
|
void EXTI3_IRQHandler(void) {
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_3)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_3)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_3);
|
|
||||||
furi_hal_gpio_int_call(3);
|
furi_hal_gpio_int_call(3);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXTI4_IRQHandler(void) {
|
void EXTI4_IRQHandler(void) {
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_4)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_4)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_4);
|
|
||||||
furi_hal_gpio_int_call(4);
|
furi_hal_gpio_int_call(4);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXTI9_5_IRQHandler(void) {
|
void EXTI9_5_IRQHandler(void) {
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_5)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_5)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_5);
|
|
||||||
furi_hal_gpio_int_call(5);
|
furi_hal_gpio_int_call(5);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_5);
|
||||||
}
|
}
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_6)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_6)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_6);
|
|
||||||
furi_hal_gpio_int_call(6);
|
furi_hal_gpio_int_call(6);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_6);
|
||||||
}
|
}
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_7)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_7)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_7);
|
|
||||||
furi_hal_gpio_int_call(7);
|
furi_hal_gpio_int_call(7);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_7);
|
||||||
}
|
}
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_8)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_8)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_8);
|
|
||||||
furi_hal_gpio_int_call(8);
|
furi_hal_gpio_int_call(8);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_8);
|
||||||
}
|
}
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_9)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_9)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_9);
|
|
||||||
furi_hal_gpio_int_call(9);
|
furi_hal_gpio_int_call(9);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXTI15_10_IRQHandler(void) {
|
void EXTI15_10_IRQHandler(void) {
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_10)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_10)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_10);
|
|
||||||
furi_hal_gpio_int_call(10);
|
furi_hal_gpio_int_call(10);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_10);
|
||||||
}
|
}
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_11)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_11)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_11);
|
|
||||||
furi_hal_gpio_int_call(11);
|
furi_hal_gpio_int_call(11);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_11);
|
||||||
}
|
}
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_12)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_12)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_12);
|
|
||||||
furi_hal_gpio_int_call(12);
|
furi_hal_gpio_int_call(12);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_12);
|
||||||
}
|
}
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_13)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_13)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_13);
|
|
||||||
furi_hal_gpio_int_call(13);
|
furi_hal_gpio_int_call(13);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_13);
|
||||||
}
|
}
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_14)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_14)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_14);
|
|
||||||
furi_hal_gpio_int_call(14);
|
furi_hal_gpio_int_call(14);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_14);
|
||||||
}
|
}
|
||||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_15)) {
|
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_15)) {
|
||||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_15);
|
|
||||||
furi_hal_gpio_int_call(15);
|
furi_hal_gpio_int_call(15);
|
||||||
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,47 +89,16 @@ void furi_hal_ibutton_emulate_stop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_ibutton_start_drive() {
|
void furi_hal_ibutton_pin_configure() {
|
||||||
furi_hal_ibutton_pin_high();
|
furi_hal_gpio_write(&ibutton_gpio, true);
|
||||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&ibutton_gpio, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_ibutton_start_drive_in_isr() {
|
void furi_hal_ibutton_pin_reset() {
|
||||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_write(&ibutton_gpio, true);
|
||||||
LL_EXTI_ClearFlag_0_31(ibutton_gpio.pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_ibutton_start_interrupt() {
|
|
||||||
furi_hal_ibutton_pin_high();
|
|
||||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow);
|
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_ibutton_start_interrupt_in_isr() {
|
|
||||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow);
|
|
||||||
LL_EXTI_ClearFlag_0_31(ibutton_gpio.pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_ibutton_stop() {
|
|
||||||
furi_hal_ibutton_pin_high();
|
|
||||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&ibutton_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_ibutton_add_interrupt(GpioExtiCallback cb, void* context) {
|
void furi_hal_ibutton_pin_write(const bool state) {
|
||||||
furi_hal_gpio_add_int_callback(&ibutton_gpio, cb, context);
|
furi_hal_gpio_write(&ibutton_gpio, state);
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_ibutton_remove_interrupt() {
|
|
||||||
furi_hal_gpio_remove_int_callback(&ibutton_gpio);
|
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_ibutton_pin_low() {
|
|
||||||
furi_hal_gpio_write(&ibutton_gpio, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void furi_hal_ibutton_pin_high() {
|
|
||||||
furi_hal_gpio_write(&ibutton_gpio, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool furi_hal_ibutton_pin_get_level() {
|
|
||||||
return furi_hal_gpio_read(&ibutton_gpio);
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <furi_hal_gpio.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -18,70 +17,43 @@ typedef void (*FuriHalIbuttonEmulateCallback)(void* context);
|
|||||||
/** Initialize */
|
/** Initialize */
|
||||||
void furi_hal_ibutton_init();
|
void furi_hal_ibutton_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start emulation timer
|
||||||
|
* @param period timer period
|
||||||
|
* @param callback timer callback
|
||||||
|
* @param context callback context
|
||||||
|
*/
|
||||||
void furi_hal_ibutton_emulate_start(
|
void furi_hal_ibutton_emulate_start(
|
||||||
uint32_t period,
|
uint32_t period,
|
||||||
FuriHalIbuttonEmulateCallback callback,
|
FuriHalIbuttonEmulateCallback callback,
|
||||||
void* context);
|
void* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update emulation timer period
|
||||||
|
* @param period new timer period
|
||||||
|
*/
|
||||||
void furi_hal_ibutton_emulate_set_next(uint32_t period);
|
void furi_hal_ibutton_emulate_set_next(uint32_t period);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop emulation timer
|
||||||
|
*/
|
||||||
void furi_hal_ibutton_emulate_stop();
|
void furi_hal_ibutton_emulate_stop();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the pin to normal mode (open collector), and sets it to float
|
* Set the pin to normal mode (open collector), and sets it to float
|
||||||
*/
|
*/
|
||||||
void furi_hal_ibutton_start_drive();
|
void furi_hal_ibutton_pin_configure();
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the pin to normal mode (open collector), and clears pin EXTI interrupt.
|
|
||||||
* Used in EXTI interrupt context.
|
|
||||||
*/
|
|
||||||
void furi_hal_ibutton_start_drive_in_isr();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the pin to interrupt mode (EXTI interrupt on rise or fall), and sets it to float
|
|
||||||
*/
|
|
||||||
void furi_hal_ibutton_start_interrupt();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the pin to interrupt mode (EXTI interrupt on rise or fall), and clears pin EXTI interrupt.
|
|
||||||
* Used in EXTI interrupt context.
|
|
||||||
*/
|
|
||||||
void furi_hal_ibutton_start_interrupt_in_isr();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the pin to analog mode, and sets it to float
|
* Sets the pin to analog mode, and sets it to float
|
||||||
*/
|
*/
|
||||||
void furi_hal_ibutton_stop();
|
void furi_hal_ibutton_pin_reset();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach interrupt callback to iButton pin
|
* iButton write pin
|
||||||
* @param cb callback
|
* @param state true / false
|
||||||
* @param context context
|
|
||||||
*/
|
*/
|
||||||
void furi_hal_ibutton_add_interrupt(GpioExtiCallback cb, void* context);
|
void furi_hal_ibutton_pin_write(const bool state);
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove interrupt callback from iButton pin
|
|
||||||
*/
|
|
||||||
void furi_hal_ibutton_remove_interrupt();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the pin to low
|
|
||||||
*/
|
|
||||||
void furi_hal_ibutton_pin_low();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the pin to high (float in iButton pin modes)
|
|
||||||
*/
|
|
||||||
void furi_hal_ibutton_pin_high();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get pin level
|
|
||||||
* @return true if level is high
|
|
||||||
* @return false if level is low
|
|
||||||
*/
|
|
||||||
bool furi_hal_ibutton_pin_get_level();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -191,3 +191,26 @@ void furi_hal_resources_init() {
|
|||||||
NVIC_SetPriority(EXTI15_10_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
NVIC_SetPriority(EXTI15_10_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||||
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio) {
|
||||||
|
if(gpio == &gpio_ext_pa7)
|
||||||
|
return 2;
|
||||||
|
else if(gpio == &gpio_ext_pa6)
|
||||||
|
return 3;
|
||||||
|
else if(gpio == &gpio_ext_pa4)
|
||||||
|
return 4;
|
||||||
|
else if(gpio == &gpio_ext_pb3)
|
||||||
|
return 5;
|
||||||
|
else if(gpio == &gpio_ext_pb2)
|
||||||
|
return 6;
|
||||||
|
else if(gpio == &gpio_ext_pc3)
|
||||||
|
return 7;
|
||||||
|
else if(gpio == &gpio_ext_pc1)
|
||||||
|
return 15;
|
||||||
|
else if(gpio == &gpio_ext_pc0)
|
||||||
|
return 16;
|
||||||
|
else if(gpio == &ibutton_gpio)
|
||||||
|
return 17;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
@ -216,6 +216,13 @@ void furi_hal_resources_deinit_early();
|
|||||||
|
|
||||||
void furi_hal_resources_init();
|
void furi_hal_resources_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a corresponding external connector pin number for a gpio
|
||||||
|
* @param gpio GpioPin
|
||||||
|
* @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);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -77,7 +77,7 @@ void furi_hal_rfid_init() {
|
|||||||
|
|
||||||
void furi_hal_rfid_pins_reset() {
|
void furi_hal_rfid_pins_reset() {
|
||||||
// ibutton bus disable
|
// ibutton bus disable
|
||||||
furi_hal_ibutton_stop();
|
furi_hal_ibutton_pin_reset();
|
||||||
|
|
||||||
// pulldown rfid antenna
|
// pulldown rfid antenna
|
||||||
furi_hal_gpio_init(&gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||||
@ -94,8 +94,8 @@ void furi_hal_rfid_pins_reset() {
|
|||||||
|
|
||||||
void furi_hal_rfid_pins_emulate() {
|
void furi_hal_rfid_pins_emulate() {
|
||||||
// ibutton low
|
// ibutton low
|
||||||
furi_hal_ibutton_start_drive();
|
furi_hal_ibutton_pin_configure();
|
||||||
furi_hal_ibutton_pin_low();
|
furi_hal_ibutton_pin_write(false);
|
||||||
|
|
||||||
// pull pin to timer out
|
// pull pin to timer out
|
||||||
furi_hal_gpio_init_ex(
|
furi_hal_gpio_init_ex(
|
||||||
@ -115,8 +115,8 @@ void furi_hal_rfid_pins_emulate() {
|
|||||||
|
|
||||||
void furi_hal_rfid_pins_read() {
|
void furi_hal_rfid_pins_read() {
|
||||||
// ibutton low
|
// ibutton low
|
||||||
furi_hal_ibutton_start_drive();
|
furi_hal_ibutton_pin_configure();
|
||||||
furi_hal_ibutton_pin_low();
|
furi_hal_ibutton_pin_write(false);
|
||||||
|
|
||||||
// dont pull rfid antenna
|
// dont pull rfid antenna
|
||||||
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||||
|
@ -25,8 +25,8 @@ iButtonWorker* ibutton_worker_alloc() {
|
|||||||
iButtonWorker* worker = malloc(sizeof(iButtonWorker));
|
iButtonWorker* worker = malloc(sizeof(iButtonWorker));
|
||||||
worker->key_p = NULL;
|
worker->key_p = NULL;
|
||||||
worker->key_data = malloc(ibutton_key_get_max_size());
|
worker->key_data = malloc(ibutton_key_get_max_size());
|
||||||
worker->host = onewire_host_alloc();
|
worker->host = onewire_host_alloc(&ibutton_gpio);
|
||||||
worker->slave = onewire_slave_alloc();
|
worker->slave = onewire_slave_alloc(&ibutton_gpio);
|
||||||
worker->writer = ibutton_writer_alloc(worker->host);
|
worker->writer = ibutton_writer_alloc(worker->host);
|
||||||
worker->device = onewire_device_alloc(0, 0, 0, 0, 0, 0, 0, 0);
|
worker->device = onewire_device_alloc(0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
worker->messages = furi_message_queue_alloc(1, sizeof(iButtonMessage));
|
worker->messages = furi_message_queue_alloc(1, sizeof(iButtonMessage));
|
||||||
|
@ -234,16 +234,13 @@ void ibutton_worker_emulate_timer_cb(void* context) {
|
|||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
iButtonWorker* worker = context;
|
iButtonWorker* worker = context;
|
||||||
|
|
||||||
LevelDuration level =
|
const LevelDuration level_duration =
|
||||||
protocol_dict_encoder_yield(worker->protocols, worker->protocol_to_encode);
|
protocol_dict_encoder_yield(worker->protocols, worker->protocol_to_encode);
|
||||||
|
|
||||||
furi_hal_ibutton_emulate_set_next(level_duration_get_duration(level));
|
const bool level = level_duration_get_level(level_duration);
|
||||||
|
|
||||||
if(level_duration_get_level(level)) {
|
furi_hal_ibutton_emulate_set_next(level);
|
||||||
furi_hal_ibutton_pin_high();
|
furi_hal_ibutton_pin_write(level);
|
||||||
} else {
|
|
||||||
furi_hal_ibutton_pin_low();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ibutton_worker_emulate_timer_start(iButtonWorker* worker) {
|
void ibutton_worker_emulate_timer_start(iButtonWorker* worker) {
|
||||||
@ -266,7 +263,7 @@ void ibutton_worker_emulate_timer_start(iButtonWorker* worker) {
|
|||||||
protocol_dict_set_data(worker->protocols, worker->protocol_to_encode, key_id, key_size);
|
protocol_dict_set_data(worker->protocols, worker->protocol_to_encode, key_id, key_size);
|
||||||
protocol_dict_encoder_start(worker->protocols, worker->protocol_to_encode);
|
protocol_dict_encoder_start(worker->protocols, worker->protocol_to_encode);
|
||||||
|
|
||||||
furi_hal_ibutton_start_drive();
|
furi_hal_ibutton_pin_configure();
|
||||||
furi_hal_ibutton_emulate_start(0, ibutton_worker_emulate_timer_cb, worker);
|
furi_hal_ibutton_emulate_start(0, ibutton_worker_emulate_timer_cb, worker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
|
||||||
#include "one_wire_host.h"
|
#include "one_wire_host.h"
|
||||||
#include "one_wire_host_timing.h"
|
#include "one_wire_host_timing.h"
|
||||||
|
|
||||||
struct OneWireHost {
|
struct OneWireHost {
|
||||||
// global search state
|
const GpioPin* gpio_pin;
|
||||||
unsigned char saved_rom[8];
|
unsigned char saved_rom[8]; /** < global search state */
|
||||||
uint8_t last_discrepancy;
|
uint8_t last_discrepancy;
|
||||||
uint8_t last_family_discrepancy;
|
uint8_t last_family_discrepancy;
|
||||||
bool last_device_flag;
|
bool last_device_flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
OneWireHost* onewire_host_alloc() {
|
OneWireHost* onewire_host_alloc(const GpioPin* gpio_pin) {
|
||||||
OneWireHost* host = malloc(sizeof(OneWireHost));
|
OneWireHost* host = malloc(sizeof(OneWireHost));
|
||||||
|
host->gpio_pin = gpio_pin;
|
||||||
onewire_host_reset_search(host);
|
onewire_host_reset_search(host);
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
@ -23,49 +24,47 @@ void onewire_host_free(OneWireHost* host) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool onewire_host_reset(OneWireHost* host) {
|
bool onewire_host_reset(OneWireHost* host) {
|
||||||
UNUSED(host);
|
|
||||||
uint8_t r;
|
uint8_t r;
|
||||||
uint8_t retries = 125;
|
uint8_t retries = 125;
|
||||||
|
|
||||||
// wait until the gpio is high
|
// wait until the gpio is high
|
||||||
furi_hal_ibutton_pin_high();
|
furi_hal_gpio_write(host->gpio_pin, true);
|
||||||
do {
|
do {
|
||||||
if(--retries == 0) return 0;
|
if(--retries == 0) return 0;
|
||||||
furi_delay_us(2);
|
furi_delay_us(2);
|
||||||
} while(!furi_hal_ibutton_pin_get_level());
|
} while(!furi_hal_gpio_read(host->gpio_pin));
|
||||||
|
|
||||||
// pre delay
|
// pre delay
|
||||||
furi_delay_us(OWH_RESET_DELAY_PRE);
|
furi_delay_us(OWH_RESET_DELAY_PRE);
|
||||||
|
|
||||||
// drive low
|
// drive low
|
||||||
furi_hal_ibutton_pin_low();
|
furi_hal_gpio_write(host->gpio_pin, false);
|
||||||
furi_delay_us(OWH_RESET_DRIVE);
|
furi_delay_us(OWH_RESET_DRIVE);
|
||||||
|
|
||||||
// release
|
// release
|
||||||
furi_hal_ibutton_pin_high();
|
furi_hal_gpio_write(host->gpio_pin, true);
|
||||||
furi_delay_us(OWH_RESET_RELEASE);
|
furi_delay_us(OWH_RESET_RELEASE);
|
||||||
|
|
||||||
// read and post delay
|
// read and post delay
|
||||||
r = !furi_hal_ibutton_pin_get_level();
|
r = !furi_hal_gpio_read(host->gpio_pin);
|
||||||
furi_delay_us(OWH_RESET_DELAY_POST);
|
furi_delay_us(OWH_RESET_DELAY_POST);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onewire_host_read_bit(OneWireHost* host) {
|
bool onewire_host_read_bit(OneWireHost* host) {
|
||||||
UNUSED(host);
|
|
||||||
bool result;
|
bool result;
|
||||||
|
|
||||||
// drive low
|
// drive low
|
||||||
furi_hal_ibutton_pin_low();
|
furi_hal_gpio_write(host->gpio_pin, false);
|
||||||
furi_delay_us(OWH_READ_DRIVE);
|
furi_delay_us(OWH_READ_DRIVE);
|
||||||
|
|
||||||
// release
|
// release
|
||||||
furi_hal_ibutton_pin_high();
|
furi_hal_gpio_write(host->gpio_pin, true);
|
||||||
furi_delay_us(OWH_READ_RELEASE);
|
furi_delay_us(OWH_READ_RELEASE);
|
||||||
|
|
||||||
// read and post delay
|
// read and post delay
|
||||||
result = furi_hal_ibutton_pin_get_level();
|
result = furi_hal_gpio_read(host->gpio_pin);
|
||||||
furi_delay_us(OWH_READ_DELAY_POST);
|
furi_delay_us(OWH_READ_DELAY_POST);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -90,22 +89,21 @@ void onewire_host_read_bytes(OneWireHost* host, uint8_t* buffer, uint16_t count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onewire_host_write_bit(OneWireHost* host, bool value) {
|
void onewire_host_write_bit(OneWireHost* host, bool value) {
|
||||||
UNUSED(host);
|
|
||||||
if(value) {
|
if(value) {
|
||||||
// drive low
|
// drive low
|
||||||
furi_hal_ibutton_pin_low();
|
furi_hal_gpio_write(host->gpio_pin, false);
|
||||||
furi_delay_us(OWH_WRITE_1_DRIVE);
|
furi_delay_us(OWH_WRITE_1_DRIVE);
|
||||||
|
|
||||||
// release
|
// release
|
||||||
furi_hal_ibutton_pin_high();
|
furi_hal_gpio_write(host->gpio_pin, true);
|
||||||
furi_delay_us(OWH_WRITE_1_RELEASE);
|
furi_delay_us(OWH_WRITE_1_RELEASE);
|
||||||
} else {
|
} else {
|
||||||
// drive low
|
// drive low
|
||||||
furi_hal_ibutton_pin_low();
|
furi_hal_gpio_write(host->gpio_pin, false);
|
||||||
furi_delay_us(OWH_WRITE_0_DRIVE);
|
furi_delay_us(OWH_WRITE_0_DRIVE);
|
||||||
|
|
||||||
// release
|
// release
|
||||||
furi_hal_ibutton_pin_high();
|
furi_hal_gpio_write(host->gpio_pin, true);
|
||||||
furi_delay_us(OWH_WRITE_0_RELEASE);
|
furi_delay_us(OWH_WRITE_0_RELEASE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,13 +121,13 @@ void onewire_host_skip(OneWireHost* host) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onewire_host_start(OneWireHost* host) {
|
void onewire_host_start(OneWireHost* host) {
|
||||||
UNUSED(host);
|
furi_hal_gpio_write(host->gpio_pin, true);
|
||||||
furi_hal_ibutton_start_drive();
|
furi_hal_gpio_init(host->gpio_pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onewire_host_stop(OneWireHost* host) {
|
void onewire_host_stop(OneWireHost* host) {
|
||||||
UNUSED(host);
|
furi_hal_gpio_write(host->gpio_pin, true);
|
||||||
furi_hal_ibutton_stop();
|
furi_hal_gpio_init(host->gpio_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onewire_host_reset_search(OneWireHost* host) {
|
void onewire_host_reset_search(OneWireHost* host) {
|
||||||
@ -150,7 +148,7 @@ void onewire_host_target_search(OneWireHost* host, uint8_t family_code) {
|
|||||||
host->last_device_flag = false;
|
host->last_device_flag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t onewire_host_search(OneWireHost* host, uint8_t* newAddr, OneWireHostSearchMode mode) {
|
uint8_t onewire_host_search(OneWireHost* host, uint8_t* new_addr, OneWireHostSearchMode mode) {
|
||||||
uint8_t id_bit_number;
|
uint8_t id_bit_number;
|
||||||
uint8_t last_zero, rom_byte_number, search_result;
|
uint8_t last_zero, rom_byte_number, search_result;
|
||||||
uint8_t id_bit, cmp_id_bit;
|
uint8_t id_bit, cmp_id_bit;
|
||||||
@ -259,7 +257,7 @@ uint8_t onewire_host_search(OneWireHost* host, uint8_t* newAddr, OneWireHostSear
|
|||||||
host->last_family_discrepancy = 0;
|
host->last_family_discrepancy = 0;
|
||||||
search_result = false;
|
search_result = false;
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < 8; i++) newAddr[i] = host->saved_rom[i];
|
for(int i = 0; i < 8; i++) new_addr[i] = host->saved_rom[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return search_result;
|
return search_result;
|
||||||
|
@ -22,10 +22,10 @@ typedef struct OneWireHost OneWireHost;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate onewire host bus
|
* Allocate onewire host bus
|
||||||
* @param gpio
|
* @param pin
|
||||||
* @return OneWireHost*
|
* @return OneWireHost*
|
||||||
*/
|
*/
|
||||||
OneWireHost* onewire_host_alloc();
|
OneWireHost* onewire_host_alloc(const GpioPin* gpio_pin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deallocate onewire host bus
|
* Deallocate onewire host bus
|
||||||
@ -114,7 +114,7 @@ void onewire_host_target_search(OneWireHost* host, uint8_t family_code);
|
|||||||
* @param mode
|
* @param mode
|
||||||
* @return uint8_t
|
* @return uint8_t
|
||||||
*/
|
*/
|
||||||
uint8_t onewire_host_search(OneWireHost* host, uint8_t* newAddr, OneWireHostSearchMode mode);
|
uint8_t onewire_host_search(OneWireHost* host, uint8_t* new_addr, OneWireHostSearchMode mode);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ typedef enum {
|
|||||||
} OneWireSlaveError;
|
} OneWireSlaveError;
|
||||||
|
|
||||||
struct OneWireSlave {
|
struct OneWireSlave {
|
||||||
|
const GpioPin* gpio_pin;
|
||||||
OneWireSlaveError error;
|
OneWireSlaveError error;
|
||||||
OneWireDevice* device;
|
OneWireDevice* device;
|
||||||
OneWireSlaveResultCallback result_cb;
|
OneWireSlaveResultCallback result_cb;
|
||||||
@ -35,15 +36,15 @@ struct OneWireSlave {
|
|||||||
|
|
||||||
/*********************** PRIVATE ***********************/
|
/*********************** PRIVATE ***********************/
|
||||||
|
|
||||||
uint32_t onewire_slave_wait_while_gpio_is(OneWireSlave* bus, uint32_t time, const bool pin_value) {
|
static uint32_t
|
||||||
UNUSED(bus);
|
onewire_slave_wait_while_gpio_is(OneWireSlave* bus, uint32_t time, const bool pin_value) {
|
||||||
uint32_t start = DWT->CYCCNT;
|
uint32_t start = DWT->CYCCNT;
|
||||||
uint32_t time_ticks = time * furi_hal_cortex_instructions_per_microsecond();
|
uint32_t time_ticks = time * furi_hal_cortex_instructions_per_microsecond();
|
||||||
uint32_t time_captured;
|
uint32_t time_captured;
|
||||||
|
|
||||||
do { //-V1044
|
do { //-V1044
|
||||||
time_captured = DWT->CYCCNT;
|
time_captured = DWT->CYCCNT;
|
||||||
if(furi_hal_ibutton_pin_get_level() != pin_value) {
|
if(furi_hal_gpio_read(bus->gpio_pin) != pin_value) {
|
||||||
uint32_t remaining_time = time_ticks - (time_captured - start);
|
uint32_t remaining_time = time_ticks - (time_captured - start);
|
||||||
remaining_time /= furi_hal_cortex_instructions_per_microsecond();
|
remaining_time /= furi_hal_cortex_instructions_per_microsecond();
|
||||||
return remaining_time;
|
return remaining_time;
|
||||||
@ -53,14 +54,14 @@ uint32_t onewire_slave_wait_while_gpio_is(OneWireSlave* bus, uint32_t time, cons
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onewire_slave_show_presence(OneWireSlave* bus) {
|
static bool onewire_slave_show_presence(OneWireSlave* bus) {
|
||||||
// wait while master delay presence check
|
// wait while master delay presence check
|
||||||
onewire_slave_wait_while_gpio_is(bus, OWS_PRESENCE_TIMEOUT, true);
|
onewire_slave_wait_while_gpio_is(bus, OWS_PRESENCE_TIMEOUT, true);
|
||||||
|
|
||||||
// show presence
|
// show presence
|
||||||
furi_hal_ibutton_pin_low();
|
furi_hal_gpio_write(bus->gpio_pin, false);
|
||||||
furi_delay_us(OWS_PRESENCE_MIN);
|
furi_delay_us(OWS_PRESENCE_MIN);
|
||||||
furi_hal_ibutton_pin_high();
|
furi_hal_gpio_write(bus->gpio_pin, true);
|
||||||
|
|
||||||
// somebody also can show presence
|
// somebody also can show presence
|
||||||
const uint32_t wait_low_time = OWS_PRESENCE_MAX - OWS_PRESENCE_MIN;
|
const uint32_t wait_low_time = OWS_PRESENCE_MAX - OWS_PRESENCE_MIN;
|
||||||
@ -74,7 +75,7 @@ bool onewire_slave_show_presence(OneWireSlave* bus) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onewire_slave_receive_bit(OneWireSlave* bus) {
|
static bool onewire_slave_receive_bit(OneWireSlave* bus) {
|
||||||
// wait while bus is low
|
// wait while bus is low
|
||||||
uint32_t time = OWS_SLOT_MAX;
|
uint32_t time = OWS_SLOT_MAX;
|
||||||
time = onewire_slave_wait_while_gpio_is(bus, time, false);
|
time = onewire_slave_wait_while_gpio_is(bus, time, false);
|
||||||
@ -98,7 +99,7 @@ bool onewire_slave_receive_bit(OneWireSlave* bus) {
|
|||||||
return (time > 0);
|
return (time > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onewire_slave_send_bit(OneWireSlave* bus, bool value) {
|
static bool onewire_slave_send_bit(OneWireSlave* bus, bool value) {
|
||||||
const bool write_zero = !value;
|
const bool write_zero = !value;
|
||||||
|
|
||||||
// wait while bus is low
|
// wait while bus is low
|
||||||
@ -119,7 +120,7 @@ bool onewire_slave_send_bit(OneWireSlave* bus, bool value) {
|
|||||||
|
|
||||||
// choose write time
|
// choose write time
|
||||||
if(write_zero) {
|
if(write_zero) {
|
||||||
furi_hal_ibutton_pin_low();
|
furi_hal_gpio_write(bus->gpio_pin, false);
|
||||||
time = OWS_WRITE_ZERO;
|
time = OWS_WRITE_ZERO;
|
||||||
} else {
|
} else {
|
||||||
time = OWS_READ_MAX;
|
time = OWS_READ_MAX;
|
||||||
@ -127,12 +128,12 @@ bool onewire_slave_send_bit(OneWireSlave* bus, bool value) {
|
|||||||
|
|
||||||
// hold line for ZERO or ONE time
|
// hold line for ZERO or ONE time
|
||||||
furi_delay_us(time);
|
furi_delay_us(time);
|
||||||
furi_hal_ibutton_pin_high();
|
furi_hal_gpio_write(bus->gpio_pin, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onewire_slave_cmd_search_rom(OneWireSlave* bus) {
|
static void onewire_slave_cmd_search_rom(OneWireSlave* bus) {
|
||||||
const uint8_t key_bytes = 8;
|
const uint8_t key_bytes = 8;
|
||||||
uint8_t* key = onewire_device_get_id_p(bus->device);
|
uint8_t* key = onewire_device_get_id_p(bus->device);
|
||||||
|
|
||||||
@ -151,7 +152,7 @@ void onewire_slave_cmd_search_rom(OneWireSlave* bus) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onewire_slave_receive_and_process_cmd(OneWireSlave* bus) {
|
static bool onewire_slave_receive_and_process_cmd(OneWireSlave* bus) {
|
||||||
uint8_t cmd;
|
uint8_t cmd;
|
||||||
onewire_slave_receive(bus, &cmd, 1);
|
onewire_slave_receive(bus, &cmd, 1);
|
||||||
|
|
||||||
@ -178,14 +179,14 @@ bool onewire_slave_receive_and_process_cmd(OneWireSlave* bus) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onewire_slave_bus_start(OneWireSlave* bus) {
|
static bool onewire_slave_bus_start(OneWireSlave* bus) {
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
if(bus->device == NULL) {
|
if(bus->device == NULL) {
|
||||||
result = false;
|
result = false;
|
||||||
} else {
|
} else {
|
||||||
FURI_CRITICAL_ENTER();
|
FURI_CRITICAL_ENTER();
|
||||||
furi_hal_ibutton_start_drive_in_isr();
|
furi_hal_gpio_init(bus->gpio_pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
||||||
bus->error = NO_ERROR;
|
bus->error = NO_ERROR;
|
||||||
|
|
||||||
if(onewire_slave_show_presence(bus)) {
|
if(onewire_slave_show_presence(bus)) {
|
||||||
@ -197,7 +198,7 @@ bool onewire_slave_bus_start(OneWireSlave* bus) {
|
|||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_hal_ibutton_start_interrupt_in_isr();
|
furi_hal_gpio_init(bus->gpio_pin, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow);
|
||||||
FURI_CRITICAL_EXIT();
|
FURI_CRITICAL_EXIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +208,7 @@ bool onewire_slave_bus_start(OneWireSlave* bus) {
|
|||||||
static void exti_cb(void* context) {
|
static void exti_cb(void* context) {
|
||||||
OneWireSlave* bus = context;
|
OneWireSlave* bus = context;
|
||||||
|
|
||||||
volatile bool input_state = furi_hal_ibutton_pin_get_level();
|
volatile bool input_state = furi_hal_gpio_read(bus->gpio_pin);
|
||||||
static uint32_t pulse_start = 0;
|
static uint32_t pulse_start = 0;
|
||||||
|
|
||||||
if(input_state) {
|
if(input_state) {
|
||||||
@ -234,8 +235,9 @@ static void exti_cb(void* context) {
|
|||||||
|
|
||||||
/*********************** PUBLIC ***********************/
|
/*********************** PUBLIC ***********************/
|
||||||
|
|
||||||
OneWireSlave* onewire_slave_alloc() {
|
OneWireSlave* onewire_slave_alloc(const GpioPin* gpio_pin) {
|
||||||
OneWireSlave* bus = malloc(sizeof(OneWireSlave));
|
OneWireSlave* bus = malloc(sizeof(OneWireSlave));
|
||||||
|
bus->gpio_pin = gpio_pin;
|
||||||
bus->error = NO_ERROR;
|
bus->error = NO_ERROR;
|
||||||
bus->device = NULL;
|
bus->device = NULL;
|
||||||
bus->result_cb = NULL;
|
bus->result_cb = NULL;
|
||||||
@ -249,14 +251,15 @@ void onewire_slave_free(OneWireSlave* bus) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onewire_slave_start(OneWireSlave* bus) {
|
void onewire_slave_start(OneWireSlave* bus) {
|
||||||
furi_hal_ibutton_add_interrupt(exti_cb, bus);
|
furi_hal_gpio_add_int_callback(bus->gpio_pin, exti_cb, bus);
|
||||||
furi_hal_ibutton_start_interrupt();
|
furi_hal_gpio_write(bus->gpio_pin, true);
|
||||||
|
furi_hal_gpio_init(bus->gpio_pin, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onewire_slave_stop(OneWireSlave* bus) {
|
void onewire_slave_stop(OneWireSlave* bus) {
|
||||||
UNUSED(bus);
|
furi_hal_gpio_write(bus->gpio_pin, true);
|
||||||
furi_hal_ibutton_stop();
|
furi_hal_gpio_init(bus->gpio_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
furi_hal_ibutton_remove_interrupt();
|
furi_hal_gpio_remove_int_callback(bus->gpio_pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onewire_slave_attach(OneWireSlave* bus, OneWireDevice* device) {
|
void onewire_slave_attach(OneWireSlave* bus, OneWireDevice* device) {
|
||||||
@ -282,7 +285,7 @@ void onewire_slave_set_result_callback(
|
|||||||
bool onewire_slave_send(OneWireSlave* bus, const uint8_t* address, const uint8_t data_length) {
|
bool onewire_slave_send(OneWireSlave* bus, const uint8_t* address, const uint8_t data_length) {
|
||||||
uint8_t bytes_sent = 0;
|
uint8_t bytes_sent = 0;
|
||||||
|
|
||||||
furi_hal_ibutton_pin_high();
|
furi_hal_gpio_write(bus->gpio_pin, true);
|
||||||
|
|
||||||
// bytes loop
|
// bytes loop
|
||||||
for(; bytes_sent < data_length; ++bytes_sent) {
|
for(; bytes_sent < data_length; ++bytes_sent) {
|
||||||
@ -304,7 +307,7 @@ bool onewire_slave_send(OneWireSlave* bus, const uint8_t* address, const uint8_t
|
|||||||
bool onewire_slave_receive(OneWireSlave* bus, uint8_t* data, const uint8_t data_length) {
|
bool onewire_slave_receive(OneWireSlave* bus, uint8_t* data, const uint8_t data_length) {
|
||||||
uint8_t bytes_received = 0;
|
uint8_t bytes_received = 0;
|
||||||
|
|
||||||
furi_hal_ibutton_pin_high();
|
furi_hal_gpio_write(bus->gpio_pin, true);
|
||||||
|
|
||||||
for(; bytes_received < data_length; ++bytes_received) {
|
for(; bytes_received < data_length; ++bytes_received) {
|
||||||
uint8_t value = 0;
|
uint8_t value = 0;
|
||||||
|
@ -19,10 +19,10 @@ typedef void (*OneWireSlaveResultCallback)(void* context);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate onewire slave
|
* Allocate onewire slave
|
||||||
* @param pin
|
* @param gpio_pin
|
||||||
* @return OneWireSlave*
|
* @return OneWireSlave*
|
||||||
*/
|
*/
|
||||||
OneWireSlave* onewire_slave_alloc();
|
OneWireSlave* onewire_slave_alloc(const GpioPin* gpio_pin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free onewire slave
|
* Free onewire slave
|
||||||
|
Loading…
Reference in New Issue
Block a user