diff --git a/applications/ibutton/ibutton.cpp b/applications/ibutton/ibutton.cpp index 94023e57a..a9bf79ff3 100644 --- a/applications/ibutton/ibutton.cpp +++ b/applications/ibutton/ibutton.cpp @@ -1,11 +1,15 @@ #include "ibutton.h" #include "ibutton_mode_dallas_read.h" #include "ibutton_mode_dallas_emulate.h" +#include "ibutton_mode_cyfral_read.h" +#include "ibutton_mode_cyfral_emulate.h" // start app void AppiButton::run() { mode[0] = new AppiButtonModeDallasRead(this); mode[1] = new AppiButtonModeDallasEmulate(this); + mode[2] = new AppiButtonModeCyfralRead(this); + mode[3] = new AppiButtonModeCyfralEmulate(this); switch_to_mode(0); @@ -21,7 +25,7 @@ void AppiButton::run() { AppiButtonEvent event; while(1) { - if(get_event(&event, 100)) { + if(get_event(&event, 20)) { if(event.type == AppiButtonEvent::EventTypeKey) { // press events if(event.value.input.state && event.value.input.input == InputBack) { @@ -60,6 +64,46 @@ void AppiButton::render(CanvasApi* canvas) { mode[state.mode_index]->render(canvas, &state); } +void AppiButton::render_dallas_list(CanvasApi* canvas, AppiButtonState* state) { + const uint8_t buffer_size = 50; + char buf[buffer_size]; + for(uint8_t i = 0; i < state->dallas_address_count; i++) { + snprintf( + buf, + buffer_size, + "%s[%u] %x:%x:%x:%x:%x:%x:%x:%x", + (i == state->dallas_address_index) ? "> " : "", + i + 1, + state->dallas_address[i][0], + state->dallas_address[i][1], + state->dallas_address[i][2], + state->dallas_address[i][3], + state->dallas_address[i][4], + state->dallas_address[i][5], + state->dallas_address[i][6], + state->dallas_address[i][7]); + canvas->draw_str(canvas, 2, 37 + i * 12, buf); + } +} + +void AppiButton::render_cyfral_list(CanvasApi* canvas, AppiButtonState* state) { + const uint8_t buffer_size = 50; + char buf[buffer_size]; + for(uint8_t i = 0; i < state->cyfral_address_count; i++) { + snprintf( + buf, + buffer_size, + "%s[%u] %x:%x:%x:%x", + (i == state->cyfral_address_index) ? "> " : "", + i + 1, + state->cyfral_address[i][0], + state->cyfral_address[i][1], + state->cyfral_address[i][2], + state->cyfral_address[i][3]); + canvas->draw_str(canvas, 2, 37 + i * 12, buf); + } +} + void AppiButton::blink_red() { gpio_write(red_led_record, 0); delay(10); @@ -92,12 +136,34 @@ void AppiButton::decrease_mode() { release_state(); } +void AppiButton::increase_dallas_address() { + if(state.dallas_address_index < (state.dallas_address_count - 1)) { + state.dallas_address_index++; + } +} + +void AppiButton::decrease_dallas_address() { + if(state.dallas_address_index > 0) { + state.dallas_address_index--; + } +} + +void AppiButton::increase_cyfral_address() { + if(state.cyfral_address_index < (state.cyfral_address_count - 1)) { + state.cyfral_address_index++; + } +} + +void AppiButton::decrease_cyfral_address() { + if(state.cyfral_address_index > 0) { + state.cyfral_address_index--; + } +} + void AppiButton::switch_to_mode(uint8_t mode_index) { - acquire_state(); mode[state.mode_index]->release(); state.mode_index = mode_index; mode[state.mode_index]->acquire(); - release_state(); } // app enter function diff --git a/applications/ibutton/ibutton.h b/applications/ibutton/ibutton.h index a99fc186c..599bcc208 100644 --- a/applications/ibutton/ibutton.h +++ b/applications/ibutton/ibutton.h @@ -8,13 +8,28 @@ typedef uint8_t event_t; class AppiButtonState { public: // state data - // test key = {0x01, 0xFD, 0x0E, 0x84, 0x01, 0x00, 0x00, 0xDB}; - uint8_t dallas_address[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static const uint8_t dallas_address_count = 3; + uint8_t dallas_address[dallas_address_count][8] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x41, 0xCE, 0x67, 0x0F, 0x00, 0x00, 0xB6}, + {0x01, 0xFD, 0x0E, 0x84, 0x01, 0x00, 0x00, 0xDB}}; + + uint8_t dallas_address_index; + + static const uint8_t cyfral_address_count = 3; + uint8_t cyfral_address[cyfral_address_count][4] = { + {0x00, 0x00, 0x00, 0x00}, + {0xBB, 0xBB, 0x7B, 0xBD}, + {0x7B, 0xDE, 0x7B, 0xDE}}; + uint8_t cyfral_address_index; + uint8_t mode_index; // state initializer AppiButtonState() { mode_index = 0; + dallas_address_index = 0; + cyfral_address_index = 0; } }; @@ -41,16 +56,22 @@ public: const GpioPin* red_led_record; const GpioPin* green_led_record; - static const uint8_t modes_count = 2; + static const uint8_t modes_count = 4; AppTemplateMode* mode[modes_count]; void run(); void render(CanvasApi* canvas); + void render_dallas_list(CanvasApi* canvas, AppiButtonState* state); + void render_cyfral_list(CanvasApi* canvas, AppiButtonState* state); void blink_red(); void blink_green(); void increase_mode(); void decrease_mode(); + void increase_dallas_address(); + void decrease_dallas_address(); + void increase_cyfral_address(); + void decrease_cyfral_address(); void switch_to_mode(uint8_t mode_index); }; \ No newline at end of file diff --git a/applications/ibutton/ibutton_mode_cyfral_emulate.h b/applications/ibutton/ibutton_mode_cyfral_emulate.h new file mode 100644 index 000000000..1ef92091d --- /dev/null +++ b/applications/ibutton/ibutton_mode_cyfral_emulate.h @@ -0,0 +1,55 @@ +#pragma once +#include "ibutton.h" +#include "cyfral_emulator.h" + +class AppiButtonModeCyfralEmulate : public AppTemplateMode { +public: + const char* name = "cyfral emulate"; + AppiButton* app; + CyfralEmulator* cyfral_emulator; + + void event(AppiButtonEvent* event, AppiButtonState* state); + void render(CanvasApi* canvas, AppiButtonState* state); + void acquire(); + void release(); + + AppiButtonModeCyfralEmulate(AppiButton* parent_app) { + app = parent_app; + + // TODO open record + const GpioPin* one_wire_pin_record = &ibutton_gpio; + cyfral_emulator = new CyfralEmulator(one_wire_pin_record); + }; +}; + +void AppiButtonModeCyfralEmulate::event(AppiButtonEvent* event, AppiButtonState* state) { + if(event->type == AppiButtonEvent::EventTypeTick) { + // repeat key sending 8 times + cyfral_emulator->send(state->cyfral_address[state->cyfral_address_index], 4, 8); + app->blink_green(); + + } else if(event->type == AppiButtonEvent::EventTypeKey) { + if(event->value.input.state && event->value.input.input == InputUp) { + app->decrease_cyfral_address(); + } + + if(event->value.input.state && event->value.input.input == InputDown) { + app->increase_cyfral_address(); + } + } +} + +void AppiButtonModeCyfralEmulate::render(CanvasApi* canvas, AppiButtonState* state) { + canvas->set_font(canvas, FontSecondary); + canvas->draw_str(canvas, 2, 25, "< Cyfral emulate"); + + app->render_cyfral_list(canvas, state); +} + +void AppiButtonModeCyfralEmulate::acquire() { + cyfral_emulator->start(); +} + +void AppiButtonModeCyfralEmulate::release() { + cyfral_emulator->stop(); +} \ No newline at end of file diff --git a/applications/ibutton/ibutton_mode_cyfral_read.h b/applications/ibutton/ibutton_mode_cyfral_read.h new file mode 100644 index 000000000..68f4cbb8c --- /dev/null +++ b/applications/ibutton/ibutton_mode_cyfral_read.h @@ -0,0 +1,53 @@ +#pragma once +#include "ibutton.h" +#include "cyfral_reader.h" + +class AppiButtonModeCyfralRead : public AppTemplateMode { +public: + const char* name = "cyfral read"; + AppiButton* app; + CyfralReader* reader; + + void event(AppiButtonEvent* event, AppiButtonState* state); + void render(CanvasApi* canvas, AppiButtonState* state); + void acquire(); + void release(); + + AppiButtonModeCyfralRead(AppiButton* parent_app) { + app = parent_app; + reader = new CyfralReader(ADC1, ADC_CHANNEL_14); + }; +}; + +void AppiButtonModeCyfralRead::event(AppiButtonEvent* event, AppiButtonState* state) { + if(event->type == AppiButtonEvent::EventTypeTick) { + uint8_t data[8]; + if(reader->read(data, 4)) { + memcpy(app->state.cyfral_address[app->state.cyfral_address_index], data, 4); + app->blink_green(); + } + } else if(event->type == AppiButtonEvent::EventTypeKey) { + if(event->value.input.state && event->value.input.input == InputUp) { + app->decrease_cyfral_address(); + } + + if(event->value.input.state && event->value.input.input == InputDown) { + app->increase_cyfral_address(); + } + } +} + +void AppiButtonModeCyfralRead::render(CanvasApi* canvas, AppiButtonState* state) { + canvas->set_font(canvas, FontSecondary); + canvas->draw_str(canvas, 2, 25, "< Cyfral read >"); + + app->render_cyfral_list(canvas, state); +} + +void AppiButtonModeCyfralRead::acquire() { + reader->start(); +} + +void AppiButtonModeCyfralRead::release() { + reader->stop(); +} \ No newline at end of file diff --git a/applications/ibutton/ibutton_mode_dallas_emulate.h b/applications/ibutton/ibutton_mode_dallas_emulate.h index 0ed185461..1e5abbba5 100644 --- a/applications/ibutton/ibutton_mode_dallas_emulate.h +++ b/applications/ibutton/ibutton_mode_dallas_emulate.h @@ -1,59 +1,56 @@ #pragma once #include "ibutton.h" #include "one_wire_slave_gpio.h" +#include "one_wire_device_ds_1990.h" class AppiButtonModeDallasEmulate : public AppTemplateMode { public: const char* name = "dallas emulate"; AppiButton* app; OneWireGpioSlave* onewire_slave; + DS1990 key; void event(AppiButtonEvent* event, AppiButtonState* state); void render(CanvasApi* canvas, AppiButtonState* state); void acquire(); void release(); - AppiButtonModeDallasEmulate(AppiButton* parent_app) { + AppiButtonModeDallasEmulate(AppiButton* parent_app) + : key(1, 2, 3, 4, 5, 6, 7) { app = parent_app; // TODO open record const GpioPin* one_wire_pin_record = &ibutton_gpio; onewire_slave = new OneWireGpioSlave(one_wire_pin_record); + onewire_slave->attach(key); }; }; void AppiButtonModeDallasEmulate::event(AppiButtonEvent* event, AppiButtonState* state) { if(event->type == AppiButtonEvent::EventTypeTick) { - app->blink_red(); - /*if(onewire_slave->emulate(state->dallas_address, 8)) { + onewire_slave->detach(key); + memcpy(key.id_storage, state->dallas_address[state->dallas_address_index], 8); + onewire_slave->attach(key); + + if(onewire_slave->emulate()) { app->blink_green(); - } else { - - }*/ + } + } else if(event->type == AppiButtonEvent::EventTypeKey) { + if(event->value.input.state && event->value.input.input == InputUp) { + app->decrease_dallas_address(); + } + + if(event->value.input.state && event->value.input.input == InputDown) { + app->increase_dallas_address(); + } } } void AppiButtonModeDallasEmulate::render(CanvasApi* canvas, AppiButtonState* state) { canvas->set_font(canvas, FontSecondary); - canvas->draw_str(canvas, 2, 25, "< dallas emulate"); - canvas->draw_str(canvas, 2, 37, "unimplemented"); - { - const uint8_t buffer_size = 32; - char buf[buffer_size]; - snprintf( - buf, - buffer_size, - "%x:%x:%x:%x:%x:%x:%x:%x", - state->dallas_address[0], - state->dallas_address[1], - state->dallas_address[2], - state->dallas_address[3], - state->dallas_address[4], - state->dallas_address[5], - state->dallas_address[6], - state->dallas_address[7]); - canvas->draw_str(canvas, 2, 50, buf); - } + canvas->draw_str(canvas, 2, 25, "< Dallas emulate >"); + + app->render_dallas_list(canvas, state); } void AppiButtonModeDallasEmulate::acquire() { diff --git a/applications/ibutton/ibutton_mode_dallas_read.h b/applications/ibutton/ibutton_mode_dallas_read.h index 639d7df30..765ed1276 100644 --- a/applications/ibutton/ibutton_mode_dallas_read.h +++ b/applications/ibutton/ibutton_mode_dallas_read.h @@ -1,6 +1,7 @@ #pragma once #include "ibutton.h" #include "one_wire_gpio.h" +#include "maxim_crc.h" class AppiButtonModeDallasRead : public AppTemplateMode { public: @@ -20,8 +21,6 @@ public: const GpioPin* one_wire_pin_record = &ibutton_gpio; onewire = new OneWireGpio(one_wire_pin_record); }; - - uint8_t crc_8(uint8_t* buffer, uint8_t count); }; void AppiButtonModeDallasRead::event(AppiButtonEvent* event, AppiButtonState* state) { @@ -48,67 +47,32 @@ void AppiButtonModeDallasRead::event(AppiButtonEvent* event, AppiButtonState* st } printf("\n"); - printf("crc8: %x\n", crc_8(address, 7)); + printf("crc8: %x\n", maxim_crc8(address, 7)); - if(crc_8(address, 8) == 0) { + if(maxim_crc8(address, 8) == 0) { printf("CRC valid\n"); - memcpy(app->state.dallas_address, address, 8); + memcpy(app->state.dallas_address[app->state.dallas_address_index], address, 8); app->blink_green(); } else { printf("CRC invalid\n"); } } else { } + } else if(event->type == AppiButtonEvent::EventTypeKey) { + if(event->value.input.state && event->value.input.input == InputUp) { + app->decrease_dallas_address(); + } + + if(event->value.input.state && event->value.input.input == InputDown) { + app->increase_dallas_address(); + } } } void AppiButtonModeDallasRead::render(CanvasApi* canvas, AppiButtonState* state) { canvas->set_font(canvas, FontSecondary); - canvas->draw_str(canvas, 2, 25, "dallas read >"); - canvas->draw_str(canvas, 2, 37, "touch me, iButton"); - { - const uint8_t buffer_size = 32; - char buf[buffer_size]; - snprintf( - buf, - buffer_size, - "%x:%x:%x:%x:%x:%x:%x:%x", - state->dallas_address[0], - state->dallas_address[1], - state->dallas_address[2], - state->dallas_address[3], - state->dallas_address[4], - state->dallas_address[5], - state->dallas_address[6], - state->dallas_address[7]); - canvas->draw_str(canvas, 2, 50, buf); - } -} - -uint8_t AppiButtonModeDallasRead::crc_8(uint8_t* buffer, uint8_t count) { - const uint8_t maxim_crc8_table[256] = { - 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 157, 195, - 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, - 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, 190, 224, 2, 92, 223, 129, - 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, 70, 24, 250, 164, 39, 121, 155, 197, - 132, 218, 56, 102, 229, 187, 89, 7, 219, 133, 103, 57, 186, 228, 6, 88, 25, 71, - 165, 251, 120, 38, 196, 154, 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, - 198, 152, 122, 36, 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, - 231, 185, 140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205, - 17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80, 175, 241, - 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238, 50, 108, 142, 208, - 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, 202, 148, 118, 40, 171, 245, - 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, 87, 9, 235, 181, 54, 104, 138, 212, - 149, 203, 41, 119, 244, 170, 72, 22, 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, - 151, 201, 74, 20, 246, 168, 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, - 215, 137, 107, 53}; - - uint8_t crc = 0; - - while(count--) { - crc = maxim_crc8_table[(crc ^ *buffer++)]; - } - return crc; + canvas->draw_str(canvas, 2, 25, "Dallas read >"); + app->render_dallas_list(canvas, state); } void AppiButtonModeDallasRead::acquire() { diff --git a/applications/ibutton/one_wire_slave_gpio.h b/applications/ibutton/one_wire_slave_gpio.h deleted file mode 100644 index f6d11e3fa..000000000 --- a/applications/ibutton/one_wire_slave_gpio.h +++ /dev/null @@ -1,177 +0,0 @@ -#pragma once -#include "flipper.h" -#include "flipper_v2.h" -#include "one_wire_timings.h" - -class OneWireGpioSlave { -private: - const GpioPin* gpio; - -public: - OneWireGpioSlave(const GpioPin* one_wire_gpio); - ~OneWireGpioSlave(); - void start(void); - void stop(void); - bool emulate(uint8_t* buffer, uint8_t length); - - bool check_reset(void); - bool show_presence(void); - bool receive_and_process_cmd(void); - bool receive(uint8_t* data, const uint8_t data_length); - bool receiveBit(void); - - bool overdrive_mode = false; - - OneWiteTimeType wait_while_gpio(volatile OneWiteTimeType retries, const bool pin_value); -}; - -OneWireGpioSlave::OneWireGpioSlave(const GpioPin* one_wire_gpio) { - gpio = one_wire_gpio; -} - -OneWireGpioSlave::~OneWireGpioSlave() { - stop(); -} - -void OneWireGpioSlave::start(void) { - gpio_init(gpio, GpioModeOutputOpenDrain); -} - -void OneWireGpioSlave::stop(void) { - gpio_init(gpio, GpioModeAnalog); -} - -bool OneWireGpioSlave::emulate(uint8_t* buffer, uint8_t length) { - if(!check_reset()) { - printf("reset error\n"); - return false; - } - - if(!show_presence()) { - printf("presence error\n"); - return false; - } - - if(!receive_and_process_cmd()) { - printf("receive_and_process_cmd error\n"); - return false; - } - - printf("ok\n"); - return true; -} - -OneWiteTimeType OneWireGpioSlave::wait_while_gpio(OneWiteTimeType time, const bool pin_value) { - uint32_t start = DWT->CYCCNT; - uint32_t time_ticks = time * (SystemCoreClock / 1000000.0f); - - while(((DWT->CYCCNT - start) < time_ticks)) { - if(gpio_read(gpio) != pin_value) { - uint32_t time = (DWT->CYCCNT - start); - time /= (SystemCoreClock / 1000000.0f); - return time; - } - } - - return 0; -} - -bool OneWireGpioSlave::check_reset(void) { - while(gpio_read(gpio) == true) { - } - - /*if(wait_while_gpio(OneWireEmulateTiming::RESET_TIMEOUT * 20, true) == 0) { - printf("RESET_TIMEOUT\n"); - return false; - }*/ - - const OneWiteTimeType time_remaining = - wait_while_gpio(OneWireEmulateTiming::RESET_MAX[0], false); - - if(time_remaining == 0) { - return false; - } - - if(overdrive_mode && ((OneWireEmulateTiming::RESET_MAX[0] - - OneWireEmulateTiming::RESET_MIN[0]) <= time_remaining)) { - // normal reset detected - overdrive_mode = false; - }; - - bool result = (time_remaining <= OneWireEmulateTiming::RESET_MAX[0]) && - time_remaining >= OneWireEmulateTiming::RESET_MIN[overdrive_mode]; - - return result; -} - -bool OneWireGpioSlave::show_presence(void) { - wait_while_gpio(OneWireEmulateTiming::PRESENCE_TIMEOUT, true); - gpio_write(gpio, false); - delay_us(OneWireEmulateTiming::PRESENCE_MIN[overdrive_mode]); - gpio_write(gpio, true); - /*OneWiteTimeType wait_time = OneWireEmulateTiming::PRESENCE_MAX[overdrive_mode] - - OneWireEmulateTiming::PRESENCE_MIN[overdrive_mode]; - if(wait_while_gpio(wait_time, false) == 0) { - return false; - }*/ - - return true; -} - -bool OneWireGpioSlave::receive_and_process_cmd(void) { - uint8_t cmd; - receive(&cmd, 1); - printf("cmd %x\n", cmd); - return false; -} - -bool OneWireGpioSlave::receiveBit(void) { - // wait while bus is HIGH - OneWiteTimeType time = OneWireEmulateTiming::SLOT_MAX[overdrive_mode]; - time = wait_while_gpio(time, true); - if(time == 0) { - printf("RESET_IN_PROGRESS\n"); - return false; - } - /*while ((DIRECT_READ(pin_baseReg, pin_bitMask) == 0) && (--retries != 0)); - if (retries == 0) - { - _error = Error::RESET_IN_PROGRESS; - return false; - }*/ - - // wait while bus is LOW - time = OneWireEmulateTiming::MSG_HIGH_TIMEOUT; - time = wait_while_gpio(time, false); - if(time == 0) { - printf("TIMEOUT_HIGH\n"); - return false; - } - /*while ((DIRECT_READ(pin_baseReg, pin_bitMask) != 0) && (--retries != 0)); - if (retries == 0) - { - _error = Error::AWAIT_TIMESLOT_TIMEOUT_HIGH; - return false; - }*/ - - // wait a specific time to do a read (data is valid by then), // first difference to inner-loop of write() - time = OneWireEmulateTiming::READ_MIN[overdrive_mode]; - time = wait_while_gpio(time, true); - //while ((DIRECT_READ(pin_baseReg, pin_bitMask) == 0) && (--retries != 0)); - - return (time > 0); -} - -bool OneWireGpioSlave::receive(uint8_t* data, const uint8_t data_length) { - uint8_t bytes_received = 0; - for(; bytes_received < data_length; ++bytes_received) { - uint8_t value = 0; - - for(uint8_t bitMask = 0x01; bitMask != 0; bitMask <<= 1) { - if(receiveBit()) value |= bitMask; - } - - data[bytes_received] = value; - } - return (bytes_received != data_length); -} \ No newline at end of file diff --git a/firmware/Makefile b/firmware/Makefile index eec67bf3b..bf2b3363a 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -14,7 +14,7 @@ include $(PROJECT_ROOT)/lib/lib.mk TARGET ?= f2 TARGET_DIR = targets/$(TARGET) include $(TARGET_DIR)/target.mk -CFLAGS += -Itargets/Inc +CFLAGS += -Itargets/api-hal-include include $(PROJECT_ROOT)/make/git.mk include $(PROJECT_ROOT)/make/toolchain.mk diff --git a/firmware/targets/Inc/api-hal-boot.h b/firmware/targets/api-hal-include/api-hal-boot.h similarity index 100% rename from firmware/targets/Inc/api-hal-boot.h rename to firmware/targets/api-hal-include/api-hal-boot.h diff --git a/firmware/targets/f2/api-hal/api-hal-delay.h b/firmware/targets/api-hal-include/api-hal-delay.h similarity index 100% rename from firmware/targets/f2/api-hal/api-hal-delay.h rename to firmware/targets/api-hal-include/api-hal-delay.h diff --git a/firmware/targets/Inc/api-hal-power.h b/firmware/targets/api-hal-include/api-hal-power.h similarity index 100% rename from firmware/targets/Inc/api-hal-power.h rename to firmware/targets/api-hal-include/api-hal-power.h diff --git a/firmware/targets/Inc/api-hal-uid.h b/firmware/targets/api-hal-include/api-hal-uid.h similarity index 100% rename from firmware/targets/Inc/api-hal-uid.h rename to firmware/targets/api-hal-include/api-hal-uid.h diff --git a/firmware/targets/Inc/api-hal-vcp.h b/firmware/targets/api-hal-include/api-hal-vcp.h similarity index 100% rename from firmware/targets/Inc/api-hal-vcp.h rename to firmware/targets/api-hal-include/api-hal-vcp.h diff --git a/firmware/targets/Inc/api-hal.h b/firmware/targets/api-hal-include/api-hal.h similarity index 100% rename from firmware/targets/Inc/api-hal.h rename to firmware/targets/api-hal-include/api-hal.h diff --git a/firmware/targets/f3/Inc/stm32wbxx_it.h b/firmware/targets/f3/Inc/stm32wbxx_it.h index f2ef1d600..d5351b83a 100644 --- a/firmware/targets/f3/Inc/stm32wbxx_it.h +++ b/firmware/targets/f3/Inc/stm32wbxx_it.h @@ -55,6 +55,7 @@ void UsageFault_Handler(void); void DebugMon_Handler(void); void EXTI1_IRQHandler(void); void EXTI2_IRQHandler(void); +void ADC1_IRQHandler(void); void USB_LP_IRQHandler(void); void COMP_IRQHandler(void); void EXTI9_5_IRQHandler(void); diff --git a/firmware/targets/f3/Makefile b/firmware/targets/f3/Makefile index 8d28cb58b..da113a2d2 100644 --- a/firmware/targets/f3/Makefile +++ b/firmware/targets/f3/Makefile @@ -1,5 +1,5 @@ ########################################################################################################################## -# File automatically-generated by tool: [projectgenerator] version: [3.10.0-B14] date: [Thu Nov 05 17:53:24 MSK 2020] +# File automatically-generated by tool: [projectgenerator] version: [3.10.0-B14] date: [Mon Nov 23 12:04:48 VLAT 2020] ########################################################################################################################## # ------------------------------------------------ diff --git a/firmware/targets/f3/Src/adc.c b/firmware/targets/f3/Src/adc.c index 048e24624..8d39940b7 100644 --- a/firmware/targets/f3/Src/adc.c +++ b/firmware/targets/f3/Src/adc.c @@ -54,7 +54,7 @@ void MX_ADC1_Init(void) } /** Configure Regular Channel */ - sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; + sConfig.Channel = ADC_CHANNEL_14; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5; sConfig.SingleDiff = ADC_SINGLE_ENDED; @@ -70,6 +70,7 @@ void MX_ADC1_Init(void) void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; if(adcHandle->Instance==ADC1) { /* USER CODE BEGIN ADC1_MspInit 0 */ @@ -77,6 +78,19 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle) /* USER CODE END ADC1_MspInit 0 */ /* ADC1 clock enable */ __HAL_RCC_ADC_CLK_ENABLE(); + + __HAL_RCC_GPIOC_CLK_ENABLE(); + /**ADC1 GPIO Configuration + PC5 ------> ADC1_IN14 + */ + GPIO_InitStruct.Pin = RFID_RF_IN_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(RFID_RF_IN_GPIO_Port, &GPIO_InitStruct); + + /* ADC1 interrupt Init */ + HAL_NVIC_SetPriority(ADC1_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(ADC1_IRQn); /* USER CODE BEGIN ADC1_MspInit 1 */ /* USER CODE END ADC1_MspInit 1 */ @@ -93,6 +107,14 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle) /* USER CODE END ADC1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_ADC_CLK_DISABLE(); + + /**ADC1 GPIO Configuration + PC5 ------> ADC1_IN14 + */ + HAL_GPIO_DeInit(RFID_RF_IN_GPIO_Port, RFID_RF_IN_Pin); + + /* ADC1 interrupt Deinit */ + HAL_NVIC_DisableIRQ(ADC1_IRQn); /* USER CODE BEGIN ADC1_MspDeInit 1 */ /* USER CODE END ADC1_MspDeInit 1 */ diff --git a/firmware/targets/f3/Src/stm32wbxx_it.c b/firmware/targets/f3/Src/stm32wbxx_it.c index ae42583a1..3d4de2697 100644 --- a/firmware/targets/f3/Src/stm32wbxx_it.c +++ b/firmware/targets/f3/Src/stm32wbxx_it.c @@ -57,6 +57,7 @@ /* External variables --------------------------------------------------------*/ extern PCD_HandleTypeDef hpcd_USB_FS; +extern ADC_HandleTypeDef hadc1; extern COMP_HandleTypeDef hcomp1; extern TIM_HandleTypeDef htim1; extern TIM_HandleTypeDef htim2; @@ -193,6 +194,20 @@ void EXTI2_IRQHandler(void) /* USER CODE END EXTI2_IRQn 1 */ } +/** + * @brief This function handles ADC1 global interrupt. + */ +void ADC1_IRQHandler(void) +{ + /* USER CODE BEGIN ADC1_IRQn 0 */ + + /* USER CODE END ADC1_IRQn 0 */ + HAL_ADC_IRQHandler(&hadc1); + /* USER CODE BEGIN ADC1_IRQn 1 */ + + /* USER CODE END ADC1_IRQn 1 */ +} + /** * @brief This function handles USB low priority interrupt, USB wake-up interrupt through EXTI line 28. */ diff --git a/firmware/targets/f3/Src/tim.c b/firmware/targets/f3/Src/tim.c index f5448cb07..2cc45ff71 100644 --- a/firmware/targets/f3/Src/tim.c +++ b/firmware/targets/f3/Src/tim.c @@ -238,7 +238,7 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) HAL_GPIO_Init(IR_RX_GPIO_Port, &GPIO_InitStruct); /* TIM2 interrupt Init */ - HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0); + HAL_NVIC_SetPriority(TIM2_IRQn, 5, 0); HAL_NVIC_EnableIRQ(TIM2_IRQn); /* USER CODE BEGIN TIM2_MspInit 1 */ diff --git a/firmware/targets/f3/api-hal/api-hal-delay.h b/firmware/targets/f3/api-hal/api-hal-delay.h deleted file mode 100644 index 9ab51e248..000000000 --- a/firmware/targets/f3/api-hal/api-hal-delay.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include "main.h" - -void delay(float milliseconds); -void delay_us(float microseconds); -void delay_us_init_DWT(void); diff --git a/firmware/targets/f3/f3.ioc b/firmware/targets/f3/f3.ioc index ffc9f8b56..317652e59 100644 --- a/firmware/targets/f3/f3.ioc +++ b/firmware/targets/f3/f3.ioc @@ -1,560 +1,565 @@ #MicroXplorer Configuration settings - do not modify -PA11.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH -PB13.GPIOParameters=GPIO_Label -RCC.USART1Freq_Value=64000000 -RF1.Locked=true -SPI1.VirtualType=VM_MASTER -PB10.GPIO_PuPd=GPIO_PULLUP -RF1.Signal=RF_RF1 -SPI2.VirtualType=VM_MASTER -VP_ADC1_TempSens_Input.Mode=IN-TempSens -PC12.Locked=true -TIM1.IPParameters=Channel-Output Compare1 CH1N,Channel-PWM Generation3 CH3N -PC12.Signal=GPIO_Output -PB14.GPIO_Label=iBTN -PC6.GPIO_Label=DISPLAY_DI -VP_RTC_VS_RTC_Activate.Mode=RTC_Enabled -RCC.RTCFreq_Value=32768 -PA3.GPIOParameters=GPIO_Speed,PinState,GPIO_Label,GPIO_ModeDefaultOutputPP -PA6.GPIO_Label=PA6 -COMP1.Hysteresis=COMP_HYSTERESIS_HIGH -PD0.Locked=true -PC5.Mode=INP -VP_COMP1_VS_VREFINT14.Signal=COMP1_VS_VREFINT14 -USART1.IPParameters=VirtualMode-Asynchronous -PA3.GPIO_Speed=GPIO_SPEED_FREQ_LOW -PB13.Signal=TIM1_CH1N -PA2.GPIOParameters=GPIO_Speed,PinState,GPIO_Label,GPIO_ModeDefaultOutputPP -PC15-OSC32_OUT.GPIO_Label=QUARTZ_32MHZ_OUT -PinOutPanel.RotationAngle=0 -RCC.MCO1PinFreq_Value=64000000 -RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK -SH.GPXTI13.0=GPIO_EXTI13 -RCC.LPTIM1Freq_Value=64000000 -NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false -FREERTOS.configENABLE_FPU=1 -NVIC.EXTI1_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true -SH.S_TIM16_CH1.ConfNb=1 -SPI1.Direction=SPI_DIRECTION_2LINES -TIM2.IPParameters=Channel-Input_Capture1_from_TI1,ICPolarity_CH1,AutoReloadPreload,Prescaler,Channel-Input_Capture2_from_TI1 -RCC.APB2TimFreq_Value=64000000 -PCC.Ble.PowerLevel=Min -COMP1.Mode=COMP_POWERMODE_MEDIUMSPEED -PB6.Signal=USART1_TX -PB6.Mode=Asynchronous -SPI1.CalculateBaudRate=4.0 MBits/s -PC3.Signal=GPIO_Analog -PD0.Signal=GPIO_Output -VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT -RCC.PREFETCH_ENABLE=1 -PB13.Locked=true -NVIC.EXTI15_10_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true -ProjectManager.ProjectBuild=false -NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false -PB2.Signal=GPIO_Analog -PB3.Mode=Full_Duplex_Master -PH3-BOOT0.Locked=true -PA8.Locked=true -PD1.GPIOParameters=GPIO_Label -RCC.RTCClockSelection=RCC_RTCCLKSOURCE_LSE -SH.GPXTI12.0=GPIO_EXTI12 -PD1.GPIO_Label=SPI_D_SCK -PB12.GPIO_Label=BUTTON_RIGHT -ProjectManager.FirmwarePackage=STM32Cube FW_WB V1.9.0 -VP_ADC1_Vref_Input.Mode=IN-Vrefint -MxDb.Version=DB.6.0.0 -PB0.GPIOParameters=GPIO_Label -PA1.GPIOParameters=GPIO_Speed,PinState,GPIO_Label,GPIO_ModeDefaultOutputPP -ProjectManager.BackupPrevious=false -VP_SYS_VS_tim17.Signal=SYS_VS_tim17 -PC4.GPIO_Label=CC1101_G0 -FREERTOS.HEAP_NUMBER=4 -PB1.GPIO_Label=BUTTON_DOWN -NVIC.TIM2_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true -SPI1.DataSize=SPI_DATASIZE_8BIT -PE4.GPIO_Label=NFC_CS -SPI2.CalculateBaudRate=4.0 MBits/s -PA8.Signal=GPXTI8 -RCC.PLLRCLKFreq_Value=64000000 -SH.GPXTI11.ConfNb=1 -PB6.Locked=true -NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false -ProjectManager.HalAssertFull=false -ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_2CYCLES_5 -VP_TIM1_VS_ClockSourceINT.Mode=Internal -TIM16.Pulse=145 -PA0.Signal=S_TIM2_CH1 -PH3-BOOT0.Signal=GPIO_Analog -NVIC.HSEM_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true -PB9.Signal=TIM1_CH3N -Mcu.Package=VFQFPN68 -TIM2.Prescaler=64-1 -PB1.Signal=GPXTI1 -NVIC.TimeBase=TIM1_TRG_COM_TIM17_IRQn -SPI2.Mode=SPI_MODE_MASTER -PA2.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD -SH.GPXTI11.0=GPIO_EXTI11 -SH.GPXTI8.0=GPIO_EXTI8 -PA14.Locked=true -SH.GPXTI8.ConfNb=1 -NVIC.TimeBaseIP=TIM17 -RCC.LSCOPinFreq_Value=32000 -PA10.Signal=I2C1_SDA -VP_RTC_VS_RTC_Calendar.Mode=RTC_Calendar -FREERTOS.FootprintOK=true -PA1.PinState=GPIO_PIN_SET -PA5.GPIOParameters=GPIO_Label -NVIC.USB_LP_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true -PB14.GPIOParameters=GPIO_Label -VP_HSEM_VS_HSEM.Mode=HSEM_Activate -NVIC.EXTI2_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true -RCC.PLLPoutputFreq_Value=64000000 -RCC.APB1TimFreq_Value=64000000 -FREERTOS.configGENERATE_RUN_TIME_STATS=1 -NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false -RCC.LPUART1Freq_Value=64000000 -PB10.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI -PB13.Mode=Output Compare1 CH1N -TIM16.Prescaler=500 - 1 -PC15-OSC32_OUT.GPIOParameters=GPIO_Label -I2C1.CustomTiming=Disabled -PA4.GPIO_Label=PA4 -ProjectManager.CustomerFirmwarePackage= -PC4.GPIOParameters=GPIO_Label -RCC.HSI48_VALUE=48000000 -PC2.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING -PA6.GPIOParameters=GPIO_Label -SH.GPXTI10.0=GPIO_EXTI10 -PCC.Ble.Mode=NOT_SELECTED -RCC.PLLQoutputFreq_Value=64000000 -ProjectManager.ProjectFileName=f3.ioc -RCC.SMPSFreq_Value=8000000 -PA3.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD -FREERTOS.Tasks01=defaultTask,24,1024,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;app_main,8,1024,app,As external,NULL,Dynamic,NULL,NULL -ADC1.Rank-0\#ChannelRegularConversion=1 -PA15.GPIOParameters=GPIO_PuPd,GPIO_Label -Mcu.PinsNb=64 -PC11.Locked=true -VP_SYS_VS_tim17.Mode=TIM17 -ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag,master -PC13.Locked=true +ADC1.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_14 +ADC1.ContinuousConvMode=DISABLE +ADC1.EnableAnalogWatchDog1=false +ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag,master,EnableAnalogWatchDog1,ContinuousConvMode +ADC1.NbrOfConversionFlag=1 ADC1.OffsetNumber-0\#ChannelRegularConversion=ADC_OFFSET_NONE -RCC.HCLK3Freq_Value=64000000 -PA9.GPIO_Label=I2C_SCL -PC13.Signal=GPXTI13 -FREERTOS.configCHECK_FOR_STACK_OVERFLOW=1 -PC2.Signal=GPXTI2 -PC6.Signal=GPIO_Output -PB11.GPIO_Label=BUTTON_LEFT -PD1.Signal=SPI2_SCK -SH.S_TIM16_CH1.0=TIM16_CH1,PWM Generation1 CH1 -VP_TIM16_VS_ClockSourceINT.Mode=Enable_Timer -SPI1.CLKPhase=SPI_PHASE_2EDGE -OSC_IN.Locked=true -RCC.HCLK2Freq_Value=32000000 -PC0.Signal=GPIO_Analog -PC14-OSC32_IN.Signal=RCC_OSC32_IN -PC11.GPIOParameters=PinState,GPIO_Label -Mcu.Pin62=VP_TIM16_VS_ClockSourceINT -Mcu.Pin63=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS -Mcu.Pin60=VP_TIM1_VS_ClockSourceINT -Mcu.Pin61=VP_TIM2_VS_ClockSourceINT -PD0.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH -PC3.GPIOParameters=GPIO_Label -PB8.GPIO_Label=SPEAKER -PA11.Locked=true -PA15.Locked=true -PA8.GPIO_Label=RFID_PULL -PC15-OSC32_OUT.Locked=true -Mcu.Pin59=VP_SYS_VS_tim17 -SH.GPXTI2.ConfNb=1 -Mcu.Pin57=VP_RTC_VS_RTC_Activate -Mcu.Pin58=VP_RTC_VS_RTC_Calendar -PC12.PinState=GPIO_PIN_SET -USB_DEVICE.PRODUCT_STRING_CDC_FS=Flipper Control Virtual ComPort -Mcu.Pin51=PB7 -Mcu.Pin52=VP_ADC1_TempSens_Input -Mcu.Pin50=PB6 -Mcu.Pin55=VP_FREERTOS_VS_CMSIS_V2 -Mcu.Pin56=VP_HSEM_VS_HSEM -Mcu.Pin53=VP_ADC1_Vref_Input -Mcu.Pin54=VP_COMP1_VS_VREFINT14 -PC6.Locked=true -PA9.Signal=I2C1_SCL -VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT -I2C1.Timing=0x10707DBC -PB11.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI -PB9.Locked=true -PB5.Locked=true -OSC_IN.Signal=RCC_OSC_IN -Mcu.Pin48=PB4 -Mcu.Pin49=PB5 -RCC.PLLSAI1PoutputFreq_Value=48000000 -Mcu.Pin46=PD1 -Mcu.Pin47=PB3 -PB10.Signal=GPXTI10 -PB14.Signal=GPIO_Analog -PA5.Signal=GPIO_Analog -Mcu.Pin40=PA14 -Mcu.Pin41=PA15 -Mcu.Pin44=PC12 -Mcu.Pin45=PD0 -Mcu.Pin42=PC10 -Mcu.Pin43=PC11 -RCC.Cortex2Freq_Value=32000000 -ProjectManager.LastFirmware=true -PD1.Mode=TX_Only_Simplex_Unidirect_Master -Mcu.Pin37=PA11 -PB4.GPIO_Label=SPI_R_MISO -PCC.Ble.DataLength=6 -Mcu.Pin38=PA12 -Mcu.Pin35=PC6 -PB15.GPIO_Label=SPI_D_MOSI -RCC.I2C1Freq_Value=64000000 -Mcu.Pin36=PA10 -SPI1.Mode=SPI_MODE_MASTER -Mcu.Pin39=PA13 -RCC.LCDFreq_Value=32768 -RCC.RNGFreq_Value=32000 -PC2.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI -VP_ADC1_TempSens_Input.Signal=ADC1_TempSens_Input -Mcu.Pin30=PE4 -NVIC.COMP_IRQn=true\:5\:0\:true\:false\:true\:false\:false\:true -PA1.GPIO_Label=LED_RED -Mcu.Pin33=PB14 -Mcu.Pin34=PB15 -Mcu.Pin31=PB12 -Mcu.Pin32=PB13 -PA9.Locked=true -VP_TIM16_VS_ClockSourceINT.Signal=TIM16_VS_ClockSourceINT -NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true -PC10.GPIOParameters=GPIO_Label -PA13.Mode=Serial_Wire -ProjectManager.FreePins=false -PB10.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING -RCC.LPTIM2Freq_Value=64000000 -Mcu.Pin26=OSC_OUT -Mcu.Pin27=OSC_IN -Mcu.Pin24=PB11 -ProjectManager.UnderRoot=false -Mcu.Pin25=RF1 -Mcu.Pin28=PB0 -Mcu.Pin29=PB1 -PB4.Locked=true -PA4.Signal=GPIO_Analog -Mcu.Pin22=PB2 -PB5.Signal=SPI1_MOSI -Mcu.Pin23=PB10 -Mcu.Pin20=PC4 +ADC1.Rank-0\#ChannelRegularConversion=1 +ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_2CYCLES_5 ADC1.master=1 -PA3.Locked=true -Mcu.Pin21=PC5 -PA5.GPIO_Label=PA5 -PA10.Locked=true -NVIC.ForceEnableDMAVector=true -OSC_IN.Mode=HSE-External-Oscillator -NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false -PC12.GPIO_Label=SD_CS -ProjectManager.CompilerOptimize=6 -PA11.Signal=USB_DM -ProjectManager.HeapSize=0x200 -PA0.GPIOParameters=GPIO_Label -Mcu.Pin15=PA5 -NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false -Mcu.Pin16=PA6 -Mcu.Pin13=PA3 -Mcu.Pin14=PA4 -Mcu.Pin19=PA9 -ProjectManager.ComputerToolchain=false -Mcu.Pin17=PA7 -Mcu.Pin18=PA8 -NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 -Mcu.Pin11=PA1 -Mcu.Pin12=PA2 -PD0.GPIOParameters=GPIO_Speed,PinState,GPIO_Label -Mcu.Pin10=PA0 -SH.GPXTI10.ConfNb=1 -USB_DEVICE.APP_RX_DATA_SIZE=512 -TIM2.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE -PC3.GPIO_Label=PC3 -PA3.PinState=GPIO_PIN_SET -PE4.PinState=GPIO_PIN_SET -RCC.PWRFreq_Value=64000000 -SPI2.DataSize=SPI_DATASIZE_8BIT -SH.GPXTI1.ConfNb=1 -PB12.GPIO_PuPd=GPIO_PULLUP -PD1.Locked=true -PB0.Signal=GPIO_Output -PA7.GPIOParameters=GPIO_Label -PC1.Signal=GPIO_Analog -PB12.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI +COMP1.Hysteresis=COMP_HYSTERESIS_HIGH +COMP1.IPParameters=TriggerMode,Hysteresis,Mode +COMP1.Mode=COMP_POWERMODE_MEDIUMSPEED +COMP1.TriggerMode=COMP_TRIGGERMODE_IT_RISING_FALLING +FREERTOS.FootprintOK=true +FREERTOS.HEAP_NUMBER=4 +FREERTOS.IPParameters=Tasks01,configTOTAL_HEAP_SIZE,HEAP_NUMBER,configUSE_TIMERS,configUSE_IDLE_HOOK,FootprintOK,configCHECK_FOR_STACK_OVERFLOW,configRECORD_STACK_HIGH_ADDRESS,configGENERATE_RUN_TIME_STATS,configENABLE_FPU +FREERTOS.Tasks01=defaultTask,24,1024,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;app_main,8,1024,app,As external,NULL,Dynamic,NULL,NULL +FREERTOS.configCHECK_FOR_STACK_OVERFLOW=1 +FREERTOS.configENABLE_FPU=1 +FREERTOS.configGENERATE_RUN_TIME_STATS=1 +FREERTOS.configRECORD_STACK_HIGH_ADDRESS=1 +FREERTOS.configTOTAL_HEAP_SIZE=40960 +FREERTOS.configUSE_IDLE_HOOK=1 +FREERTOS.configUSE_TIMERS=1 +File.Version=6 +GPIO.groupedBy=Show All +I2C1.CustomTiming=Disabled +I2C1.IPParameters=Timing,CustomTiming +I2C1.Timing=0x10707DBC +KeepUserPlacement=false Mcu.Family=STM32WB -SH.GPXTI1.0=GPIO_EXTI1 -ProjectManager.MainLocation=Src -OSC_OUT.GPIO_Label=QUARTZ_32KHZ_OUT -USB_DEVICE.CLASS_NAME_FS=CDC -RCC.SAI1Freq_Value=48000000 -RCC.CortexFreq_Value=64000000 -TIM2.Channel-Input_Capture1_from_TI1=TIM_CHANNEL_1 -ProjectManager.KeepUserCode=true -Mcu.UserName=STM32WB55RGVx -RCC.RFWKPFreq_Value=976.5625 -PC10.Signal=GPIO_Analog -RCC.PLLSAI1RoutputFreq_Value=48000000 -PC5.Locked=true -PA0.GPIO_Label=IR_RX -PA12.GPIOParameters=GPIO_Speed -ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_ADC1_Init-ADC1-false-HAL-true,4-MX_I2C1_Init-I2C1-false-HAL-true,5-MX_RTC_Init-RTC-false-HAL-true,6-MX_SPI1_Init-SPI1-false-HAL-true,7-MX_SPI2_Init-SPI2-false-HAL-true,8-MX_USART1_UART_Init-USART1-false-HAL-true,9-MX_USB_Device_Init-USB_DEVICE-false-HAL-false,10-MX_TIM1_Init-TIM1-false-HAL-true,11-MX_TIM2_Init-TIM2-false-HAL-true,12-MX_TIM16_Init-TIM16-false-HAL-true,13-MX_COMP1_Init-COMP1-false-HAL-true,14-MX_RF_Init-RF-false-HAL-true,0-MX_HSEM_Init-HSEM-false-HAL-true -PC0.GPIOParameters=GPIO_Label -PA9.GPIOParameters=GPIO_Speed,GPIO_Label -PA2.GPIO_Speed=GPIO_SPEED_FREQ_LOW -PH3-BOOT0.GPIO_Label=BOOT0 -PA11.GPIOParameters=GPIO_Speed -PD0.GPIO_Label=CC1101_CS -PC0.GPIO_Label=PC0 -PA11.Mode=Device -PB0.GPIO_Label=DISPLAY_RST -VP_RTC_VS_RTC_Calendar.Signal=RTC_VS_RTC_Calendar -PB11.GPIO_PuPd=GPIO_PULLUP -PC13.GPIO_Label=BUTTON_BACK -PB13.GPIO_Label=RFID_OUT -PB11.Signal=GPXTI11 -PB15.Signal=SPI2_MOSI -OSC_OUT.GPIOParameters=GPIO_Label -ProjectManager.StackSize=0x400 -PB5.GPIOParameters=GPIO_Label -VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2 -SH.GPXTI2.0=GPIO_EXTI2 -RCC.I2C3Freq_Value=64000000 +Mcu.IP0=ADC1 +Mcu.IP1=COMP1 +Mcu.IP10=SPI2 +Mcu.IP11=SYS +Mcu.IP12=TIM1 +Mcu.IP13=TIM2 +Mcu.IP14=TIM16 +Mcu.IP15=USART1 +Mcu.IP16=USB +Mcu.IP17=USB_DEVICE +Mcu.IP2=FREERTOS +Mcu.IP3=HSEM Mcu.IP4=I2C1 Mcu.IP5=NVIC -RCC.FCLKCortexFreq_Value=64000000 -USB_DEVICE.MANUFACTURER_STRING=Flipper -Mcu.IP2=FREERTOS -I2C1.IPParameters=Timing,CustomTiming -Mcu.IP3=HSEM -Mcu.IP0=ADC1 -PB4.GPIOParameters=GPIO_Label -PA15.GPIO_Label=DISPLAY_BACKLIGHT -PA12.Locked=true -Mcu.IP1=COMP1 -PA12.Signal=USB_DP -PE4.GPIOParameters=GPIO_Speed,PinState,GPIO_Label -Mcu.UserConstants= -RCC.VCOSAI1OutputFreq_Value=96000000 -TIM2.ICPolarity_CH1=TIM_INPUTCHANNELPOLARITY_FALLING -PC1.GPIOParameters=GPIO_Label -SH.GPXTI13.ConfNb=1 -Mcu.ThirdPartyNb=0 -PB1.GPIO_PuPd=GPIO_PULLUP -RCC.HCLKFreq_Value=64000000 +Mcu.IP6=RCC +Mcu.IP7=RF +Mcu.IP8=RTC +Mcu.IP9=SPI1 Mcu.IPNb=18 -ProjectManager.PreviousToolchain= -PB1.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING -PA8.GPIOParameters=GPIO_Label +Mcu.Name=STM32WB55RGVx +Mcu.Package=VFQFPN68 +Mcu.Pin0=PC13 +Mcu.Pin1=PC14-OSC32_IN +Mcu.Pin10=PA0 +Mcu.Pin11=PA1 +Mcu.Pin12=PA2 +Mcu.Pin13=PA3 +Mcu.Pin14=PA4 +Mcu.Pin15=PA5 +Mcu.Pin16=PA6 +Mcu.Pin17=PA7 +Mcu.Pin18=PA8 +Mcu.Pin19=PA9 +Mcu.Pin2=PC15-OSC32_OUT +Mcu.Pin20=PC4 +Mcu.Pin21=PC5 +Mcu.Pin22=PB2 +Mcu.Pin23=PB10 +Mcu.Pin24=PB11 +Mcu.Pin25=RF1 +Mcu.Pin26=OSC_OUT +Mcu.Pin27=OSC_IN +Mcu.Pin28=PB0 +Mcu.Pin29=PB1 +Mcu.Pin3=PH3-BOOT0 +Mcu.Pin30=PE4 +Mcu.Pin31=PB12 +Mcu.Pin32=PB13 +Mcu.Pin33=PB14 +Mcu.Pin34=PB15 +Mcu.Pin35=PC6 +Mcu.Pin36=PA10 +Mcu.Pin37=PA11 +Mcu.Pin38=PA12 +Mcu.Pin39=PA13 +Mcu.Pin4=PB8 +Mcu.Pin40=PA14 +Mcu.Pin41=PA15 +Mcu.Pin42=PC10 +Mcu.Pin43=PC11 +Mcu.Pin44=PC12 +Mcu.Pin45=PD0 +Mcu.Pin46=PD1 +Mcu.Pin47=PB3 +Mcu.Pin48=PB4 +Mcu.Pin49=PB5 +Mcu.Pin5=PB9 +Mcu.Pin50=PB6 +Mcu.Pin51=PB7 +Mcu.Pin52=VP_ADC1_TempSens_Input +Mcu.Pin53=VP_ADC1_Vref_Input +Mcu.Pin54=VP_COMP1_VS_VREFINT14 +Mcu.Pin55=VP_FREERTOS_VS_CMSIS_V2 +Mcu.Pin56=VP_HSEM_VS_HSEM +Mcu.Pin57=VP_RTC_VS_RTC_Activate +Mcu.Pin58=VP_RTC_VS_RTC_Calendar +Mcu.Pin59=VP_SYS_VS_tim17 Mcu.Pin6=PC0 +Mcu.Pin60=VP_TIM1_VS_ClockSourceINT +Mcu.Pin61=VP_TIM2_VS_ClockSourceINT +Mcu.Pin62=VP_TIM16_VS_ClockSourceINT +Mcu.Pin63=VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS Mcu.Pin7=PC1 Mcu.Pin8=PC2 Mcu.Pin9=PC3 -OSC_OUT.Mode=HSE-External-Oscillator -FREERTOS.IPParameters=Tasks01,configTOTAL_HEAP_SIZE,HEAP_NUMBER,configUSE_TIMERS,configUSE_IDLE_HOOK,FootprintOK,configCHECK_FOR_STACK_OVERFLOW,configRECORD_STACK_HIGH_ADDRESS,configGENERATE_RUN_TIME_STATS,configENABLE_FPU -OSC_OUT.Signal=RCC_OSC_OUT -RCC.AHBFreq_Value=64000000 -SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_16 -Mcu.Pin0=PC13 -Mcu.Pin1=PC14-OSC32_IN -GPIO.groupedBy=Show All -Mcu.Pin2=PC15-OSC32_OUT -Mcu.Pin3=PH3-BOOT0 -Mcu.Pin4=PB8 -Mcu.Pin5=PB9 -ADC1.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_TEMPSENSOR -RCC.HSE_VALUE=32000000 -RCC.FCLK2Freq_Value=32000000 -FREERTOS.configUSE_TIMERS=1 -NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false -PH3-BOOT0.GPIOParameters=GPIO_Label -Mcu.IP10=SPI2 -NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false -Mcu.IP12=TIM1 -Mcu.IP11=SYS -Mcu.IP17=USB_DEVICE -NVIC.TIM1_TRG_COM_TIM17_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true -PA2.PinState=GPIO_PIN_SET -Mcu.IP14=TIM16 -PB4.Mode=Full_Duplex_Master -Mcu.IP13=TIM2 -Mcu.IP16=USB -Mcu.IP15=USART1 -PC14-OSC32_IN.Mode=LSE-External-Oscillator -RCC.VCOInputFreq_Value=16000000 -PD0.PinState=GPIO_PIN_SET -PA14.Mode=Serial_Wire -PE4.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH -PC11.GPIO_Label=DISPLAY_CS -PB5.Mode=Full_Duplex_Master -File.Version=6 -PA10.GPIO_Label=I2C_SDA -PC13.GPIO_PuPd=GPIO_PULLUP -PB3.GPIOParameters=GPIO_Label -SH.S_TIM2_CH1.ConfNb=2 -PB7.Signal=USART1_RX -PB8.Locked=true -PE4.Signal=GPIO_Output -PB0.Locked=true -FREERTOS.configTOTAL_HEAP_SIZE=40960 -PC14-OSC32_IN.GPIOParameters=GPIO_Label -ProjectManager.ProjectName=f3 -RCC.APB3Freq_Value=16000000 -PA6.Signal=GPIO_Analog -TIM2.Channel-Input_Capture2_from_TI1=TIM_CHANNEL_2 -RCC.EnbaleCSS=true -ProjectManager.ToolChainLocation= -PA2.GPIO_Label=LED_GREEN -RCC.LSI_VALUE=32000 -PB11.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING -PA15.Signal=GPIO_Output -VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Signal=USB_DEVICE_VS_USB_DEVICE_CDC_FS -RCC.MSIOscState=DISABLED -SPI2.CLKPhase=SPI_PHASE_1EDGE -PA10.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH -PB5.GPIO_Label=SPI_R_MOSI -PC4.Locked=true -PC14-OSC32_IN.GPIO_Label=QUARTZ_32MHZ_IN -SPI2.Direction=SPI_DIRECTION_2LINES -PC5.Signal=COMP1_INP -SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_16 -OSC_IN.GPIO_Label=QUARTZ_32KHZ_IN -PC2.GPIO_Label=BUTTON_OK -PC14-OSC32_IN.Locked=true -PA12.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH -COMP1.TriggerMode=COMP_TRIGGERMODE_IT_RISING_FALLING -PB15.Locked=true -PB3.Locked=true -PB4.Signal=SPI1_MISO -RCC.PLLSAI1N=6 -PA3.Signal=GPIO_Output -PA2.Locked=true -PB3.GPIO_Label=SPI_R_SCK -VP_RTC_VS_RTC_Activate.Signal=RTC_VS_RTC_Activate -RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE -PC15-OSC32_OUT.Mode=LSE-External-Oscillator -SH.S_TIM2_CH1.1=TIM2_CH1,Input_Capture2_from_TI1 -SH.S_TIM2_CH1.0=TIM2_CH1,Input_Capture1_from_TI1 -PB8.GPIOParameters=GPIO_Label -PB9.GPIO_Label=IR_TX -PC10.GPIO_Label=PC10 -PA10.Mode=I2C -ProjectManager.NoMain=false -SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler,DataSize,CLKPhase -USB_DEVICE.VirtualModeFS=Cdc_FS -NVIC.SavedSvcallIrqHandlerGenerated=false -PC11.Signal=GPIO_Output -PC4.Signal=GPIO_Input -ProjectManager.DefaultFWLocation=true -VP_HSEM_VS_HSEM.Signal=HSEM_VS_HSEM -OSC_IN.GPIOParameters=GPIO_Label -PB12.Locked=true -ProjectManager.DeletePrevious=true -PB10.Locked=true -USB_DEVICE.IPParameters=VirtualMode,VirtualModeFS,CLASS_NAME_FS,MANUFACTURER_STRING,PRODUCT_STRING_CDC_FS,APP_RX_DATA_SIZE,APP_TX_DATA_SIZE -TIM16.Channel=TIM_CHANNEL_1 -RCC.AHB2CLKDivider=RCC_SYSCLK_DIV2 -RCC.FamilyName=M -PB9.GPIOParameters=GPIO_Label -PC12.GPIOParameters=GPIO_Speed,PinState,GPIO_Label -USART1.VirtualMode-Asynchronous=VM_ASYNC -PA13.Signal=SYS_JTMS-SWDIO -FREERTOS.configUSE_IDLE_HOOK=1 -VP_COMP1_VS_VREFINT14.Mode=VREFINT_14 -PA9.Mode=I2C -TIM1.Channel-Output\ Compare1\ CH1N=TIM_CHANNEL_1 -FREERTOS.configRECORD_STACK_HIGH_ADDRESS=1 -ProjectManager.TargetToolchain=Makefile -PB10.GPIO_Label=BUTTON_UP -VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Mode=CDC_FS -RCC.HCLKRFFreq_Value=16000000 -PC5.GPIOParameters=GPIO_Label -PB9.Mode=PWM Generation3 CH3N -PB2.GPIOParameters=GPIO_Label -SH.GPXTI12.ConfNb=1 -PE4.Locked=true -SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,BaudRatePrescaler,CLKPhase -PC2.Locked=true -ProjectManager.RegisterCallBack= -RCC.USBFreq_Value=48000000 -TIM1.Channel-PWM\ Generation3\ CH3N=TIM_CHANNEL_3 -PC15-OSC32_OUT.Signal=RCC_OSC32_OUT -PA1.Signal=GPIO_Output -PB1.Locked=true -RCC.SMPSCLockSelectionVirtual=RCC_SMPSCLKSOURCE_HSE -board=custom -RCC.VCOOutputFreq_Value=128000000 -RCC.SMPS1Freq_Value=16000000 -PB15.Mode=TX_Only_Simplex_Unidirect_Master -TIM16.Period=291 -NVIC.SavedSystickIrqHandlerGenerated=true -RCC.APB2Freq_Value=64000000 -PC11.PinState=GPIO_PIN_SET -COMP1.IPParameters=TriggerMode,Hysteresis,Mode +Mcu.PinsNb=64 +Mcu.ThirdPartyNb=0 +Mcu.UserConstants= +Mcu.UserName=STM32WB55RGVx MxCube.Version=6.0.1 -VP_TIM2_VS_ClockSourceINT.Mode=Internal -PC13.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI -PA1.GPIO_Speed=GPIO_SPEED_FREQ_LOW -RCC.PLLSAI1QoutputFreq_Value=48000000 -RCC.ADCFreq_Value=48000000 -PC1.GPIO_Label=PC1 -PA10.GPIOParameters=GPIO_Speed,GPIO_Label -VP_ADC1_Vref_Input.Signal=ADC1_Vref_Input -OSC_OUT.Locked=true -PA4.GPIOParameters=GPIO_Label -PC2.GPIO_PuPd=GPIO_PULLUP -PB15.GPIOParameters=GPIO_Label -RCC.IPParameters=ADCFreq_Value,AHB2CLKDivider,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,APB3Freq_Value,Cortex2Freq_Value,CortexFreq_Value,EnbaleCSS,FCLK2Freq_Value,FCLKCortexFreq_Value,FamilyName,HCLK2Freq_Value,HCLK3Freq_Value,HCLKFreq_Value,HCLKRFFreq_Value,HSE_VALUE,HSI48_VALUE,HSI_VALUE,I2C1Freq_Value,I2C3Freq_Value,LCDFreq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSI_VALUE,MCO1PinFreq_Value,MSIOscState,PLLM,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PLLSAI1N,PLLSAI1PoutputFreq_Value,PLLSAI1QoutputFreq_Value,PLLSAI1RoutputFreq_Value,PLLSourceVirtual,PREFETCH_ENABLE,PWRFreq_Value,RFWKPFreq_Value,RNGFreq_Value,RTCClockSelection,RTCFreq_Value,SAI1Freq_Value,SMPS1Freq_Value,SMPSCLockSelectionVirtual,SMPSFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,USART1Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAI1OutputFreq_Value -ProjectManager.AskForMigrate=true -Mcu.Name=STM32WB55RGVx -NVIC.SavedPendsvIrqHandlerGenerated=false -PA2.Signal=GPIO_Output -Mcu.IP8=RTC -VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2 -Mcu.IP9=SPI1 -Mcu.IP6=RCC -Mcu.IP7=RF -ProjectManager.CoupleFile=true -PB3.Signal=SPI1_SCK -RCC.SYSCLKFreq_VALUE=64000000 -PA7.GPIO_Label=PA7 -PA1.Locked=true -PA12.Mode=Device -PCC.Ble.ConnectionInterval=1000.0 -KeepUserPlacement=false -PC13.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING -PC5.GPIO_Label=RFID_RF_IN -PA13.Locked=true -RF1.Mode=RF1_Activate -PB7.Mode=Asynchronous +MxDb.Version=DB.6.0.0 +NVIC.ADC1_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.COMP_IRQn=true\:5\:0\:true\:false\:true\:false\:false\:true +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.EXTI15_10_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true +NVIC.EXTI1_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true +NVIC.EXTI2_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true NVIC.EXTI9_5_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true -USB_DEVICE.APP_TX_DATA_SIZE=512 -PA14.Signal=SYS_JTCK-SWCLK -PB2.GPIO_Label=PB2 -PC6.GPIOParameters=GPIO_Label -PB12.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING -RCC.HSI_VALUE=16000000 -ADC1.NbrOfConversionFlag=1 -RCC.PLLM=RCC_PLLM_DIV2 -PA15.GPIO_PuPd=GPIO_PULLDOWN -PB7.Locked=true -PB8.Signal=S_TIM16_CH1 -PA9.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH -TIM16.IPParameters=Channel,Pulse,Prescaler,Period -RCC.APB1Freq_Value=64000000 -PC12.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH -USB_DEVICE.VirtualMode=Cdc -PB11.Locked=true -ProjectManager.DeviceId=STM32WB55RGVx -PB12.Signal=GPXTI12 -ProjectManager.LibraryCopy=2 -PA3.GPIO_Label=LED_BLUE -PB1.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI -PA7.Signal=GPIO_Analog +NVIC.ForceEnableDMAVector=true +NVIC.HSEM_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false +NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false +NVIC.SavedPendsvIrqHandlerGenerated=false +NVIC.SavedSvcallIrqHandlerGenerated=false +NVIC.SavedSystickIrqHandlerGenerated=true +NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false +NVIC.TIM1_TRG_COM_TIM17_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true +NVIC.TIM2_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true +NVIC.TimeBase=TIM1_TRG_COM_TIM17_IRQn +NVIC.TimeBaseIP=TIM17 +NVIC.USB_LP_IRQn=true\:5\:0\:true\:false\:true\:true\:false\:true +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +OSC_IN.GPIOParameters=GPIO_Label +OSC_IN.GPIO_Label=QUARTZ_32KHZ_IN +OSC_IN.Locked=true +OSC_IN.Mode=HSE-External-Oscillator +OSC_IN.Signal=RCC_OSC_IN +OSC_OUT.GPIOParameters=GPIO_Label +OSC_OUT.GPIO_Label=QUARTZ_32KHZ_OUT +OSC_OUT.Locked=true +OSC_OUT.Mode=HSE-External-Oscillator +OSC_OUT.Signal=RCC_OSC_OUT +PA0.GPIOParameters=GPIO_Label +PA0.GPIO_Label=IR_RX +PA0.Signal=S_TIM2_CH1 +PA1.GPIOParameters=GPIO_Speed,PinState,GPIO_Label,GPIO_ModeDefaultOutputPP +PA1.GPIO_Label=LED_RED PA1.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD +PA1.GPIO_Speed=GPIO_SPEED_FREQ_LOW +PA1.Locked=true +PA1.PinState=GPIO_PIN_SET +PA1.Signal=GPIO_Output +PA10.GPIOParameters=GPIO_Speed,GPIO_Label +PA10.GPIO_Label=I2C_SDA +PA10.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH +PA10.Locked=true +PA10.Mode=I2C +PA10.Signal=I2C1_SDA +PA11.GPIOParameters=GPIO_Speed +PA11.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH +PA11.Locked=true +PA11.Mode=Device +PA11.Signal=USB_DM +PA12.GPIOParameters=GPIO_Speed +PA12.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH +PA12.Locked=true +PA12.Mode=Device +PA12.Signal=USB_DP +PA13.Locked=true +PA13.Mode=Serial_Wire +PA13.Signal=SYS_JTMS-SWDIO +PA14.Locked=true +PA14.Mode=Serial_Wire +PA14.Signal=SYS_JTCK-SWCLK +PA15.GPIOParameters=GPIO_PuPd,GPIO_Label +PA15.GPIO_Label=DISPLAY_BACKLIGHT +PA15.GPIO_PuPd=GPIO_PULLDOWN +PA15.Locked=true +PA15.Signal=GPIO_Output +PA2.GPIOParameters=GPIO_Speed,PinState,GPIO_Label,GPIO_ModeDefaultOutputPP +PA2.GPIO_Label=LED_GREEN +PA2.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD +PA2.GPIO_Speed=GPIO_SPEED_FREQ_LOW +PA2.Locked=true +PA2.PinState=GPIO_PIN_SET +PA2.Signal=GPIO_Output +PA3.GPIOParameters=GPIO_Speed,PinState,GPIO_Label,GPIO_ModeDefaultOutputPP +PA3.GPIO_Label=LED_BLUE +PA3.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD +PA3.GPIO_Speed=GPIO_SPEED_FREQ_LOW +PA3.Locked=true +PA3.PinState=GPIO_PIN_SET +PA3.Signal=GPIO_Output +PA4.GPIOParameters=GPIO_Label +PA4.GPIO_Label=PA4 +PA4.Signal=GPIO_Analog +PA5.GPIOParameters=GPIO_Label +PA5.GPIO_Label=PA5 +PA5.Signal=GPIO_Analog +PA6.GPIOParameters=GPIO_Label +PA6.GPIO_Label=PA6 +PA6.Signal=GPIO_Analog +PA7.GPIOParameters=GPIO_Label +PA7.GPIO_Label=PA7 +PA7.Signal=GPIO_Analog +PA8.GPIOParameters=GPIO_Label +PA8.GPIO_Label=RFID_PULL +PA8.Locked=true +PA8.Signal=GPXTI8 +PA9.GPIOParameters=GPIO_Speed,GPIO_Label +PA9.GPIO_Label=I2C_SCL +PA9.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH +PA9.Locked=true +PA9.Mode=I2C +PA9.Signal=I2C1_SCL +PB0.GPIOParameters=GPIO_Label +PB0.GPIO_Label=DISPLAY_RST +PB0.Locked=true +PB0.Signal=GPIO_Output +PB1.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI +PB1.GPIO_Label=BUTTON_DOWN +PB1.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING +PB1.GPIO_PuPd=GPIO_PULLUP +PB1.Locked=true +PB1.Signal=GPXTI1 +PB10.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI +PB10.GPIO_Label=BUTTON_UP +PB10.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING +PB10.GPIO_PuPd=GPIO_PULLUP +PB10.Locked=true +PB10.Signal=GPXTI10 +PB11.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI +PB11.GPIO_Label=BUTTON_LEFT +PB11.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING +PB11.GPIO_PuPd=GPIO_PULLUP +PB11.Locked=true +PB11.Signal=GPXTI11 +PB12.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI +PB12.GPIO_Label=BUTTON_RIGHT +PB12.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING +PB12.GPIO_PuPd=GPIO_PULLUP +PB12.Locked=true +PB12.Signal=GPXTI12 +PB13.GPIOParameters=GPIO_Label +PB13.GPIO_Label=RFID_OUT +PB13.Locked=true +PB13.Mode=Output Compare1 CH1N +PB13.Signal=TIM1_CH1N +PB14.GPIOParameters=GPIO_Label +PB14.GPIO_Label=iBTN +PB14.Signal=GPIO_Analog +PB15.GPIOParameters=GPIO_Label +PB15.GPIO_Label=SPI_D_MOSI +PB15.Locked=true +PB15.Mode=TX_Only_Simplex_Unidirect_Master +PB15.Signal=SPI2_MOSI +PB2.GPIOParameters=GPIO_Label +PB2.GPIO_Label=PB2 +PB2.Signal=GPIO_Analog +PB3.GPIOParameters=GPIO_Label +PB3.GPIO_Label=SPI_R_SCK +PB3.Locked=true +PB3.Mode=Full_Duplex_Master +PB3.Signal=SPI1_SCK +PB4.GPIOParameters=GPIO_Label +PB4.GPIO_Label=SPI_R_MISO +PB4.Locked=true +PB4.Mode=Full_Duplex_Master +PB4.Signal=SPI1_MISO +PB5.GPIOParameters=GPIO_Label +PB5.GPIO_Label=SPI_R_MOSI +PB5.Locked=true +PB5.Mode=Full_Duplex_Master +PB5.Signal=SPI1_MOSI +PB6.Locked=true +PB6.Mode=Asynchronous +PB6.Signal=USART1_TX +PB7.Locked=true +PB7.Mode=Asynchronous +PB7.Signal=USART1_RX +PB8.GPIOParameters=GPIO_Label +PB8.GPIO_Label=SPEAKER +PB8.Locked=true +PB8.Signal=S_TIM16_CH1 +PB9.GPIOParameters=GPIO_Label +PB9.GPIO_Label=IR_TX +PB9.Locked=true +PB9.Mode=PWM Generation3 CH3N +PB9.Signal=TIM1_CH3N +PC0.GPIOParameters=GPIO_Label +PC0.GPIO_Label=PC0 +PC0.Signal=GPIO_Analog +PC1.GPIOParameters=GPIO_Label +PC1.GPIO_Label=PC1 +PC1.Signal=GPIO_Analog +PC10.GPIOParameters=GPIO_Label +PC10.GPIO_Label=PC10 +PC10.Signal=GPIO_Analog +PC11.GPIOParameters=PinState,GPIO_Label +PC11.GPIO_Label=DISPLAY_CS +PC11.Locked=true +PC11.PinState=GPIO_PIN_SET +PC11.Signal=GPIO_Output +PC12.GPIOParameters=GPIO_Speed,PinState,GPIO_Label +PC12.GPIO_Label=SD_CS +PC12.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH +PC12.Locked=true +PC12.PinState=GPIO_PIN_SET +PC12.Signal=GPIO_Output +PC13.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI +PC13.GPIO_Label=BUTTON_BACK +PC13.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING +PC13.GPIO_PuPd=GPIO_PULLUP +PC13.Locked=true +PC13.Signal=GPXTI13 +PC14-OSC32_IN.GPIOParameters=GPIO_Label +PC14-OSC32_IN.GPIO_Label=QUARTZ_32MHZ_IN +PC14-OSC32_IN.Locked=true +PC14-OSC32_IN.Mode=LSE-External-Oscillator +PC14-OSC32_IN.Signal=RCC_OSC32_IN +PC15-OSC32_OUT.GPIOParameters=GPIO_Label +PC15-OSC32_OUT.GPIO_Label=QUARTZ_32MHZ_OUT +PC15-OSC32_OUT.Locked=true +PC15-OSC32_OUT.Mode=LSE-External-Oscillator +PC15-OSC32_OUT.Signal=RCC_OSC32_OUT +PC2.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultEXTI +PC2.GPIO_Label=BUTTON_OK +PC2.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING +PC2.GPIO_PuPd=GPIO_PULLUP +PC2.Locked=true +PC2.Signal=GPXTI2 +PC3.GPIOParameters=GPIO_Label +PC3.GPIO_Label=PC3 +PC3.Signal=GPIO_Analog +PC4.GPIOParameters=GPIO_Label +PC4.GPIO_Label=CC1101_G0 +PC4.Locked=true +PC4.Signal=GPIO_Input +PC5.GPIOParameters=GPIO_Label +PC5.GPIO_Label=RFID_RF_IN +PC5.Locked=true +PC5.Signal=SharedAnalog_PC5 +PC6.GPIOParameters=GPIO_Label +PC6.GPIO_Label=DISPLAY_DI +PC6.Locked=true +PC6.Signal=GPIO_Output +PCC.Ble.ConnectionInterval=1000.0 +PCC.Ble.DataLength=6 +PCC.Ble.Mode=NOT_SELECTED +PCC.Ble.PowerLevel=Min +PD0.GPIOParameters=GPIO_Speed,PinState,GPIO_Label +PD0.GPIO_Label=CC1101_CS +PD0.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH +PD0.Locked=true +PD0.PinState=GPIO_PIN_SET +PD0.Signal=GPIO_Output +PD1.GPIOParameters=GPIO_Label +PD1.GPIO_Label=SPI_D_SCK +PD1.Locked=true +PD1.Mode=TX_Only_Simplex_Unidirect_Master +PD1.Signal=SPI2_SCK +PE4.GPIOParameters=GPIO_Speed,PinState,GPIO_Label +PE4.GPIO_Label=NFC_CS +PE4.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH +PE4.Locked=true +PE4.PinState=GPIO_PIN_SET +PE4.Signal=GPIO_Output +PH3-BOOT0.GPIOParameters=GPIO_Label +PH3-BOOT0.GPIO_Label=BOOT0 +PH3-BOOT0.Locked=true +PH3-BOOT0.Signal=GPIO_Analog +PinOutPanel.RotationAngle=0 +ProjectManager.AskForMigrate=true +ProjectManager.BackupPrevious=false +ProjectManager.CompilerOptimize=6 +ProjectManager.ComputerToolchain=false +ProjectManager.CoupleFile=true +ProjectManager.CustomerFirmwarePackage= +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +ProjectManager.DeviceId=STM32WB55RGVx +ProjectManager.FirmwarePackage=STM32Cube FW_WB V1.9.0 +ProjectManager.FreePins=false +ProjectManager.HalAssertFull=false +ProjectManager.HeapSize=0x200 +ProjectManager.KeepUserCode=true +ProjectManager.LastFirmware=true +ProjectManager.LibraryCopy=2 +ProjectManager.MainLocation=Src +ProjectManager.NoMain=false +ProjectManager.PreviousToolchain= +ProjectManager.ProjectBuild=false +ProjectManager.ProjectFileName=f3.ioc +ProjectManager.ProjectName=f3 +ProjectManager.RegisterCallBack= +ProjectManager.StackSize=0x400 +ProjectManager.TargetToolchain=Makefile +ProjectManager.ToolChainLocation= +ProjectManager.UnderRoot=false +ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_ADC1_Init-ADC1-false-HAL-true,4-MX_I2C1_Init-I2C1-false-HAL-true,5-MX_RTC_Init-RTC-false-HAL-true,6-MX_SPI1_Init-SPI1-false-HAL-true,7-MX_SPI2_Init-SPI2-false-HAL-true,8-MX_USART1_UART_Init-USART1-false-HAL-true,9-MX_USB_Device_Init-USB_DEVICE-false-HAL-false,10-MX_TIM1_Init-TIM1-false-HAL-true,11-MX_TIM2_Init-TIM2-false-HAL-true,12-MX_TIM16_Init-TIM16-false-HAL-true,13-MX_COMP1_Init-COMP1-false-HAL-true,14-MX_RF_Init-RF-false-HAL-true,0-MX_HSEM_Init-HSEM-false-HAL-true +RCC.ADCFreq_Value=48000000 +RCC.AHB2CLKDivider=RCC_SYSCLK_DIV2 +RCC.AHBFreq_Value=64000000 +RCC.APB1Freq_Value=64000000 +RCC.APB1TimFreq_Value=64000000 +RCC.APB2Freq_Value=64000000 +RCC.APB2TimFreq_Value=64000000 +RCC.APB3Freq_Value=16000000 +RCC.Cortex2Freq_Value=32000000 +RCC.CortexFreq_Value=64000000 +RCC.EnbaleCSS=true +RCC.FCLK2Freq_Value=32000000 +RCC.FCLKCortexFreq_Value=64000000 +RCC.FamilyName=M +RCC.HCLK2Freq_Value=32000000 +RCC.HCLK3Freq_Value=64000000 +RCC.HCLKFreq_Value=64000000 +RCC.HCLKRFFreq_Value=16000000 +RCC.HSE_VALUE=32000000 +RCC.HSI48_VALUE=48000000 +RCC.HSI_VALUE=16000000 +RCC.I2C1Freq_Value=64000000 +RCC.I2C3Freq_Value=64000000 +RCC.IPParameters=ADCFreq_Value,AHB2CLKDivider,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,APB3Freq_Value,Cortex2Freq_Value,CortexFreq_Value,EnbaleCSS,FCLK2Freq_Value,FCLKCortexFreq_Value,FamilyName,HCLK2Freq_Value,HCLK3Freq_Value,HCLKFreq_Value,HCLKRFFreq_Value,HSE_VALUE,HSI48_VALUE,HSI_VALUE,I2C1Freq_Value,I2C3Freq_Value,LCDFreq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSI_VALUE,MCO1PinFreq_Value,MSIOscState,PLLM,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PLLSAI1N,PLLSAI1PoutputFreq_Value,PLLSAI1QoutputFreq_Value,PLLSAI1RoutputFreq_Value,PLLSourceVirtual,PREFETCH_ENABLE,PWRFreq_Value,RFWKPFreq_Value,RNGFreq_Value,RTCClockSelection,RTCFreq_Value,SAI1Freq_Value,SMPS1Freq_Value,SMPSCLockSelectionVirtual,SMPSFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,USART1Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAI1OutputFreq_Value +RCC.LCDFreq_Value=32768 +RCC.LPTIM1Freq_Value=64000000 +RCC.LPTIM2Freq_Value=64000000 +RCC.LPUART1Freq_Value=64000000 +RCC.LSCOPinFreq_Value=32000 +RCC.LSI_VALUE=32000 +RCC.MCO1PinFreq_Value=64000000 +RCC.MSIOscState=DISABLED +RCC.PLLM=RCC_PLLM_DIV2 +RCC.PLLPoutputFreq_Value=64000000 +RCC.PLLQoutputFreq_Value=64000000 +RCC.PLLRCLKFreq_Value=64000000 +RCC.PLLSAI1N=6 +RCC.PLLSAI1PoutputFreq_Value=48000000 +RCC.PLLSAI1QoutputFreq_Value=48000000 +RCC.PLLSAI1RoutputFreq_Value=48000000 +RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE +RCC.PREFETCH_ENABLE=1 +RCC.PWRFreq_Value=64000000 +RCC.RFWKPFreq_Value=976.5625 +RCC.RNGFreq_Value=32000 +RCC.RTCClockSelection=RCC_RTCCLKSOURCE_LSE +RCC.RTCFreq_Value=32768 +RCC.SAI1Freq_Value=48000000 +RCC.SMPS1Freq_Value=16000000 +RCC.SMPSCLockSelectionVirtual=RCC_SMPSCLKSOURCE_HSE +RCC.SMPSFreq_Value=8000000 +RCC.SYSCLKFreq_VALUE=64000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +RCC.USART1Freq_Value=64000000 +RCC.USBFreq_Value=48000000 +RCC.VCOInputFreq_Value=16000000 +RCC.VCOOutputFreq_Value=128000000 +RCC.VCOSAI1OutputFreq_Value=96000000 +RF1.Locked=true +RF1.Mode=RF1_Activate +RF1.Signal=RF_RF1 +SH.GPXTI1.0=GPIO_EXTI1 +SH.GPXTI1.ConfNb=1 +SH.GPXTI10.0=GPIO_EXTI10 +SH.GPXTI10.ConfNb=1 +SH.GPXTI11.0=GPIO_EXTI11 +SH.GPXTI11.ConfNb=1 +SH.GPXTI12.0=GPIO_EXTI12 +SH.GPXTI12.ConfNb=1 +SH.GPXTI13.0=GPIO_EXTI13 +SH.GPXTI13.ConfNb=1 +SH.GPXTI2.0=GPIO_EXTI2 +SH.GPXTI2.ConfNb=1 +SH.GPXTI8.0=GPIO_EXTI8 +SH.GPXTI8.ConfNb=1 +SH.S_TIM16_CH1.0=TIM16_CH1,PWM Generation1 CH1 +SH.S_TIM16_CH1.ConfNb=1 +SH.S_TIM2_CH1.0=TIM2_CH1,Input_Capture1_from_TI1 +SH.S_TIM2_CH1.1=TIM2_CH1,Input_Capture2_from_TI1 +SH.S_TIM2_CH1.ConfNb=2 +SH.SharedAnalog_PC5.0=COMP1_INP,INP +SH.SharedAnalog_PC5.1=ADC1_IN14,IN14-Single-Ended +SH.SharedAnalog_PC5.ConfNb=2 +SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_16 +SPI1.CLKPhase=SPI_PHASE_2EDGE +SPI1.CalculateBaudRate=4.0 MBits/s +SPI1.DataSize=SPI_DATASIZE_8BIT +SPI1.Direction=SPI_DIRECTION_2LINES +SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler,DataSize,CLKPhase +SPI1.Mode=SPI_MODE_MASTER +SPI1.VirtualType=VM_MASTER +SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_16 +SPI2.CLKPhase=SPI_PHASE_1EDGE +SPI2.CalculateBaudRate=4.0 MBits/s +SPI2.DataSize=SPI_DATASIZE_8BIT +SPI2.Direction=SPI_DIRECTION_2LINES +SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,BaudRatePrescaler,CLKPhase +SPI2.Mode=SPI_MODE_MASTER +SPI2.VirtualType=VM_MASTER +TIM1.Channel-Output\ Compare1\ CH1N=TIM_CHANNEL_1 +TIM1.Channel-PWM\ Generation3\ CH3N=TIM_CHANNEL_3 +TIM1.IPParameters=Channel-Output Compare1 CH1N,Channel-PWM Generation3 CH3N +TIM16.Channel=TIM_CHANNEL_1 +TIM16.IPParameters=Channel,Pulse,Prescaler,Period +TIM16.Period=291 +TIM16.Prescaler=500 - 1 +TIM16.Pulse=145 +TIM2.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE +TIM2.Channel-Input_Capture1_from_TI1=TIM_CHANNEL_1 +TIM2.Channel-Input_Capture2_from_TI1=TIM_CHANNEL_2 +TIM2.ICPolarity_CH1=TIM_INPUTCHANNELPOLARITY_FALLING +TIM2.IPParameters=Channel-Input_Capture1_from_TI1,ICPolarity_CH1,AutoReloadPreload,Prescaler,Channel-Input_Capture2_from_TI1 +TIM2.Prescaler=64-1 +USART1.IPParameters=VirtualMode-Asynchronous +USART1.VirtualMode-Asynchronous=VM_ASYNC +USB_DEVICE.APP_RX_DATA_SIZE=512 +USB_DEVICE.APP_TX_DATA_SIZE=512 +USB_DEVICE.CLASS_NAME_FS=CDC +USB_DEVICE.IPParameters=VirtualMode,VirtualModeFS,CLASS_NAME_FS,MANUFACTURER_STRING,PRODUCT_STRING_CDC_FS,APP_RX_DATA_SIZE,APP_TX_DATA_SIZE +USB_DEVICE.MANUFACTURER_STRING=Flipper +USB_DEVICE.PRODUCT_STRING_CDC_FS=Flipper Control Virtual ComPort +USB_DEVICE.VirtualMode=Cdc +USB_DEVICE.VirtualModeFS=Cdc_FS +VP_ADC1_TempSens_Input.Mode=IN-TempSens +VP_ADC1_TempSens_Input.Signal=ADC1_TempSens_Input +VP_ADC1_Vref_Input.Mode=IN-Vrefint +VP_ADC1_Vref_Input.Signal=ADC1_Vref_Input +VP_COMP1_VS_VREFINT14.Mode=VREFINT_14 +VP_COMP1_VS_VREFINT14.Signal=COMP1_VS_VREFINT14 +VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2 +VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2 +VP_HSEM_VS_HSEM.Mode=HSEM_Activate +VP_HSEM_VS_HSEM.Signal=HSEM_VS_HSEM +VP_RTC_VS_RTC_Activate.Mode=RTC_Enabled +VP_RTC_VS_RTC_Activate.Signal=RTC_VS_RTC_Activate +VP_RTC_VS_RTC_Calendar.Mode=RTC_Calendar +VP_RTC_VS_RTC_Calendar.Signal=RTC_VS_RTC_Calendar +VP_SYS_VS_tim17.Mode=TIM17 +VP_SYS_VS_tim17.Signal=SYS_VS_tim17 +VP_TIM16_VS_ClockSourceINT.Mode=Enable_Timer +VP_TIM16_VS_ClockSourceINT.Signal=TIM16_VS_ClockSourceINT +VP_TIM1_VS_ClockSourceINT.Mode=Internal +VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT +VP_TIM2_VS_ClockSourceINT.Mode=Internal +VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT +VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Mode=CDC_FS +VP_USB_DEVICE_VS_USB_DEVICE_CDC_FS.Signal=USB_DEVICE_VS_USB_DEVICE_CDC_FS +board=custom diff --git a/firmware/targets/local/fatfs/heap.h b/firmware/targets/local/Inc/heap.h similarity index 100% rename from firmware/targets/local/fatfs/heap.h rename to firmware/targets/local/Inc/heap.h diff --git a/firmware/targets/local/api-hal/api-hal-delay.h b/firmware/targets/local/api-hal/api-hal-delay.h deleted file mode 100644 index ff69ce4bb..000000000 --- a/firmware/targets/local/api-hal/api-hal-delay.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include "main.h" - -void delay_us(float microseconds); - -void delay(float milliseconds); \ No newline at end of file diff --git a/lib/cyfral/cyfral_emulator.h b/lib/cyfral/cyfral_emulator.h new file mode 100644 index 000000000..f62b2dee6 --- /dev/null +++ b/lib/cyfral/cyfral_emulator.h @@ -0,0 +1,95 @@ +#pragma once +#include "flipper.h" +#include "flipper_v2.h" + +class CyfralTiming { +public: + constexpr static const uint8_t ZERO_HIGH = 50; + constexpr static const uint8_t ZERO_LOW = 70; + constexpr static const uint8_t ONE_HIGH = 100; + constexpr static const uint8_t ONE_LOW = 70; +}; + +class CyfralEmulator { +private: + void send_nibble(uint8_t nibble); + void send_byte(uint8_t data); + inline void send_bit(bool bit); + const GpioPin* emulate_pin_record; + +public: + CyfralEmulator(const GpioPin* emulate_pin); + ~CyfralEmulator(); + void send(uint8_t* data, uint8_t count = 1, uint8_t repeat = 1); + void start(void); + void stop(void); +}; + +// 7 = 0 1 1 1 +// B = 1 0 1 1 +// D = 1 1 0 1 +// E = 1 1 1 0 + +void CyfralEmulator::send_nibble(uint8_t nibble) { + for(uint8_t i = 0; i < 4; i++) { + bool bit = nibble & (0b1000 >> i); + send_bit(bit); + } +} + +void CyfralEmulator::send_byte(uint8_t data) { + for(uint8_t i = 0; i < 8; i++) { + bool bit = data & (0b10000000 >> i); + send_bit(bit); + } +} + +void CyfralEmulator::send_bit(bool bit) { + if(!bit) { + gpio_write(&ibutton_gpio, false); + delay_us(CyfralTiming::ZERO_LOW); + gpio_write(&ibutton_gpio, true); + delay_us(CyfralTiming::ZERO_HIGH); + gpio_write(&ibutton_gpio, false); + delay_us(CyfralTiming::ZERO_LOW); + } else { + gpio_write(&ibutton_gpio, true); + delay_us(CyfralTiming::ONE_HIGH); + gpio_write(&ibutton_gpio, false); + delay_us(CyfralTiming::ONE_LOW); + } +} + +CyfralEmulator::CyfralEmulator(const GpioPin* emulate_pin) { + emulate_pin_record = emulate_pin; +} + +CyfralEmulator::~CyfralEmulator() { +} + +void CyfralEmulator::send(uint8_t* data, uint8_t count, uint8_t repeat) { + osKernelLock(); + __disable_irq(); + + for(uint8_t i = 0; i < repeat; i++) { + // start sequence + send_nibble(0x01); + + // send data + for(uint8_t i = 0; i < count; i++) { + send_byte(data[i]); + } + } + + __enable_irq(); + osKernelUnlock(); +} + +void CyfralEmulator::start(void) { + gpio_init(emulate_pin_record, GpioModeOutputOpenDrain); + gpio_write(emulate_pin_record, false); +} + +void CyfralEmulator::stop(void) { + gpio_init(emulate_pin_record, GpioModeAnalog); +} \ No newline at end of file diff --git a/lib/cyfral/cyfral_reader.h b/lib/cyfral/cyfral_reader.h new file mode 100644 index 000000000..01f72f713 --- /dev/null +++ b/lib/cyfral/cyfral_reader.h @@ -0,0 +1,273 @@ +#pragma once +#include "flipper.h" +#include "flipper_v2.h" + +enum class CyfralReaderError : uint8_t { + NO_ERROR = 0, + UNABLE_TO_DETECT = 1, + RAW_DATA_SIZE_ERROR = 2, + UNKNOWN_NIBBLE_VALUE = 3, + NO_START_NIBBLE = 4, +}; + +class CyfralReader { +private: + ADC_HandleTypeDef adc_config; + ADC_TypeDef* adc_instance; + uint32_t adc_channel; + + void get_line_minmax(uint16_t times, uint32_t* min_level, uint32_t* max_level); + void capture_data(bool* data, uint16_t capture_size, uint32_t line_min, uint32_t line_max); + bool parse_data(bool* raw_data, uint16_t capture_size, uint8_t* data, uint8_t count); + uint32_t search_array_in_array( + const bool* haystack, + const uint32_t haystack_size, + const bool* needle, + const uint32_t needle_size); + + // key is 9 nibbles + static const uint16_t bits_in_nibble = 4; + static const uint16_t key_length = 9; + static const uint32_t capture_size = key_length * bits_in_nibble * 2; + CyfralReaderError error; + +public: + CyfralReader(ADC_TypeDef* adc, uint32_t Channel); + ~CyfralReader(); + void start(void); + void stop(void); + bool read(uint8_t* data, uint8_t count); +}; + +void CyfralReader::get_line_minmax(uint16_t times, uint32_t* min_level, uint32_t* max_level) { + uint32_t in = 0; + uint32_t min = UINT_MAX; + uint32_t max = 0; + + for(uint32_t i = 0; i < 256; i++) { + HAL_ADC_Start(&adc_config); + HAL_ADC_PollForConversion(&adc_config, 100); + in = HAL_ADC_GetValue(&adc_config); + if(in < min) min = in; + if(in > max) max = in; + } + + *min_level = min; + *max_level = max; +} + +void CyfralReader::capture_data( + bool* data, + uint16_t capture_size, + uint32_t line_min, + uint32_t line_max) { + uint32_t input_value = 0; + bool last_input_value = 0; + + uint32_t diff = line_max - line_min; + uint32_t mid = line_min + diff / 2; + + uint32_t low_threshold = mid - (diff / 4); + uint32_t high_threshold = mid - (diff / 4); + + uint16_t capture_position = 0; + uint32_t instructions_per_us = (SystemCoreClock / 1000000.0f); + uint32_t time_threshold = 75 * instructions_per_us; + uint32_t capture_max_time = 140 * (capture_size * 2) * instructions_per_us; + + uint32_t start = DWT->CYCCNT; + uint32_t end = DWT->CYCCNT; + + memset(data, 0, capture_size); + + osKernelLock(); + + uint32_t capture_start = DWT->CYCCNT; + while((capture_position < capture_size) && + ((DWT->CYCCNT - capture_start) < capture_max_time)) { + // read adc + HAL_ADC_Start(&adc_config); + HAL_ADC_PollForConversion(&adc_config, 100); + input_value = HAL_ADC_GetValue(&adc_config); + + // low to high transition + if((input_value > high_threshold) && last_input_value == 0) { + last_input_value = 1; + start = DWT->CYCCNT; + } + + // high to low transition + if((input_value < low_threshold) && last_input_value == 1) { + last_input_value = 0; + end = DWT->CYCCNT; + + // check transition time + if(end - start < time_threshold) { + data[capture_position] = 1; + capture_position++; + } else { + data[capture_position] = 0; + capture_position++; + } + } + } + + osKernelUnlock(); +} + +uint32_t CyfralReader::search_array_in_array( + const bool* haystack, + const uint32_t haystack_size, + const bool* needle, + const uint32_t needle_size) { + uint32_t haystack_index = 0, needle_index = 0; + + while(haystack_index < haystack_size && needle_index < needle_size) { + if(haystack[haystack_index] == needle[needle_index]) { + haystack_index++; + needle_index++; + if(needle_index == needle_size) { + return (haystack_index - needle_size); + }; + } else { + haystack_index = haystack_index - needle_index + 1; + needle_index = 0; + } + } + + return haystack_index; +} + +bool CyfralReader::parse_data(bool* raw_data, uint16_t capture_size, uint8_t* data, uint8_t count) { + const bool start_nibble[bits_in_nibble] = {1, 1, 1, 0}; + uint32_t start_position = + search_array_in_array(raw_data, capture_size, start_nibble, bits_in_nibble); + uint32_t end_position = 0; + + memset(data, 0, count); + + if(start_position < capture_size) { + start_position = start_position + bits_in_nibble; + end_position = start_position + count * 2 * bits_in_nibble; + + if(end_position >= capture_size) { + error = CyfralReaderError::RAW_DATA_SIZE_ERROR; + return false; + } + + bool first_nibble = true; + uint8_t data_position = 0; + uint8_t nibble_value = 0; + + while(data_position < count) { + nibble_value = !raw_data[start_position] << 3 | !raw_data[start_position + 1] << 2 | + !raw_data[start_position + 2] << 1 | !raw_data[start_position + 3]; + + switch(nibble_value) { + case(0x7): + case(0xB): + case(0xD): + case(0xE): + break; + default: + error = CyfralReaderError::UNKNOWN_NIBBLE_VALUE; + return false; + break; + } + + if(first_nibble) { + data[data_position] |= nibble_value << 4; + } else { + data[data_position] |= nibble_value; + } + + first_nibble = !first_nibble; + + if(first_nibble) { + data_position++; + } + + start_position = start_position + bits_in_nibble; + } + + error = CyfralReaderError::NO_ERROR; + return true; + } + + error = CyfralReaderError::NO_START_NIBBLE; + return false; +} + +CyfralReader::CyfralReader(ADC_TypeDef* adc, uint32_t channel) { + adc_instance = adc; + adc_channel = channel; +} + +CyfralReader::~CyfralReader() { +} + +void CyfralReader::start(void) { + ADC_ChannelConfTypeDef sConfig = {0}; + + // init ADC + adc_config.Instance = adc_instance; + adc_config.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; + adc_config.Init.Resolution = ADC_RESOLUTION_12B; + adc_config.Init.DataAlign = ADC_DATAALIGN_RIGHT; + adc_config.Init.ScanConvMode = ADC_SCAN_DISABLE; + adc_config.Init.EOCSelection = ADC_EOC_SINGLE_CONV; + adc_config.Init.LowPowerAutoWait = DISABLE; + adc_config.Init.ContinuousConvMode = DISABLE; + adc_config.Init.NbrOfConversion = 1; + adc_config.Init.DiscontinuousConvMode = DISABLE; + adc_config.Init.ExternalTrigConv = ADC_SOFTWARE_START; + adc_config.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + adc_config.Init.DMAContinuousRequests = DISABLE; + adc_config.Init.Overrun = ADC_OVR_DATA_PRESERVED; + adc_config.Init.OversamplingMode = DISABLE; + if(HAL_ADC_Init(&adc_config) != HAL_OK) { + Error_Handler(); + } + + // init channel + sConfig.Channel = adc_channel; + sConfig.Rank = ADC_REGULAR_RANK_1; + sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5; + sConfig.SingleDiff = ADC_SINGLE_ENDED; + sConfig.OffsetNumber = ADC_OFFSET_NONE; + sConfig.Offset = 0; + if(HAL_ADC_ConfigChannel(&adc_config, &sConfig) != HAL_OK) { + Error_Handler(); + } +} + +void CyfralReader::stop(void) { + HAL_ADC_DeInit(&adc_config); +} + +bool CyfralReader::read(uint8_t* data, uint8_t count) { + uint32_t line_level_min, line_level_max; + bool raw_data[capture_size]; + bool result = false; + error = CyfralReaderError::NO_ERROR; + + // calibrate + get_line_minmax(256, &line_level_min, &line_level_max); + + // TODO think about other detection method + // key not on line + if(line_level_max > 2000) { + error = CyfralReaderError::UNABLE_TO_DETECT; + return false; + } + + // capturing raw data consisting of bits + capture_data(raw_data, capture_size, line_level_min, line_level_max); + + // parse captured data + if(parse_data(raw_data, capture_size, data, count)) { + result = true; + } + + return result; +} \ No newline at end of file diff --git a/lib/lib.mk b/lib/lib.mk index ab7c74013..483e5dbae 100644 --- a/lib/lib.mk +++ b/lib/lib.mk @@ -54,4 +54,18 @@ CFLAGS += -I$(LIB_DIR)/app-template # fnv1a hash library CFLAGS += -I$(LIB_DIR)/fnv1a-hash -C_SOURCES += $(LIB_DIR)/fnv1a-hash/fnv1a-hash.c \ No newline at end of file +C_SOURCES += $(LIB_DIR)/fnv1a-hash/fnv1a-hash.c + +# build onewire/cyfral library only if +# we build iButton application +ifeq ($(BUILD_IBUTTON), 1) +# onewire library +ONEWIRE_DIR = $(LIB_DIR)/onewire +CFLAGS += -I$(ONEWIRE_DIR) +CPP_SOURCES += $(wildcard $(ONEWIRE_DIR)/*.cpp) + +# cyfral library +CYFRAL_DIR = $(LIB_DIR)/cyfral +CFLAGS += -I$(CYFRAL_DIR) +CPP_SOURCES += $(wildcard $(CYFRAL_DIR)/*.cpp) +endif \ No newline at end of file diff --git a/lib/onewire/maxim_crc.cpp b/lib/onewire/maxim_crc.cpp new file mode 100644 index 000000000..f56d84dc3 --- /dev/null +++ b/lib/onewire/maxim_crc.cpp @@ -0,0 +1,48 @@ +#include "maxim_crc.h" + +uint8_t maxim_crc8(const uint8_t* data, const uint8_t data_size, const uint8_t crc_init) { + uint8_t crc = crc_init; + + for(uint8_t index = 0; index < data_size; ++index) { + uint8_t input_byte = data[index]; + for(uint8_t bit_position = 0; bit_position < 8; ++bit_position) { + const uint8_t mix = (crc ^ input_byte) & static_cast(0x01); + crc >>= 1; + if(mix != 0) crc ^= 0x8C; + input_byte >>= 1; + } + } + return crc; +} + +uint16_t maxim_crc16(const uint8_t* address, const uint8_t length, const uint16_t init) { + uint16_t crc = init; + + static const uint8_t odd_parity[16] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0}; + + for(uint8_t i = 0; i < length; ++i) { + uint16_t cdata = address[i]; + cdata = (cdata ^ crc) & static_cast(0xff); + crc >>= 8; + + if((odd_parity[cdata & 0x0F] ^ odd_parity[cdata >> 4]) != 0) crc ^= 0xC001; + + cdata <<= 6; + crc ^= cdata; + cdata <<= 1; + crc ^= cdata; + } + + return crc; +} + +uint16_t maxim_crc16(uint8_t value, uint16_t crc) { + static const uint8_t odd_parity[16] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0}; + value = (value ^ static_cast(crc)); + crc >>= 8; + if((odd_parity[value & 0x0F] ^ odd_parity[value >> 4]) != 0) crc ^= 0xC001; + uint16_t cdata = (static_cast(value) << 6); + crc ^= cdata; + crc ^= (static_cast(cdata) << 1); + return crc; +} \ No newline at end of file diff --git a/lib/onewire/maxim_crc.h b/lib/onewire/maxim_crc.h new file mode 100644 index 000000000..1a9569fa8 --- /dev/null +++ b/lib/onewire/maxim_crc.h @@ -0,0 +1,6 @@ +#pragma once +#include + +uint8_t maxim_crc8(const uint8_t* data, const uint8_t data_size, const uint8_t crc_init = 0); +uint16_t maxim_crc16(const uint8_t* address, const uint8_t length, const uint16_t init = 0); +uint16_t maxim_crc16(uint8_t value, uint16_t crc); \ No newline at end of file diff --git a/lib/onewire/one_wire_device.cpp b/lib/onewire/one_wire_device.cpp new file mode 100644 index 000000000..391295491 --- /dev/null +++ b/lib/onewire/one_wire_device.cpp @@ -0,0 +1,26 @@ +#include "one_wire_device.h" + +// TODO fix GPL compability +// currently we use rework of OneWireHub + +OneWireDevice::OneWireDevice( + uint8_t id_1, + uint8_t id_2, + uint8_t id_3, + uint8_t id_4, + uint8_t id_5, + uint8_t id_6, + uint8_t id_7) { + id_storage[0] = id_1; + id_storage[1] = id_2; + id_storage[2] = id_3; + id_storage[3] = id_4; + id_storage[4] = id_5; + id_storage[5] = id_6; + id_storage[6] = id_7; + id_storage[7] = maxim_crc8(id_storage, 7); +} + +void OneWireDevice::send_id(OneWireGpioSlave* owner) const { + owner->send(id_storage, 8); +} diff --git a/lib/onewire/one_wire_device.h b/lib/onewire/one_wire_device.h new file mode 100644 index 000000000..d4f0abe53 --- /dev/null +++ b/lib/onewire/one_wire_device.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include "maxim_crc.h" +#include "one_wire_slave_gpio.h" + +// TODO fix GPL compability +// currently we use rework of OneWireHub + +class OneWireDevice { +public: + OneWireDevice( + uint8_t id_1, + uint8_t id_2, + uint8_t id_3, + uint8_t id_4, + uint8_t id_5, + uint8_t id_6, + uint8_t id_7); + + ~OneWireDevice() = default; // TODO: detach if deleted before hub + + // allow only move constructor + OneWireDevice(OneWireDevice&& one_wire_device) = default; + OneWireDevice(const OneWireDevice& one_wire_device) = delete; + OneWireDevice& operator=(OneWireDevice& one_wire_device) = delete; + OneWireDevice& operator=(const OneWireDevice& one_wire_device) = delete; + OneWireDevice& operator=(OneWireDevice&& one_wire_device) = delete; + + uint8_t id_storage[8]; + + void send_id(OneWireGpioSlave* owner) const; + + virtual void do_work(OneWireGpioSlave* owner) = 0; +}; \ No newline at end of file diff --git a/lib/onewire/one_wire_device_ds_1990.cpp b/lib/onewire/one_wire_device_ds_1990.cpp new file mode 100644 index 000000000..663553fbe --- /dev/null +++ b/lib/onewire/one_wire_device_ds_1990.cpp @@ -0,0 +1,27 @@ +#include "one_wire_device_ds_1990.h" + +// TODO fix GPL compability +// currently we use rework of OneWireHub + +DS1990::DS1990( + uint8_t ID1, + uint8_t ID2, + uint8_t ID3, + uint8_t ID4, + uint8_t ID5, + uint8_t ID6, + uint8_t ID7) + : OneWireDevice(ID1, ID2, ID3, ID4, ID5, ID6, ID7) { +} + +void DS1990::do_work(OneWireGpioSlave* owner) { + uint8_t cmd; + + if(owner->receive(&cmd)) return; + + switch(cmd) { + default: + return; + //owner->raiseSlaveError(cmd); + } +} \ No newline at end of file diff --git a/lib/onewire/one_wire_device_ds_1990.h b/lib/onewire/one_wire_device_ds_1990.h new file mode 100644 index 000000000..6b3d99b89 --- /dev/null +++ b/lib/onewire/one_wire_device_ds_1990.h @@ -0,0 +1,21 @@ +#pragma once +#include "one_wire_device.h" + +// TODO fix GPL compability +// currently we use rework of OneWireHub + +class DS1990 : public OneWireDevice { +public: + static constexpr uint8_t family_code{0x01}; + + DS1990( + uint8_t ID1, + uint8_t ID2, + uint8_t ID3, + uint8_t ID4, + uint8_t ID5, + uint8_t ID6, + uint8_t ID7); + + void do_work(OneWireGpioSlave* owner) final; +}; \ No newline at end of file diff --git a/applications/ibutton/one_wire_gpio.h b/lib/onewire/one_wire_gpio.h similarity index 100% rename from applications/ibutton/one_wire_gpio.h rename to lib/onewire/one_wire_gpio.h diff --git a/lib/onewire/one_wire_slave_gpio.cpp b/lib/onewire/one_wire_slave_gpio.cpp new file mode 100644 index 000000000..9e9cab7f6 --- /dev/null +++ b/lib/onewire/one_wire_slave_gpio.cpp @@ -0,0 +1,511 @@ +#include "one_wire_slave_gpio.h" +#include "one_wire_device.h" +#include "one_wire_device_ds_1990.h" + +// TODO fix GPL compability +// currently we use rework of OneWireHub + +static uint32_t __instructions_per_us = 0; + +OneWireGpioSlave::OneWireGpioSlave(const GpioPin* one_wire_gpio) { + gpio = one_wire_gpio; + error = OneWireGpioSlaveError::NO_ERROR; + devices_count = 0; + device_selected = nullptr; + + for(uint8_t i = 0; i < ONE_WIRE_MAX_DEVICES; ++i) { + devices[i] = nullptr; + } + + __instructions_per_us = (SystemCoreClock / 1000000.0f); +} + +OneWireGpioSlave::~OneWireGpioSlave() { + stop(); +} + +void OneWireGpioSlave::start(void) { + gpio_init(gpio, GpioModeOutputOpenDrain); +} + +void OneWireGpioSlave::stop(void) { + gpio_init(gpio, GpioModeAnalog); +} + +bool OneWireGpioSlave::emulate() { + error = OneWireGpioSlaveError::NO_ERROR; + + while(1) { + if(devices_count == 0) return false; + + if(!check_reset()) { + return false; + } else { + } + + // OK, we receive reset + osKernelLock(); + + if(!show_presence()) { + return false; + } else { + } + + // and we succefully show our presence on bus + __disable_irq(); + + if(!receive_and_process_cmd()) { + __enable_irq(); + osKernelUnlock(); + return false; + } else { + __enable_irq(); + osKernelUnlock(); + return (error == OneWireGpioSlaveError::NO_ERROR); + } + } +} + +OneWiteTimeType OneWireGpioSlave::wait_while_gpio_is(OneWiteTimeType time, const bool pin_value) { + uint32_t start = DWT->CYCCNT; + uint32_t time_ticks = time * __instructions_per_us; + uint32_t time_captured; + + do { + time_captured = DWT->CYCCNT; + if(gpio_read(gpio) != pin_value) { + OneWiteTimeType remaining_time = time_ticks - (time_captured - start); + remaining_time /= __instructions_per_us; + return remaining_time; + } + } while((time_captured - start) < time_ticks); + + return 0; +} + +void OneWireGpioSlave::pin_set_float() { + gpio_write(gpio, true); +} + +void OneWireGpioSlave::pin_set_low() { + gpio_write(gpio, false); +} + +const char* OneWireGpioSlave::decode_error() { + const char* error_text[16] = { + "NO_ERROR", + "READ_TIMESLOT_TIMEOUT", + "WRITE_TIMESLOT_TIMEOUT", + "WAIT_RESET_TIMEOUT", + "VERY_LONG_RESET", + "VERY_SHORT_RESET", + "PRESENCE_LOW_ON_LINE", + "READ_TIMESLOT_TIMEOUT_LOW", + "AWAIT_TIMESLOT_TIMEOUT_HIGH", + "PRESENCE_HIGH_ON_LINE", + "INCORRECT_ONEWIRE_CMD", + "INCORRECT_SLAVE_USAGE", + "TRIED_INCORRECT_WRITE", + "FIRST_TIMESLOT_TIMEOUT", + "FIRST_BIT_OF_BYTE_TIMEOUT", + "RESET_IN_PROGRESS"}; + + return error_text[static_cast(error)]; +} + +uint8_t OneWireGpioSlave::attach(OneWireDevice& device) { + if(devices_count >= ONE_WIRE_MAX_DEVICES) return 255; // hub is full + + uint8_t position = 255; + for(uint8_t i = 0; i < ONE_WIRE_MAX_DEVICES; ++i) { + if(devices[i] == &device) { + return i; + } + if((position > ONE_WIRE_MAX_DEVICES) && (devices[i] == nullptr)) { + position = i; + } + } + + if(position == 255) return 255; + + devices[position] = &device; + devices_count++; + build_id_tree(); + return position; +} + +bool OneWireGpioSlave::detach(const OneWireDevice& device) { + uint8_t position = 255; + + for(uint8_t i = 0; i < ONE_WIRE_MAX_DEVICES; ++i) { + if(devices[i] == &device) { + position = i; + break; + } + } + + if(position != 255) return detach(position); + + return false; +} + +bool OneWireGpioSlave::detach(uint8_t device_number) { + if(devices[device_number] == nullptr) return false; + if(devices_count == 0) return false; + if(device_number >= ONE_WIRE_MAX_DEVICES) return false; + + devices[device_number] = nullptr; + devices_count--; + build_id_tree(); + + return true; +} + +uint8_t OneWireGpioSlave::get_next_device_index(const uint8_t index_start) const { + for(uint8_t i = index_start; i < ONE_WIRE_MAX_DEVICES; ++i) { + if(devices[i] != nullptr) return i; + } + return 0; +} + +uint8_t OneWireGpioSlave::build_id_tree(void) { + uint32_t device_mask = 0; + uint32_t bit_mask = 0x01; + + // build mask + for(uint8_t i = 0; i < ONE_WIRE_MAX_DEVICES; ++i) { + if(devices[i] != nullptr) device_mask |= bit_mask; + bit_mask <<= 1; + } + + for(uint8_t i = 0; i < ONE_WIRE_MAX_DEVICES; ++i) { + id_tree[i].id_position = 255; + } + + // begin with root-element + build_id_tree(0, device_mask); // goto branch + + return 0; +} + +uint8_t OneWireGpioSlave::build_id_tree(uint8_t id_bit_position, uint32_t device_mask) { + if(device_mask == 0) return (255); + + while(id_bit_position < 64) { + uint32_t mask_pos{0}; + uint32_t mask_neg{0}; + const uint8_t pos_byte{static_cast(id_bit_position >> 3)}; + const uint8_t mask_bit{static_cast(1 << (id_bit_position & 7))}; + uint32_t mask_id{1}; + + // searchid_tree through all active slaves + for(uint8_t id = 0; id < ONE_WIRE_MAX_DEVICES; ++id) { + if((device_mask & mask_id) != 0) { + // if slave is in mask differentiate the bitValue + if((devices[id]->id_storage[pos_byte] & mask_bit) != 0) + mask_pos |= mask_id; + else + mask_neg |= mask_id; + } + mask_id <<= 1; + } + + if((mask_neg != 0) && (mask_pos != 0)) { + // there was found a junction + const uint8_t active_element = get_first_id_tree_el_position(); + + id_tree[active_element].id_position = id_bit_position; + id_tree[active_element].device_selected = get_first_bit_set_position(device_mask); + id_bit_position++; + id_tree[active_element].got_one = build_id_tree(id_bit_position, mask_pos); + id_tree[active_element].got_zero = build_id_tree(id_bit_position, mask_neg); + return active_element; + } + + id_bit_position++; + } + + // gone through the address, store this result + uint8_t active_element = get_first_id_tree_el_position(); + + id_tree[active_element].id_position = 128; + id_tree[active_element].device_selected = get_first_bit_set_position(device_mask); + id_tree[active_element].got_one = 255; + id_tree[active_element].got_zero = 255; + + return active_element; +} + +uint8_t OneWireGpioSlave::get_first_bit_set_position(uint32_t mask) const { + uint32_t _mask = mask; + for(uint8_t i = 0; i < ONE_WIRE_MAX_DEVICES; ++i) { + if((_mask & 1) != 0) return i; + _mask >>= 1; + } + return 0; +} + +uint8_t OneWireGpioSlave::get_first_id_tree_el_position(void) const { + for(uint8_t i = 0; i < ONE_WIRE_MAX_DEVICES; ++i) { + if(id_tree[i].id_position == 255) return i; + } + return 0; +} + +void OneWireGpioSlave::cmd_search_rom(void) { + uint8_t id_bit_position = 0; + uint8_t trigger_position = 0; + uint8_t active_slave = id_tree[trigger_position].device_selected; + uint8_t trigger_bit = id_tree[trigger_position].id_position; + + while(id_bit_position < 64) { + // if junction is reached, act different + if(id_bit_position == trigger_bit) { + if(!send_bit(false)) return; + if(!send_bit(false)) return; + + const bool bit_recv = receive_bit(); + if(error != OneWireGpioSlaveError::NO_ERROR) return; + + // switch to next junction + trigger_position = bit_recv ? id_tree[trigger_position].got_one : + id_tree[trigger_position].got_zero; + + active_slave = id_tree[trigger_position].device_selected; + + trigger_bit = (trigger_position == 255) ? uint8_t(255) : + id_tree[trigger_position].id_position; + } else { + const uint8_t pos_byte = (id_bit_position >> 3); + const uint8_t mask_bit = (static_cast(1) << (id_bit_position & (7))); + bool bit_send; + + if((devices[active_slave]->id_storage[pos_byte] & mask_bit) != 0) { + bit_send = true; + if(!send_bit(true)) return; + if(!send_bit(false)) return; + } else { + bit_send = false; + if(!send_bit(false)) return; + if(!send_bit(true)) return; + } + + const bool bit_recv = receive_bit(); + if(error != OneWireGpioSlaveError::NO_ERROR) return; + + if(bit_send != bit_recv) return; + } + id_bit_position++; + } + + device_selected = devices[active_slave]; +} + +bool OneWireGpioSlave::check_reset(void) { + pin_set_float(); + + if(error == OneWireGpioSlaveError::RESET_IN_PROGRESS) { + error = OneWireGpioSlaveError::NO_ERROR; + + if(wait_while_gpio_is( + OWET::RESET_MIN[overdrive_mode] - OWET::SLOT_MAX[overdrive_mode] - + OWET::READ_MAX[overdrive_mode], + false) == 0) { + // we want to show_presence on high, so wait for it + const OneWiteTimeType time_remaining = wait_while_gpio_is(OWET::RESET_MAX[0], false); + + if(overdrive_mode && + ((OWET::RESET_MAX[0] - OWET::RESET_MIN[overdrive_mode]) > time_remaining)) { + overdrive_mode = false; + }; + + return true; + } + } + + // if line is low, then just leave + if(gpio_read(gpio) == 0) return false; + + // wait while gpio is high + if(wait_while_gpio_is(OWET::RESET_TIMEOUT, true) == 0) { + return false; + } + + // store low time + const OneWiteTimeType time_remaining = wait_while_gpio_is(OWET::RESET_MAX[0], false); + + // low time more than RESET_MAX time + if(time_remaining == 0) { + error = OneWireGpioSlaveError::VERY_LONG_RESET; + return false; + } + + // if time, while bus was low, fit in standart reset timings + if(overdrive_mode && ((OWET::RESET_MAX[0] - OWET::RESET_MIN[0]) <= time_remaining)) { + // normal reset detected + overdrive_mode = false; + }; + + bool result = (time_remaining <= OWET::RESET_MAX[0]) && + time_remaining >= OWET::RESET_MIN[overdrive_mode]; + + return result; +} + +bool OneWireGpioSlave::show_presence(void) { + // wait while master delay presence check + wait_while_gpio_is(OWET::PRESENCE_TIMEOUT, true); + + // show presence + pin_set_low(); + delay_us(OWET::PRESENCE_MIN[overdrive_mode]); + pin_set_float(); + + // somebody also can show presence + const OneWiteTimeType wait_low_time = + OWET::PRESENCE_MAX[overdrive_mode] - OWET::PRESENCE_MIN[overdrive_mode]; + + // so we will wait + if(wait_while_gpio_is(wait_low_time, false) == 0) { + error = OneWireGpioSlaveError::PRESENCE_LOW_ON_LINE; + return false; + } + + return true; +} + +bool OneWireGpioSlave::receive_and_process_cmd(void) { + receive(&cmd); + + if(error == OneWireGpioSlaveError::RESET_IN_PROGRESS) return true; + if(error != OneWireGpioSlaveError::NO_ERROR) return false; + + switch(cmd) { + case 0xF0: + // SEARCH ROM + device_selected = nullptr; + cmd_search_rom(); + + // trigger reinit + return true; + + case 0x33: + // READ ROM + + // work only when one slave on the bus + if((device_selected == nullptr) && (devices_count == 1)) { + device_selected = devices[get_next_device_index()]; + } + if(device_selected != nullptr) { + device_selected->send_id(this); + } + return false; + + default: // Unknown command + error = OneWireGpioSlaveError::INCORRECT_ONEWIRE_CMD; + //error_cmd = cmd; + } + + if(error == OneWireGpioSlaveError::RESET_IN_PROGRESS) return true; + return (error == OneWireGpioSlaveError::NO_ERROR); +} + +bool OneWireGpioSlave::receive_bit(void) { + // wait while bus is low + OneWiteTimeType time = OWET::SLOT_MAX[overdrive_mode]; + time = wait_while_gpio_is(time, false); + if(time == 0) { + error = OneWireGpioSlaveError::RESET_IN_PROGRESS; + return false; + } + + // wait while bus is high + time = OWET::MSG_HIGH_TIMEOUT; + time = wait_while_gpio_is(time, true); + if(time == 0) { + error = OneWireGpioSlaveError::AWAIT_TIMESLOT_TIMEOUT_HIGH; + error_place = 1; + return false; + } + + // wait a time of zero + time = OWET::READ_MIN[overdrive_mode]; + time = wait_while_gpio_is(time, false); + + return (time > 0); +} + +bool OneWireGpioSlave::send_bit(bool value) { + const bool write_zero = !value; + + // wait while bus is low + OneWiteTimeType time = OWET::SLOT_MAX[overdrive_mode]; + time = wait_while_gpio_is(time, false); + if(time == 0) { + error = OneWireGpioSlaveError::RESET_IN_PROGRESS; + return false; + } + + // wait while bus is high + time = OWET::MSG_HIGH_TIMEOUT; + time = wait_while_gpio_is(time, true); + if(time == 0) { + error = OneWireGpioSlaveError::AWAIT_TIMESLOT_TIMEOUT_HIGH; + error_place = 2; + return false; + } + + // choose write time + if(write_zero) { + pin_set_low(); + time = OWET::WRITE_ZERO[overdrive_mode]; + } else { + time = OWET::READ_MAX[overdrive_mode]; + } + + // hold line for ZERO or ONE time + delay_us(time); + pin_set_float(); + + return true; +} + +bool OneWireGpioSlave::send(const uint8_t* address, const uint8_t data_length) { + uint8_t bytes_sent = 0; + + pin_set_float(); + + // bytes loop + for(; bytes_sent < data_length; ++bytes_sent) { + const uint8_t data_byte = address[bytes_sent]; + + // bit loop + for(uint8_t bit_mask = 0x01; bit_mask != 0; bit_mask <<= 1) { + if(!send_bit(static_cast(bit_mask & data_byte))) { + // if we cannot send first bit + if((bit_mask == 0x01) && + (error == OneWireGpioSlaveError::AWAIT_TIMESLOT_TIMEOUT_HIGH)) + error = OneWireGpioSlaveError::FIRST_BIT_OF_BYTE_TIMEOUT; + return false; + } + } + } + return true; +} + +bool OneWireGpioSlave::receive(uint8_t* data, const uint8_t data_length) { + uint8_t bytes_received = 0; + + pin_set_float(); + + for(; bytes_received < data_length; ++bytes_received) { + uint8_t value = 0; + + for(uint8_t bit_mask = 0x01; bit_mask != 0; bit_mask <<= 1) { + if(receive_bit()) value |= bit_mask; + } + + data[bytes_received] = value; + } + return (bytes_received != data_length); +} \ No newline at end of file diff --git a/lib/onewire/one_wire_slave_gpio.h b/lib/onewire/one_wire_slave_gpio.h new file mode 100644 index 000000000..d7d7daa81 --- /dev/null +++ b/lib/onewire/one_wire_slave_gpio.h @@ -0,0 +1,93 @@ +#pragma once +#include "flipper.h" +#include "flipper_v2.h" +#include "one_wire_timings.h" + +// TODO fix GPL compability +// currently we use rework of OneWireHub + +#define ONE_WIRE_MAX_DEVICES 1 +#define ONE_WIRE_TREE_SIZE ((2 * ONE_WIRE_MAX_DEVICES) - 1) + +#define OWET OneWireEmulateTiming + +class OneWireDevice; + +enum class OneWireGpioSlaveError : uint8_t { + NO_ERROR = 0, + READ_TIMESLOT_TIMEOUT = 1, + WRITE_TIMESLOT_TIMEOUT = 2, + WAIT_RESET_TIMEOUT = 3, + VERY_LONG_RESET = 4, + VERY_SHORT_RESET = 5, + PRESENCE_LOW_ON_LINE = 6, + READ_TIMESLOT_TIMEOUT_LOW = 7, + AWAIT_TIMESLOT_TIMEOUT_HIGH = 8, + PRESENCE_HIGH_ON_LINE = 9, + INCORRECT_ONEWIRE_CMD = 10, + INCORRECT_SLAVE_USAGE = 11, + TRIED_INCORRECT_WRITE = 12, + FIRST_TIMESLOT_TIMEOUT = 13, + FIRST_BIT_OF_BYTE_TIMEOUT = 14, + RESET_IN_PROGRESS = 15 +}; + +class OneWireGpioSlave { +private: + const GpioPin* gpio; + bool overdrive_mode = false; + uint8_t cmd; + OneWireGpioSlaveError error; + uint8_t error_place; + + uint8_t devices_count; + OneWireDevice* devices[ONE_WIRE_MAX_DEVICES]; + OneWireDevice* device_selected; + + struct IDTree { + uint8_t device_selected; // for which slave is this jump-command relevant + uint8_t id_position; // where does the algorithm has to look for a junction + uint8_t got_zero; // if 0 switch to which tree branch + uint8_t got_one; // if 1 switch to which tree branch + } id_tree[ONE_WIRE_TREE_SIZE]; + +public: + OneWireGpioSlave(const GpioPin* one_wire_gpio); + ~OneWireGpioSlave(); + + void start(void); + void stop(void); + bool emulate(); + bool check_reset(void); + bool show_presence(void); + bool receive_and_process_cmd(void); + bool receive(uint8_t* data, const uint8_t data_length = 1); + bool receive_bit(void); + bool send_bit(bool value); + bool send(const uint8_t* address, const uint8_t data_length = 1); + + OneWiteTimeType wait_while_gpio_is(volatile OneWiteTimeType retries, const bool pin_value); + + // set pin state + inline void pin_set_float(); + inline void pin_set_low(); + + // get error text + const char* decode_error(); + + // devices managment + uint8_t attach(OneWireDevice& device); + bool detach(const OneWireDevice& device); + bool detach(uint8_t device_number); + uint8_t get_next_device_index(const uint8_t index_start = 0) const; + + // id tree managment + uint8_t build_id_tree(void); + uint8_t build_id_tree(uint8_t id_bit_position, uint32_t device_mask); + + uint8_t get_first_bit_set_position(uint32_t mask) const; + uint8_t get_first_id_tree_el_position(void) const; + + // commands + void cmd_search_rom(void); +}; \ No newline at end of file diff --git a/lib/onewire/one_wire_timings.cpp b/lib/onewire/one_wire_timings.cpp new file mode 100644 index 000000000..b6c3d55c0 --- /dev/null +++ b/lib/onewire/one_wire_timings.cpp @@ -0,0 +1,17 @@ +#include "one_wire_timings.h" + +// fix pre C++17 "undefined reference" errors +constexpr const OneWiteTimeType OneWireEmulateTiming::RESET_TIMEOUT; +constexpr const OneWiteTimeType OneWireEmulateTiming::RESET_MIN[2]; +constexpr const OneWiteTimeType OneWireEmulateTiming::RESET_MAX[2]; + +constexpr const OneWiteTimeType OneWireEmulateTiming::PRESENCE_TIMEOUT; +constexpr const OneWiteTimeType OneWireEmulateTiming::PRESENCE_MIN[2]; +constexpr const OneWiteTimeType OneWireEmulateTiming::PRESENCE_MAX[2]; + +constexpr const OneWiteTimeType OneWireEmulateTiming::MSG_HIGH_TIMEOUT; +constexpr const OneWiteTimeType OneWireEmulateTiming::SLOT_MAX[2]; + +constexpr const OneWiteTimeType OneWireEmulateTiming::READ_MIN[2]; +constexpr const OneWiteTimeType OneWireEmulateTiming::READ_MAX[2]; +constexpr const OneWiteTimeType OneWireEmulateTiming::WRITE_ZERO[2]; diff --git a/applications/ibutton/one_wire_timings.h b/lib/onewire/one_wire_timings.h similarity index 100% rename from applications/ibutton/one_wire_timings.h rename to lib/onewire/one_wire_timings.h