Merge branch 'release-candidate' into release
This commit is contained in:
		
						commit
						5f582abfe0
					
				| @ -9,7 +9,7 @@ void AccessorApp::run(void) { | |||||||
|     bool exit = false; |     bool exit = false; | ||||||
| 
 | 
 | ||||||
|     wiegand.begin(); |     wiegand.begin(); | ||||||
|     onewire_master.start(); |     onewire_host_start(onewire_host); | ||||||
| 
 | 
 | ||||||
|     scenes[current_scene]->on_enter(this); |     scenes[current_scene]->on_enter(this); | ||||||
| 
 | 
 | ||||||
| @ -28,19 +28,20 @@ void AccessorApp::run(void) { | |||||||
|     scenes[current_scene]->on_exit(this); |     scenes[current_scene]->on_exit(this); | ||||||
| 
 | 
 | ||||||
|     wiegand.end(); |     wiegand.end(); | ||||||
|     onewire_master.stop(); |     onewire_host_stop(onewire_host); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| AccessorApp::AccessorApp() | AccessorApp::AccessorApp() { | ||||||
|     : onewire_master{&ibutton_gpio} { |  | ||||||
|     furi_hal_power_insomnia_enter(); |     furi_hal_power_insomnia_enter(); | ||||||
|     notification = static_cast<NotificationApp*>(furi_record_open("notification")); |     notification = static_cast<NotificationApp*>(furi_record_open("notification")); | ||||||
|  |     onewire_host = onewire_host_alloc(); | ||||||
|     furi_hal_power_enable_otg(); |     furi_hal_power_enable_otg(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| AccessorApp::~AccessorApp() { | AccessorApp::~AccessorApp() { | ||||||
|     furi_hal_power_disable_otg(); |     furi_hal_power_disable_otg(); | ||||||
|     furi_record_close("notification"); |     furi_record_close("notification"); | ||||||
|  |     onewire_host_free(onewire_host); | ||||||
|     furi_hal_power_insomnia_exit(); |     furi_hal_power_insomnia_exit(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -136,6 +137,6 @@ WIEGAND* AccessorApp::get_wiegand() { | |||||||
|     return &wiegand; |     return &wiegand; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| OneWireMaster* AccessorApp::get_one_wire() { | OneWireHost* AccessorApp::get_one_wire() { | ||||||
|     return &onewire_master; |     return onewire_host; | ||||||
| } | } | ||||||
| @ -2,13 +2,9 @@ | |||||||
| #include <map> | #include <map> | ||||||
| #include <list> | #include <list> | ||||||
| #include "accessor_view_manager.h" | #include "accessor_view_manager.h" | ||||||
| 
 |  | ||||||
| #include "scene/accessor_scene_start.h" | #include "scene/accessor_scene_start.h" | ||||||
| 
 |  | ||||||
| #include "helpers/wiegand.h" | #include "helpers/wiegand.h" | ||||||
| 
 | #include <one_wire/one_wire_host.h> | ||||||
| #include <one_wire_master.h> |  | ||||||
| 
 |  | ||||||
| #include <notification/notification_messages.h> | #include <notification/notification_messages.h> | ||||||
| 
 | 
 | ||||||
| class AccessorApp { | class AccessorApp { | ||||||
| @ -37,7 +33,7 @@ public: | |||||||
|     void set_text_store(const char* text...); |     void set_text_store(const char* text...); | ||||||
| 
 | 
 | ||||||
|     WIEGAND* get_wiegand(); |     WIEGAND* get_wiegand(); | ||||||
|     OneWireMaster* get_one_wire(); |     OneWireHost* get_one_wire(); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     std::list<Scene> previous_scenes_list = {Scene::Exit}; |     std::list<Scene> previous_scenes_list = {Scene::Exit}; | ||||||
| @ -52,7 +48,7 @@ private: | |||||||
|     char text_store[text_store_size + 1]; |     char text_store[text_store_size + 1]; | ||||||
| 
 | 
 | ||||||
|     WIEGAND wiegand; |     WIEGAND wiegand; | ||||||
|     OneWireMaster onewire_master; |     OneWireHost* onewire_host; | ||||||
| 
 | 
 | ||||||
|     NotificationApp* notification; |     NotificationApp* notification; | ||||||
| }; | }; | ||||||
| @ -55,19 +55,19 @@ void WIEGAND::begin() { | |||||||
|     _wiegandType = 0; |     _wiegandType = 0; | ||||||
|     _bitCount = 0; |     _bitCount = 0; | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init_simple(pinD0, GpioModeInterruptFall); // Set D0 pin as input
 |     furi_hal_gpio_init_simple(pinD0, GpioModeInterruptFall); // Set D0 pin as input
 | ||||||
|     hal_gpio_init_simple(pinD1, GpioModeInterruptFall); // Set D1 pin as input
 |     furi_hal_gpio_init_simple(pinD1, GpioModeInterruptFall); // Set D1 pin as input
 | ||||||
| 
 | 
 | ||||||
|     hal_gpio_add_int_callback(pinD0, input_isr_d0, this); |     furi_hal_gpio_add_int_callback(pinD0, input_isr_d0, this); | ||||||
|     hal_gpio_add_int_callback(pinD1, input_isr_d1, this); |     furi_hal_gpio_add_int_callback(pinD1, input_isr_d1, this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WIEGAND::end() { | void WIEGAND::end() { | ||||||
|     hal_gpio_remove_int_callback(pinD0); |     furi_hal_gpio_remove_int_callback(pinD0); | ||||||
|     hal_gpio_remove_int_callback(pinD1); |     furi_hal_gpio_remove_int_callback(pinD1); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init_simple(pinD0, GpioModeAnalog); |     furi_hal_gpio_init_simple(pinD0, GpioModeAnalog); | ||||||
|     hal_gpio_init_simple(pinD1, GpioModeAnalog); |     furi_hal_gpio_init_simple(pinD1, GpioModeAnalog); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WIEGAND::ReadD0() { | void WIEGAND::ReadD0() { | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ bool AccessorSceneStart::on_event(AccessorApp* app, AccessorEvent* event) { | |||||||
|     if(event->type == AccessorEvent::Type::Tick) { |     if(event->type == AccessorEvent::Type::Tick) { | ||||||
|         WIEGAND* wiegand = app->get_wiegand(); |         WIEGAND* wiegand = app->get_wiegand(); | ||||||
|         Popup* popup = app->get_view_manager()->get_popup(); |         Popup* popup = app->get_view_manager()->get_popup(); | ||||||
|         OneWireMaster* onewire = app->get_one_wire(); |         OneWireHost* onewire_host = app->get_one_wire(); | ||||||
| 
 | 
 | ||||||
|         uint8_t data[8] = {0, 0, 0, 0, 0, 0, 0, 0}; |         uint8_t data[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||||
|         uint8_t type = 0; |         uint8_t type = 0; | ||||||
| @ -38,11 +38,11 @@ bool AccessorSceneStart::on_event(AccessorApp* app, AccessorEvent* event) { | |||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             FURI_CRITICAL_ENTER(); |             FURI_CRITICAL_ENTER(); | ||||||
|             if(onewire->reset()) { |             if(onewire_host_reset(onewire_host)) { | ||||||
|                 type = 255; |                 type = 255; | ||||||
|                 onewire->write(0x33); |                 onewire_host_write(onewire_host, 0x33); | ||||||
|                 for(uint8_t i = 0; i < 8; i++) { |                 for(uint8_t i = 0; i < 8; i++) { | ||||||
|                     data[i] = onewire->read(); |                     data[i] = onewire_host_read(onewire_host); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 for(uint8_t i = 0; i < 7; i++) { |                 for(uint8_t i = 0; i < 7; i++) { | ||||||
|  | |||||||
| @ -99,6 +99,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { | |||||||
|             if(favorites) { |             if(favorites) { | ||||||
|                 browser->callback(ArchiveBrowserEventEnterFavMove, browser->context); |                 browser->callback(ArchiveBrowserEventEnterFavMove, browser->context); | ||||||
|             } else if((known_app) && (selected->is_app == false)) { |             } else if((known_app) && (selected->is_app == false)) { | ||||||
|  |                 archive_show_file_menu(browser, false); | ||||||
|                 scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneRename); |                 scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneRename); | ||||||
|             } |             } | ||||||
|             consumed = true; |             consumed = true; | ||||||
|  | |||||||
| @ -155,7 +155,7 @@ void desktop_scene_pin_input_on_exit(void* context) { | |||||||
|         desktop->scene_manager, DesktopScenePinInput); |         desktop->scene_manager, DesktopScenePinInput); | ||||||
|     xTimerStop(state->timer, portMAX_DELAY); |     xTimerStop(state->timer, portMAX_DELAY); | ||||||
|     while(xTimerIsTimerActive(state->timer)) { |     while(xTimerIsTimerActive(state->timer)) { | ||||||
|         delay(1); |         furi_hal_delay_ms(1); | ||||||
|     } |     } | ||||||
|     xTimerDelete(state->timer, portMAX_DELAY); |     xTimerDelete(state->timer, portMAX_DELAY); | ||||||
|     free(state); |     free(state); | ||||||
|  | |||||||
| @ -214,7 +214,7 @@ void desktop_view_pin_input_free(DesktopViewPinInput* pin_input) { | |||||||
| 
 | 
 | ||||||
|     xTimerStop(pin_input->timer, portMAX_DELAY); |     xTimerStop(pin_input->timer, portMAX_DELAY); | ||||||
|     while(xTimerIsTimerActive(pin_input->timer)) { |     while(xTimerIsTimerActive(pin_input->timer)) { | ||||||
|         delay(1); |         furi_hal_delay_ms(1); | ||||||
|     } |     } | ||||||
|     xTimerDelete(pin_input->timer, portMAX_DELAY); |     xTimerDelete(pin_input->timer, portMAX_DELAY); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -20,8 +20,8 @@ static const GpioItem gpio_item[GPIO_ITEM_COUNT] = { | |||||||
| 
 | 
 | ||||||
| void gpio_item_configure_pin(uint8_t index, GpioMode mode) { | void gpio_item_configure_pin(uint8_t index, GpioMode mode) { | ||||||
|     furi_assert(index < GPIO_ITEM_COUNT); |     furi_assert(index < GPIO_ITEM_COUNT); | ||||||
|     hal_gpio_write(gpio_item[index].pin, false); |     furi_hal_gpio_write(gpio_item[index].pin, false); | ||||||
|     hal_gpio_init(gpio_item[index].pin, mode, GpioPullNo, GpioSpeedVeryHigh); |     furi_hal_gpio_init(gpio_item[index].pin, mode, GpioPullNo, GpioSpeedVeryHigh); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void gpio_item_configure_all_pins(GpioMode mode) { | void gpio_item_configure_all_pins(GpioMode mode) { | ||||||
| @ -32,7 +32,7 @@ void gpio_item_configure_all_pins(GpioMode mode) { | |||||||
| 
 | 
 | ||||||
| void gpio_item_set_pin(uint8_t index, bool level) { | void gpio_item_set_pin(uint8_t index, bool level) { | ||||||
|     furi_assert(index < GPIO_ITEM_COUNT); |     furi_assert(index < GPIO_ITEM_COUNT); | ||||||
|     hal_gpio_write(gpio_item[index].pin, level); |     furi_hal_gpio_write(gpio_item[index].pin, level); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void gpio_item_set_all_pins(bool level) { | void gpio_item_set_all_pins(bool level) { | ||||||
|  | |||||||
| @ -134,8 +134,8 @@ static void usb_uart_update_ctrl_lines(UsbUartBridge* usb_uart) { | |||||||
|         furi_assert((usb_uart->cfg.flow_pins - 1) < (sizeof(flow_pins) / sizeof(flow_pins[0]))); |         furi_assert((usb_uart->cfg.flow_pins - 1) < (sizeof(flow_pins) / sizeof(flow_pins[0]))); | ||||||
|         uint8_t state = furi_hal_cdc_get_ctrl_line_state(usb_uart->cfg.vcp_ch); |         uint8_t state = furi_hal_cdc_get_ctrl_line_state(usb_uart->cfg.vcp_ch); | ||||||
| 
 | 
 | ||||||
|         hal_gpio_write(flow_pins[usb_uart->cfg.flow_pins - 1][0], !(state & USB_CDC_BIT_RTS)); |         furi_hal_gpio_write(flow_pins[usb_uart->cfg.flow_pins - 1][0], !(state & USB_CDC_BIT_RTS)); | ||||||
|         hal_gpio_write(flow_pins[usb_uart->cfg.flow_pins - 1][1], !(state & USB_CDC_BIT_DTR)); |         furi_hal_gpio_write(flow_pins[usb_uart->cfg.flow_pins - 1][1], !(state & USB_CDC_BIT_DTR)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -161,8 +161,10 @@ static int32_t usb_uart_worker(void* context) { | |||||||
|     usb_uart_set_baudrate(usb_uart, usb_uart->cfg.baudrate); |     usb_uart_set_baudrate(usb_uart, usb_uart->cfg.baudrate); | ||||||
|     if(usb_uart->cfg.flow_pins != 0) { |     if(usb_uart->cfg.flow_pins != 0) { | ||||||
|         furi_assert((usb_uart->cfg.flow_pins - 1) < (sizeof(flow_pins) / sizeof(flow_pins[0]))); |         furi_assert((usb_uart->cfg.flow_pins - 1) < (sizeof(flow_pins) / sizeof(flow_pins[0]))); | ||||||
|         hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeOutputPushPull); |         furi_hal_gpio_init_simple( | ||||||
|         hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeOutputPushPull); |             flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeOutputPushPull); | ||||||
|  |         furi_hal_gpio_init_simple( | ||||||
|  |             flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeOutputPushPull); | ||||||
|         usb_uart_update_ctrl_lines(usb_uart); |         usb_uart_update_ctrl_lines(usb_uart); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -219,18 +221,18 @@ static int32_t usb_uart_worker(void* context) { | |||||||
|             } |             } | ||||||
|             if(usb_uart->cfg.flow_pins != usb_uart->cfg_new.flow_pins) { |             if(usb_uart->cfg.flow_pins != usb_uart->cfg_new.flow_pins) { | ||||||
|                 if(usb_uart->cfg.flow_pins != 0) { |                 if(usb_uart->cfg.flow_pins != 0) { | ||||||
|                     hal_gpio_init_simple( |                     furi_hal_gpio_init_simple( | ||||||
|                         flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeAnalog); |                         flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeAnalog); | ||||||
|                     hal_gpio_init_simple( |                     furi_hal_gpio_init_simple( | ||||||
|                         flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog); |                         flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog); | ||||||
|                 } |                 } | ||||||
|                 if(usb_uart->cfg_new.flow_pins != 0) { |                 if(usb_uart->cfg_new.flow_pins != 0) { | ||||||
|                     furi_assert( |                     furi_assert( | ||||||
|                         (usb_uart->cfg_new.flow_pins - 1) < |                         (usb_uart->cfg_new.flow_pins - 1) < | ||||||
|                         (sizeof(flow_pins) / sizeof(flow_pins[0]))); |                         (sizeof(flow_pins) / sizeof(flow_pins[0]))); | ||||||
|                     hal_gpio_init_simple( |                     furi_hal_gpio_init_simple( | ||||||
|                         flow_pins[usb_uart->cfg_new.flow_pins - 1][0], GpioModeOutputPushPull); |                         flow_pins[usb_uart->cfg_new.flow_pins - 1][0], GpioModeOutputPushPull); | ||||||
|                     hal_gpio_init_simple( |                     furi_hal_gpio_init_simple( | ||||||
|                         flow_pins[usb_uart->cfg_new.flow_pins - 1][1], GpioModeOutputPushPull); |                         flow_pins[usb_uart->cfg_new.flow_pins - 1][1], GpioModeOutputPushPull); | ||||||
|                 } |                 } | ||||||
|                 usb_uart->cfg.flow_pins = usb_uart->cfg_new.flow_pins; |                 usb_uart->cfg.flow_pins = usb_uart->cfg_new.flow_pins; | ||||||
| @ -251,8 +253,8 @@ static int32_t usb_uart_worker(void* context) { | |||||||
|     furi_hal_usb_unlock(); |     furi_hal_usb_unlock(); | ||||||
|     furi_hal_usb_set_config(usb_mode_prev, NULL); |     furi_hal_usb_set_config(usb_mode_prev, NULL); | ||||||
|     if(usb_uart->cfg.flow_pins != 0) { |     if(usb_uart->cfg.flow_pins != 0) { | ||||||
|         hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeAnalog); |         furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeAnalog); | ||||||
|         hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog); |         furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtTxStop); |     osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtTxStop); | ||||||
|  | |||||||
| @ -1,193 +0,0 @@ | |||||||
| #include "cyfral_decoder.h" |  | ||||||
| #include <furi.h> |  | ||||||
| 
 |  | ||||||
| void CyfralDecoder::reset_state() { |  | ||||||
|     state = State::WAIT_START_NIBBLE; |  | ||||||
|     bit_state = BitState::WAIT_FRONT_LOW; |  | ||||||
| 
 |  | ||||||
|     period_time = 0; |  | ||||||
|     bit_index = 0; |  | ||||||
|     ready = false; |  | ||||||
|     index = 0; |  | ||||||
| 
 |  | ||||||
|     key_data = 0; |  | ||||||
|     readed_nibble = 0; |  | ||||||
|     data_valid = true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool CyfralDecoder::nibble_valid(uint8_t data) { |  | ||||||
|     uint8_t data_value = data & 0x0F; |  | ||||||
| 
 |  | ||||||
|     switch(data_value) { |  | ||||||
|     case 0b1110: |  | ||||||
|     case 0b1101: |  | ||||||
|     case 0b1011: |  | ||||||
|     case 0b0111: |  | ||||||
|         return true; |  | ||||||
|         break; |  | ||||||
|     default: |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| CyfralDecoder::CyfralDecoder() { |  | ||||||
|     reset_state(); |  | ||||||
|     max_period = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void CyfralDecoder::process_front(bool polarity, uint32_t time) { |  | ||||||
|     bool readed; |  | ||||||
|     bool value; |  | ||||||
| 
 |  | ||||||
|     if(max_period == 0) { |  | ||||||
|         max_period = 230 * (SystemCoreClock / 1000000.0f); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(ready) return; |  | ||||||
| 
 |  | ||||||
|     switch(state) { |  | ||||||
|     case State::WAIT_START_NIBBLE: |  | ||||||
|         // wait for start word
 |  | ||||||
|         if(process_bit(polarity, time, &readed, &value)) { |  | ||||||
|             if(readed) { |  | ||||||
|                 readed_nibble = ((readed_nibble << 1) | value) & 0x0F; |  | ||||||
|                 if(readed_nibble == 0b0001) { |  | ||||||
|                     readed_nibble = 0; |  | ||||||
|                     state = State::READ_NIBBLE; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             reset_state(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         break; |  | ||||||
|     case State::READ_NIBBLE: |  | ||||||
|         // read nibbles
 |  | ||||||
|         if(process_bit(polarity, time, &readed, &value)) { |  | ||||||
|             if(readed) { |  | ||||||
|                 readed_nibble = (readed_nibble << 1) | value; |  | ||||||
| 
 |  | ||||||
|                 bit_index++; |  | ||||||
| 
 |  | ||||||
|                 //convert every nibble to 2-bit index
 |  | ||||||
|                 if(bit_index == 4) { |  | ||||||
|                     switch(readed_nibble) { |  | ||||||
|                     case 0b1110: |  | ||||||
|                         key_data = (key_data << 2) | 0b11; |  | ||||||
|                         break; |  | ||||||
|                     case 0b1101: |  | ||||||
|                         key_data = (key_data << 2) | 0b10; |  | ||||||
|                         break; |  | ||||||
|                     case 0b1011: |  | ||||||
|                         key_data = (key_data << 2) | 0b01; |  | ||||||
|                         break; |  | ||||||
|                     case 0b0111: |  | ||||||
|                         key_data = (key_data << 2) | 0b00; |  | ||||||
|                         break; |  | ||||||
|                     default: |  | ||||||
|                         data_valid = false; |  | ||||||
|                         break; |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     readed_nibble = 0; |  | ||||||
|                     bit_index = 0; |  | ||||||
|                     index++; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 // succefully read 8 nibbles
 |  | ||||||
|                 if(index == 8) { |  | ||||||
|                     state = State::READ_STOP_NIBBLE; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             reset_state(); |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     case State::READ_STOP_NIBBLE: |  | ||||||
|         // read stop nibble
 |  | ||||||
|         if(process_bit(polarity, time, &readed, &value)) { |  | ||||||
|             if(readed) { |  | ||||||
|                 readed_nibble = ((readed_nibble << 1) | value) & 0x0F; |  | ||||||
|                 bit_index++; |  | ||||||
| 
 |  | ||||||
|                 switch(bit_index) { |  | ||||||
|                 case 0: |  | ||||||
|                 case 1: |  | ||||||
|                 case 2: |  | ||||||
|                 case 3: |  | ||||||
|                     break; |  | ||||||
|                 case 4: |  | ||||||
|                     if(readed_nibble == 0b0001) { |  | ||||||
|                         // validate data
 |  | ||||||
|                         if(data_valid) { |  | ||||||
|                             ready = true; |  | ||||||
|                         } else { |  | ||||||
|                             reset_state(); |  | ||||||
|                         } |  | ||||||
|                     } else { |  | ||||||
|                         reset_state(); |  | ||||||
|                     } |  | ||||||
|                     break; |  | ||||||
|                 default: |  | ||||||
|                     reset_state(); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             reset_state(); |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool CyfralDecoder::process_bit(bool polarity, uint32_t time, bool* readed, bool* readed_value) { |  | ||||||
|     bool result = true; |  | ||||||
|     *readed = false; |  | ||||||
| 
 |  | ||||||
|     // bit start from low
 |  | ||||||
|     switch(bit_state) { |  | ||||||
|     case BitState::WAIT_FRONT_LOW: |  | ||||||
|         if(polarity == true) { |  | ||||||
|             period_time += time; |  | ||||||
| 
 |  | ||||||
|             *readed = true; |  | ||||||
|             if(period_time <= max_period) { |  | ||||||
|                 if((period_time / 2) > time) { |  | ||||||
|                     *readed_value = false; |  | ||||||
|                 } else { |  | ||||||
|                     *readed_value = true; |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 result = false; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             bit_state = BitState::WAIT_FRONT_HIGH; |  | ||||||
|         } else { |  | ||||||
|             result = false; |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     case BitState::WAIT_FRONT_HIGH: |  | ||||||
|         if(polarity == false) { |  | ||||||
|             period_time = time; |  | ||||||
|             bit_state = BitState::WAIT_FRONT_LOW; |  | ||||||
|         } else { |  | ||||||
|             result = false; |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool CyfralDecoder::read(uint8_t* _data, uint8_t data_size) { |  | ||||||
|     furi_check(data_size <= 2); |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     if(ready) { |  | ||||||
|         memcpy(_data, &key_data, data_size); |  | ||||||
|         reset_state(); |  | ||||||
|         result = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| @ -1,55 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <stdint.h> |  | ||||||
| #include <atomic> |  | ||||||
| 
 |  | ||||||
| class CyfralDecoder { |  | ||||||
| public: |  | ||||||
|     bool read(uint8_t* data, uint8_t data_size); |  | ||||||
|     void process_front(bool polarity, uint32_t time); |  | ||||||
| 
 |  | ||||||
|     CyfralDecoder(); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     enum class BitState : uint8_t { |  | ||||||
|         WAIT_FRONT_HIGH, |  | ||||||
|         WAIT_FRONT_LOW, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     enum class State : uint8_t { |  | ||||||
|         WAIT_START_NIBBLE, |  | ||||||
|         READ_NIBBLE, |  | ||||||
|         READ_STOP_NIBBLE, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     State state; |  | ||||||
|     BitState bit_state; |  | ||||||
| 
 |  | ||||||
|     bool process_bit(bool polarity, uint32_t time, bool* readed, bool* readed_value); |  | ||||||
|     void reset_state(); |  | ||||||
|     bool nibble_valid(uint8_t data); |  | ||||||
| 
 |  | ||||||
|     // high + low period time
 |  | ||||||
|     uint32_t period_time; |  | ||||||
| 
 |  | ||||||
|     // ready flag, key is readed and valid
 |  | ||||||
|     std::atomic<bool> ready; |  | ||||||
| 
 |  | ||||||
|     // key data storage
 |  | ||||||
|     uint16_t key_data; |  | ||||||
| 
 |  | ||||||
|     // temporary nibble storage
 |  | ||||||
|     uint8_t readed_nibble; |  | ||||||
| 
 |  | ||||||
|     // data valid flag
 |  | ||||||
|     // MUST be checked only in READ_STOP_NIBBLE state
 |  | ||||||
|     bool data_valid; |  | ||||||
| 
 |  | ||||||
|     // nibble index, we expect 8 nibbles
 |  | ||||||
|     uint8_t index; |  | ||||||
| 
 |  | ||||||
|     // bit index in nibble, 4 bit per nibble
 |  | ||||||
|     uint8_t bit_index; |  | ||||||
| 
 |  | ||||||
|     // max period, 230us x clock per us
 |  | ||||||
|     uint32_t max_period; |  | ||||||
| }; |  | ||||||
| @ -1,39 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <stdint.h> |  | ||||||
| 
 |  | ||||||
| class RW1990_1 { |  | ||||||
| public: |  | ||||||
|     constexpr static const uint8_t CMD_WRITE_RECORD_FLAG = 0xD1; |  | ||||||
|     constexpr static const uint8_t CMD_READ_RECORD_FLAG = 0xB5; |  | ||||||
|     constexpr static const uint8_t CMD_WRITE_ROM = 0xD5; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class RW1990_2 { |  | ||||||
| public: |  | ||||||
|     constexpr static const uint8_t CMD_WRITE_RECORD_FLAG = 0x1D; |  | ||||||
|     constexpr static const uint8_t CMD_READ_RECORD_FLAG = 0x1E; |  | ||||||
|     constexpr static const uint8_t CMD_WRITE_ROM = 0xD5; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class TM2004 { |  | ||||||
| public: |  | ||||||
|     constexpr static const uint8_t CMD_READ_STATUS = 0xAA; |  | ||||||
|     constexpr static const uint8_t CMD_READ_MEMORY = 0xF0; |  | ||||||
|     constexpr static const uint8_t CMD_WRITE_ROM = 0x3C; |  | ||||||
|     constexpr static const uint8_t CMD_FINALIZATION = 0x35; |  | ||||||
| 
 |  | ||||||
|     constexpr static const uint8_t ANSWER_READ_MEMORY = 0xF5; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class TM01 { |  | ||||||
| public: |  | ||||||
|     constexpr static const uint8_t CMD_WRITE_RECORD_FLAG = 0xC1; |  | ||||||
|     constexpr static const uint8_t CMD_WRITE_ROM = 0xC5; |  | ||||||
|     constexpr static const uint8_t CMD_SWITCH_TO_CYFRAL = 0xCA; |  | ||||||
|     constexpr static const uint8_t CMD_SWITCH_TO_METAKOM = 0xCB; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class DS1990 { |  | ||||||
| public: |  | ||||||
|     constexpr static const uint8_t CMD_READ_ROM = 0x33; |  | ||||||
| }; |  | ||||||
| @ -1,208 +0,0 @@ | |||||||
| #include "key_emulator.h" |  | ||||||
| #include <callback-connector.h> |  | ||||||
| 
 |  | ||||||
| KeyEmulator::~KeyEmulator() { |  | ||||||
|     stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| KeyEmulator::KeyEmulator(OneWireSlave* _onewire_slave) |  | ||||||
|     : dallas_key{0, 0, 0, 0, 0, 0, 0} { |  | ||||||
|     onewire_slave = _onewire_slave; |  | ||||||
| 
 |  | ||||||
|     auto cb = cbc::obtain_connector(this, &KeyEmulator::result_callback); |  | ||||||
|     onewire_slave->set_result_callback(cb, this); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyEmulator::start(iButtonKey* key) { |  | ||||||
|     anything_emulated = false; |  | ||||||
|     stop(); |  | ||||||
| 
 |  | ||||||
|     // pulldown pull pin, to prevent low-pass filtering by the RFID part of the schematic
 |  | ||||||
|     furi_hal_rfid_pin_pull_pulldown(); |  | ||||||
| 
 |  | ||||||
|     switch(key->get_key_type()) { |  | ||||||
|     case iButtonKeyType::KeyDallas: |  | ||||||
|         start_dallas_emulate(key); |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyType::KeyCyfral: |  | ||||||
|         start_cyfral_emulate(key); |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyType::KeyMetakom: |  | ||||||
|         start_metakom_emulate(key); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool KeyEmulator::emulated() { |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     if(anything_emulated) { |  | ||||||
|         anything_emulated = false; |  | ||||||
|         result = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyEmulator::stop() { |  | ||||||
|     onewire_slave->stop(); |  | ||||||
|     pulser.stop(); |  | ||||||
|     furi_hal_rfid_pins_reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyEmulator::start_cyfral_emulate(iButtonKey* key) { |  | ||||||
|     furi_assert(key->get_key_type() == iButtonKeyType::KeyCyfral); |  | ||||||
|     furi_assert(key->get_type_data_size() == 2); |  | ||||||
| 
 |  | ||||||
|     const uint32_t cyfral_period_full = 8000; |  | ||||||
|     const uint32_t cyfral_period_one[2] = { |  | ||||||
|         uint32_t(cyfral_period_full * 0.33f), uint32_t(cyfral_period_full * 0.66f)}; |  | ||||||
|     const uint32_t cyfral_period_zero[2] = { |  | ||||||
|         uint32_t(cyfral_period_full * 0.66f), uint32_t(cyfral_period_full * 0.33f)}; |  | ||||||
|     uint8_t pd_index = 0; |  | ||||||
|     uint8_t* key_data = key->get_data(); |  | ||||||
| 
 |  | ||||||
|     // start nibble
 |  | ||||||
|     set_pulse_data_cyfral(pd_index, cyfral_period_zero); |  | ||||||
|     pd_index++; |  | ||||||
|     set_pulse_data_cyfral(pd_index, cyfral_period_zero); |  | ||||||
|     pd_index++; |  | ||||||
|     set_pulse_data_cyfral(pd_index, cyfral_period_zero); |  | ||||||
|     pd_index++; |  | ||||||
|     set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|     pd_index++; |  | ||||||
| 
 |  | ||||||
|     // data nibbles x 8
 |  | ||||||
|     for(int8_t i = key->get_type_data_size() - 1; i >= 0; i--) { |  | ||||||
|         for(int8_t j = 3; j >= 0; j--) { |  | ||||||
|             switch((key_data[i] >> (j * 2)) & 0b00000011) { |  | ||||||
|             case 0b11: |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_zero); |  | ||||||
|                 pd_index++; |  | ||||||
|                 break; |  | ||||||
|             case 0b10: |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_zero); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 break; |  | ||||||
|             case 0b01: |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_zero); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 break; |  | ||||||
|             case 0b00: |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_zero); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 set_pulse_data_cyfral(pd_index, cyfral_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|                 break; |  | ||||||
|             default: |  | ||||||
|                 // cannot be anyway
 |  | ||||||
|                 furi_check(false); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // 4 (nibbles) x (8 data + 1 start) = 4 x 9 = 36
 |  | ||||||
|     if(pd_index != 36) { |  | ||||||
|         // something is very wrong
 |  | ||||||
|         furi_check(false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pulser.set_periods(pulse_data, 72, false); |  | ||||||
|     pulser.start(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyEmulator::start_metakom_emulate(iButtonKey* key) { |  | ||||||
|     furi_assert(key->get_key_type() == iButtonKeyType::KeyMetakom); |  | ||||||
|     furi_assert(key->get_type_data_size() == 4); |  | ||||||
| 
 |  | ||||||
|     const uint32_t metakom_period_full = 8000; |  | ||||||
|     const uint32_t metakom_period_zero[2] = { |  | ||||||
|         uint32_t(metakom_period_full * 0.33f), uint32_t(metakom_period_full * 0.66f)}; |  | ||||||
|     const uint32_t metakom_period_one[2] = { |  | ||||||
|         uint32_t(metakom_period_full * 0.66f), uint32_t(metakom_period_full * 0.33f)}; |  | ||||||
|     uint8_t pd_index = 0; |  | ||||||
| 
 |  | ||||||
|     uint8_t* key_data = key->get_data(); |  | ||||||
| 
 |  | ||||||
|     // start pulse
 |  | ||||||
|     pulse_data[0] = metakom_period_full; |  | ||||||
| 
 |  | ||||||
|     // start triplet
 |  | ||||||
|     set_pulse_data_metakom(pd_index, metakom_period_zero); |  | ||||||
|     pd_index++; |  | ||||||
|     set_pulse_data_metakom(pd_index, metakom_period_one); |  | ||||||
|     pd_index++; |  | ||||||
|     set_pulse_data_metakom(pd_index, metakom_period_zero); |  | ||||||
|     pd_index++; |  | ||||||
| 
 |  | ||||||
|     for(int8_t i = key->get_type_data_size() - 1; i >= 0; i--) { |  | ||||||
|         for(int8_t j = 7; j >= 0; j--) { |  | ||||||
|             if(((key_data[i] >> j) & 0b00000001) == 1) { |  | ||||||
|                 set_pulse_data_metakom(pd_index, metakom_period_one); |  | ||||||
|                 pd_index++; |  | ||||||
|             } else { |  | ||||||
|                 set_pulse_data_metakom(pd_index, metakom_period_zero); |  | ||||||
|                 pd_index++; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // 4 byte x 8 bits + 3 start bits = 35
 |  | ||||||
|     if(pd_index != 35) { |  | ||||||
|         // something is very wrong
 |  | ||||||
|         furi_check(false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pulser.set_periods(pulse_data, 71, false); |  | ||||||
|     pulser.start(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyEmulator::start_dallas_emulate(iButtonKey* key) { |  | ||||||
|     furi_assert(key->get_key_type() == iButtonKeyType::KeyDallas); |  | ||||||
|     furi_assert(key->get_type_data_size() == 8); |  | ||||||
| 
 |  | ||||||
|     onewire_slave->deattach(); |  | ||||||
|     memcpy(dallas_key.id_storage, key->get_data(), key->get_type_data_size()); |  | ||||||
|     onewire_slave->attach(&dallas_key); |  | ||||||
|     onewire_slave->start(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyEmulator::set_pulse_data_cyfral(uint8_t index, const uint32_t* data) { |  | ||||||
|     pulse_data[index * 2] = data[0]; |  | ||||||
|     pulse_data[index * 2 + 1] = data[1]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyEmulator::set_pulse_data_metakom(uint8_t index, const uint32_t* data) { |  | ||||||
|     // damn start pulse
 |  | ||||||
|     pulse_data[(index * 2) + 1] = data[0]; |  | ||||||
|     pulse_data[(index * 2) + 2] = data[1]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyEmulator::result_callback(bool success, void* ctx) { |  | ||||||
|     KeyEmulator* _this = static_cast<KeyEmulator*>(ctx); |  | ||||||
| 
 |  | ||||||
|     _this->anything_emulated = true; |  | ||||||
| } |  | ||||||
| @ -1,34 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "pulse_sequencer.h" |  | ||||||
| #include "../ibutton_key.h" |  | ||||||
| #include <one_wire_slave.h> |  | ||||||
| #include <one_wire_device_ds_1990.h> |  | ||||||
| #include <atomic> |  | ||||||
| 
 |  | ||||||
| class KeyEmulator { |  | ||||||
| public: |  | ||||||
|     KeyEmulator(OneWireSlave* onewire_slave); |  | ||||||
|     ~KeyEmulator(); |  | ||||||
| 
 |  | ||||||
|     void start(iButtonKey* key); |  | ||||||
|     bool emulated(); |  | ||||||
|     void stop(); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     DS1990 dallas_key; |  | ||||||
|     OneWireSlave* onewire_slave; |  | ||||||
| 
 |  | ||||||
|     PulseSequencer pulser; |  | ||||||
|     uint32_t pulse_data[72]; |  | ||||||
| 
 |  | ||||||
|     std::atomic<bool> anything_emulated; |  | ||||||
| 
 |  | ||||||
|     void start_cyfral_emulate(iButtonKey* key); |  | ||||||
|     void start_metakom_emulate(iButtonKey* key); |  | ||||||
|     void start_dallas_emulate(iButtonKey* key); |  | ||||||
| 
 |  | ||||||
|     void set_pulse_data_cyfral(uint8_t index, const uint32_t* data); |  | ||||||
|     void set_pulse_data_metakom(uint8_t index, const uint32_t* data); |  | ||||||
| 
 |  | ||||||
|     void result_callback(bool success, void* ctx); |  | ||||||
| }; |  | ||||||
| @ -1,11 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <stdint.h> |  | ||||||
| 
 |  | ||||||
| static const uint8_t IBUTTON_KEY_DATA_SIZE = 8; |  | ||||||
| static const uint8_t IBUTTON_KEY_NAME_SIZE = 22; |  | ||||||
| 
 |  | ||||||
| enum class iButtonKeyType : uint8_t { |  | ||||||
|     KeyDallas, |  | ||||||
|     KeyCyfral, |  | ||||||
|     KeyMetakom, |  | ||||||
| }; |  | ||||||
| @ -1,181 +0,0 @@ | |||||||
| #include "key_reader.h" |  | ||||||
| #include "key_commands.h" |  | ||||||
| #include <callback-connector.h> |  | ||||||
| #include <maxim_crc.h> |  | ||||||
| 
 |  | ||||||
| KeyReader::Error KeyReader::read(iButtonKey* key) { |  | ||||||
|     uint8_t tmp_key_data[8] = {0, 0, 0, 0, 0, 0, 0, 0}; |  | ||||||
|     iButtonKeyType key_type; |  | ||||||
| 
 |  | ||||||
|     KeyReader::Error result = KeyReader::Error::EMPTY; |  | ||||||
| 
 |  | ||||||
|     if(read_key(&key_type, tmp_key_data, 8)) { |  | ||||||
|         switch(key_type) { |  | ||||||
|         case iButtonKeyType::KeyDallas: |  | ||||||
|             if(verify_key(key_type, tmp_key_data, 8)) { |  | ||||||
|                 if(maxim_crc8(tmp_key_data, 8) == 0) { |  | ||||||
|                     if(tmp_key_data[0] == 0x01) { |  | ||||||
|                         result = KeyReader::Error::OK; |  | ||||||
|                     } else { |  | ||||||
|                         result = KeyReader::Error::NOT_ARE_KEY; |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     result = KeyReader::Error::CRC_ERROR; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             break; |  | ||||||
|         case iButtonKeyType::KeyCyfral: |  | ||||||
|             result = KeyReader::Error::OK; |  | ||||||
|             break; |  | ||||||
|         case iButtonKeyType::KeyMetakom: |  | ||||||
|             result = KeyReader::Error::OK; |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if(result != KeyReader::Error::EMPTY) { |  | ||||||
|             key->set_type(key_type); |  | ||||||
|             key->set_data(tmp_key_data, 8); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     switch_mode_if_needed(); |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| KeyReader::KeyReader(OneWireMaster* _onewire_master) { |  | ||||||
|     onewire_master = _onewire_master; |  | ||||||
|     read_mode_switch_time = 0; |  | ||||||
|     read_mode = ReadMode::DALLAS; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| KeyReader::~KeyReader() { |  | ||||||
|     stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool KeyReader::read_key(iButtonKeyType* key_type, uint8_t* data, uint8_t data_size) { |  | ||||||
|     bool readed = false; |  | ||||||
| 
 |  | ||||||
|     if(read_mode == ReadMode::DALLAS) { |  | ||||||
|         FURI_CRITICAL_ENTER(); |  | ||||||
|         if(onewire_master->search(data)) { |  | ||||||
|             onewire_master->reset_search(); |  | ||||||
|             readed = true; |  | ||||||
|             *key_type = iButtonKeyType::KeyDallas; |  | ||||||
|         } else { |  | ||||||
|             onewire_master->reset_search(); |  | ||||||
|         } |  | ||||||
|         FURI_CRITICAL_EXIT(); |  | ||||||
|     } else if(read_mode == ReadMode::CYFRAL_METAKOM) { |  | ||||||
|         if(cyfral_decoder.read(data, 2)) { |  | ||||||
|             readed = true; |  | ||||||
|             *key_type = iButtonKeyType::KeyCyfral; |  | ||||||
|         } else if(metakom_decoder.read(data, 4)) { |  | ||||||
|             readed = true; |  | ||||||
|             *key_type = iButtonKeyType::KeyMetakom; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return readed; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool KeyReader::verify_key(iButtonKeyType key_type, const uint8_t* const data, uint8_t data_size) { |  | ||||||
|     bool result = true; |  | ||||||
| 
 |  | ||||||
|     if(key_type == iButtonKeyType::KeyDallas) { |  | ||||||
|         switch_to(ReadMode::DALLAS); |  | ||||||
| 
 |  | ||||||
|         FURI_CRITICAL_ENTER(); |  | ||||||
|         if(onewire_master->reset()) { |  | ||||||
|             onewire_master->write(DS1990::CMD_READ_ROM); |  | ||||||
|             for(uint8_t i = 0; i < data_size; i++) { |  | ||||||
|                 if(onewire_master->read() != data[i]) { |  | ||||||
|                     result = false; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             result = false; |  | ||||||
|         } |  | ||||||
|         FURI_CRITICAL_EXIT(); |  | ||||||
| 
 |  | ||||||
|     } else { |  | ||||||
|         result = false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyReader::start_comaparator(void) { |  | ||||||
|     furi_hal_rfid_pins_reset(); |  | ||||||
| 
 |  | ||||||
|     // pulldown pull pin, we sense the signal through the analog part of the RFID schematic
 |  | ||||||
|     furi_hal_rfid_pin_pull_pulldown(); |  | ||||||
| 
 |  | ||||||
|     comparator_callback_pointer = |  | ||||||
|         cbc::obtain_connector(this, &KeyReader::comparator_trigger_callback); |  | ||||||
|     furi_hal_rfid_comp_set_callback(comparator_callback_pointer, this); |  | ||||||
|     last_dwt_value = DWT->CYCCNT; |  | ||||||
|     furi_hal_rfid_comp_start(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyReader::stop_comaparator(void) { |  | ||||||
|     furi_hal_rfid_pins_reset(); |  | ||||||
| 
 |  | ||||||
|     // rfid_pins_reset will disable ibutton pin
 |  | ||||||
|     furi_hal_ibutton_start(); |  | ||||||
| 
 |  | ||||||
|     furi_hal_rfid_comp_stop(); |  | ||||||
|     furi_hal_rfid_comp_set_callback(NULL, NULL); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyReader::comparator_trigger_callback(bool level, void* comp_ctx) { |  | ||||||
|     KeyReader* _this = static_cast<KeyReader*>(comp_ctx); |  | ||||||
| 
 |  | ||||||
|     uint32_t current_dwt_value = DWT->CYCCNT; |  | ||||||
| 
 |  | ||||||
|     _this->cyfral_decoder.process_front(level, current_dwt_value - last_dwt_value); |  | ||||||
|     _this->metakom_decoder.process_front(level, current_dwt_value - last_dwt_value); |  | ||||||
| 
 |  | ||||||
|     last_dwt_value = current_dwt_value; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyReader::switch_to(ReadMode mode) { |  | ||||||
|     switch(mode) { |  | ||||||
|     case ReadMode::DALLAS: |  | ||||||
|         onewire_master->start(); |  | ||||||
|         stop_comaparator(); |  | ||||||
|         break; |  | ||||||
|     case ReadMode::CYFRAL_METAKOM: |  | ||||||
|         onewire_master->stop(); |  | ||||||
|         start_comaparator(); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     read_mode = mode; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyReader::switch_mode_if_needed() { |  | ||||||
|     if(osKernelGetTickCount() - read_mode_switch_time > (osKernelGetTickFreq() / 5)) { |  | ||||||
|         read_mode_switch_time = osKernelGetTickCount(); |  | ||||||
|         switch(read_mode) { |  | ||||||
|         case ReadMode::DALLAS: |  | ||||||
|             switch_to(ReadMode::CYFRAL_METAKOM); |  | ||||||
|             break; |  | ||||||
|         case ReadMode::CYFRAL_METAKOM: |  | ||||||
|             switch_to(ReadMode::DALLAS); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyReader::start() { |  | ||||||
|     furi_hal_power_enable_otg(); |  | ||||||
|     switch_to(ReadMode::CYFRAL_METAKOM); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyReader::stop() { |  | ||||||
|     furi_hal_power_disable_otg(); |  | ||||||
|     onewire_master->stop(); |  | ||||||
|     stop_comaparator(); |  | ||||||
| } |  | ||||||
| @ -1,54 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <stdint.h> |  | ||||||
| #include <furi.h> |  | ||||||
| #include "cyfral_decoder.h" |  | ||||||
| #pragma once |  | ||||||
| #include "metakom_decoder.h" |  | ||||||
| #include "../ibutton_key.h" |  | ||||||
| #include <one_wire_master.h> |  | ||||||
| #include <one_wire_slave.h> |  | ||||||
| 
 |  | ||||||
| class KeyReader { |  | ||||||
| public: |  | ||||||
|     enum class Error : uint8_t { |  | ||||||
|         EMPTY, |  | ||||||
|         CRC_ERROR, |  | ||||||
|         NOT_ARE_KEY, |  | ||||||
|         OK, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     void start(); |  | ||||||
|     void stop(); |  | ||||||
|     KeyReader::Error read(iButtonKey* key); |  | ||||||
|     KeyReader(OneWireMaster* onewire_master); |  | ||||||
|     ~KeyReader(); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     bool read_key(iButtonKeyType* key_type, uint8_t* data, uint8_t data_size); |  | ||||||
|     bool verify_key(iButtonKeyType key_type, const uint8_t* const data, uint8_t data_size); |  | ||||||
| 
 |  | ||||||
|     // cyfral and metakom readers data
 |  | ||||||
|     void comparator_trigger_callback(bool level, void* comp_ctx); |  | ||||||
|     void (*comparator_callback_pointer)(bool level, void* comp_ctx); |  | ||||||
| 
 |  | ||||||
|     void start_comaparator(void); |  | ||||||
|     void stop_comaparator(void); |  | ||||||
|     uint32_t last_dwt_value; |  | ||||||
| 
 |  | ||||||
|     CyfralDecoder cyfral_decoder; |  | ||||||
|     MetakomDecoder metakom_decoder; |  | ||||||
| 
 |  | ||||||
|     // mode
 |  | ||||||
|     uint32_t read_mode_switch_time; |  | ||||||
|     enum class ReadMode : uint8_t { |  | ||||||
|         CYFRAL_METAKOM, |  | ||||||
|         DALLAS, |  | ||||||
|     }; |  | ||||||
|     ReadMode read_mode; |  | ||||||
| 
 |  | ||||||
|     // one wire
 |  | ||||||
|     OneWireMaster* onewire_master; |  | ||||||
| 
 |  | ||||||
|     void switch_to(ReadMode mode); |  | ||||||
|     void switch_mode_if_needed(); |  | ||||||
| }; |  | ||||||
| @ -1,52 +0,0 @@ | |||||||
| #include "key_worker.h" |  | ||||||
| #include <callback-connector.h> |  | ||||||
| #include <maxim_crc.h> |  | ||||||
| 
 |  | ||||||
| KeyReader::Error KeyWorker::read(iButtonKey* key) { |  | ||||||
|     KeyReader::Error result = key_reader.read(key); |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyWorker::start_read() { |  | ||||||
|     key_reader.start(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyWorker::stop_read() { |  | ||||||
|     key_reader.stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool KeyWorker::emulated() { |  | ||||||
|     return key_emulator.emulated(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyWorker::start_emulate(iButtonKey* key) { |  | ||||||
|     key_emulator.start(key); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyWorker::stop_emulate() { |  | ||||||
|     key_emulator.stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| KeyWriter::Error KeyWorker::write(iButtonKey* key) { |  | ||||||
|     return key_writer.write(key); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyWorker::start_write() { |  | ||||||
|     key_writer.start(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyWorker::stop_write() { |  | ||||||
|     key_writer.stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| KeyWorker::KeyWorker(const GpioPin* one_wire_gpio) |  | ||||||
|     : onewire_master{one_wire_gpio} |  | ||||||
|     , onewire_slave{one_wire_gpio} |  | ||||||
|     , key_reader{&onewire_master} |  | ||||||
|     , key_emulator{&onewire_slave} |  | ||||||
|     , key_writer{&onewire_master} { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| KeyWorker::~KeyWorker() { |  | ||||||
| } |  | ||||||
| @ -1,35 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <furi.h> |  | ||||||
| #include "key_info.h" |  | ||||||
| #include "key_reader.h" |  | ||||||
| #include "key_emulator.h" |  | ||||||
| #include "key_writer.h" |  | ||||||
| #include "../ibutton_key.h" |  | ||||||
| #include <one_wire_master.h> |  | ||||||
| #include <one_wire_slave.h> |  | ||||||
| 
 |  | ||||||
| class KeyWorker { |  | ||||||
| public: |  | ||||||
|     KeyReader::Error read(iButtonKey* key); |  | ||||||
|     void start_read(); |  | ||||||
|     void stop_read(); |  | ||||||
| 
 |  | ||||||
|     bool emulated(); |  | ||||||
|     void start_emulate(iButtonKey* key); |  | ||||||
|     void stop_emulate(); |  | ||||||
| 
 |  | ||||||
|     KeyWriter::Error write(iButtonKey* key); |  | ||||||
|     void start_write(); |  | ||||||
|     void stop_write(); |  | ||||||
| 
 |  | ||||||
|     KeyWorker(const GpioPin* one_wire_gpio); |  | ||||||
|     ~KeyWorker(); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     // one wire
 |  | ||||||
|     OneWireMaster onewire_master; |  | ||||||
|     OneWireSlave onewire_slave; |  | ||||||
|     KeyReader key_reader; |  | ||||||
|     KeyEmulator key_emulator; |  | ||||||
|     KeyWriter key_writer; |  | ||||||
| }; |  | ||||||
| @ -1,278 +0,0 @@ | |||||||
| #include "key_writer.h" |  | ||||||
| #include "key_commands.h" |  | ||||||
| 
 |  | ||||||
| KeyWriter::KeyWriter(OneWireMaster* _onewire_master) { |  | ||||||
|     onewire_master = _onewire_master; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| KeyWriter::~KeyWriter() { |  | ||||||
|     stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| KeyWriter::Error KeyWriter::write(iButtonKey* key) { |  | ||||||
|     return write_internal(key); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyWriter::start() { |  | ||||||
|     furi_hal_power_enable_otg(); |  | ||||||
|     onewire_master->start(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyWriter::stop() { |  | ||||||
|     furi_hal_power_disable_otg(); |  | ||||||
|     onewire_master->stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| KeyWriter::Error KeyWriter::write_internal(iButtonKey* key) { |  | ||||||
|     Error result = Error::NO_DETECT; |  | ||||||
|     bool same_key = false; |  | ||||||
| 
 |  | ||||||
|     osKernelLock(); |  | ||||||
|     bool presence = onewire_master->reset(); |  | ||||||
|     osKernelUnlock(); |  | ||||||
| 
 |  | ||||||
|     if(presence) { |  | ||||||
|         switch(key->get_key_type()) { |  | ||||||
|         case iButtonKeyType::KeyDallas: |  | ||||||
|             same_key = compare_key_ds1990(key); |  | ||||||
| 
 |  | ||||||
|             if(!same_key) { |  | ||||||
|                 bool write_result = false; |  | ||||||
|                 // currently we can write:
 |  | ||||||
|                 // RW1990, TM08v2, TM08vi-2 by write_1990_1()
 |  | ||||||
|                 // RW2004, RW2004 with EEPROM by write_TM2004();
 |  | ||||||
| 
 |  | ||||||
|                 if(!write_result) { |  | ||||||
|                     write_result = write_1990_1(key); |  | ||||||
|                 } |  | ||||||
|                 if(!write_result) { |  | ||||||
|                     write_result = write_1990_2(key); |  | ||||||
|                 } |  | ||||||
|                 if(!write_result) { |  | ||||||
|                     write_result = write_TM2004(key); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 if(write_result) { |  | ||||||
|                     result = Error::OK; |  | ||||||
|                 } else { |  | ||||||
|                     result = Error::CANNOT_WRITE; |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 result = Error::SAME_KEY; |  | ||||||
|             } |  | ||||||
|             break; |  | ||||||
| 
 |  | ||||||
|         default: |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool KeyWriter::compare_key_ds1990(iButtonKey* key) { |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     if(key->get_key_type() == iButtonKeyType::KeyDallas) { |  | ||||||
|         FURI_CRITICAL_ENTER(); |  | ||||||
|         bool presence = onewire_master->reset(); |  | ||||||
| 
 |  | ||||||
|         if(presence) { |  | ||||||
|             onewire_master->write(DS1990::CMD_READ_ROM); |  | ||||||
| 
 |  | ||||||
|             result = true; |  | ||||||
|             for(uint8_t i = 0; i < key->get_type_data_size(); i++) { |  | ||||||
|                 if(key->get_data()[i] != onewire_master->read()) { |  | ||||||
|                     result = false; |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         FURI_CRITICAL_EXIT(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool KeyWriter::write_1990_1(iButtonKey* key) { |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     if(key->get_key_type() == iButtonKeyType::KeyDallas) { |  | ||||||
|         FURI_CRITICAL_ENTER(); |  | ||||||
| 
 |  | ||||||
|         // unlock
 |  | ||||||
|         onewire_master->reset(); |  | ||||||
|         onewire_master->write(RW1990_1::CMD_WRITE_RECORD_FLAG); |  | ||||||
|         delay_us(10); |  | ||||||
|         onewire_write_one_bit(0, 5000); |  | ||||||
| 
 |  | ||||||
|         // write key
 |  | ||||||
|         onewire_master->reset(); |  | ||||||
|         onewire_master->write(RW1990_1::CMD_WRITE_ROM); |  | ||||||
|         for(uint8_t i = 0; i < key->get_type_data_size(); i++) { |  | ||||||
|             // inverted key for RW1990.1
 |  | ||||||
|             write_byte_ds1990(~key->get_data()[i]); |  | ||||||
|             delay_us(30000); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // lock
 |  | ||||||
|         onewire_master->write(RW1990_1::CMD_WRITE_RECORD_FLAG); |  | ||||||
|         onewire_write_one_bit(1); |  | ||||||
| 
 |  | ||||||
|         FURI_CRITICAL_EXIT(); |  | ||||||
| 
 |  | ||||||
|         if(compare_key_ds1990(key)) { |  | ||||||
|             result = true; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool KeyWriter::write_1990_2(iButtonKey* key) { |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     if(key->get_key_type() == iButtonKeyType::KeyDallas) { |  | ||||||
|         FURI_CRITICAL_ENTER(); |  | ||||||
| 
 |  | ||||||
|         // unlock
 |  | ||||||
|         onewire_master->reset(); |  | ||||||
|         onewire_master->write(RW1990_2::CMD_WRITE_RECORD_FLAG); |  | ||||||
|         delay_us(10); |  | ||||||
|         onewire_write_one_bit(1, 5000); |  | ||||||
| 
 |  | ||||||
|         // write key
 |  | ||||||
|         onewire_master->reset(); |  | ||||||
|         onewire_master->write(RW1990_2::CMD_WRITE_ROM); |  | ||||||
|         for(uint8_t i = 0; i < key->get_type_data_size(); i++) { |  | ||||||
|             write_byte_ds1990(key->get_data()[i]); |  | ||||||
|             delay_us(30000); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         // lock
 |  | ||||||
|         onewire_master->write(RW1990_2::CMD_WRITE_RECORD_FLAG); |  | ||||||
|         onewire_write_one_bit(0); |  | ||||||
| 
 |  | ||||||
|         FURI_CRITICAL_EXIT(); |  | ||||||
| 
 |  | ||||||
|         if(compare_key_ds1990(key)) { |  | ||||||
|             result = true; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool KeyWriter::write_TM2004(iButtonKey* key) { |  | ||||||
|     uint8_t answer; |  | ||||||
|     bool result = true; |  | ||||||
| 
 |  | ||||||
|     if(key->get_key_type() == iButtonKeyType::KeyDallas) { |  | ||||||
|         FURI_CRITICAL_ENTER(); |  | ||||||
| 
 |  | ||||||
|         // write rom, addr is 0x0000
 |  | ||||||
|         onewire_master->reset(); |  | ||||||
|         onewire_master->write(TM2004::CMD_WRITE_ROM); |  | ||||||
|         onewire_master->write(0x00); |  | ||||||
|         onewire_master->write(0x00); |  | ||||||
| 
 |  | ||||||
|         // write key
 |  | ||||||
|         for(uint8_t i = 0; i < key->get_type_data_size(); i++) { |  | ||||||
|             // write key byte
 |  | ||||||
|             onewire_master->write(key->get_data()[i]); |  | ||||||
|             answer = onewire_master->read(); |  | ||||||
|             // TODO: check answer CRC
 |  | ||||||
| 
 |  | ||||||
|             // pulse indicating that data is correct
 |  | ||||||
|             delay_us(600); |  | ||||||
|             onewire_write_one_bit(1, 50000); |  | ||||||
| 
 |  | ||||||
|             // read writed key byte
 |  | ||||||
|             answer = onewire_master->read(); |  | ||||||
| 
 |  | ||||||
|             // check that writed and readed are same
 |  | ||||||
|             if(key->get_data()[i] != answer) { |  | ||||||
|                 result = false; |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if(!compare_key_ds1990(key)) { |  | ||||||
|             result = false; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         onewire_master->reset(); |  | ||||||
| 
 |  | ||||||
|         FURI_CRITICAL_EXIT(); |  | ||||||
|     } else { |  | ||||||
|         result = false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool KeyWriter::write_TM01(iButtonKey* key) { |  | ||||||
|     /*bool result = true;
 |  | ||||||
| 
 |  | ||||||
|     // TODO test and encoding
 |  | ||||||
|     FURI_CRITICAL_ENTER(); |  | ||||||
| 
 |  | ||||||
|     // unlock
 |  | ||||||
|     onewire_master->reset(); |  | ||||||
|     onewire_master->write(TM01::CMD_WRITE_RECORD_FLAG); |  | ||||||
|     onewire_write_one_bit(1, 10000); |  | ||||||
| 
 |  | ||||||
|     // write key
 |  | ||||||
|     onewire_master->reset(); |  | ||||||
|     onewire_master->write(TM01::CMD_WRITE_ROM); |  | ||||||
| 
 |  | ||||||
|     // TODO: key types
 |  | ||||||
|     //if(type == KEY_METAKOM || type == KEY_CYFRAL) {
 |  | ||||||
|     //} else {
 |  | ||||||
|     for(uint8_t i = 0; i < key->get_type_data_size(); i++) { |  | ||||||
|         write_byte_ds1990(key->get_data()[i]); |  | ||||||
|         delay_us(10000); |  | ||||||
|     } |  | ||||||
|     //}
 |  | ||||||
| 
 |  | ||||||
|     // lock
 |  | ||||||
|     onewire_master->write(TM01::CMD_WRITE_RECORD_FLAG); |  | ||||||
|     onewire_write_one_bit(0, 10000); |  | ||||||
| 
 |  | ||||||
|     FURI_CRITICAL_EXIT(); |  | ||||||
| 
 |  | ||||||
|     if(!compare_key_ds1990(key)) { |  | ||||||
|         result = false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     FURI_CRITICAL_ENTER(); |  | ||||||
| 
 |  | ||||||
|     if(key->get_key_type() == iButtonKeyType::KeyMetakom || |  | ||||||
|        key->get_key_type() == iButtonKeyType::KeyCyfral) { |  | ||||||
|         onewire_master->reset(); |  | ||||||
|         if(key->get_key_type() == iButtonKeyType::KeyCyfral) |  | ||||||
|             onewire_master->write(TM01::CMD_SWITCH_TO_CYFRAL); |  | ||||||
|         else |  | ||||||
|             onewire_master->write(TM01::CMD_SWITCH_TO_METAKOM); |  | ||||||
|         onewire_write_one_bit(1); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     FURI_CRITICAL_EXIT(); |  | ||||||
| 
 |  | ||||||
|     return result;*/ |  | ||||||
|     return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyWriter::onewire_write_one_bit(bool value, uint32_t delay) { |  | ||||||
|     onewire_master->write_bit(value); |  | ||||||
|     delay_us(delay); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void KeyWriter::write_byte_ds1990(uint8_t data) { |  | ||||||
|     for(uint8_t n_bit = 0; n_bit < 8; n_bit++) { |  | ||||||
|         onewire_master->write_bit(data & 1); |  | ||||||
|         delay_us(5000); |  | ||||||
|         data = data >> 1; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,35 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include "../ibutton_key.h" |  | ||||||
| #include <one_wire_master.h> |  | ||||||
| 
 |  | ||||||
| class KeyWriter { |  | ||||||
| public: |  | ||||||
|     enum class Error : uint8_t { |  | ||||||
|         OK, |  | ||||||
|         SAME_KEY, |  | ||||||
|         NO_DETECT, |  | ||||||
|         CANNOT_WRITE, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     KeyWriter(OneWireMaster* onewire_master); |  | ||||||
|     ~KeyWriter(); |  | ||||||
| 
 |  | ||||||
|     KeyWriter::Error write(iButtonKey* key); |  | ||||||
|     void start(); |  | ||||||
|     void stop(); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     OneWireMaster* onewire_master; |  | ||||||
| 
 |  | ||||||
|     KeyWriter::Error write_internal(iButtonKey* key); |  | ||||||
|     bool compare_key_ds1990(iButtonKey* key); |  | ||||||
| 
 |  | ||||||
|     // write strategy
 |  | ||||||
|     bool write_1990_1(iButtonKey* key); |  | ||||||
|     bool write_1990_2(iButtonKey* key); |  | ||||||
|     bool write_TM2004(iButtonKey* key); |  | ||||||
|     bool write_TM01(iButtonKey* key); |  | ||||||
| 
 |  | ||||||
|     void onewire_write_one_bit(bool value, uint32_t delay = 10000); |  | ||||||
|     void write_byte_ds1990(uint8_t data); |  | ||||||
| }; |  | ||||||
| @ -1,191 +0,0 @@ | |||||||
| #include "metakom_decoder.h" |  | ||||||
| #include <furi.h> |  | ||||||
| 
 |  | ||||||
| bool MetakomDecoder::read(uint8_t* _data, uint8_t data_size) { |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     if(ready) { |  | ||||||
|         memcpy(_data, &key_data, 4); |  | ||||||
|         reset_state(); |  | ||||||
|         result = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void MetakomDecoder::process_front(bool polarity, uint32_t time) { |  | ||||||
|     if(max_period == 0) { |  | ||||||
|         max_period = 230 * (SystemCoreClock / 1000000.0f); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(ready) return; |  | ||||||
| 
 |  | ||||||
|     uint32_t high_time = 0; |  | ||||||
|     uint32_t low_time = 0; |  | ||||||
| 
 |  | ||||||
|     switch(state) { |  | ||||||
|     case State::WAIT_PERIOD_SYNC: |  | ||||||
|         if(process_bit(polarity, time, &high_time, &low_time)) { |  | ||||||
|             period_sample_data[period_sample_index] = high_time + low_time; |  | ||||||
|             period_sample_index++; |  | ||||||
| 
 |  | ||||||
|             if(period_sample_index == period_sample_count) { |  | ||||||
|                 for(uint8_t i = 0; i < period_sample_count; i++) { |  | ||||||
|                     period_time += period_sample_data[i]; |  | ||||||
|                 }; |  | ||||||
|                 period_time /= period_sample_count; |  | ||||||
| 
 |  | ||||||
|                 state = State::WAIT_START_BIT; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         break; |  | ||||||
|     case State::WAIT_START_BIT: |  | ||||||
|         if(process_bit(polarity, time, &high_time, &low_time)) { |  | ||||||
|             tmp_counter++; |  | ||||||
|             if(high_time > period_time) { |  | ||||||
|                 tmp_counter = 0; |  | ||||||
|                 state = State::WAIT_START_WORD; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if(tmp_counter > 40) { |  | ||||||
|                 reset_state(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         break; |  | ||||||
|     case State::WAIT_START_WORD: |  | ||||||
|         if(process_bit(polarity, time, &high_time, &low_time)) { |  | ||||||
|             if(low_time < (period_time / 2)) { |  | ||||||
|                 tmp_data = (tmp_data << 1) | 0b0; |  | ||||||
|             } else { |  | ||||||
|                 tmp_data = (tmp_data << 1) | 0b1; |  | ||||||
|             } |  | ||||||
|             tmp_counter++; |  | ||||||
| 
 |  | ||||||
|             if(tmp_counter == 3) { |  | ||||||
|                 if(tmp_data == 0b010) { |  | ||||||
|                     tmp_counter = 0; |  | ||||||
|                     tmp_data = 0; |  | ||||||
|                     state = State::READ_WORD; |  | ||||||
|                 } else { |  | ||||||
|                     reset_state(); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     case State::READ_WORD: |  | ||||||
|         if(process_bit(polarity, time, &high_time, &low_time)) { |  | ||||||
|             if(low_time < (period_time / 2)) { |  | ||||||
|                 tmp_data = (tmp_data << 1) | 0b0; |  | ||||||
|             } else { |  | ||||||
|                 tmp_data = (tmp_data << 1) | 0b1; |  | ||||||
|             } |  | ||||||
|             tmp_counter++; |  | ||||||
| 
 |  | ||||||
|             if(tmp_counter == 8) { |  | ||||||
|                 if(parity_check(tmp_data)) { |  | ||||||
|                     key_data = (key_data << 8) | tmp_data; |  | ||||||
|                     key_data_index++; |  | ||||||
|                     tmp_data = 0; |  | ||||||
|                     tmp_counter = 0; |  | ||||||
| 
 |  | ||||||
|                     if(key_data_index == 4) { |  | ||||||
|                         // check for stop bit
 |  | ||||||
|                         if(high_time > period_time) { |  | ||||||
|                             state = State::READ_STOP_WORD; |  | ||||||
|                         } else { |  | ||||||
|                             reset_state(); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     reset_state(); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     case State::READ_STOP_WORD: |  | ||||||
|         if(process_bit(polarity, time, &high_time, &low_time)) { |  | ||||||
|             if(low_time < (period_time / 2)) { |  | ||||||
|                 tmp_data = (tmp_data << 1) | 0b0; |  | ||||||
|             } else { |  | ||||||
|                 tmp_data = (tmp_data << 1) | 0b1; |  | ||||||
|             } |  | ||||||
|             tmp_counter++; |  | ||||||
| 
 |  | ||||||
|             if(tmp_counter == 3) { |  | ||||||
|                 if(tmp_data == 0b010) { |  | ||||||
|                     ready = true; |  | ||||||
|                 } else { |  | ||||||
|                     reset_state(); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| MetakomDecoder::MetakomDecoder() { |  | ||||||
|     reset_state(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void MetakomDecoder::reset_state() { |  | ||||||
|     ready = false; |  | ||||||
|     period_sample_index = 0; |  | ||||||
|     period_time = 0; |  | ||||||
| 
 |  | ||||||
|     tmp_counter = 0; |  | ||||||
|     tmp_data = 0; |  | ||||||
| 
 |  | ||||||
|     for(uint8_t i = 0; i < period_sample_count; i++) { |  | ||||||
|         period_sample_data[i] = 0; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     state = State::WAIT_PERIOD_SYNC; |  | ||||||
|     bit_state = BitState::WAIT_FRONT_LOW; |  | ||||||
| 
 |  | ||||||
|     key_data = 0; |  | ||||||
|     key_data_index = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool MetakomDecoder::parity_check(uint8_t data) { |  | ||||||
|     uint8_t ones_count = 0; |  | ||||||
|     bool result; |  | ||||||
| 
 |  | ||||||
|     for(uint8_t i = 0; i < 8; i++) { |  | ||||||
|         if((data >> i) & 0b00000001) { |  | ||||||
|             ones_count++; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     result = (ones_count % 2 == 0); |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool MetakomDecoder::process_bit( |  | ||||||
|     bool polarity, |  | ||||||
|     uint32_t time, |  | ||||||
|     uint32_t* high_time, |  | ||||||
|     uint32_t* low_time) { |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     switch(bit_state) { |  | ||||||
|     case BitState::WAIT_FRONT_LOW: |  | ||||||
|         if(polarity == false) { |  | ||||||
|             *low_time = low_time_storage; |  | ||||||
|             *high_time = time; |  | ||||||
|             result = true; |  | ||||||
|             bit_state = BitState::WAIT_FRONT_HIGH; |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     case BitState::WAIT_FRONT_HIGH: |  | ||||||
|         if(polarity == true) { |  | ||||||
|             low_time_storage = time; |  | ||||||
|             bit_state = BitState::WAIT_FRONT_LOW; |  | ||||||
|         } |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| @ -1,54 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <stdint.h> |  | ||||||
| #include <atomic> |  | ||||||
| 
 |  | ||||||
| class MetakomDecoder { |  | ||||||
| public: |  | ||||||
|     bool read(uint8_t* data, uint8_t data_size); |  | ||||||
|     void process_front(bool polarity, uint32_t time); |  | ||||||
| 
 |  | ||||||
|     MetakomDecoder(); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     enum class BitState : uint8_t { |  | ||||||
|         WAIT_FRONT_HIGH, |  | ||||||
|         WAIT_FRONT_LOW, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     BitState bit_state; |  | ||||||
| 
 |  | ||||||
|     enum class State : uint8_t { |  | ||||||
|         WAIT_PERIOD_SYNC, |  | ||||||
|         WAIT_START_BIT, |  | ||||||
|         WAIT_START_WORD, |  | ||||||
|         READ_WORD, |  | ||||||
|         READ_STOP_WORD, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     State state; |  | ||||||
| 
 |  | ||||||
|     // high + low period time
 |  | ||||||
|     uint32_t period_time; |  | ||||||
|     uint32_t low_time_storage; |  | ||||||
| 
 |  | ||||||
|     static const uint8_t period_sample_count = 10; |  | ||||||
|     uint8_t period_sample_index; |  | ||||||
|     uint32_t period_sample_data[period_sample_count]; |  | ||||||
| 
 |  | ||||||
|     // ready flag, key is readed and valid
 |  | ||||||
|     std::atomic<bool> ready; |  | ||||||
| 
 |  | ||||||
|     // max period, 230us x clock per us
 |  | ||||||
|     uint32_t max_period; |  | ||||||
| 
 |  | ||||||
|     uint8_t tmp_data; |  | ||||||
|     uint8_t tmp_counter; |  | ||||||
| 
 |  | ||||||
|     uint32_t key_data; |  | ||||||
|     uint8_t key_data_index; |  | ||||||
| 
 |  | ||||||
|     void reset_state(); |  | ||||||
|     bool parity_check(uint8_t data); |  | ||||||
| 
 |  | ||||||
|     bool process_bit(bool polarity, uint32_t time, uint32_t* high_time, uint32_t* low_time); |  | ||||||
| }; |  | ||||||
| @ -1,52 +0,0 @@ | |||||||
| #include "pulse_sequencer.h" |  | ||||||
| 
 |  | ||||||
| #include <furi.h> |  | ||||||
| #include <furi_hal.h> |  | ||||||
| 
 |  | ||||||
| void PulseSequencer::set_periods( |  | ||||||
|     uint32_t* _periods, |  | ||||||
|     uint16_t _periods_count, |  | ||||||
|     bool _pin_start_state) { |  | ||||||
|     periods = _periods; |  | ||||||
|     periods_count = _periods_count; |  | ||||||
|     pin_start_state = _pin_start_state; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void PulseSequencer::start() { |  | ||||||
|     period_index = 1; |  | ||||||
|     pin_state = pin_start_state; |  | ||||||
|     hal_gpio_write(&ibutton_gpio, pin_state); |  | ||||||
|     pin_state = !pin_state; |  | ||||||
| 
 |  | ||||||
|     hal_gpio_init(&ibutton_gpio, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedVeryHigh); |  | ||||||
|     furi_hal_ibutton_emulate_start( |  | ||||||
|         periods[period_index], PulseSequencer::timer_elapsed_callback, this); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void PulseSequencer::stop() { |  | ||||||
|     furi_hal_ibutton_emulate_stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| PulseSequencer::~PulseSequencer() { |  | ||||||
|     stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void PulseSequencer::timer_elapsed_callback(void* context) { |  | ||||||
|     PulseSequencer* self = static_cast<PulseSequencer*>(context); |  | ||||||
| 
 |  | ||||||
|     furi_hal_ibutton_emulate_set_next(self->periods[self->period_index]); |  | ||||||
| 
 |  | ||||||
|     if(self->period_index == 0) { |  | ||||||
|         self->pin_state = self->pin_start_state; |  | ||||||
|     } else { |  | ||||||
|         self->pin_state = !self->pin_state; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     hal_gpio_write(&ibutton_gpio, self->pin_state); |  | ||||||
| 
 |  | ||||||
|     self->period_index++; |  | ||||||
| 
 |  | ||||||
|     if(self->period_index == self->periods_count) { |  | ||||||
|         self->period_index = 0; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,26 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <stdint.h> |  | ||||||
| 
 |  | ||||||
| class PulseSequencer { |  | ||||||
| public: |  | ||||||
|     void set_periods(uint32_t* periods, uint16_t periods_count, bool pin_start_state); |  | ||||||
|     void start(); |  | ||||||
|     void stop(); |  | ||||||
| 
 |  | ||||||
|     ~PulseSequencer(); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     uint16_t period_index; |  | ||||||
|     uint16_t periods_count; |  | ||||||
|     uint32_t* periods; |  | ||||||
|     bool pin_start_state; |  | ||||||
|     bool pin_state; |  | ||||||
| 
 |  | ||||||
|     void init_timer(uint32_t period); |  | ||||||
| 
 |  | ||||||
|     void reset_period_index(PulseSequencer* _this); |  | ||||||
| 
 |  | ||||||
|     void (*callback_pointer)(void*, void*); |  | ||||||
| 
 |  | ||||||
|     static void timer_elapsed_callback(void* comp_ctx); |  | ||||||
| }; |  | ||||||
| @ -1,6 +1,6 @@ | |||||||
| #include "ibutton_app.h" | #include "ibutton_app.h" | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
| #include <callback-connector.h> | #include <furi_hal.h> | ||||||
| #include <m-string.h> | #include <m-string.h> | ||||||
| #include <toolbox/path.h> | #include <toolbox/path.h> | ||||||
| #include <flipper_format/flipper_format.h> | #include <flipper_format/flipper_format.h> | ||||||
| @ -42,7 +42,9 @@ iButtonApp::iButtonApp() | |||||||
|     , storage{"storage"} |     , storage{"storage"} | ||||||
|     , dialogs{"dialogs"} { |     , dialogs{"dialogs"} { | ||||||
|     furi_hal_power_insomnia_enter(); |     furi_hal_power_insomnia_enter(); | ||||||
|     key_worker = new KeyWorker(&ibutton_gpio); |     key = ibutton_key_alloc(); | ||||||
|  |     key_worker = ibutton_worker_alloc(); | ||||||
|  |     ibutton_worker_start_thread(key_worker); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| iButtonApp::~iButtonApp() { | iButtonApp::~iButtonApp() { | ||||||
| @ -50,7 +52,10 @@ iButtonApp::~iButtonApp() { | |||||||
|         delete it->second; |         delete it->second; | ||||||
|     } |     } | ||||||
|     scenes.clear(); |     scenes.clear(); | ||||||
|     delete key_worker; | 
 | ||||||
|  |     ibutton_worker_stop_thread(key_worker); | ||||||
|  |     ibutton_worker_free(key_worker); | ||||||
|  |     ibutton_key_free(key); | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_insomnia_exit(); |     furi_hal_power_insomnia_exit(); | ||||||
| } | } | ||||||
| @ -112,17 +117,12 @@ iButtonApp::Scene iButtonApp::get_previous_scene() { | |||||||
|     return scene; |     return scene; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const GpioPin* iButtonApp::get_ibutton_pin() { | iButtonWorker* iButtonApp::get_key_worker() { | ||||||
|     // TODO open record
 |  | ||||||
|     return &ibutton_gpio; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| KeyWorker* iButtonApp::get_key_worker() { |  | ||||||
|     return key_worker; |     return key_worker; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| iButtonKey* iButtonApp::get_key() { | iButtonKey* iButtonApp::get_key() { | ||||||
|     return &key; |     return key; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| char* iButtonApp::get_file_name() { | char* iButtonApp::get_file_name() { | ||||||
| @ -201,10 +201,11 @@ bool iButtonApp::save_key(const char* key_name) { | |||||||
|         if(!delete_key()) break; |         if(!delete_key()) break; | ||||||
| 
 | 
 | ||||||
|         // Save the key
 |         // Save the key
 | ||||||
|         key.set_name(key_name); |         ibutton_key_set_name(key, key_name); | ||||||
| 
 | 
 | ||||||
|         // Set full file name, for new key
 |         // Set full file name, for new key
 | ||||||
|         string_printf(key_file_name, "%s/%s%s", app_folder, key.get_name(), app_extension); |         string_printf( | ||||||
|  |             key_file_name, "%s/%s%s", app_folder, ibutton_key_get_name_p(key), app_extension); | ||||||
| 
 | 
 | ||||||
|         // Open file for write
 |         // Open file for write
 | ||||||
|         if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break; |         if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break; | ||||||
| @ -215,7 +216,7 @@ bool iButtonApp::save_key(const char* key_name) { | |||||||
|         // Write key type
 |         // Write key type
 | ||||||
|         if(!flipper_format_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom")) |         if(!flipper_format_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom")) | ||||||
|             break; |             break; | ||||||
|         const char* key_type = key.get_key_type_string_by_type(key.get_key_type()); |         const char* key_type = ibutton_key_get_string_by_type(ibutton_key_get_type(key)); | ||||||
|         if(!flipper_format_write_string_cstr(file, "Key type", key_type)) break; |         if(!flipper_format_write_string_cstr(file, "Key type", key_type)) break; | ||||||
| 
 | 
 | ||||||
|         // Write data
 |         // Write data
 | ||||||
| @ -223,7 +224,8 @@ bool iButtonApp::save_key(const char* key_name) { | |||||||
|                file, "Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8")) |                file, "Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8")) | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         if(!flipper_format_write_hex(file, "Data", key.get_data(), key.get_type_data_size())) |         if(!flipper_format_write_hex( | ||||||
|  |                file, "Data", ibutton_key_get_data_p(key), ibutton_key_get_data_size(key))) | ||||||
|             break; |             break; | ||||||
|         result = true; |         result = true; | ||||||
| 
 | 
 | ||||||
| @ -258,15 +260,15 @@ bool iButtonApp::load_key_data(string_t key_path) { | |||||||
|         // key type
 |         // key type
 | ||||||
|         iButtonKeyType type; |         iButtonKeyType type; | ||||||
|         if(!flipper_format_read_string(file, "Key type", data)) break; |         if(!flipper_format_read_string(file, "Key type", data)) break; | ||||||
|         if(!key.get_key_type_by_type_string(string_get_cstr(data), &type)) break; |         if(!ibutton_key_get_type_by_string(string_get_cstr(data), &type)) break; | ||||||
| 
 | 
 | ||||||
|         // key data
 |         // key data
 | ||||||
|         uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0}; |         uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0}; | ||||||
|         if(!flipper_format_read_hex(file, "Data", key_data, key.get_type_data_size_by_type(type))) |         if(!flipper_format_read_hex(file, "Data", key_data, ibutton_key_get_size_by_type(type))) | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         key.set_type(type); |         ibutton_key_set_type(key, type); | ||||||
|         key.set_data(key_data, IBUTTON_KEY_DATA_SIZE); |         ibutton_key_set_data(key, key_data, IBUTTON_KEY_DATA_SIZE); | ||||||
| 
 | 
 | ||||||
|         result = true; |         result = true; | ||||||
|     } while(false); |     } while(false); | ||||||
| @ -290,7 +292,7 @@ bool iButtonApp::load_key(const char* key_name) { | |||||||
|     result = load_key_data(key_path); |     result = load_key_data(key_path); | ||||||
|     if(result) { |     if(result) { | ||||||
|         path_extract_filename_no_ext(key_name, key_path); |         path_extract_filename_no_ext(key_name, key_path); | ||||||
|         get_key()->set_name(string_get_cstr(key_path)); |         ibutton_key_set_name(key, string_get_cstr(key_path)); | ||||||
|     } |     } | ||||||
|     string_clear(key_path); |     string_clear(key_path); | ||||||
|     return result; |     return result; | ||||||
| @ -306,7 +308,7 @@ bool iButtonApp::load_key() { | |||||||
|         app_extension, |         app_extension, | ||||||
|         get_file_name(), |         get_file_name(), | ||||||
|         get_file_name_size(), |         get_file_name_size(), | ||||||
|         get_key()->get_name()); |         ibutton_key_get_name_p(key)); | ||||||
| 
 | 
 | ||||||
|     if(res) { |     if(res) { | ||||||
|         string_t key_str; |         string_t key_str; | ||||||
| @ -316,7 +318,7 @@ bool iButtonApp::load_key() { | |||||||
| 
 | 
 | ||||||
|         result = load_key_data(key_str); |         result = load_key_data(key_str); | ||||||
|         if(result) { |         if(result) { | ||||||
|             get_key()->set_name(get_file_name()); |             ibutton_key_set_name(key, get_file_name()); | ||||||
|         } |         } | ||||||
|         string_clear(key_str); |         string_clear(key_str); | ||||||
|     } |     } | ||||||
| @ -328,7 +330,8 @@ bool iButtonApp::delete_key() { | |||||||
|     string_t file_name; |     string_t file_name; | ||||||
|     bool result = false; |     bool result = false; | ||||||
| 
 | 
 | ||||||
|     string_init_printf(file_name, "%s/%s%s", app_folder, get_key()->get_name(), app_extension); |     string_init_printf( | ||||||
|  |         file_name, "%s/%s%s", app_folder, ibutton_key_get_name_p(key), app_extension); | ||||||
|     result = storage_simply_remove(storage, string_get_cstr(file_name)); |     result = storage_simply_remove(storage, string_get_cstr(file_name)); | ||||||
|     string_clear(file_name); |     string_clear(file_name); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -22,17 +22,10 @@ | |||||||
| #include "scene/ibutton_scene_select_key.h" | #include "scene/ibutton_scene_select_key.h" | ||||||
| #include "scene/ibutton_scene_add_type.h" | #include "scene/ibutton_scene_add_type.h" | ||||||
| #include "scene/ibutton_scene_add_value.h" | #include "scene/ibutton_scene_add_value.h" | ||||||
| 
 | #include <one_wire/ibutton/ibutton_worker.h> | ||||||
| #include "helpers/key_worker.h" |  | ||||||
| 
 |  | ||||||
| #include "one_wire_master.h" |  | ||||||
| #include "maxim_crc.h" |  | ||||||
| #include "ibutton_key.h" |  | ||||||
| 
 |  | ||||||
| #include <notification/notification_messages.h> | #include <notification/notification_messages.h> | ||||||
| #include <storage/storage.h> | #include <storage/storage.h> | ||||||
| #include <dialogs/dialogs.h> | #include <dialogs/dialogs.h> | ||||||
| 
 |  | ||||||
| #include <record_controller.hpp> | #include <record_controller.hpp> | ||||||
| 
 | 
 | ||||||
| class iButtonApp { | class iButtonApp { | ||||||
| @ -75,7 +68,7 @@ public: | |||||||
|     Scene get_previous_scene(); |     Scene get_previous_scene(); | ||||||
| 
 | 
 | ||||||
|     const GpioPin* get_ibutton_pin(); |     const GpioPin* get_ibutton_pin(); | ||||||
|     KeyWorker* get_key_worker(); |     iButtonWorker* get_key_worker(); | ||||||
|     iButtonKey* get_key(); |     iButtonKey* get_key(); | ||||||
| 
 | 
 | ||||||
|     void notify_green_blink(); |     void notify_green_blink(); | ||||||
| @ -127,9 +120,8 @@ private: | |||||||
|         {Scene::SceneAddValue, new iButtonSceneAddValue()}, |         {Scene::SceneAddValue, new iButtonSceneAddValue()}, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     KeyWorker* key_worker; |     iButtonWorker* key_worker; | ||||||
| 
 |     iButtonKey* key; | ||||||
|     iButtonKey key; |  | ||||||
| 
 | 
 | ||||||
|     RecordController<NotificationApp> notification; |     RecordController<NotificationApp> notification; | ||||||
|     RecordController<Storage> storage; |     RecordController<Storage> storage; | ||||||
|  | |||||||
							
								
								
									
										309
									
								
								applications/ibutton/ibutton_cli.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										309
									
								
								applications/ibutton/ibutton_cli.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,309 @@ | |||||||
|  | #include <furi.h> | ||||||
|  | #include <furi_hal.h> | ||||||
|  | #include <stdarg.h> | ||||||
|  | #include <cli/cli.h> | ||||||
|  | #include <lib/toolbox/args.h> | ||||||
|  | #include <one_wire/ibutton/ibutton_worker.h> | ||||||
|  | #include <one_wire/one_wire_host.h> | ||||||
|  | 
 | ||||||
|  | void ibutton_cli(Cli* cli, string_t args, void* context); | ||||||
|  | void onewire_cli(Cli* cli, string_t args, void* context); | ||||||
|  | 
 | ||||||
|  | // app cli function
 | ||||||
|  | void ibutton_on_system_start() { | ||||||
|  | #ifdef SRV_CLI | ||||||
|  |     Cli* cli = furi_record_open("cli"); | ||||||
|  |     cli_add_command(cli, "ikey", CliCommandFlagDefault, ibutton_cli, cli); | ||||||
|  |     cli_add_command(cli, "onewire", CliCommandFlagDefault, onewire_cli, cli); | ||||||
|  |     furi_record_close("cli"); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ibutton_cli_print_usage() { | ||||||
|  |     printf("Usage:\r\n"); | ||||||
|  |     printf("ikey read\r\n"); | ||||||
|  |     printf("ikey emulate <key_type> <key_data>\r\n"); | ||||||
|  |     printf("ikey write Dallas <key_data>\r\n"); | ||||||
|  |     printf("\t<key_type> choose from:\r\n"); | ||||||
|  |     printf("\tDallas (8 bytes key_data)\r\n"); | ||||||
|  |     printf("\tCyfral (2 bytes key_data)\r\n"); | ||||||
|  |     printf("\tMetakom (4 bytes key_data), must contain correct parity\r\n"); | ||||||
|  |     printf("\t<key_data> are hex-formatted\r\n"); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | bool ibutton_cli_get_key_type(string_t data, iButtonKeyType* type) { | ||||||
|  |     bool result = false; | ||||||
|  | 
 | ||||||
|  |     if(string_cmp_str(data, "Dallas") == 0 || string_cmp_str(data, "dallas") == 0) { | ||||||
|  |         result = true; | ||||||
|  |         *type = iButtonKeyDS1990; | ||||||
|  |     } else if(string_cmp_str(data, "Cyfral") == 0 || string_cmp_str(data, "cyfral") == 0) { | ||||||
|  |         result = true; | ||||||
|  |         *type = iButtonKeyCyfral; | ||||||
|  |     } else if(string_cmp_str(data, "Metakom") == 0 || string_cmp_str(data, "metakom") == 0) { | ||||||
|  |         result = true; | ||||||
|  |         *type = iButtonKeyMetakom; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ibutton_cli_print_key_data(iButtonKey* key) { | ||||||
|  |     const uint8_t* key_data = ibutton_key_get_data_p(key); | ||||||
|  |     iButtonKeyType type = ibutton_key_get_type(key); | ||||||
|  | 
 | ||||||
|  |     printf("%s ", ibutton_key_get_string_by_type(type)); | ||||||
|  |     for(size_t i = 0; i < ibutton_key_get_size_by_type(type); i++) { | ||||||
|  |         printf("%02X", key_data[i]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     printf("\r\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define EVENT_FLAG_IBUTTON_COMPLETE (1 << 0) | ||||||
|  | 
 | ||||||
|  | static void ibutton_cli_worker_read_cb(void* context) { | ||||||
|  |     osEventFlagsId_t event = context; | ||||||
|  |     osEventFlagsSet(event, EVENT_FLAG_IBUTTON_COMPLETE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ibutton_cli_read(Cli* cli) { | ||||||
|  |     iButtonKey* key = ibutton_key_alloc(); | ||||||
|  |     iButtonWorker* worker = ibutton_worker_alloc(); | ||||||
|  |     osEventFlagsId_t event = osEventFlagsNew(NULL); | ||||||
|  | 
 | ||||||
|  |     ibutton_worker_start_thread(worker); | ||||||
|  |     ibutton_worker_read_set_callback(worker, ibutton_cli_worker_read_cb, event); | ||||||
|  | 
 | ||||||
|  |     printf("Reading iButton...\r\nPress Ctrl+C to abort\r\n"); | ||||||
|  |     ibutton_worker_read_start(worker, key); | ||||||
|  |     while(true) { | ||||||
|  |         uint32_t flags = osEventFlagsWait(event, EVENT_FLAG_IBUTTON_COMPLETE, osFlagsWaitAny, 100); | ||||||
|  | 
 | ||||||
|  |         if(flags & EVENT_FLAG_IBUTTON_COMPLETE) { | ||||||
|  |             ibutton_cli_print_key_data(key); | ||||||
|  | 
 | ||||||
|  |             if(ibutton_key_get_type(key) == iButtonKeyDS1990) { | ||||||
|  |                 if(!ibutton_key_dallas_crc_is_valid(key)) { | ||||||
|  |                     printf("Warning: invalid CRC\r\n"); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if(!ibutton_key_dallas_is_1990_key(key)) { | ||||||
|  |                     printf("Warning: not a key\r\n"); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(cli_cmd_interrupt_received(cli)) break; | ||||||
|  |     } | ||||||
|  |     ibutton_worker_stop(worker); | ||||||
|  | 
 | ||||||
|  |     ibutton_worker_stop_thread(worker); | ||||||
|  |     ibutton_worker_free(worker); | ||||||
|  |     ibutton_key_free(key); | ||||||
|  | 
 | ||||||
|  |     osEventFlagsDelete(event); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     osEventFlagsId_t event; | ||||||
|  |     iButtonWorkerWriteResult result; | ||||||
|  | } iButtonWriteContext; | ||||||
|  | 
 | ||||||
|  | static void ibutton_cli_worker_write_cb(void* context, iButtonWorkerWriteResult result) { | ||||||
|  |     iButtonWriteContext* write_context = (iButtonWriteContext*)context; | ||||||
|  |     write_context->result = result; | ||||||
|  |     osEventFlagsSet(write_context->event, EVENT_FLAG_IBUTTON_COMPLETE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ibutton_cli_write(Cli* cli, string_t args) { | ||||||
|  |     iButtonKey* key = ibutton_key_alloc(); | ||||||
|  |     iButtonWorker* worker = ibutton_worker_alloc(); | ||||||
|  |     iButtonKeyType type; | ||||||
|  |     iButtonWriteContext write_context; | ||||||
|  |     uint8_t key_data[IBUTTON_KEY_DATA_SIZE]; | ||||||
|  |     string_t data; | ||||||
|  | 
 | ||||||
|  |     write_context.event = osEventFlagsNew(NULL); | ||||||
|  | 
 | ||||||
|  |     string_init(data); | ||||||
|  |     ibutton_worker_start_thread(worker); | ||||||
|  |     ibutton_worker_write_set_callback(worker, ibutton_cli_worker_write_cb, &write_context); | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         if(!args_read_string_and_trim(args, data)) { | ||||||
|  |             ibutton_cli_print_usage(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(!ibutton_cli_get_key_type(data, &type)) { | ||||||
|  |             ibutton_cli_print_usage(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(type != iButtonKeyDS1990) { | ||||||
|  |             ibutton_cli_print_usage(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(!args_read_hex_bytes(args, key_data, ibutton_key_get_size_by_type(type))) { | ||||||
|  |             ibutton_cli_print_usage(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         ibutton_key_set_type(key, type); | ||||||
|  |         ibutton_key_set_data(key, key_data, ibutton_key_get_size_by_type(type)); | ||||||
|  | 
 | ||||||
|  |         printf("Writing key "); | ||||||
|  |         ibutton_cli_print_key_data(key); | ||||||
|  |         printf("Press Ctrl+C to abort\r\n"); | ||||||
|  | 
 | ||||||
|  |         ibutton_worker_write_start(worker, key); | ||||||
|  |         while(true) { | ||||||
|  |             uint32_t flags = osEventFlagsWait( | ||||||
|  |                 write_context.event, EVENT_FLAG_IBUTTON_COMPLETE, osFlagsWaitAny, 100); | ||||||
|  | 
 | ||||||
|  |             if(flags & EVENT_FLAG_IBUTTON_COMPLETE) { | ||||||
|  |                 if(write_context.result == iButtonWorkerWriteSameKey || | ||||||
|  |                    write_context.result == iButtonWorkerWriteOK) { | ||||||
|  |                     printf("Write success\r\n"); | ||||||
|  |                     break; | ||||||
|  |                 } else if(write_context.result == iButtonWorkerWriteCannotWrite) { | ||||||
|  |                     printf("Write fail\r\n"); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if(cli_cmd_interrupt_received(cli)) break; | ||||||
|  |         } | ||||||
|  |         ibutton_worker_stop(worker); | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     string_clear(data); | ||||||
|  |     ibutton_worker_stop_thread(worker); | ||||||
|  |     ibutton_worker_free(worker); | ||||||
|  |     ibutton_key_free(key); | ||||||
|  | 
 | ||||||
|  |     osEventFlagsDelete(write_context.event); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void ibutton_cli_emulate(Cli* cli, string_t args) { | ||||||
|  |     iButtonKey* key = ibutton_key_alloc(); | ||||||
|  |     iButtonWorker* worker = ibutton_worker_alloc(); | ||||||
|  |     iButtonKeyType type; | ||||||
|  |     uint8_t key_data[IBUTTON_KEY_DATA_SIZE]; | ||||||
|  |     string_t data; | ||||||
|  | 
 | ||||||
|  |     string_init(data); | ||||||
|  |     ibutton_worker_start_thread(worker); | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         if(!args_read_string_and_trim(args, data)) { | ||||||
|  |             ibutton_cli_print_usage(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(!ibutton_cli_get_key_type(data, &type)) { | ||||||
|  |             ibutton_cli_print_usage(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(!args_read_hex_bytes(args, key_data, ibutton_key_get_size_by_type(type))) { | ||||||
|  |             ibutton_cli_print_usage(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         ibutton_key_set_type(key, type); | ||||||
|  |         ibutton_key_set_data(key, key_data, ibutton_key_get_size_by_type(type)); | ||||||
|  | 
 | ||||||
|  |         printf("Emulating key "); | ||||||
|  |         ibutton_cli_print_key_data(key); | ||||||
|  |         printf("Press Ctrl+C to abort\r\n"); | ||||||
|  | 
 | ||||||
|  |         ibutton_worker_emulate_start(worker, key); | ||||||
|  |         while(!cli_cmd_interrupt_received(cli)) { | ||||||
|  |             furi_hal_delay_ms(100); | ||||||
|  |         }; | ||||||
|  |         ibutton_worker_stop(worker); | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     string_clear(data); | ||||||
|  |     ibutton_worker_stop_thread(worker); | ||||||
|  |     ibutton_worker_free(worker); | ||||||
|  |     ibutton_key_free(key); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void ibutton_cli(Cli* cli, string_t args, void* context) { | ||||||
|  |     string_t cmd; | ||||||
|  |     string_init(cmd); | ||||||
|  | 
 | ||||||
|  |     if(!args_read_string_and_trim(args, cmd)) { | ||||||
|  |         string_clear(cmd); | ||||||
|  |         ibutton_cli_print_usage(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(string_cmp_str(cmd, "read") == 0) { | ||||||
|  |         ibutton_cli_read(cli); | ||||||
|  |     } else if(string_cmp_str(cmd, "write") == 0) { | ||||||
|  |         ibutton_cli_write(cli, args); | ||||||
|  |     } else if(string_cmp_str(cmd, "emulate") == 0) { | ||||||
|  |         ibutton_cli_emulate(cli, args); | ||||||
|  |     } else { | ||||||
|  |         ibutton_cli_print_usage(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     string_clear(cmd); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void onewire_cli_print_usage() { | ||||||
|  |     printf("Usage:\r\n"); | ||||||
|  |     printf("onewire search\r\n"); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void onewire_cli_search(Cli* cli) { | ||||||
|  |     OneWireHost* onewire = onewire_host_alloc(); | ||||||
|  |     uint8_t address[8]; | ||||||
|  |     bool done = false; | ||||||
|  | 
 | ||||||
|  |     printf("Search started\r\n"); | ||||||
|  | 
 | ||||||
|  |     onewire_host_start(onewire); | ||||||
|  |     furi_hal_power_enable_otg(); | ||||||
|  | 
 | ||||||
|  |     while(!done) { | ||||||
|  |         if(onewire_host_search(onewire, address, NORMAL_SEARCH) != 1) { | ||||||
|  |             printf("Search finished\r\n"); | ||||||
|  |             onewire_host_reset_search(onewire); | ||||||
|  |             done = true; | ||||||
|  |         } else { | ||||||
|  |             printf("Found: "); | ||||||
|  |             for(uint8_t i = 0; i < 8; i++) { | ||||||
|  |                 printf("%02X", address[i]); | ||||||
|  |             } | ||||||
|  |             printf("\r\n"); | ||||||
|  |         } | ||||||
|  |         furi_hal_delay_ms(100); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     furi_hal_power_disable_otg(); | ||||||
|  |     onewire_host_free(onewire); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void onewire_cli(Cli* cli, string_t args, void* context) { | ||||||
|  |     string_t cmd; | ||||||
|  |     string_init(cmd); | ||||||
|  | 
 | ||||||
|  |     if(!args_read_string_and_trim(args, cmd)) { | ||||||
|  |         string_clear(cmd); | ||||||
|  |         onewire_cli_print_usage(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(string_cmp_str(cmd, "search") == 0) { | ||||||
|  |         onewire_cli_search(cli); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     string_clear(cmd); | ||||||
|  | } | ||||||
| @ -1,292 +0,0 @@ | |||||||
| #include <furi.h> |  | ||||||
| #include <furi_hal.h> |  | ||||||
| #include <stdarg.h> |  | ||||||
| #include <cli/cli.h> |  | ||||||
| #include <lib/toolbox/args.h> |  | ||||||
| 
 |  | ||||||
| #include "helpers/key_info.h" |  | ||||||
| #include "helpers/key_worker.h" |  | ||||||
| 
 |  | ||||||
| #include <memory> |  | ||||||
| 
 |  | ||||||
| void ibutton_cli(Cli* cli, string_t args, void* context); |  | ||||||
| void onewire_cli(Cli* cli, string_t args, void* context); |  | ||||||
| 
 |  | ||||||
| // app cli function
 |  | ||||||
| extern "C" void ibutton_on_system_start() { |  | ||||||
| #ifdef SRV_CLI |  | ||||||
|     Cli* cli = static_cast<Cli*>(furi_record_open("cli")); |  | ||||||
|     cli_add_command(cli, "ikey", CliCommandFlagDefault, ibutton_cli, cli); |  | ||||||
|     cli_add_command(cli, "onewire", CliCommandFlagDefault, onewire_cli, cli); |  | ||||||
|     furi_record_close("cli"); |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ibutton_cli_print_usage() { |  | ||||||
|     printf("Usage:\r\n"); |  | ||||||
|     printf("ikey read\r\n"); |  | ||||||
|     printf("ikey <write | emulate> <key_type> <key_data>\r\n"); |  | ||||||
|     printf("\t<key_type> choose from:\r\n"); |  | ||||||
|     printf("\tDallas (8 bytes key_data)\r\n"); |  | ||||||
|     printf("\tCyfral (2 bytes key_data)\r\n"); |  | ||||||
|     printf("\tMetakom (4 bytes key_data)\r\n"); |  | ||||||
|     printf("\t<key_data> are hex-formatted\r\n"); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| bool ibutton_cli_get_key_type(string_t data, iButtonKeyType* type) { |  | ||||||
|     bool result = false; |  | ||||||
| 
 |  | ||||||
|     if(string_cmp_str(data, "Dallas") == 0 || string_cmp_str(data, "dallas") == 0) { |  | ||||||
|         result = true; |  | ||||||
|         *type = iButtonKeyType::KeyDallas; |  | ||||||
|     } else if(string_cmp_str(data, "Cyfral") == 0 || string_cmp_str(data, "cyfral") == 0) { |  | ||||||
|         result = true; |  | ||||||
|         *type = iButtonKeyType::KeyCyfral; |  | ||||||
|     } else if(string_cmp_str(data, "Metakom") == 0 || string_cmp_str(data, "metakom") == 0) { |  | ||||||
|         result = true; |  | ||||||
|         *type = iButtonKeyType::KeyMetakom; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ibutton_cli_print_key_data(iButtonKey* key) { |  | ||||||
|     uint8_t* key_data = key->get_data(); |  | ||||||
|     switch(key->get_key_type()) { |  | ||||||
|     case iButtonKeyType::KeyDallas: |  | ||||||
|         printf( |  | ||||||
|             "Dallas %02X%02X%02X%02X%02X%02X%02X%02X\r\n", |  | ||||||
|             key_data[0], |  | ||||||
|             key_data[1], |  | ||||||
|             key_data[2], |  | ||||||
|             key_data[3], |  | ||||||
|             key_data[4], |  | ||||||
|             key_data[5], |  | ||||||
|             key_data[6], |  | ||||||
|             key_data[7]); |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyType::KeyCyfral: |  | ||||||
|         printf("Cyfral %02X%02X\r\n", key_data[0], key_data[1]); |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyType::KeyMetakom: |  | ||||||
|         printf("Metakom %02X%02X%02X%02X\r\n", key_data[0], key_data[1], key_data[2], key_data[3]); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ibutton_cli_read(Cli* cli) { |  | ||||||
|     iButtonKey key; |  | ||||||
|     std::unique_ptr<KeyWorker> worker(new KeyWorker(&ibutton_gpio)); |  | ||||||
| 
 |  | ||||||
|     bool exit = false; |  | ||||||
| 
 |  | ||||||
|     worker->start_read(); |  | ||||||
|     printf("Reading iButton...\r\nPress Ctrl+C to abort\r\n"); |  | ||||||
| 
 |  | ||||||
|     while(!exit) { |  | ||||||
|         exit = cli_cmd_interrupt_received(cli); |  | ||||||
| 
 |  | ||||||
|         switch(worker->read(&key)) { |  | ||||||
|         case KeyReader::Error::EMPTY: |  | ||||||
|             break; |  | ||||||
|         case KeyReader::Error::CRC_ERROR: |  | ||||||
|             ibutton_cli_print_key_data(&key); |  | ||||||
|             printf("Warning: invalid CRC\r\n"); |  | ||||||
|             exit = true; |  | ||||||
|             break; |  | ||||||
|         case KeyReader::Error::OK: |  | ||||||
|             ibutton_cli_print_key_data(&key); |  | ||||||
|             exit = true; |  | ||||||
|             break; |  | ||||||
|         case KeyReader::Error::NOT_ARE_KEY: |  | ||||||
|             ibutton_cli_print_key_data(&key); |  | ||||||
|             printf("Warning: not a key\r\n"); |  | ||||||
|             exit = true; |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         delay(100); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     worker->stop_read(); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void ibutton_cli_write(Cli* cli, string_t args) { |  | ||||||
|     iButtonKey key; |  | ||||||
|     iButtonKeyType type; |  | ||||||
|     std::unique_ptr<KeyWorker> worker(new KeyWorker(&ibutton_gpio)); |  | ||||||
| 
 |  | ||||||
|     bool exit = false; |  | ||||||
|     string_t data; |  | ||||||
|     string_init(data); |  | ||||||
| 
 |  | ||||||
|     if(!args_read_string_and_trim(args, data)) { |  | ||||||
|         ibutton_cli_print_usage(); |  | ||||||
|         string_clear(data); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(!ibutton_cli_get_key_type(data, &type)) { |  | ||||||
|         ibutton_cli_print_usage(); |  | ||||||
|         string_clear(data); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     key.set_type(type); |  | ||||||
| 
 |  | ||||||
|     if(!args_read_hex_bytes(args, key.get_data(), key.get_type_data_size())) { |  | ||||||
|         ibutton_cli_print_usage(); |  | ||||||
|         string_clear(data); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     printf("Writing key "); |  | ||||||
|     ibutton_cli_print_key_data(&key); |  | ||||||
|     printf("Press Ctrl+C to abort\r\n"); |  | ||||||
| 
 |  | ||||||
|     worker->start_write(); |  | ||||||
| 
 |  | ||||||
|     while(!exit) { |  | ||||||
|         exit = cli_cmd_interrupt_received(cli); |  | ||||||
| 
 |  | ||||||
|         KeyWriter::Error result = worker->write(&key); |  | ||||||
| 
 |  | ||||||
|         switch(result) { |  | ||||||
|         case KeyWriter::Error::SAME_KEY: |  | ||||||
|         case KeyWriter::Error::OK: |  | ||||||
|             printf("Write success\r\n"); |  | ||||||
|             exit = true; |  | ||||||
|             break; |  | ||||||
|         case KeyWriter::Error::NO_DETECT: |  | ||||||
|             break; |  | ||||||
|         case KeyWriter::Error::CANNOT_WRITE: |  | ||||||
|             printf("Write fail\r\n"); |  | ||||||
|             exit = true; |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         delay(100); |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     worker->stop_write(); |  | ||||||
| 
 |  | ||||||
|     string_clear(data); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void ibutton_cli_emulate(Cli* cli, string_t args) { |  | ||||||
|     iButtonKey key; |  | ||||||
|     iButtonKeyType type; |  | ||||||
|     std::unique_ptr<KeyWorker> worker(new KeyWorker(&ibutton_gpio)); |  | ||||||
|     bool exit = false; |  | ||||||
|     string_t data; |  | ||||||
|     string_init(data); |  | ||||||
| 
 |  | ||||||
|     if(!args_read_string_and_trim(args, data)) { |  | ||||||
|         ibutton_cli_print_usage(); |  | ||||||
|         string_clear(data); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(!ibutton_cli_get_key_type(data, &type)) { |  | ||||||
|         ibutton_cli_print_usage(); |  | ||||||
|         string_clear(data); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     key.set_type(type); |  | ||||||
| 
 |  | ||||||
|     if(!args_read_hex_bytes(args, key.get_data(), key.get_type_data_size())) { |  | ||||||
|         ibutton_cli_print_usage(); |  | ||||||
|         string_clear(data); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     printf("Emulating key "); |  | ||||||
|     ibutton_cli_print_key_data(&key); |  | ||||||
|     printf("Press Ctrl+C to abort\r\n"); |  | ||||||
| 
 |  | ||||||
|     worker->start_emulate(&key); |  | ||||||
| 
 |  | ||||||
|     while(!exit) { |  | ||||||
|         exit = cli_cmd_interrupt_received(cli); |  | ||||||
|         delay(100); |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     worker->stop_emulate(); |  | ||||||
| 
 |  | ||||||
|     string_clear(data); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void ibutton_cli(Cli* cli, string_t args, void* context) { |  | ||||||
|     string_t cmd; |  | ||||||
|     string_init(cmd); |  | ||||||
| 
 |  | ||||||
|     if(!args_read_string_and_trim(args, cmd)) { |  | ||||||
|         string_clear(cmd); |  | ||||||
|         ibutton_cli_print_usage(); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(string_cmp_str(cmd, "read") == 0) { |  | ||||||
|         ibutton_cli_read(cli); |  | ||||||
|     } else if(string_cmp_str(cmd, "write") == 0) { |  | ||||||
|         ibutton_cli_write(cli, args); |  | ||||||
|     } else if(string_cmp_str(cmd, "emulate") == 0) { |  | ||||||
|         ibutton_cli_emulate(cli, args); |  | ||||||
|     } else { |  | ||||||
|         ibutton_cli_print_usage(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     string_clear(cmd); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void onewire_cli_print_usage() { |  | ||||||
|     printf("Usage:\r\n"); |  | ||||||
|     printf("onewire search\r\n"); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void onewire_cli_search(Cli* cli) { |  | ||||||
|     OneWireMaster onewire(&ibutton_gpio); |  | ||||||
|     uint8_t address[8]; |  | ||||||
|     bool done = false; |  | ||||||
| 
 |  | ||||||
|     printf("Search started\r\n"); |  | ||||||
| 
 |  | ||||||
|     onewire.start(); |  | ||||||
|     furi_hal_power_enable_otg(); |  | ||||||
| 
 |  | ||||||
|     while(!done) { |  | ||||||
|         if(onewire.search(address, true) != 1) { |  | ||||||
|             printf("Search finished\r\n"); |  | ||||||
|             onewire.reset_search(); |  | ||||||
|             done = true; |  | ||||||
|         } else { |  | ||||||
|             printf("Found: "); |  | ||||||
|             for(uint8_t i = 0; i < 8; i++) { |  | ||||||
|                 printf("%02X", address[i]); |  | ||||||
|             } |  | ||||||
|             printf("\r\n"); |  | ||||||
|         } |  | ||||||
|         delay(100); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     furi_hal_power_disable_otg(); |  | ||||||
|     onewire.stop(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void onewire_cli(Cli* cli, string_t args, void* context) { |  | ||||||
|     string_t cmd; |  | ||||||
|     string_init(cmd); |  | ||||||
| 
 |  | ||||||
|     if(!args_read_string_and_trim(args, cmd)) { |  | ||||||
|         string_clear(cmd); |  | ||||||
|         onewire_cli_print_usage(); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(string_cmp_str(cmd, "search") == 0) { |  | ||||||
|         onewire_cli_search(cli); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     string_clear(cmd); |  | ||||||
| } |  | ||||||
| @ -2,6 +2,7 @@ | |||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <gui/modules/dialog_ex.h> | #include <gui/modules/dialog_ex.h> | ||||||
| #include <gui/modules/widget.h> | #include <gui/modules/widget.h> | ||||||
|  | #include <one_wire/ibutton/ibutton_worker.h> | ||||||
| 
 | 
 | ||||||
| class iButtonApp; | class iButtonApp; | ||||||
| 
 | 
 | ||||||
| @ -16,6 +17,9 @@ public: | |||||||
|         EventTypeTextEditResult, |         EventTypeTextEditResult, | ||||||
|         EventTypeByteEditResult, |         EventTypeByteEditResult, | ||||||
|         EventTypeWidgetButtonResult, |         EventTypeWidgetButtonResult, | ||||||
|  |         EventTypeWorkerEmulated, | ||||||
|  |         EventTypeWorkerRead, | ||||||
|  |         EventTypeWorkerWrite, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     // payload
 |     // payload
 | ||||||
| @ -23,6 +27,7 @@ public: | |||||||
|         uint32_t menu_index; |         uint32_t menu_index; | ||||||
|         DialogExResult dialog_result; |         DialogExResult dialog_result; | ||||||
|         GuiButtonType widget_button_result; |         GuiButtonType widget_button_result; | ||||||
|  |         iButtonWorkerWriteResult worker_write_result; | ||||||
|     } payload; |     } payload; | ||||||
| 
 | 
 | ||||||
|     // event type
 |     // event type
 | ||||||
|  | |||||||
| @ -1,95 +0,0 @@ | |||||||
| #include "ibutton_key.h" |  | ||||||
| #include <furi.h> |  | ||||||
| 
 |  | ||||||
| uint8_t iButtonKey::get_size() { |  | ||||||
|     return IBUTTON_KEY_DATA_SIZE; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonKey::set_data(uint8_t* _data, uint8_t _data_count) { |  | ||||||
|     furi_check(_data_count > 0); |  | ||||||
|     furi_check(_data_count <= get_size()); |  | ||||||
| 
 |  | ||||||
|     memset(data, 0, get_size()); |  | ||||||
|     memcpy(data, _data, _data_count); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonKey::clear_data() { |  | ||||||
|     memset(data, 0, get_size()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| uint8_t* iButtonKey::get_data() { |  | ||||||
|     return data; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| uint8_t iButtonKey::get_type_data_size() { |  | ||||||
|     return get_type_data_size_by_type(type); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonKey::set_name(const char* _name) { |  | ||||||
|     strlcpy(name, _name, IBUTTON_KEY_NAME_SIZE); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| char* iButtonKey::get_name() { |  | ||||||
|     return name; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void iButtonKey::set_type(iButtonKeyType _key_type) { |  | ||||||
|     type = _key_type; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| iButtonKeyType iButtonKey::get_key_type() { |  | ||||||
|     return type; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const char* iButtonKey::get_key_type_string_by_type(iButtonKeyType key_type) { |  | ||||||
|     switch(key_type) { |  | ||||||
|     case iButtonKeyType::KeyCyfral: |  | ||||||
|         return "Cyfral"; |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyType::KeyMetakom: |  | ||||||
|         return "Metakom"; |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyType::KeyDallas: |  | ||||||
|         return "Dallas"; |  | ||||||
|         break; |  | ||||||
|     default: |  | ||||||
|         furi_crash("Invalid iButton type"); |  | ||||||
|         return ""; |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iButtonKey::get_key_type_by_type_string(const char* type_string, iButtonKeyType* key_type) { |  | ||||||
|     if(strcmp(type_string, get_key_type_string_by_type(iButtonKeyType::KeyCyfral)) == 0) { |  | ||||||
|         *key_type = iButtonKeyType::KeyCyfral; |  | ||||||
|     } else if(strcmp(type_string, get_key_type_string_by_type(iButtonKeyType::KeyMetakom)) == 0) { |  | ||||||
|         *key_type = iButtonKeyType::KeyMetakom; |  | ||||||
|     } else if(strcmp(type_string, get_key_type_string_by_type(iButtonKeyType::KeyDallas)) == 0) { |  | ||||||
|         *key_type = iButtonKeyType::KeyDallas; |  | ||||||
|     } else { |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| uint8_t iButtonKey::get_type_data_size_by_type(iButtonKeyType key_type) { |  | ||||||
|     uint8_t size = 0; |  | ||||||
| 
 |  | ||||||
|     switch(key_type) { |  | ||||||
|     case iButtonKeyType::KeyCyfral: |  | ||||||
|         size = 2; |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyType::KeyMetakom: |  | ||||||
|         size = 4; |  | ||||||
|         break; |  | ||||||
|     case iButtonKeyType::KeyDallas: |  | ||||||
|         size = 8; |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return size; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| iButtonKey::iButtonKey() { |  | ||||||
| } |  | ||||||
| @ -1,31 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #include <stdint.h> |  | ||||||
| #include "helpers/key_info.h" |  | ||||||
| 
 |  | ||||||
| class iButtonKey { |  | ||||||
| public: |  | ||||||
|     uint8_t get_size(); |  | ||||||
| 
 |  | ||||||
|     void set_data(uint8_t* data, uint8_t data_count); |  | ||||||
|     void clear_data(); |  | ||||||
|     uint8_t* get_data(); |  | ||||||
|     uint8_t get_type_data_size(); |  | ||||||
| 
 |  | ||||||
|     void set_name(const char* name); |  | ||||||
|     char* get_name(); |  | ||||||
| 
 |  | ||||||
|     void set_type(iButtonKeyType key_type); |  | ||||||
|     iButtonKeyType get_key_type(); |  | ||||||
| 
 |  | ||||||
|     const char* get_key_type_string_by_type(iButtonKeyType key_type); |  | ||||||
|     bool get_key_type_by_type_string(const char* type_string, iButtonKeyType* key_type); |  | ||||||
|     uint8_t get_type_data_size_by_type(iButtonKeyType key_type); |  | ||||||
| 
 |  | ||||||
|     iButtonKey(); |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     uint8_t data[IBUTTON_KEY_DATA_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0}; |  | ||||||
|     char name[IBUTTON_KEY_NAME_SIZE] = {0}; |  | ||||||
| 
 |  | ||||||
|     iButtonKeyType type = iButtonKeyType::KeyDallas; |  | ||||||
| }; |  | ||||||
| @ -1,7 +1,5 @@ | |||||||
| #include "ibutton_scene_add_type.h" | #include "ibutton_scene_add_type.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" |  | ||||||
| #include "../ibutton_event.h" |  | ||||||
| #include <callback-connector.h> | #include <callback-connector.h> | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
| @ -10,14 +8,23 @@ typedef enum { | |||||||
|     SubmenuIndexMetakom, |     SubmenuIndexMetakom, | ||||||
| } SubmenuIndex; | } SubmenuIndex; | ||||||
| 
 | 
 | ||||||
|  | static void submenu_callback(void* context, uint32_t index) { | ||||||
|  |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeMenuSelected; | ||||||
|  |     event.payload.menu_index = index; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void iButtonSceneAddType::on_enter(iButtonApp* app) { | void iButtonSceneAddType::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Submenu* submenu = view_manager->get_submenu(); |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneAddType::submenu_callback); |  | ||||||
| 
 | 
 | ||||||
|     submenu_add_item(submenu, "Cyfral", SubmenuIndexCyfral, callback, app); |     submenu_add_item(submenu, "Cyfral", SubmenuIndexCyfral, submenu_callback, app); | ||||||
|     submenu_add_item(submenu, "Dallas", SubmenuIndexDallas, callback, app); |     submenu_add_item(submenu, "Dallas", SubmenuIndexDallas, submenu_callback, app); | ||||||
|     submenu_add_item(submenu, "Metakom", SubmenuIndexMetakom, callback, app); |     submenu_add_item(submenu, "Metakom", SubmenuIndexMetakom, submenu_callback, app); | ||||||
|     submenu_set_selected_item(submenu, submenu_item_selected); |     submenu_set_selected_item(submenu, submenu_item_selected); | ||||||
| 
 | 
 | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); |     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); | ||||||
| @ -28,19 +35,21 @@ bool iButtonSceneAddType::on_event(iButtonApp* app, iButtonEvent* event) { | |||||||
| 
 | 
 | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeMenuSelected) { |     if(event->type == iButtonEvent::Type::EventTypeMenuSelected) { | ||||||
|         submenu_item_selected = event->payload.menu_index; |         submenu_item_selected = event->payload.menu_index; | ||||||
|  |         iButtonKey* key = app->get_key(); | ||||||
|  | 
 | ||||||
|         switch(event->payload.menu_index) { |         switch(event->payload.menu_index) { | ||||||
|         case SubmenuIndexCyfral: |         case SubmenuIndexCyfral: | ||||||
|             app->get_key()->set_type(iButtonKeyType::KeyCyfral); |             ibutton_key_set_type(key, iButtonKeyCyfral); | ||||||
|             break; |             break; | ||||||
|         case SubmenuIndexDallas: |         case SubmenuIndexDallas: | ||||||
|             app->get_key()->set_type(iButtonKeyType::KeyDallas); |             ibutton_key_set_type(key, iButtonKeyDS1990); | ||||||
|             break; |             break; | ||||||
|         case SubmenuIndexMetakom: |         case SubmenuIndexMetakom: | ||||||
|             app->get_key()->set_type(iButtonKeyType::KeyMetakom); |             ibutton_key_set_type(key, iButtonKeyMetakom); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         app->get_key()->set_name(""); |         ibutton_key_set_name(key, ""); | ||||||
|         app->get_key()->clear_data(); |         ibutton_key_clear_data(key); | ||||||
|         app->switch_to_next_scene(iButtonApp::Scene::SceneAddValue); |         app->switch_to_next_scene(iButtonApp::Scene::SceneAddValue); | ||||||
|         consumed = true; |         consumed = true; | ||||||
|     } |     } | ||||||
| @ -54,13 +63,3 @@ void iButtonSceneAddType::on_exit(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     submenu_reset(submenu); |     submenu_reset(submenu); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneAddType::submenu_callback(void* context, uint32_t index) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeMenuSelected; |  | ||||||
|     event.payload.menu_index = index; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -8,6 +8,5 @@ public: | |||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void submenu_callback(void* context, uint32_t index); |  | ||||||
|     uint32_t submenu_item_selected = 0; |     uint32_t submenu_item_selected = 0; | ||||||
| }; | }; | ||||||
| @ -1,17 +1,30 @@ | |||||||
| #include "ibutton_scene_add_value.h" | #include "ibutton_scene_add_value.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" |  | ||||||
| #include "../ibutton_event.h" |  | ||||||
| #include <callback-connector.h> |  | ||||||
| #include <dolphin/dolphin.h> | #include <dolphin/dolphin.h> | ||||||
| 
 | 
 | ||||||
|  | static void byte_input_callback(void* context) { | ||||||
|  |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeByteEditResult; | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void iButtonSceneAddValue::on_enter(iButtonApp* app) { | void iButtonSceneAddValue::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     ByteInput* byte_input = view_manager->get_byte_input(); |     ByteInput* byte_input = view_manager->get_byte_input(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneAddValue::byte_input_callback); |     iButtonKey* key = app->get_key(); | ||||||
|     memcpy(this->new_key_data, app->get_key()->get_data(), app->get_key()->get_type_data_size()); | 
 | ||||||
|  |     memcpy(this->new_key_data, ibutton_key_get_data_p(key), ibutton_key_get_data_size(key)); | ||||||
|  | 
 | ||||||
|     byte_input_set_result_callback( |     byte_input_set_result_callback( | ||||||
|         byte_input, callback, NULL, app, this->new_key_data, app->get_key()->get_type_data_size()); |         byte_input, | ||||||
|  |         byte_input_callback, | ||||||
|  |         NULL, | ||||||
|  |         app, | ||||||
|  |         this->new_key_data, | ||||||
|  |         ibutton_key_get_data_size(key)); | ||||||
|  | 
 | ||||||
|     byte_input_set_header_text(byte_input, "Enter the key"); |     byte_input_set_header_text(byte_input, "Enter the key"); | ||||||
| 
 | 
 | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewByteInput); |     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewByteInput); | ||||||
| @ -21,6 +34,7 @@ bool iButtonSceneAddValue::on_event(iButtonApp* app, iButtonEvent* event) { | |||||||
|     bool consumed = false; |     bool consumed = false; | ||||||
| 
 | 
 | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeByteEditResult) { |     if(event->type == iButtonEvent::Type::EventTypeByteEditResult) { | ||||||
|  |         ibutton_key_set_data(app->get_key(), this->new_key_data, IBUTTON_KEY_DATA_SIZE); | ||||||
|         DOLPHIN_DEED(DolphinDeedIbuttonAdd); |         DOLPHIN_DEED(DolphinDeedIbuttonAdd); | ||||||
|         app->switch_to_next_scene(iButtonApp::Scene::SceneSaveName); |         app->switch_to_next_scene(iButtonApp::Scene::SceneSaveName); | ||||||
|         consumed = true; |         consumed = true; | ||||||
| @ -36,12 +50,3 @@ void iButtonSceneAddValue::on_exit(iButtonApp* app) { | |||||||
|     byte_input_set_result_callback(byte_input, NULL, NULL, NULL, NULL, 0); |     byte_input_set_result_callback(byte_input, NULL, NULL, NULL, NULL, 0); | ||||||
|     byte_input_set_header_text(byte_input, {0}); |     byte_input_set_header_text(byte_input, {0}); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneAddValue::byte_input_callback(void* context) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeByteEditResult; |  | ||||||
|     memcpy(app->get_key()->get_data(), this->new_key_data, app->get_key()->get_type_data_size()); |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "ibutton_scene_generic.h" | #include "ibutton_scene_generic.h" | ||||||
| #include "../ibutton_key.h" | #include <one_wire/ibutton/ibutton_key.h> | ||||||
| 
 | 
 | ||||||
| class iButtonSceneAddValue : public iButtonScene { | class iButtonSceneAddValue : public iButtonScene { | ||||||
| public: | public: | ||||||
| @ -9,6 +9,5 @@ public: | |||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void byte_input_callback(void* context); |  | ||||||
|     uint8_t new_key_data[IBUTTON_KEY_DATA_SIZE] = {}; |     uint8_t new_key_data[IBUTTON_KEY_DATA_SIZE] = {}; | ||||||
| }; | }; | ||||||
| @ -1,25 +1,31 @@ | |||||||
| #include "ibutton_scene_delete_confirm.h" | #include "ibutton_scene_delete_confirm.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" | 
 | ||||||
| #include "../ibutton_event.h" | static void widget_callback(GuiButtonType result, InputType type, void* context) { | ||||||
| #include <callback-connector.h> |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  | 
 | ||||||
|  |     if(type == InputTypeShort) { | ||||||
|  |         event.type = iButtonEvent::Type::EventTypeWidgetButtonResult; | ||||||
|  |         event.payload.widget_button_result = result; | ||||||
|  |         app->get_view_manager()->send_event(&event); | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneDeleteConfirm::on_enter(iButtonApp* app) { | void iButtonSceneDeleteConfirm::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Widget* widget = view_manager->get_widget(); |     Widget* widget = view_manager->get_widget(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneDeleteConfirm::widget_callback); |  | ||||||
| 
 |  | ||||||
|     iButtonKey* key = app->get_key(); |     iButtonKey* key = app->get_key(); | ||||||
|     uint8_t* key_data = key->get_data(); |     const uint8_t* key_data = ibutton_key_get_data_p(key); | ||||||
| 
 | 
 | ||||||
|     app->set_text_store("\e#Delete %s?\e#", key->get_name()); |     app->set_text_store("\e#Delete %s?\e#", ibutton_key_get_name_p(key)); | ||||||
|     widget_add_text_box_element( |     widget_add_text_box_element( | ||||||
|         widget, 0, 0, 128, 27, AlignCenter, AlignCenter, app->get_text_store()); |         widget, 0, 0, 128, 27, AlignCenter, AlignCenter, app->get_text_store()); | ||||||
|     widget_add_button_element(widget, GuiButtonTypeLeft, "Back", callback, app); |     widget_add_button_element(widget, GuiButtonTypeLeft, "Back", widget_callback, app); | ||||||
|     widget_add_button_element(widget, GuiButtonTypeRight, "Delete", callback, app); |     widget_add_button_element(widget, GuiButtonTypeRight, "Delete", widget_callback, app); | ||||||
| 
 | 
 | ||||||
|     switch(key->get_key_type()) { |     switch(ibutton_key_get_type(key)) { | ||||||
|     case iButtonKeyType::KeyDallas: |     case iButtonKeyDS1990: | ||||||
|         app->set_text_store( |         app->set_text_store( | ||||||
|             "%02X %02X %02X %02X %02X %02X %02X %02X", |             "%02X %02X %02X %02X %02X %02X %02X %02X", | ||||||
|             key_data[0], |             key_data[0], | ||||||
| @ -33,12 +39,12 @@ void iButtonSceneDeleteConfirm::on_enter(iButtonApp* app) { | |||||||
|         widget_add_string_element( |         widget_add_string_element( | ||||||
|             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Dallas"); |             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Dallas"); | ||||||
|         break; |         break; | ||||||
|     case iButtonKeyType::KeyCyfral: |     case iButtonKeyCyfral: | ||||||
|         app->set_text_store("%02X %02X", key_data[0], key_data[1]); |         app->set_text_store("%02X %02X", key_data[0], key_data[1]); | ||||||
|         widget_add_string_element( |         widget_add_string_element( | ||||||
|             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Cyfral"); |             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Cyfral"); | ||||||
|         break; |         break; | ||||||
|     case iButtonKeyType::KeyMetakom: |     case iButtonKeyMetakom: | ||||||
|         app->set_text_store( |         app->set_text_store( | ||||||
|             "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); |             "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); | ||||||
|         widget_add_string_element( |         widget_add_string_element( | ||||||
| @ -77,18 +83,3 @@ void iButtonSceneDeleteConfirm::on_exit(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     widget_reset(widget); |     widget_reset(widget); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneDeleteConfirm::widget_callback( |  | ||||||
|     GuiButtonType result, |  | ||||||
|     InputType type, |  | ||||||
|     void* context) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     if(type == InputTypeShort) { |  | ||||||
|         event.type = iButtonEvent::Type::EventTypeWidgetButtonResult; |  | ||||||
|         event.payload.widget_button_result = result; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -6,7 +6,4 @@ public: | |||||||
|     void on_enter(iButtonApp* app) final; |     void on_enter(iButtonApp* app) final; | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     void widget_callback(GuiButtonType result, InputType type, void* context); |  | ||||||
| }; | }; | ||||||
| @ -1,19 +1,21 @@ | |||||||
| #include "ibutton_scene_delete_success.h" | #include "ibutton_scene_delete_success.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" | 
 | ||||||
| #include "../ibutton_event.h" | static void popup_callback(void* context) { | ||||||
| #include "../ibutton_key.h" |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
| #include <callback-connector.h> |     iButtonEvent event; | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeBack; | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneDeleteSuccess::on_enter(iButtonApp* app) { | void iButtonSceneDeleteSuccess::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Popup* popup = view_manager->get_popup(); |     Popup* popup = view_manager->get_popup(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneDeleteSuccess::popup_callback); |  | ||||||
| 
 | 
 | ||||||
|     popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); |     popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); | ||||||
|     popup_set_text(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); |     popup_set_text(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); | ||||||
| 
 | 
 | ||||||
|     popup_set_callback(popup, callback); |     popup_set_callback(popup, popup_callback); | ||||||
|     popup_set_context(popup, app); |     popup_set_context(popup, app); | ||||||
|     popup_set_timeout(popup, 1500); |     popup_set_timeout(popup, 1500); | ||||||
|     popup_enable_timeout(popup); |     popup_enable_timeout(popup); | ||||||
| @ -42,10 +44,3 @@ void iButtonSceneDeleteSuccess::on_exit(iButtonApp* app) { | |||||||
|     popup_set_context(popup, NULL); |     popup_set_context(popup, NULL); | ||||||
|     popup_set_callback(popup, NULL); |     popup_set_callback(popup, NULL); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneDeleteSuccess::popup_callback(void* context) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeBack; |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
| @ -6,7 +6,4 @@ public: | |||||||
|     void on_enter(iButtonApp* app) final; |     void on_enter(iButtonApp* app) final; | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     void popup_callback(void* context); |  | ||||||
| }; | }; | ||||||
| @ -1,17 +1,21 @@ | |||||||
| #include "ibutton_scene_emulate.h" | #include "ibutton_scene_emulate.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" |  | ||||||
| #include "../ibutton_event.h" |  | ||||||
| #include "../ibutton_key.h" |  | ||||||
| #include <dolphin/dolphin.h> | #include <dolphin/dolphin.h> | ||||||
| #include <callback-connector.h> | 
 | ||||||
|  | static void emulate_callback(void* context, bool emulated) { | ||||||
|  |     if(emulated) { | ||||||
|  |         iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |         iButtonEvent event = {.type = iButtonEvent::Type::EventTypeWorkerEmulated}; | ||||||
|  |         app->get_view_manager()->send_event(&event); | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneEmulate::on_enter(iButtonApp* app) { | void iButtonSceneEmulate::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Popup* popup = view_manager->get_popup(); |     Popup* popup = view_manager->get_popup(); | ||||||
|     iButtonKey* key = app->get_key(); |     iButtonKey* key = app->get_key(); | ||||||
|     uint8_t* key_data = key->get_data(); |     const uint8_t* key_data = ibutton_key_get_data_p(key); | ||||||
|     const char* key_name = key->get_name(); |     const char* key_name = ibutton_key_get_name_p(key); | ||||||
|     uint8_t line_count = 2; |     uint8_t line_count = 2; | ||||||
|     DOLPHIN_DEED(DolphinDeedIbuttonEmulate); |     DOLPHIN_DEED(DolphinDeedIbuttonEmulate); | ||||||
| 
 | 
 | ||||||
| @ -21,8 +25,8 @@ void iButtonSceneEmulate::on_enter(iButtonApp* app) { | |||||||
|         line_count = 2; |         line_count = 2; | ||||||
|     } else { |     } else { | ||||||
|         // if not, show key data
 |         // if not, show key data
 | ||||||
|         switch(key->get_key_type()) { |         switch(ibutton_key_get_type(key)) { | ||||||
|         case iButtonKeyType::KeyDallas: |         case iButtonKeyDS1990: | ||||||
|             app->set_text_store( |             app->set_text_store( | ||||||
|                 "emulating\n%02X %02X %02X %02X\n%02X %02X %02X %02X", |                 "emulating\n%02X %02X %02X %02X\n%02X %02X %02X %02X", | ||||||
|                 key_data[0], |                 key_data[0], | ||||||
| @ -35,11 +39,11 @@ void iButtonSceneEmulate::on_enter(iButtonApp* app) { | |||||||
|                 key_data[7]); |                 key_data[7]); | ||||||
|             line_count = 3; |             line_count = 3; | ||||||
|             break; |             break; | ||||||
|         case iButtonKeyType::KeyCyfral: |         case iButtonKeyCyfral: | ||||||
|             app->set_text_store("emulating\n%02X %02X", key_data[0], key_data[1]); |             app->set_text_store("emulating\n%02X %02X", key_data[0], key_data[1]); | ||||||
|             line_count = 2; |             line_count = 2; | ||||||
|             break; |             break; | ||||||
|         case iButtonKeyType::KeyMetakom: |         case iButtonKeyMetakom: | ||||||
|             app->set_text_store( |             app->set_text_store( | ||||||
|                 "emulating\n%02X %02X %02X %02X", |                 "emulating\n%02X %02X %02X %02X", | ||||||
|                 key_data[0], |                 key_data[0], | ||||||
| @ -66,29 +70,28 @@ void iButtonSceneEmulate::on_enter(iButtonApp* app) { | |||||||
|     popup_set_icon(popup, 2, 10, &I_iButtonKey_49x44); |     popup_set_icon(popup, 2, 10, &I_iButtonKey_49x44); | ||||||
| 
 | 
 | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); |     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); | ||||||
|     app->get_key_worker()->start_emulate(app->get_key()); | 
 | ||||||
|  |     ibutton_worker_emulate_set_callback(app->get_key_worker(), emulate_callback, app); | ||||||
|  |     ibutton_worker_emulate_start(app->get_key_worker(), key); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool iButtonSceneEmulate::on_event(iButtonApp* app, iButtonEvent* event) { | bool iButtonSceneEmulate::on_event(iButtonApp* app, iButtonEvent* event) { | ||||||
|     bool consumed = false; |     bool consumed = false; | ||||||
| 
 | 
 | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeTick) { |     if(event->type == iButtonEvent::Type::EventTypeWorkerEmulated) { | ||||||
|         consumed = true; |  | ||||||
|         if(app->get_key_worker()->emulated()) { |  | ||||||
|         app->notify_yellow_blink(); |         app->notify_yellow_blink(); | ||||||
|         } else { |         consumed = true; | ||||||
|  |     } else if(event->type == iButtonEvent::Type::EventTypeTick) { | ||||||
|         app->notify_red_blink(); |         app->notify_red_blink(); | ||||||
|         } |         consumed = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return consumed; |     return consumed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneEmulate::on_exit(iButtonApp* app) { | void iButtonSceneEmulate::on_exit(iButtonApp* app) { | ||||||
|     app->get_key_worker()->stop_emulate(); |  | ||||||
| 
 |  | ||||||
|     Popup* popup = app->get_view_manager()->get_popup(); |     Popup* popup = app->get_view_manager()->get_popup(); | ||||||
| 
 |     ibutton_worker_stop(app->get_key_worker()); | ||||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); |     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); |     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||||
|     popup_set_icon(popup, 0, 0, NULL); |     popup_set_icon(popup, 0, 0, NULL); | ||||||
|  | |||||||
| @ -1,6 +1,5 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "ibutton_scene_generic.h" | #include "ibutton_scene_generic.h" | ||||||
| #include "../helpers/key_emulator.h" |  | ||||||
| 
 | 
 | ||||||
| class iButtonSceneEmulate : public iButtonScene { | class iButtonSceneEmulate : public iButtonScene { | ||||||
| public: | public: | ||||||
|  | |||||||
| @ -1,24 +1,30 @@ | |||||||
| #include "ibutton_scene_info.h" | #include "ibutton_scene_info.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" | 
 | ||||||
| #include "../ibutton_event.h" | static void widget_callback(GuiButtonType result, InputType type, void* context) { | ||||||
| #include <callback-connector.h> |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  | 
 | ||||||
|  |     if(type == InputTypeShort) { | ||||||
|  |         event.type = iButtonEvent::Type::EventTypeWidgetButtonResult; | ||||||
|  |         event.payload.widget_button_result = result; | ||||||
|  |         app->get_view_manager()->send_event(&event); | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneInfo::on_enter(iButtonApp* app) { | void iButtonSceneInfo::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Widget* widget = view_manager->get_widget(); |     Widget* widget = view_manager->get_widget(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneInfo::widget_callback); |  | ||||||
| 
 |  | ||||||
|     iButtonKey* key = app->get_key(); |     iButtonKey* key = app->get_key(); | ||||||
|     uint8_t* key_data = key->get_data(); |     const uint8_t* key_data = ibutton_key_get_data_p(key); | ||||||
| 
 | 
 | ||||||
|     app->set_text_store("%s", key->get_name()); |     app->set_text_store("%s", ibutton_key_get_name_p(key)); | ||||||
|     widget_add_text_box_element( |     widget_add_text_box_element( | ||||||
|         widget, 0, 0, 128, 27, AlignCenter, AlignCenter, app->get_text_store()); |         widget, 0, 0, 128, 27, AlignCenter, AlignCenter, app->get_text_store()); | ||||||
|     widget_add_button_element(widget, GuiButtonTypeLeft, "Back", callback, app); |     widget_add_button_element(widget, GuiButtonTypeLeft, "Back", widget_callback, app); | ||||||
| 
 | 
 | ||||||
|     switch(key->get_key_type()) { |     switch(ibutton_key_get_type(key)) { | ||||||
|     case iButtonKeyType::KeyDallas: |     case iButtonKeyDS1990: | ||||||
|         app->set_text_store( |         app->set_text_store( | ||||||
|             "%02X %02X %02X %02X %02X %02X %02X %02X", |             "%02X %02X %02X %02X %02X %02X %02X %02X", | ||||||
|             key_data[0], |             key_data[0], | ||||||
| @ -32,13 +38,13 @@ void iButtonSceneInfo::on_enter(iButtonApp* app) { | |||||||
|         widget_add_string_element( |         widget_add_string_element( | ||||||
|             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Dallas"); |             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Dallas"); | ||||||
|         break; |         break; | ||||||
|     case iButtonKeyType::KeyMetakom: |     case iButtonKeyMetakom: | ||||||
|         app->set_text_store( |         app->set_text_store( | ||||||
|             "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); |             "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); | ||||||
|         widget_add_string_element( |         widget_add_string_element( | ||||||
|             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Metakom"); |             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Metakom"); | ||||||
|         break; |         break; | ||||||
|     case iButtonKeyType::KeyCyfral: |     case iButtonKeyCyfral: | ||||||
|         app->set_text_store("%02X %02X", key_data[0], key_data[1]); |         app->set_text_store("%02X %02X", key_data[0], key_data[1]); | ||||||
|         widget_add_string_element( |         widget_add_string_element( | ||||||
|             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Cyfral"); |             widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Cyfral"); | ||||||
| @ -71,15 +77,3 @@ void iButtonSceneInfo::on_exit(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     widget_reset(widget); |     widget_reset(widget); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneInfo::widget_callback(GuiButtonType result, InputType type, void* context) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     if(type == InputTypeShort) { |  | ||||||
|         event.type = iButtonEvent::Type::EventTypeWidgetButtonResult; |  | ||||||
|         event.payload.widget_button_result = result; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -6,7 +6,4 @@ public: | |||||||
|     void on_enter(iButtonApp* app) final; |     void on_enter(iButtonApp* app) final; | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     void widget_callback(GuiButtonType result, InputType type, void* context); |  | ||||||
| }; | }; | ||||||
| @ -1,12 +1,18 @@ | |||||||
| #include "ibutton_scene_read.h" | #include "ibutton_scene_read.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" |  | ||||||
| #include "../ibutton_event.h" |  | ||||||
| #include <dolphin/dolphin.h> | #include <dolphin/dolphin.h> | ||||||
| 
 | 
 | ||||||
|  | static void read_callback(void* context) { | ||||||
|  |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event = {.type = iButtonEvent::Type::EventTypeWorkerRead}; | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void iButtonSceneRead::on_enter(iButtonApp* app) { | void iButtonSceneRead::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Popup* popup = view_manager->get_popup(); |     Popup* popup = view_manager->get_popup(); | ||||||
|  |     iButtonKey* key = app->get_key(); | ||||||
|  |     iButtonWorker* worker = app->get_key_worker(); | ||||||
|     DOLPHIN_DEED(DolphinDeedIbuttonRead); |     DOLPHIN_DEED(DolphinDeedIbuttonRead); | ||||||
| 
 | 
 | ||||||
|     popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); |     popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); | ||||||
| @ -14,41 +20,41 @@ void iButtonSceneRead::on_enter(iButtonApp* app) { | |||||||
|     popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59); |     popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59); | ||||||
| 
 | 
 | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); |     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); | ||||||
|     app->get_key()->set_name(""); |     ibutton_key_set_name(key, ""); | ||||||
| 
 | 
 | ||||||
|     app->get_key_worker()->start_read(); |     ibutton_worker_read_set_callback(worker, read_callback, app); | ||||||
|  |     ibutton_worker_read_start(worker, key); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool iButtonSceneRead::on_event(iButtonApp* app, iButtonEvent* event) { | bool iButtonSceneRead::on_event(iButtonApp* app, iButtonEvent* event) { | ||||||
|     bool consumed = false; |     bool consumed = false; | ||||||
| 
 | 
 | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeTick) { |     if(event->type == iButtonEvent::Type::EventTypeWorkerRead) { | ||||||
|  |         consumed = true; | ||||||
|  | 
 | ||||||
|  |         iButtonKey* key = app->get_key(); | ||||||
|  |         if(ibutton_key_get_type(key) == iButtonKeyDS1990) { | ||||||
|  |             if(!ibutton_key_dallas_crc_is_valid(key)) { | ||||||
|  |                 app->switch_to_next_scene(iButtonApp::Scene::SceneReadCRCError); | ||||||
|  |             } else if(!ibutton_key_dallas_is_1990_key(key)) { | ||||||
|  |                 app->switch_to_next_scene(iButtonApp::Scene::SceneReadNotKeyError); | ||||||
|  |             } else { | ||||||
|  |                 app->switch_to_next_scene(iButtonApp::Scene::SceneReadSuccess); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             app->switch_to_next_scene(iButtonApp::Scene::SceneReadSuccess); | ||||||
|  |         } | ||||||
|  |     } else if(event->type == iButtonEvent::Type::EventTypeTick) { | ||||||
|         consumed = true; |         consumed = true; | ||||||
|         app->notify_red_blink(); |         app->notify_red_blink(); | ||||||
| 
 |  | ||||||
|         switch(app->get_key_worker()->read(app->get_key())) { |  | ||||||
|         case KeyReader::Error::EMPTY: |  | ||||||
|             break; |  | ||||||
|         case KeyReader::Error::OK: |  | ||||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneReadSuccess); |  | ||||||
|             break; |  | ||||||
|         case KeyReader::Error::CRC_ERROR: |  | ||||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneReadCRCError); |  | ||||||
|             break; |  | ||||||
|         case KeyReader::Error::NOT_ARE_KEY: |  | ||||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneReadNotKeyError); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return consumed; |     return consumed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneRead::on_exit(iButtonApp* app) { | void iButtonSceneRead::on_exit(iButtonApp* app) { | ||||||
|     app->get_key_worker()->stop_read(); |  | ||||||
| 
 |  | ||||||
|     Popup* popup = app->get_view_manager()->get_popup(); |     Popup* popup = app->get_view_manager()->get_popup(); | ||||||
| 
 |     ibutton_worker_stop(app->get_key_worker()); | ||||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); |     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); |     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||||
|     popup_set_icon(popup, 0, 0, NULL); |     popup_set_icon(popup, 0, 0, NULL); | ||||||
|  | |||||||
| @ -6,6 +6,4 @@ public: | |||||||
|     void on_enter(iButtonApp* app) final; |     void on_enter(iButtonApp* app) final; | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
| }; | }; | ||||||
| @ -1,16 +1,21 @@ | |||||||
| #include "ibutton_scene_read_crc_error.h" | #include "ibutton_scene_read_crc_error.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" | #include <one_wire/maxim_crc.h> | ||||||
| #include "../ibutton_event.h" | 
 | ||||||
| #include <callback-connector.h> | static void dialog_ex_callback(DialogExResult result, void* context) { | ||||||
|  |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeDialogResult; | ||||||
|  |     event.payload.dialog_result = result; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneReadCRCError::on_enter(iButtonApp* app) { | void iButtonSceneReadCRCError::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     DialogEx* dialog_ex = view_manager->get_dialog_ex(); |     DialogEx* dialog_ex = view_manager->get_dialog_ex(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneReadCRCError::dialog_ex_callback); |     const uint8_t* key_data = ibutton_key_get_data_p(app->get_key()); | ||||||
| 
 |  | ||||||
|     iButtonKey* key = app->get_key(); |  | ||||||
|     uint8_t* key_data = key->get_data(); |  | ||||||
| 
 | 
 | ||||||
|     app->set_text_store( |     app->set_text_store( | ||||||
|         "%02X %02X %02X %02X %02X %02X %02X %02X\nExpected CRC: %X", |         "%02X %02X %02X %02X %02X %02X %02X %02X\nExpected CRC: %X", | ||||||
| @ -22,13 +27,13 @@ void iButtonSceneReadCRCError::on_enter(iButtonApp* app) { | |||||||
|         key_data[5], |         key_data[5], | ||||||
|         key_data[6], |         key_data[6], | ||||||
|         key_data[7], |         key_data[7], | ||||||
|         maxim_crc8(key_data, 7)); |         maxim_crc8(key_data, 7, MAXIM_CRC8_INIT)); | ||||||
| 
 | 
 | ||||||
|     dialog_ex_set_header(dialog_ex, "CRC ERROR", 64, 10, AlignCenter, AlignCenter); |     dialog_ex_set_header(dialog_ex, "CRC ERROR", 64, 10, AlignCenter, AlignCenter); | ||||||
|     dialog_ex_set_text(dialog_ex, app->get_text_store(), 64, 19, AlignCenter, AlignTop); |     dialog_ex_set_text(dialog_ex, app->get_text_store(), 64, 19, AlignCenter, AlignTop); | ||||||
|     dialog_ex_set_left_button_text(dialog_ex, "Retry"); |     dialog_ex_set_left_button_text(dialog_ex, "Retry"); | ||||||
|     dialog_ex_set_right_button_text(dialog_ex, "More"); |     dialog_ex_set_right_button_text(dialog_ex, "More"); | ||||||
|     dialog_ex_set_result_callback(dialog_ex, callback); |     dialog_ex_set_result_callback(dialog_ex, dialog_ex_callback); | ||||||
|     dialog_ex_set_context(dialog_ex, app); |     dialog_ex_set_context(dialog_ex, app); | ||||||
| 
 | 
 | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx); |     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx); | ||||||
| @ -66,13 +71,3 @@ void iButtonSceneReadCRCError::on_exit(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     app->notify_red_off(); |     app->notify_red_off(); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneReadCRCError::dialog_ex_callback(DialogExResult result, void* context) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeDialogResult; |  | ||||||
|     event.payload.dialog_result = result; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
| @ -1,13 +1,9 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "ibutton_scene_generic.h" | #include "ibutton_scene_generic.h" | ||||||
| #include <gui/modules/dialog_ex.h> |  | ||||||
| 
 | 
 | ||||||
| class iButtonSceneReadCRCError : public iButtonScene { | class iButtonSceneReadCRCError : public iButtonScene { | ||||||
| public: | public: | ||||||
|     void on_enter(iButtonApp* app) final; |     void on_enter(iButtonApp* app) final; | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     void dialog_ex_callback(DialogExResult result, void* context); |  | ||||||
| }; | }; | ||||||
| @ -1,16 +1,21 @@ | |||||||
| #include "ibutton_scene_read_not_key_error.h" | #include "ibutton_scene_read_not_key_error.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" | #include <one_wire/maxim_crc.h> | ||||||
| #include "../ibutton_event.h" | 
 | ||||||
| #include <callback-connector.h> | static void dialog_ex_callback(DialogExResult result, void* context) { | ||||||
|  |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeDialogResult; | ||||||
|  |     event.payload.dialog_result = result; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneReadNotKeyError::on_enter(iButtonApp* app) { | void iButtonSceneReadNotKeyError::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     DialogEx* dialog_ex = view_manager->get_dialog_ex(); |     DialogEx* dialog_ex = view_manager->get_dialog_ex(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneReadNotKeyError::dialog_ex_callback); |     const uint8_t* key_data = ibutton_key_get_data_p(app->get_key()); | ||||||
| 
 |  | ||||||
|     iButtonKey* key = app->get_key(); |  | ||||||
|     uint8_t* key_data = key->get_data(); |  | ||||||
| 
 | 
 | ||||||
|     app->set_text_store( |     app->set_text_store( | ||||||
|         "THIS IS NOT A KEY\n%02X %02X %02X %02X %02X %02X %02X %02X", |         "THIS IS NOT A KEY\n%02X %02X %02X %02X %02X %02X %02X %02X", | ||||||
| @ -22,13 +27,13 @@ void iButtonSceneReadNotKeyError::on_enter(iButtonApp* app) { | |||||||
|         key_data[5], |         key_data[5], | ||||||
|         key_data[6], |         key_data[6], | ||||||
|         key_data[7], |         key_data[7], | ||||||
|         maxim_crc8(key_data, 7)); |         maxim_crc8(key_data, 7, MAXIM_CRC8_INIT)); | ||||||
| 
 | 
 | ||||||
|     dialog_ex_set_header(dialog_ex, "ERROR:", 64, 10, AlignCenter, AlignCenter); |     dialog_ex_set_header(dialog_ex, "ERROR:", 64, 10, AlignCenter, AlignCenter); | ||||||
|     dialog_ex_set_text(dialog_ex, app->get_text_store(), 64, 19, AlignCenter, AlignTop); |     dialog_ex_set_text(dialog_ex, app->get_text_store(), 64, 19, AlignCenter, AlignTop); | ||||||
|     dialog_ex_set_left_button_text(dialog_ex, "Retry"); |     dialog_ex_set_left_button_text(dialog_ex, "Retry"); | ||||||
|     dialog_ex_set_right_button_text(dialog_ex, "More"); |     dialog_ex_set_right_button_text(dialog_ex, "More"); | ||||||
|     dialog_ex_set_result_callback(dialog_ex, callback); |     dialog_ex_set_result_callback(dialog_ex, dialog_ex_callback); | ||||||
|     dialog_ex_set_context(dialog_ex, app); |     dialog_ex_set_context(dialog_ex, app); | ||||||
| 
 | 
 | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx); |     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx); | ||||||
| @ -66,13 +71,3 @@ void iButtonSceneReadNotKeyError::on_exit(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     app->notify_red_off(); |     app->notify_red_off(); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneReadNotKeyError::dialog_ex_callback(DialogExResult result, void* context) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeDialogResult; |  | ||||||
|     event.payload.dialog_result = result; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
| @ -1,13 +1,9 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "ibutton_scene_generic.h" | #include "ibutton_scene_generic.h" | ||||||
| #include <gui/modules/dialog_ex.h> |  | ||||||
| 
 | 
 | ||||||
| class iButtonSceneReadNotKeyError : public iButtonScene { | class iButtonSceneReadNotKeyError : public iButtonScene { | ||||||
| public: | public: | ||||||
|     void on_enter(iButtonApp* app) final; |     void on_enter(iButtonApp* app) final; | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     void dialog_ex_callback(DialogExResult result, void* context); |  | ||||||
| }; | }; | ||||||
| @ -1,21 +1,26 @@ | |||||||
| #include "ibutton_scene_read_success.h" | #include "ibutton_scene_read_success.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" |  | ||||||
| #include "../ibutton_event.h" |  | ||||||
| #include <dolphin/dolphin.h> | #include <dolphin/dolphin.h> | ||||||
| #include <callback-connector.h> | 
 | ||||||
|  | static void dialog_ex_callback(DialogExResult result, void* context) { | ||||||
|  |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeDialogResult; | ||||||
|  |     event.payload.dialog_result = result; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneReadSuccess::on_enter(iButtonApp* app) { | void iButtonSceneReadSuccess::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     DialogEx* dialog_ex = view_manager->get_dialog_ex(); |     DialogEx* dialog_ex = view_manager->get_dialog_ex(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneReadSuccess::dialog_ex_callback); |     iButtonKey* key = app->get_key(); | ||||||
|  |     const uint8_t* key_data = ibutton_key_get_data_p(key); | ||||||
|     DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess); |     DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess); | ||||||
| 
 | 
 | ||||||
|     iButtonKey* key = app->get_key(); |     switch(ibutton_key_get_type(key)) { | ||||||
|     uint8_t* key_data = key->get_data(); |     case iButtonKeyDS1990: | ||||||
| 
 |  | ||||||
|     switch(key->get_key_type()) { |  | ||||||
|     case iButtonKeyType::KeyDallas: |  | ||||||
|         app->set_text_store( |         app->set_text_store( | ||||||
|             "Dallas\n%02X %02X %02X %02X\n%02X %02X %02X %02X", |             "Dallas\n%02X %02X %02X %02X\n%02X %02X %02X %02X", | ||||||
|             key_data[0], |             key_data[0], | ||||||
| @ -27,10 +32,10 @@ void iButtonSceneReadSuccess::on_enter(iButtonApp* app) { | |||||||
|             key_data[6], |             key_data[6], | ||||||
|             key_data[7]); |             key_data[7]); | ||||||
|         break; |         break; | ||||||
|     case iButtonKeyType::KeyCyfral: |     case iButtonKeyCyfral: | ||||||
|         app->set_text_store("Cyfral\n%02X %02X", key_data[0], key_data[1]); |         app->set_text_store("Cyfral\n%02X %02X", key_data[0], key_data[1]); | ||||||
|         break; |         break; | ||||||
|     case iButtonKeyType::KeyMetakom: |     case iButtonKeyMetakom: | ||||||
|         app->set_text_store( |         app->set_text_store( | ||||||
|             "Metakom\n%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); |             "Metakom\n%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); | ||||||
|         break; |         break; | ||||||
| @ -40,7 +45,7 @@ void iButtonSceneReadSuccess::on_enter(iButtonApp* app) { | |||||||
|     dialog_ex_set_left_button_text(dialog_ex, "Retry"); |     dialog_ex_set_left_button_text(dialog_ex, "Retry"); | ||||||
|     dialog_ex_set_right_button_text(dialog_ex, "More"); |     dialog_ex_set_right_button_text(dialog_ex, "More"); | ||||||
|     dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinExcited_64x63); |     dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinExcited_64x63); | ||||||
|     dialog_ex_set_result_callback(dialog_ex, callback); |     dialog_ex_set_result_callback(dialog_ex, dialog_ex_callback); | ||||||
|     dialog_ex_set_context(dialog_ex, app); |     dialog_ex_set_context(dialog_ex, app); | ||||||
| 
 | 
 | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx); |     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx); | ||||||
| @ -80,13 +85,3 @@ void iButtonSceneReadSuccess::on_exit(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     app->notify_green_off(); |     app->notify_green_off(); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneReadSuccess::dialog_ex_callback(DialogExResult result, void* context) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeDialogResult; |  | ||||||
|     event.payload.dialog_result = result; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -1,13 +1,9 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "ibutton_scene_generic.h" | #include "ibutton_scene_generic.h" | ||||||
| #include <gui/modules/dialog_ex.h> |  | ||||||
| 
 | 
 | ||||||
| class iButtonSceneReadSuccess : public iButtonScene { | class iButtonSceneReadSuccess : public iButtonScene { | ||||||
| public: | public: | ||||||
|     void on_enter(iButtonApp* app) final; |     void on_enter(iButtonApp* app) final; | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     void dialog_ex_callback(DialogExResult result, void* context); |  | ||||||
| }; | }; | ||||||
| @ -1,8 +1,5 @@ | |||||||
| #include "ibutton_scene_readed_key_menu.h" | #include "ibutton_scene_readed_key_menu.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" |  | ||||||
| #include "../ibutton_event.h" |  | ||||||
| #include <callback-connector.h> |  | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     SubmenuIndexWrite, |     SubmenuIndexWrite, | ||||||
| @ -11,17 +8,26 @@ typedef enum { | |||||||
|     SubmenuIndexReadNewKey, |     SubmenuIndexReadNewKey, | ||||||
| } SubmenuIndex; | } SubmenuIndex; | ||||||
| 
 | 
 | ||||||
|  | static void submenu_callback(void* context, uint32_t index) { | ||||||
|  |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeMenuSelected; | ||||||
|  |     event.payload.menu_index = index; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void iButtonSceneReadedKeyMenu::on_enter(iButtonApp* app) { | void iButtonSceneReadedKeyMenu::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Submenu* submenu = view_manager->get_submenu(); |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneReadedKeyMenu::submenu_callback); |  | ||||||
| 
 | 
 | ||||||
|     if(app->get_key()->get_key_type() == iButtonKeyType::KeyDallas) { |     if(ibutton_key_get_type(app->get_key()) == iButtonKeyDS1990) { | ||||||
|         submenu_add_item(submenu, "Write", SubmenuIndexWrite, callback, app); |         submenu_add_item(submenu, "Write", SubmenuIndexWrite, submenu_callback, app); | ||||||
|     } |     } | ||||||
|     submenu_add_item(submenu, "Name and save", SubmenuIndexNameAndSave, callback, app); |     submenu_add_item(submenu, "Name and save", SubmenuIndexNameAndSave, submenu_callback, app); | ||||||
|     submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, callback, app); |     submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, submenu_callback, app); | ||||||
|     submenu_add_item(submenu, "Read new key", SubmenuIndexReadNewKey, callback, app); |     submenu_add_item(submenu, "Read new key", SubmenuIndexReadNewKey, submenu_callback, app); | ||||||
|     submenu_set_selected_item(submenu, submenu_item_selected); |     submenu_set_selected_item(submenu, submenu_item_selected); | ||||||
| 
 | 
 | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); |     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); | ||||||
| @ -61,13 +67,3 @@ void iButtonSceneReadedKeyMenu::on_exit(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     submenu_reset(submenu); |     submenu_reset(submenu); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneReadedKeyMenu::submenu_callback(void* context, uint32_t index) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeMenuSelected; |  | ||||||
|     event.payload.menu_index = index; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -8,6 +8,5 @@ public: | |||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void submenu_callback(void* context, uint32_t index); |  | ||||||
|     uint32_t submenu_item_selected = 0; |     uint32_t submenu_item_selected = 0; | ||||||
| }; | }; | ||||||
| @ -1,18 +1,21 @@ | |||||||
| #include "ibutton_scene_save_name.h" | #include "ibutton_scene_save_name.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" |  | ||||||
| #include "../ibutton_event.h" |  | ||||||
| #include "../ibutton_key.h" |  | ||||||
| #include <callback-connector.h> |  | ||||||
| #include <lib/toolbox/random_name.h> | #include <lib/toolbox/random_name.h> | ||||||
| 
 | 
 | ||||||
|  | static void text_input_callback(void* context) { | ||||||
|  |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeTextEditResult; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void iButtonSceneSaveName::on_enter(iButtonApp* app) { | void iButtonSceneSaveName::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     TextInput* text_input = view_manager->get_text_input(); |     TextInput* text_input = view_manager->get_text_input(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneSaveName::text_input_callback); |  | ||||||
| 
 | 
 | ||||||
|     iButtonKey* key = app->get_key(); |     const char* key_name = ibutton_key_get_name_p(app->get_key()); | ||||||
|     const char* key_name = key->get_name(); |  | ||||||
|     bool key_name_empty = !strcmp(key_name, ""); |     bool key_name_empty = !strcmp(key_name, ""); | ||||||
| 
 | 
 | ||||||
|     if(key_name_empty) { |     if(key_name_empty) { | ||||||
| @ -23,7 +26,12 @@ void iButtonSceneSaveName::on_enter(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     text_input_set_header_text(text_input, "Name the key"); |     text_input_set_header_text(text_input, "Name the key"); | ||||||
|     text_input_set_result_callback( |     text_input_set_result_callback( | ||||||
|         text_input, callback, app, app->get_text_store(), IBUTTON_KEY_NAME_SIZE, key_name_empty); |         text_input, | ||||||
|  |         text_input_callback, | ||||||
|  |         app, | ||||||
|  |         app->get_text_store(), | ||||||
|  |         IBUTTON_KEY_NAME_SIZE, | ||||||
|  |         key_name_empty); | ||||||
| 
 | 
 | ||||||
|     ValidatorIsFile* validator_is_file = |     ValidatorIsFile* validator_is_file = | ||||||
|         validator_is_file_alloc_init(app->app_folder, app->app_extension); |         validator_is_file_alloc_init(app->app_folder, app->app_extension); | ||||||
| @ -59,12 +67,3 @@ void iButtonSceneSaveName::on_exit(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     text_input_reset(text_input); |     text_input_reset(text_input); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneSaveName::text_input_callback(void* context) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeTextEditResult; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -6,7 +6,4 @@ public: | |||||||
|     void on_enter(iButtonApp* app) final; |     void on_enter(iButtonApp* app) final; | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     void text_input_callback(void* context); |  | ||||||
| }; | }; | ||||||
| @ -1,21 +1,23 @@ | |||||||
| #include "ibutton_scene_save_success.h" | #include "ibutton_scene_save_success.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" |  | ||||||
| #include "../ibutton_event.h" |  | ||||||
| #include "../ibutton_key.h" |  | ||||||
| #include <dolphin/dolphin.h> | #include <dolphin/dolphin.h> | ||||||
| #include <callback-connector.h> | 
 | ||||||
|  | static void popup_callback(void* context) { | ||||||
|  |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeBack; | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneSaveSuccess::on_enter(iButtonApp* app) { | void iButtonSceneSaveSuccess::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Popup* popup = view_manager->get_popup(); |     Popup* popup = view_manager->get_popup(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneSaveSuccess::popup_callback); |  | ||||||
|     DOLPHIN_DEED(DolphinDeedIbuttonSave); |     DOLPHIN_DEED(DolphinDeedIbuttonSave); | ||||||
| 
 | 
 | ||||||
|     popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); |     popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); | ||||||
|     popup_set_text(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); |     popup_set_text(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); | ||||||
| 
 | 
 | ||||||
|     popup_set_callback(popup, callback); |     popup_set_callback(popup, popup_callback); | ||||||
|     popup_set_context(popup, app); |     popup_set_context(popup, app); | ||||||
|     popup_set_timeout(popup, 1500); |     popup_set_timeout(popup, 1500); | ||||||
|     popup_enable_timeout(popup); |     popup_enable_timeout(popup); | ||||||
| @ -47,10 +49,3 @@ void iButtonSceneSaveSuccess::on_exit(iButtonApp* app) { | |||||||
|     popup_set_context(popup, NULL); |     popup_set_context(popup, NULL); | ||||||
|     popup_set_callback(popup, NULL); |     popup_set_callback(popup, NULL); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneSaveSuccess::popup_callback(void* context) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeBack; |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -6,7 +6,4 @@ public: | |||||||
|     void on_enter(iButtonApp* app) final; |     void on_enter(iButtonApp* app) final; | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     void popup_callback(void* context); |  | ||||||
| }; | }; | ||||||
| @ -1,7 +1,5 @@ | |||||||
| #include "ibutton_scene_saved_key_menu.h" | #include "ibutton_scene_saved_key_menu.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" |  | ||||||
| #include "../ibutton_event.h" |  | ||||||
| #include <callback-connector.h> | #include <callback-connector.h> | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
| @ -12,18 +10,27 @@ typedef enum { | |||||||
|     SubmenuIndexInfo, |     SubmenuIndexInfo, | ||||||
| } SubmenuIndex; | } SubmenuIndex; | ||||||
| 
 | 
 | ||||||
|  | static void submenu_callback(void* context, uint32_t index) { | ||||||
|  |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeMenuSelected; | ||||||
|  |     event.payload.menu_index = index; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void iButtonSceneSavedKeyMenu::on_enter(iButtonApp* app) { | void iButtonSceneSavedKeyMenu::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Submenu* submenu = view_manager->get_submenu(); |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneSavedKeyMenu::submenu_callback); |  | ||||||
| 
 | 
 | ||||||
|     submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, callback, app); |     submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, submenu_callback, app); | ||||||
|     if(app->get_key()->get_key_type() == iButtonKeyType::KeyDallas) { |     if(ibutton_key_get_type(app->get_key()) == iButtonKeyDS1990) { | ||||||
|         submenu_add_item(submenu, "Write", SubmenuIndexWrite, callback, app); |         submenu_add_item(submenu, "Write", SubmenuIndexWrite, submenu_callback, app); | ||||||
|     } |     } | ||||||
|     submenu_add_item(submenu, "Edit", SubmenuIndexEdit, callback, app); |     submenu_add_item(submenu, "Edit", SubmenuIndexEdit, submenu_callback, app); | ||||||
|     submenu_add_item(submenu, "Delete", SubmenuIndexDelete, callback, app); |     submenu_add_item(submenu, "Delete", SubmenuIndexDelete, submenu_callback, app); | ||||||
|     submenu_add_item(submenu, "Info", SubmenuIndexInfo, callback, app); |     submenu_add_item(submenu, "Info", SubmenuIndexInfo, submenu_callback, app); | ||||||
|     submenu_set_selected_item(submenu, submenu_item_selected); |     submenu_set_selected_item(submenu, submenu_item_selected); | ||||||
| 
 | 
 | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); |     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); | ||||||
| @ -63,13 +70,3 @@ void iButtonSceneSavedKeyMenu::on_exit(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     submenu_reset(submenu); |     submenu_reset(submenu); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneSavedKeyMenu::submenu_callback(void* context, uint32_t index) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeMenuSelected; |  | ||||||
|     event.payload.menu_index = index; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -8,6 +8,5 @@ public: | |||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void submenu_callback(void* context, uint32_t index); |  | ||||||
|     uint32_t submenu_item_selected = 0; |     uint32_t submenu_item_selected = 0; | ||||||
| }; | }; | ||||||
| @ -1,7 +1,5 @@ | |||||||
| #include "ibutton_scene_select_key.h" | #include "ibutton_scene_select_key.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_event.h" |  | ||||||
| #include "../ibutton_key.h" |  | ||||||
| 
 | 
 | ||||||
| void iButtonSceneSelectKey::on_enter(iButtonApp* app) { | void iButtonSceneSelectKey::on_enter(iButtonApp* app) { | ||||||
|     // Process file_select return
 |     // Process file_select return
 | ||||||
|  | |||||||
| @ -1,8 +1,5 @@ | |||||||
| #include "ibutton_scene_start.h" | #include "ibutton_scene_start.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" |  | ||||||
| #include "../ibutton_event.h" |  | ||||||
| #include <callback-connector.h> |  | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     SubmenuIndexRead, |     SubmenuIndexRead, | ||||||
| @ -10,14 +7,23 @@ typedef enum { | |||||||
|     SubmenuIndexAdd, |     SubmenuIndexAdd, | ||||||
| } SubmenuIndex; | } SubmenuIndex; | ||||||
| 
 | 
 | ||||||
|  | static void submenu_callback(void* context, uint32_t index) { | ||||||
|  |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  | 
 | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeMenuSelected; | ||||||
|  |     event.payload.menu_index = index; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void iButtonSceneStart::on_enter(iButtonApp* app) { | void iButtonSceneStart::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Submenu* submenu = view_manager->get_submenu(); |     Submenu* submenu = view_manager->get_submenu(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneStart::submenu_callback); |  | ||||||
| 
 | 
 | ||||||
|     submenu_add_item(submenu, "Read", SubmenuIndexRead, callback, app); |     submenu_add_item(submenu, "Read", SubmenuIndexRead, submenu_callback, app); | ||||||
|     submenu_add_item(submenu, "Saved", SubmenuIndexSaved, callback, app); |     submenu_add_item(submenu, "Saved", SubmenuIndexSaved, submenu_callback, app); | ||||||
|     submenu_add_item(submenu, "Add manually", SubmenuIndexAdd, callback, app); |     submenu_add_item(submenu, "Add manually", SubmenuIndexAdd, submenu_callback, app); | ||||||
|     submenu_set_selected_item(submenu, submenu_item_selected); |     submenu_set_selected_item(submenu, submenu_item_selected); | ||||||
| 
 | 
 | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); |     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu); | ||||||
| @ -51,13 +57,3 @@ void iButtonSceneStart::on_exit(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     submenu_reset(submenu); |     submenu_reset(submenu); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneStart::submenu_callback(void* context, uint32_t index) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
| 
 |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeMenuSelected; |  | ||||||
|     event.payload.menu_index = index; |  | ||||||
| 
 |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -8,6 +8,5 @@ public: | |||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void submenu_callback(void* context, uint32_t index); |  | ||||||
|     uint32_t submenu_item_selected = 0; |     uint32_t submenu_item_selected = 0; | ||||||
| }; | }; | ||||||
| @ -1,15 +1,22 @@ | |||||||
| #include "ibutton_scene_write.h" | #include "ibutton_scene_write.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" | 
 | ||||||
| #include "../ibutton_event.h" | static void ibutton_worker_write_cb(void* context, iButtonWorkerWriteResult result) { | ||||||
| #include "../ibutton_key.h" |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
|  |     iButtonEvent event; | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeWorkerWrite; | ||||||
|  |     event.payload.worker_write_result = result; | ||||||
|  | 
 | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneWrite::on_enter(iButtonApp* app) { | void iButtonSceneWrite::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Popup* popup = view_manager->get_popup(); |     Popup* popup = view_manager->get_popup(); | ||||||
|     iButtonKey* key = app->get_key(); |     iButtonKey* key = app->get_key(); | ||||||
|     uint8_t* key_data = key->get_data(); |     iButtonWorker* worker = app->get_key_worker(); | ||||||
|     const char* key_name = key->get_name(); |     const uint8_t* key_data = ibutton_key_get_data_p(key); | ||||||
|  |     const char* key_name = ibutton_key_get_name_p(key); | ||||||
|     uint8_t line_count = 2; |     uint8_t line_count = 2; | ||||||
| 
 | 
 | ||||||
|     // check that stored key has name
 |     // check that stored key has name
 | ||||||
| @ -18,8 +25,8 @@ void iButtonSceneWrite::on_enter(iButtonApp* app) { | |||||||
|         line_count = 2; |         line_count = 2; | ||||||
|     } else { |     } else { | ||||||
|         // if not, show key data
 |         // if not, show key data
 | ||||||
|         switch(key->get_key_type()) { |         switch(ibutton_key_get_type(key)) { | ||||||
|         case iButtonKeyType::KeyDallas: |         case iButtonKeyDS1990: | ||||||
|             app->set_text_store( |             app->set_text_store( | ||||||
|                 "writing\n%02X %02X %02X %02X\n%02X %02X %02X %02X", |                 "writing\n%02X %02X %02X %02X\n%02X %02X %02X %02X", | ||||||
|                 key_data[0], |                 key_data[0], | ||||||
| @ -32,11 +39,11 @@ void iButtonSceneWrite::on_enter(iButtonApp* app) { | |||||||
|                 key_data[7]); |                 key_data[7]); | ||||||
|             line_count = 3; |             line_count = 3; | ||||||
|             break; |             break; | ||||||
|         case iButtonKeyType::KeyCyfral: |         case iButtonKeyCyfral: | ||||||
|             app->set_text_store("writing\n%02X %02X", key_data[0], key_data[1]); |             app->set_text_store("writing\n%02X %02X", key_data[0], key_data[1]); | ||||||
|             line_count = 2; |             line_count = 2; | ||||||
|             break; |             break; | ||||||
|         case iButtonKeyType::KeyMetakom: |         case iButtonKeyMetakom: | ||||||
|             app->set_text_store( |             app->set_text_store( | ||||||
|                 "writing\n%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); |                 "writing\n%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); | ||||||
|             line_count = 2; |             line_count = 2; | ||||||
| @ -60,27 +67,34 @@ void iButtonSceneWrite::on_enter(iButtonApp* app) { | |||||||
| 
 | 
 | ||||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); |     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); | ||||||
| 
 | 
 | ||||||
|     app->get_key_worker()->start_write(); |     blink_yellow = false; | ||||||
|  |     ibutton_worker_write_set_callback(worker, ibutton_worker_write_cb, app); | ||||||
|  |     ibutton_worker_write_start(worker, key); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool iButtonSceneWrite::on_event(iButtonApp* app, iButtonEvent* event) { | bool iButtonSceneWrite::on_event(iButtonApp* app, iButtonEvent* event) { | ||||||
|     bool consumed = false; |     bool consumed = false; | ||||||
| 
 | 
 | ||||||
|     if(event->type == iButtonEvent::Type::EventTypeTick) { |     if(event->type == iButtonEvent::Type::EventTypeWorkerWrite) { | ||||||
|         consumed = true; |         consumed = true; | ||||||
|         KeyWriter::Error result = app->get_key_worker()->write(app->get_key()); |  | ||||||
| 
 | 
 | ||||||
|         switch(result) { |         switch(event->payload.worker_write_result) { | ||||||
|         case KeyWriter::Error::SAME_KEY: |         case iButtonWorkerWriteOK: | ||||||
|         case KeyWriter::Error::OK: |         case iButtonWorkerWriteSameKey: | ||||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneWriteSuccess); |             app->switch_to_next_scene(iButtonApp::Scene::SceneWriteSuccess); | ||||||
|             break; |             break; | ||||||
|         case KeyWriter::Error::NO_DETECT: |         case iButtonWorkerWriteNoDetect: | ||||||
|             app->notify_red_blink(); |             blink_yellow = false; | ||||||
|             break; |             break; | ||||||
|         case KeyWriter::Error::CANNOT_WRITE: |         case iButtonWorkerWriteCannotWrite: | ||||||
|  |             blink_yellow = true; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } else if(event->type == iButtonEvent::Type::EventTypeTick) { | ||||||
|  |         if(blink_yellow) { | ||||||
|             app->notify_yellow_blink(); |             app->notify_yellow_blink(); | ||||||
|             break; |         } else { | ||||||
|  |             app->notify_red_blink(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -89,10 +103,8 @@ bool iButtonSceneWrite::on_event(iButtonApp* app, iButtonEvent* event) { | |||||||
| 
 | 
 | ||||||
| void iButtonSceneWrite::on_exit(iButtonApp* app) { | void iButtonSceneWrite::on_exit(iButtonApp* app) { | ||||||
|     Popup* popup = app->get_view_manager()->get_popup(); |     Popup* popup = app->get_view_manager()->get_popup(); | ||||||
| 
 |     ibutton_worker_stop(app->get_key_worker()); | ||||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); |     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); |     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||||
|     popup_set_icon(popup, 0, 0, NULL); |     popup_set_icon(popup, 0, 0, NULL); | ||||||
| 
 |  | ||||||
|     app->get_key_worker()->stop_write(); |  | ||||||
| } | } | ||||||
| @ -8,4 +8,5 @@ public: | |||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     bool blink_yellow; | ||||||
| }; | }; | ||||||
| @ -1,19 +1,22 @@ | |||||||
| #include "ibutton_scene_write_success.h" | #include "ibutton_scene_write_success.h" | ||||||
| #include "../ibutton_app.h" | #include "../ibutton_app.h" | ||||||
| #include "../ibutton_view_manager.h" | 
 | ||||||
| #include "../ibutton_event.h" | static void popup_callback(void* context) { | ||||||
| #include "../ibutton_key.h" |     iButtonApp* app = static_cast<iButtonApp*>(context); | ||||||
| #include <callback-connector.h> |     iButtonEvent event; | ||||||
|  |     event.type = iButtonEvent::Type::EventTypeBack; | ||||||
|  |     app->get_view_manager()->send_event(&event); | ||||||
|  |     app->notify_green_off(); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void iButtonSceneWriteSuccess::on_enter(iButtonApp* app) { | void iButtonSceneWriteSuccess::on_enter(iButtonApp* app) { | ||||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); |     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||||
|     Popup* popup = view_manager->get_popup(); |     Popup* popup = view_manager->get_popup(); | ||||||
|     auto callback = cbc::obtain_connector(this, &iButtonSceneWriteSuccess::popup_callback); |  | ||||||
| 
 | 
 | ||||||
|     popup_set_icon(popup, 0, 12, &I_iButtonDolphinVerySuccess_108x52); |     popup_set_icon(popup, 0, 12, &I_iButtonDolphinVerySuccess_108x52); | ||||||
|     popup_set_text(popup, "Successfully written!", 40, 12, AlignLeft, AlignBottom); |     popup_set_text(popup, "Successfully written!", 40, 12, AlignLeft, AlignBottom); | ||||||
| 
 | 
 | ||||||
|     popup_set_callback(popup, callback); |     popup_set_callback(popup, popup_callback); | ||||||
|     popup_set_context(popup, app); |     popup_set_context(popup, app); | ||||||
|     popup_set_timeout(popup, 1500); |     popup_set_timeout(popup, 1500); | ||||||
|     popup_enable_timeout(popup); |     popup_enable_timeout(popup); | ||||||
| @ -46,11 +49,3 @@ void iButtonSceneWriteSuccess::on_exit(iButtonApp* app) { | |||||||
|     popup_set_context(popup, NULL); |     popup_set_context(popup, NULL); | ||||||
|     popup_set_callback(popup, NULL); |     popup_set_callback(popup, NULL); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| void iButtonSceneWriteSuccess::popup_callback(void* context) { |  | ||||||
|     iButtonApp* app = static_cast<iButtonApp*>(context); |  | ||||||
|     iButtonEvent event; |  | ||||||
|     event.type = iButtonEvent::Type::EventTypeBack; |  | ||||||
|     app->get_view_manager()->send_event(&event); |  | ||||||
|     app->notify_green_off(); |  | ||||||
| } |  | ||||||
| @ -6,7 +6,4 @@ public: | |||||||
|     void on_enter(iButtonApp* app) final; |     void on_enter(iButtonApp* app) final; | ||||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; |     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||||
|     void on_exit(iButtonApp* app) final; |     void on_exit(iButtonApp* app) final; | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     void popup_callback(void* context); |  | ||||||
| }; | }; | ||||||
| @ -66,7 +66,7 @@ static void infrared_cli_start_ir_rx(Cli* cli, string_t args) { | |||||||
| 
 | 
 | ||||||
|     printf("Receiving INFRARED...\r\nPress Ctrl+C to abort\r\n"); |     printf("Receiving INFRARED...\r\nPress Ctrl+C to abort\r\n"); | ||||||
|     while(!cli_cmd_interrupt_received(cli)) { |     while(!cli_cmd_interrupt_received(cli)) { | ||||||
|         delay(50); |         furi_hal_delay_ms(50); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     infrared_worker_rx_stop(worker); |     infrared_worker_rx_stop(worker); | ||||||
|  | |||||||
| @ -37,6 +37,7 @@ void InfraredAppSceneLearn::on_enter(InfraredApp* app) { | |||||||
|     infrared_worker_rx_start(worker); |     infrared_worker_rx_start(worker); | ||||||
| 
 | 
 | ||||||
|     popup_set_icon(popup, 0, 32, &I_InfraredLearnShort_128x31); |     popup_set_icon(popup, 0, 32, &I_InfraredLearnShort_128x31); | ||||||
|  |     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignCenter); | ||||||
|     popup_set_text( |     popup_set_text( | ||||||
|         popup, "Point the remote at IR port\nand push the button", 5, 10, AlignLeft, AlignCenter); |         popup, "Point the remote at IR port\nand push the button", 5, 10, AlignLeft, AlignCenter); | ||||||
|     popup_set_callback(popup, NULL); |     popup_set_callback(popup, NULL); | ||||||
|  | |||||||
| @ -1,8 +1,6 @@ | |||||||
| #include "input_i.h" | #include "input_i.h" | ||||||
| 
 | 
 | ||||||
| #define GPIO_Read(input_pin)                                                    \ | #define GPIO_Read(input_pin) (furi_hal_gpio_read(input_pin.pin->gpio) ^ (input_pin.pin->inverted)) | ||||||
|     (HAL_GPIO_ReadPin((GPIO_TypeDef*)input_pin.pin->port, input_pin.pin->pin) ^ \ |  | ||||||
|      input_pin.pin->inverted) |  | ||||||
| 
 | 
 | ||||||
| static Input* input = NULL; | static Input* input = NULL; | ||||||
| 
 | 
 | ||||||
| @ -81,8 +79,7 @@ int32_t input_srv() { | |||||||
|     input->pin_states = malloc(input_pins_count * sizeof(InputPinState)); |     input->pin_states = malloc(input_pins_count * sizeof(InputPinState)); | ||||||
| 
 | 
 | ||||||
|     for(size_t i = 0; i < input_pins_count; i++) { |     for(size_t i = 0; i < input_pins_count; i++) { | ||||||
|         GpioPin gpio = {(GPIO_TypeDef*)input_pins[i].port, (uint16_t)input_pins[i].pin}; |         furi_hal_gpio_add_int_callback(input_pins[i].gpio, input_isr, NULL); | ||||||
|         hal_gpio_add_int_callback(&gpio, input_isr, NULL); |  | ||||||
|         input->pin_states[i].pin = &input_pins[i]; |         input->pin_states[i].pin = &input_pins[i]; | ||||||
|         input->pin_states[i].state = GPIO_Read(input->pin_states[i]); |         input->pin_states[i].state = GPIO_Read(input->pin_states[i]); | ||||||
|         input->pin_states[i].debounce = INPUT_DEBOUNCE_TICKS_HALF; |         input->pin_states[i].debounce = INPUT_DEBOUNCE_TICKS_HALF; | ||||||
|  | |||||||
| @ -3,13 +3,13 @@ | |||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| 
 | 
 | ||||||
| void DecoderGpioOut::process_front(bool polarity, uint32_t time) { | void DecoderGpioOut::process_front(bool polarity, uint32_t time) { | ||||||
|     hal_gpio_write(&gpio_ext_pa7, polarity); |     furi_hal_gpio_write(&gpio_ext_pa7, polarity); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DecoderGpioOut::DecoderGpioOut() { | DecoderGpioOut::DecoderGpioOut() { | ||||||
|     hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull); |     furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DecoderGpioOut::~DecoderGpioOut() { | DecoderGpioOut::~DecoderGpioOut() { | ||||||
|     hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog); |     furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog); | ||||||
| } | } | ||||||
|  | |||||||
| @ -48,15 +48,15 @@ void RfidWriter::stop() { | |||||||
| 
 | 
 | ||||||
| void RfidWriter::write_gap(uint32_t gap_time) { | void RfidWriter::write_gap(uint32_t gap_time) { | ||||||
|     furi_hal_rfid_tim_read_stop(); |     furi_hal_rfid_tim_read_stop(); | ||||||
|     delay_us(gap_time * 8); |     furi_hal_delay_us(gap_time * 8); | ||||||
|     furi_hal_rfid_tim_read_start(); |     furi_hal_rfid_tim_read_start(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RfidWriter::write_bit(bool value) { | void RfidWriter::write_bit(bool value) { | ||||||
|     if(value) { |     if(value) { | ||||||
|         delay_us(T55xxTiming::data_1 * 8); |         furi_hal_delay_us(T55xxTiming::data_1 * 8); | ||||||
|     } else { |     } else { | ||||||
|         delay_us(T55xxTiming::data_0 * 8); |         furi_hal_delay_us(T55xxTiming::data_0 * 8); | ||||||
|     } |     } | ||||||
|     write_gap(T55xxTiming::write_gap); |     write_gap(T55xxTiming::write_gap); | ||||||
| } | } | ||||||
| @ -68,7 +68,7 @@ void RfidWriter::write_byte(uint8_t value) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RfidWriter::write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_t data) { | void RfidWriter::write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_t data) { | ||||||
|     delay_us(T55xxTiming::wait_time * 8); |     furi_hal_delay_us(T55xxTiming::wait_time * 8); | ||||||
| 
 | 
 | ||||||
|     // start gap
 |     // start gap
 | ||||||
|     write_gap(T55xxTiming::start_gap); |     write_gap(T55xxTiming::start_gap); | ||||||
| @ -101,9 +101,9 @@ void RfidWriter::write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_ | |||||||
|     write_bit((block >> 1) & 1); |     write_bit((block >> 1) & 1); | ||||||
|     write_bit((block >> 0) & 1); |     write_bit((block >> 0) & 1); | ||||||
| 
 | 
 | ||||||
|     delay_us(T55xxTiming::program * 8); |     furi_hal_delay_us(T55xxTiming::program * 8); | ||||||
| 
 | 
 | ||||||
|     delay_us(T55xxTiming::wait_time * 8); |     furi_hal_delay_us(T55xxTiming::wait_time * 8); | ||||||
|     write_reset(); |     write_reset(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -88,7 +88,7 @@ void lfrfid_cli_read(Cli* cli, string_t args) { | |||||||
|             printf("\r\n"); |             printf("\r\n"); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         delay(100); |         furi_hal_delay_ms(100); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     printf("Reading stopped\r\n"); |     printf("Reading stopped\r\n"); | ||||||
| @ -136,7 +136,7 @@ void lfrfid_cli_emulate(Cli* cli, string_t args) { | |||||||
| 
 | 
 | ||||||
|     printf("Emulating RFID...\r\nPress Ctrl+C to abort\r\n"); |     printf("Emulating RFID...\r\nPress Ctrl+C to abort\r\n"); | ||||||
|     while(!cli_cmd_interrupt_received(cli)) { |     while(!cli_cmd_interrupt_received(cli)) { | ||||||
|         delay(100); |         furi_hal_delay_ms(100); | ||||||
|     } |     } | ||||||
|     printf("Emulation stopped\r\n"); |     printf("Emulation stopped\r\n"); | ||||||
|     emulator.stop(); |     emulator.stop(); | ||||||
|  | |||||||
| @ -2,12 +2,12 @@ | |||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| 
 | 
 | ||||||
| static void comparator_trigger_callback(bool level, void* comp_ctx) { | static void comparator_trigger_callback(bool level, void* comp_ctx) { | ||||||
|     hal_gpio_write(&gpio_ext_pa7, !level); |     furi_hal_gpio_write(&gpio_ext_pa7, !level); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void LfRfidDebugAppSceneTune::on_enter(LfRfidDebugApp* app, bool need_restore) { | void LfRfidDebugAppSceneTune::on_enter(LfRfidDebugApp* app, bool need_restore) { | ||||||
|     app->view_controller.switch_to<LfRfidViewTuneVM>(); |     app->view_controller.switch_to<LfRfidViewTuneVM>(); | ||||||
|     hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull); |     furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull); | ||||||
| 
 | 
 | ||||||
|     furi_hal_rfid_comp_set_callback(comparator_trigger_callback, this); |     furi_hal_rfid_comp_set_callback(comparator_trigger_callback, this); | ||||||
|     furi_hal_rfid_comp_start(); |     furi_hal_rfid_comp_start(); | ||||||
| @ -34,7 +34,7 @@ void LfRfidDebugAppSceneTune::on_exit(LfRfidDebugApp* app) { | |||||||
|     furi_hal_rfid_comp_stop(); |     furi_hal_rfid_comp_stop(); | ||||||
|     furi_hal_rfid_comp_set_callback(NULL, NULL); |     furi_hal_rfid_comp_set_callback(NULL, NULL); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog); |     furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog); | ||||||
|     furi_hal_rfid_tim_read_stop(); |     furi_hal_rfid_tim_read_stop(); | ||||||
|     furi_hal_rfid_tim_reset(); |     furi_hal_rfid_tim_reset(); | ||||||
|     furi_hal_rfid_pins_reset(); |     furi_hal_rfid_pins_reset(); | ||||||
|  | |||||||
| @ -245,7 +245,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con | |||||||
|          * started and after task completed. In process of leakage monitoring |          * started and after task completed. In process of leakage monitoring | ||||||
|          * both values should be taken into account. |          * both values should be taken into account. | ||||||
|          */ |          */ | ||||||
|         delay(20); |         furi_hal_delay_ms(20); | ||||||
|         int heap_diff = instance->free_heap_size - memmgr_get_free_heap(); |         int heap_diff = instance->free_heap_size - memmgr_get_free_heap(); | ||||||
|         FURI_LOG_I( |         FURI_LOG_I( | ||||||
|             TAG, |             TAG, | ||||||
|  | |||||||
| @ -334,7 +334,7 @@ void process_note( | |||||||
|     if(note_record->note != N) { |     if(note_record->note != N) { | ||||||
|         furi_hal_speaker_start(note_record->note, volume); |         furi_hal_speaker_start(note_record->note, volume); | ||||||
|     } |     } | ||||||
|     delay(note_delay); |     furi_hal_delay_ms(note_delay); | ||||||
|     furi_hal_speaker_stop(); |     furi_hal_speaker_stop(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -780,6 +780,7 @@ void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break; |                 if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break; | ||||||
|  |                 osDelay(1); | ||||||
|             } |             } | ||||||
|             if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break; |             if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break; | ||||||
|             if(sector_key_found) { |             if(sector_key_found) { | ||||||
|  | |||||||
| @ -248,7 +248,7 @@ void notification_process_notification_message( | |||||||
|             if(led_active) { |             if(led_active) { | ||||||
|                 if(notification_is_any_led_layer_internal_and_not_empty(app)) { |                 if(notification_is_any_led_layer_internal_and_not_empty(app)) { | ||||||
|                     notification_apply_notification_leds(app, led_off_values); |                     notification_apply_notification_leds(app, led_off_values); | ||||||
|                     delay(minimal_delay); |                     furi_hal_delay_ms(minimal_delay); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 led_active = false; |                 led_active = false; | ||||||
| @ -259,7 +259,7 @@ void notification_process_notification_message( | |||||||
|                 reset_mask |= reset_blue_mask; |                 reset_mask |= reset_blue_mask; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             delay(notification_message->data.delay.length); |             furi_hal_delay_ms(notification_message->data.delay.length); | ||||||
|             break; |             break; | ||||||
|         case NotificationMessageTypeDoNotReset: |         case NotificationMessageTypeDoNotReset: | ||||||
|             reset_notifications = false; |             reset_notifications = false; | ||||||
| @ -293,7 +293,7 @@ void notification_process_notification_message( | |||||||
| 
 | 
 | ||||||
|         if(need_minimal_delay) { |         if(need_minimal_delay) { | ||||||
|             notification_apply_notification_leds(app, led_off_values); |             notification_apply_notification_leds(app, led_off_values); | ||||||
|             delay(minimal_delay); |             furi_hal_delay_ms(minimal_delay); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -334,7 +334,7 @@ int32_t storage_test_app(void* p) { | |||||||
|     do_test_end(api, "/ext"); |     do_test_end(api, "/ext"); | ||||||
| 
 | 
 | ||||||
|     while(true) { |     while(true) { | ||||||
|         delay(1000); |         furi_hal_delay_ms(1000); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return 0; |     return 0; | ||||||
|  | |||||||
| @ -82,7 +82,7 @@ static bool sd_mount_card(StorageData* storage, bool notify) { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(!result) { |         if(!result) { | ||||||
|             delay(1000); |             furi_hal_delay_ms(1000); | ||||||
|             FURI_LOG_E( |             FURI_LOG_E( | ||||||
|                 TAG, "init cycle %d, error: %s", counter, storage_data_status_text(storage)); |                 TAG, "init cycle %d, error: %s", counter, storage_data_status_text(storage)); | ||||||
|             counter--; |             counter--; | ||||||
|  | |||||||
| @ -42,11 +42,12 @@ static void subghz_chat_worker_update_rx_event_chat(void* context) { | |||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhzChatWorker* instance = context; |     SubGhzChatWorker* instance = context; | ||||||
|     SubGhzChatEvent event; |     SubGhzChatEvent event; | ||||||
|     if((millis() - instance->last_time_rx_data) > SUBGHZ_CHAT_WORKER_TIMEOUT_BETWEEN_MESSAGES) { |     if((furi_hal_get_tick() - instance->last_time_rx_data) > | ||||||
|  |        SUBGHZ_CHAT_WORKER_TIMEOUT_BETWEEN_MESSAGES) { | ||||||
|         event.event = SubGhzChatEventNewMessage; |         event.event = SubGhzChatEventNewMessage; | ||||||
|         osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); |         osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); | ||||||
|     } |     } | ||||||
|     instance->last_time_rx_data = millis(); |     instance->last_time_rx_data = furi_hal_get_tick(); | ||||||
|     event.event = SubGhzChatEventRXData; |     event.event = SubGhzChatEventRXData; | ||||||
|     osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); |     osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); | ||||||
| } | } | ||||||
|  | |||||||
| @ -40,8 +40,8 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { | |||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); | ||||||
|     frequency = furi_hal_subghz_set_frequency_and_path(frequency); |     frequency = furi_hal_subghz_set_frequency_and_path(frequency); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|     hal_gpio_write(&gpio_cc1101_g0, true); |     furi_hal_gpio_write(&gpio_cc1101_g0, true); | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_suppress_charge_enter(); |     furi_hal_power_suppress_charge_enter(); | ||||||
| 
 | 
 | ||||||
| @ -254,7 +254,7 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { | |||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); | ||||||
|     frequency = furi_hal_subghz_set_frequency_and_path(frequency); |     frequency = furi_hal_subghz_set_frequency_and_path(frequency); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_suppress_charge_enter(); |     furi_hal_power_suppress_charge_enter(); | ||||||
| 
 | 
 | ||||||
| @ -495,7 +495,7 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { | |||||||
|                     subghz_chat, |                     subghz_chat, | ||||||
|                     (uint8_t*)string_get_cstr(input), |                     (uint8_t*)string_get_cstr(input), | ||||||
|                     strlen(string_get_cstr(input)))) { |                     strlen(string_get_cstr(input)))) { | ||||||
|                     delay(10); |                     furi_hal_delay_ms(10); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 string_printf(input, "%s", string_get_cstr(name)); |                 string_printf(input, "%s", string_get_cstr(name)); | ||||||
| @ -547,7 +547,7 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { | |||||||
|                     subghz_chat, |                     subghz_chat, | ||||||
|                     (uint8_t*)string_get_cstr(sysmsg), |                     (uint8_t*)string_get_cstr(sysmsg), | ||||||
|                     strlen(string_get_cstr(sysmsg))); |                     strlen(string_get_cstr(sysmsg))); | ||||||
|                 delay(10); |                 furi_hal_delay_ms(10); | ||||||
|                 exit = true; |                 exit = true; | ||||||
|                 break; |                 break; | ||||||
|             default: |             default: | ||||||
|  | |||||||
| @ -140,13 +140,13 @@ bool subghz_history_add_to_history( | |||||||
|     SubGhzProtocolDecoderBase* decoder_base = context; |     SubGhzProtocolDecoderBase* decoder_base = context; | ||||||
|     if((instance->code_last_hash_data == |     if((instance->code_last_hash_data == | ||||||
|         subghz_protocol_decoder_base_get_hash_data(decoder_base)) && |         subghz_protocol_decoder_base_get_hash_data(decoder_base)) && | ||||||
|        ((millis() - instance->last_update_timestamp) < 500)) { |        ((furi_hal_get_tick() - instance->last_update_timestamp) < 500)) { | ||||||
|         instance->last_update_timestamp = millis(); |         instance->last_update_timestamp = furi_hal_get_tick(); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); |     instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); | ||||||
|     instance->last_update_timestamp = millis(); |     instance->last_update_timestamp = furi_hal_get_tick(); | ||||||
| 
 | 
 | ||||||
|     string_t text; |     string_t text; | ||||||
|     string_init(text); |     string_init(text); | ||||||
|  | |||||||
| @ -62,7 +62,7 @@ void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset) { | |||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_idle(); |     furi_hal_subghz_idle(); | ||||||
|     furi_hal_subghz_load_preset(preset); |     furi_hal_subghz_load_preset(preset); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
|     subghz->txrx->txrx_state = SubGhzTxRxStateIDLE; |     subghz->txrx->txrx_state = SubGhzTxRxStateIDLE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -77,7 +77,7 @@ uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency) { | |||||||
| 
 | 
 | ||||||
|     furi_hal_subghz_idle(); |     furi_hal_subghz_idle(); | ||||||
|     uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); |     uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
|     furi_hal_subghz_flush_rx(); |     furi_hal_subghz_flush_rx(); | ||||||
|     furi_hal_subghz_rx(); |     furi_hal_subghz_rx(); | ||||||
| 
 | 
 | ||||||
| @ -95,8 +95,8 @@ static bool subghz_tx(SubGhz* subghz, uint32_t frequency) { | |||||||
|     furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep); |     furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep); | ||||||
|     furi_hal_subghz_idle(); |     furi_hal_subghz_idle(); | ||||||
|     furi_hal_subghz_set_frequency_and_path(frequency); |     furi_hal_subghz_set_frequency_and_path(frequency); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|     hal_gpio_write(&gpio_cc1101_g0, true); |     furi_hal_gpio_write(&gpio_cc1101_g0, true); | ||||||
|     bool ret = furi_hal_subghz_tx(); |     bool ret = furi_hal_subghz_tx(); | ||||||
|     subghz->txrx->txrx_state = SubGhzTxRxStateTx; |     subghz->txrx->txrx_state = SubGhzTxRxStateTx; | ||||||
|     return ret; |     return ret; | ||||||
|  | |||||||
| @ -113,13 +113,14 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) { | |||||||
|             furi_hal_subghz_set_path(model->path); |             furi_hal_subghz_set_path(model->path); | ||||||
| 
 | 
 | ||||||
|             if(model->status == SubGhzTestCarrierModelStatusRx) { |             if(model->status == SubGhzTestCarrierModelStatusRx) { | ||||||
|                 hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |                 furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
|                 furi_hal_subghz_rx(); |                 furi_hal_subghz_rx(); | ||||||
|             } else { |             } else { | ||||||
|                 hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |                 furi_hal_gpio_init( | ||||||
|                 hal_gpio_write(&gpio_cc1101_g0, true); |                     &gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|  |                 furi_hal_gpio_write(&gpio_cc1101_g0, true); | ||||||
|                 if(!furi_hal_subghz_tx()) { |                 if(!furi_hal_subghz_tx()) { | ||||||
|                     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |                     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
|                     subghz_test_carrier->callback( |                     subghz_test_carrier->callback( | ||||||
|                         SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context); |                         SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context); | ||||||
|                 } |                 } | ||||||
| @ -138,7 +139,7 @@ void subghz_test_carrier_enter(void* context) { | |||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         subghz_test_carrier->view, (SubGhzTestCarrierModel * model) { |         subghz_test_carrier->view, (SubGhzTestCarrierModel * model) { | ||||||
|  | |||||||
| @ -140,7 +140,7 @@ static bool subghz_test_packet_input(InputEvent* event, void* context) { | |||||||
|             if(model->status == SubGhzTestPacketModelStatusRx) { |             if(model->status == SubGhzTestPacketModelStatusRx) { | ||||||
|                 furi_hal_subghz_stop_async_rx(); |                 furi_hal_subghz_stop_async_rx(); | ||||||
|             } else if(model->status == SubGhzTestPacketModelStatusTx) { |             } else if(model->status == SubGhzTestPacketModelStatusTx) { | ||||||
|                 subghz_encoder_princeton_for_testing_stop(instance->encoder, millis()); |                 subghz_encoder_princeton_for_testing_stop(instance->encoder, furi_hal_get_tick()); | ||||||
|                 furi_hal_subghz_stop_async_tx(); |                 furi_hal_subghz_stop_async_tx(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @ -220,7 +220,7 @@ void subghz_test_packet_exit(void* context) { | |||||||
|             if(model->status == SubGhzTestPacketModelStatusRx) { |             if(model->status == SubGhzTestPacketModelStatusRx) { | ||||||
|                 furi_hal_subghz_stop_async_rx(); |                 furi_hal_subghz_stop_async_rx(); | ||||||
|             } else if(model->status == SubGhzTestPacketModelStatusTx) { |             } else if(model->status == SubGhzTestPacketModelStatusTx) { | ||||||
|                 subghz_encoder_princeton_for_testing_stop(instance->encoder, millis()); |                 subghz_encoder_princeton_for_testing_stop(instance->encoder, furi_hal_get_tick()); | ||||||
|                 furi_hal_subghz_stop_async_tx(); |                 furi_hal_subghz_stop_async_tx(); | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|  | |||||||
| @ -118,7 +118,8 @@ bool subghz_test_static_input(InputEvent* event, void* context) { | |||||||
|                 } else if(event->type == InputTypeRelease) { |                 } else if(event->type == InputTypeRelease) { | ||||||
|                     if(instance->satus_tx == SubGhzTestStaticStatusTX) { |                     if(instance->satus_tx == SubGhzTestStaticStatusTX) { | ||||||
|                         FURI_LOG_I(TAG, "TX Stop"); |                         FURI_LOG_I(TAG, "TX Stop"); | ||||||
|                         subghz_encoder_princeton_for_testing_stop(instance->encoder, millis()); |                         subghz_encoder_princeton_for_testing_stop( | ||||||
|  |                             instance->encoder, furi_hal_get_tick()); | ||||||
|                         subghz_encoder_princeton_for_testing_print_log(instance->encoder); |                         subghz_encoder_princeton_for_testing_print_log(instance->encoder); | ||||||
|                         furi_hal_subghz_stop_async_tx(); |                         furi_hal_subghz_stop_async_tx(); | ||||||
|                         notification_message(notification, &sequence_reset_red); |                         notification_message(notification, &sequence_reset_red); | ||||||
| @ -141,8 +142,8 @@ void subghz_test_static_enter(void* context) { | |||||||
|     furi_hal_subghz_reset(); |     furi_hal_subghz_reset(); | ||||||
|     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); |     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|     hal_gpio_write(&gpio_cc1101_g0, false); |     furi_hal_gpio_write(&gpio_cc1101_g0, false); | ||||||
|     instance->satus_tx = SubGhzTestStaticStatusIDLE; |     instance->satus_tx = SubGhzTestStaticStatusIDLE; | ||||||
| 
 | 
 | ||||||
|     with_view_model( |     with_view_model( | ||||||
|  | |||||||
| @ -78,7 +78,7 @@ void furi_concurent_app(void* p) { | |||||||
|         uint8_t b = value->b; |         uint8_t b = value->b; | ||||||
|         a++; |         a++; | ||||||
|         b++; |         b++; | ||||||
|         delay(2); |         furi_hal_delay_ms(2); | ||||||
|         value->a = a; |         value->a = a; | ||||||
|         value->b = b; |         value->b = b; | ||||||
|         release_mutex(mutex, value); |         release_mutex(mutex, value); | ||||||
| @ -114,12 +114,12 @@ void test_furi_concurrent_access() { | |||||||
|         a++; |         a++; | ||||||
|         b++; |         b++; | ||||||
|         value->a = a; |         value->a = a; | ||||||
|         delay(10); // this is only for test, do not add delay between take/give in prod!
 |         furi_hal_delay_ms(10); // this is only for test, do not add delay between take/give in prod!
 | ||||||
|         value->b = b; |         value->b = b; | ||||||
|         release_mutex(&mutex, value); |         release_mutex(&mutex, value); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     delay(50); |     furi_hal_delay_ms(50); | ||||||
| 
 | 
 | ||||||
|     mu_assert_pointers_eq(second_app->handler, NULL); |     mu_assert_pointers_eq(second_app->handler, NULL); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -86,7 +86,7 @@ static void test_rpc_setup(void) { | |||||||
|     rpc = furi_record_open("rpc"); |     rpc = furi_record_open("rpc"); | ||||||
|     for(int i = 0; !(rpc_session[0].session) && (i < 10000); ++i) { |     for(int i = 0; !(rpc_session[0].session) && (i < 10000); ++i) { | ||||||
|         rpc_session[0].session = rpc_session_open(rpc); |         rpc_session[0].session = rpc_session_open(rpc); | ||||||
|         delay(1); |         furi_hal_delay_ms(1); | ||||||
|     } |     } | ||||||
|     furi_check(rpc_session[0].session); |     furi_check(rpc_session[0].session); | ||||||
| 
 | 
 | ||||||
| @ -106,7 +106,7 @@ static void test_rpc_setup_second_session(void) { | |||||||
| 
 | 
 | ||||||
|     for(int i = 0; !(rpc_session[1].session) && (i < 10000); ++i) { |     for(int i = 0; !(rpc_session[1].session) && (i < 10000); ++i) { | ||||||
|         rpc_session[1].session = rpc_session_open(rpc); |         rpc_session[1].session = rpc_session_open(rpc); | ||||||
|         delay(1); |         furi_hal_delay_ms(1); | ||||||
|     } |     } | ||||||
|     furi_check(rpc_session[1].session); |     furi_check(rpc_session[1].session); | ||||||
| 
 | 
 | ||||||
| @ -1518,28 +1518,28 @@ MU_TEST(test_app_start_and_lock_status) { | |||||||
|     test_app_get_status_lock_run(false, ++command_id); |     test_app_get_status_lock_run(false, ++command_id); | ||||||
| 
 | 
 | ||||||
|     test_app_start_run("Delay Test", "0", PB_CommandStatus_OK, ++command_id); |     test_app_start_run("Delay Test", "0", PB_CommandStatus_OK, ++command_id); | ||||||
|     delay(100); |     furi_hal_delay_ms(100); | ||||||
|     test_app_get_status_lock_run(false, ++command_id); |     test_app_get_status_lock_run(false, ++command_id); | ||||||
| 
 | 
 | ||||||
|     test_app_start_run("Delay Test", "200", PB_CommandStatus_OK, ++command_id); |     test_app_start_run("Delay Test", "200", PB_CommandStatus_OK, ++command_id); | ||||||
|     test_app_get_status_lock_run(true, ++command_id); |     test_app_get_status_lock_run(true, ++command_id); | ||||||
|     delay(100); |     furi_hal_delay_ms(100); | ||||||
|     test_app_get_status_lock_run(true, ++command_id); |     test_app_get_status_lock_run(true, ++command_id); | ||||||
|     test_app_start_run("Delay Test", "0", PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED, ++command_id); |     test_app_start_run("Delay Test", "0", PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED, ++command_id); | ||||||
|     delay(200); |     furi_hal_delay_ms(200); | ||||||
|     test_app_get_status_lock_run(false, ++command_id); |     test_app_get_status_lock_run(false, ++command_id); | ||||||
| 
 | 
 | ||||||
|     test_app_start_run("Delay Test", "500", PB_CommandStatus_OK, ++command_id); |     test_app_start_run("Delay Test", "500", PB_CommandStatus_OK, ++command_id); | ||||||
|     delay(100); |     furi_hal_delay_ms(100); | ||||||
|     test_app_get_status_lock_run(true, ++command_id); |     test_app_get_status_lock_run(true, ++command_id); | ||||||
|     test_app_start_run("Infrared", "0", PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED, ++command_id); |     test_app_start_run("Infrared", "0", PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED, ++command_id); | ||||||
|     delay(100); |     furi_hal_delay_ms(100); | ||||||
|     test_app_get_status_lock_run(true, ++command_id); |     test_app_get_status_lock_run(true, ++command_id); | ||||||
|     test_app_start_run( |     test_app_start_run( | ||||||
|         "2_girls_1_app", "0", PB_CommandStatus_ERROR_INVALID_PARAMETERS, ++command_id); |         "2_girls_1_app", "0", PB_CommandStatus_ERROR_INVALID_PARAMETERS, ++command_id); | ||||||
|     delay(100); |     furi_hal_delay_ms(100); | ||||||
|     test_app_get_status_lock_run(true, ++command_id); |     test_app_get_status_lock_run(true, ++command_id); | ||||||
|     delay(500); |     furi_hal_delay_ms(500); | ||||||
|     test_app_get_status_lock_run(false, ++command_id); |     test_app_get_status_lock_run(false, ++command_id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1786,7 +1786,7 @@ int32_t delay_test_app(void* p) { | |||||||
|     int timeout = atoi((const char*)p); |     int timeout = atoi((const char*)p); | ||||||
| 
 | 
 | ||||||
|     if(timeout > 0) { |     if(timeout > 0) { | ||||||
|         delay(timeout); |         furi_hal_delay_ms(timeout); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return 0; |     return 0; | ||||||
|  | |||||||
| @ -63,7 +63,7 @@ void unit_tests_cli(Cli* cli, string_t args, void* context) { | |||||||
|         FURI_LOG_I(TAG, "Consumed: %0.2fs", (float)cycle_counter / (SystemCoreClock)); |         FURI_LOG_I(TAG, "Consumed: %0.2fs", (float)cycle_counter / (SystemCoreClock)); | ||||||
| 
 | 
 | ||||||
|         if(test_result == 0) { |         if(test_result == 0) { | ||||||
|             delay(200); /* wait for tested services and apps to deallocate */ |             furi_hal_delay_ms(200); /* wait for tested services and apps to deallocate */ | ||||||
|             uint32_t heap_after = memmgr_get_free_heap(); |             uint32_t heap_after = memmgr_get_free_heap(); | ||||||
|             notification_message(notification, &sequence_success); |             notification_message(notification, &sequence_success); | ||||||
|             if(heap_after != heap_before) { |             if(heap_after != heap_before) { | ||||||
|  | |||||||
| @ -1,3 +1,3 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #define PROTOBUF_MAJOR_VERSION 0 | #define PROTOBUF_MAJOR_VERSION 0 | ||||||
| #define PROTOBUF_MINOR_VERSION 2 | #define PROTOBUF_MINOR_VERSION 3 | ||||||
|  | |||||||
| @ -1 +1 @@ | |||||||
| Subproject commit 232e7e9a50b12a95f950fabb515204775e51b04a | Subproject commit cd11b029ac21462ea8a7615126d0a29e087c2908 | ||||||
| @ -8,11 +8,11 @@ void furi_hal_init() { | |||||||
|     furi_hal_version_init(); |     furi_hal_version_init(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void delay(float milliseconds) { | void furi_hal_delay_ms(float milliseconds) { | ||||||
|     LL_mDelay((uint32_t)milliseconds); |     LL_mDelay((uint32_t)milliseconds); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void delay_us(float microseconds) { | void furi_hal_delay_us(float microseconds) { | ||||||
|     microseconds = microseconds / 1000; |     microseconds = microseconds / 1000; | ||||||
|     if(microseconds < 1) { |     if(microseconds < 1) { | ||||||
|         microseconds = 1; |         microseconds = 1; | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ | |||||||
| 
 | 
 | ||||||
| static volatile GpioInterrupt gpio_interrupt[GPIO_NUMBER]; | static volatile GpioInterrupt gpio_interrupt[GPIO_NUMBER]; | ||||||
| 
 | 
 | ||||||
| static uint8_t hal_gpio_get_pin_num(const GpioPin* gpio) { | static uint8_t furi_hal_gpio_get_pin_num(const GpioPin* gpio) { | ||||||
|     uint8_t pin_num = 0; |     uint8_t pin_num = 0; | ||||||
|     for(pin_num = 0; pin_num < GPIO_NUMBER; pin_num++) { |     for(pin_num = 0; pin_num < GPIO_NUMBER; pin_num++) { | ||||||
|         if(gpio->pin & (1 << pin_num)) break; |         if(gpio->pin & (1 << pin_num)) break; | ||||||
| @ -41,11 +41,11 @@ static uint8_t hal_gpio_get_pin_num(const GpioPin* gpio) { | |||||||
|     return pin_num; |     return pin_num; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode) { | void furi_hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode) { | ||||||
|     hal_gpio_init(gpio, mode, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(gpio, mode, GpioPullNo, GpioSpeedLow); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void hal_gpio_init( | void furi_hal_gpio_init( | ||||||
|     const GpioPin* gpio, |     const GpioPin* gpio, | ||||||
|     const GpioMode mode, |     const GpioMode mode, | ||||||
|     const GpioPull pull, |     const GpioPull pull, | ||||||
| @ -54,10 +54,10 @@ void hal_gpio_init( | |||||||
|     assert(mode != GpioModeAltFunctionPushPull); |     assert(mode != GpioModeAltFunctionPushPull); | ||||||
|     assert(mode != GpioModeAltFunctionOpenDrain); |     assert(mode != GpioModeAltFunctionOpenDrain); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init_ex(gpio, mode, pull, speed, GpioAltFnUnused); |     furi_hal_gpio_init_ex(gpio, mode, pull, speed, GpioAltFnUnused); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void hal_gpio_init_ex( | void furi_hal_gpio_init_ex( | ||||||
|     const GpioPin* gpio, |     const GpioPin* gpio, | ||||||
|     const GpioMode mode, |     const GpioMode mode, | ||||||
|     const GpioPull pull, |     const GpioPull pull, | ||||||
| @ -132,7 +132,7 @@ void hal_gpio_init_ex( | |||||||
|         // Prepare alternative part if any
 |         // Prepare alternative part if any
 | ||||||
|         if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { |         if(mode == GpioModeAltFunctionPushPull || mode == GpioModeAltFunctionOpenDrain) { | ||||||
|             // set alternate function
 |             // set alternate function
 | ||||||
|             if(hal_gpio_get_pin_num(gpio) < 8) { |             if(furi_hal_gpio_get_pin_num(gpio) < 8) { | ||||||
|                 LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn); |                 LL_GPIO_SetAFPin_0_7(gpio->port, gpio->pin, alt_fn); | ||||||
|             } else { |             } else { | ||||||
|                 LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); |                 LL_GPIO_SetAFPin_8_15(gpio->port, gpio->pin, alt_fn); | ||||||
| @ -170,43 +170,43 @@ void hal_gpio_init_ex( | |||||||
|     __enable_irq(); |     __enable_irq(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx) { | void furi_hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx) { | ||||||
|     assert(gpio); |     assert(gpio); | ||||||
|     assert(cb); |     assert(cb); | ||||||
| 
 | 
 | ||||||
|     __disable_irq(); |     __disable_irq(); | ||||||
|     uint8_t pin_num = hal_gpio_get_pin_num(gpio); |     uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio); | ||||||
|     gpio_interrupt[pin_num].callback = cb; |     gpio_interrupt[pin_num].callback = cb; | ||||||
|     gpio_interrupt[pin_num].context = ctx; |     gpio_interrupt[pin_num].context = ctx; | ||||||
|     gpio_interrupt[pin_num].ready = true; |     gpio_interrupt[pin_num].ready = true; | ||||||
|     __enable_irq(); |     __enable_irq(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void hal_gpio_enable_int_callback(const GpioPin* gpio) { | void furi_hal_gpio_enable_int_callback(const GpioPin* gpio) { | ||||||
|     assert(gpio); |     assert(gpio); | ||||||
| 
 | 
 | ||||||
|     __disable_irq(); |     __disable_irq(); | ||||||
|     uint8_t pin_num = hal_gpio_get_pin_num(gpio); |     uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio); | ||||||
|     if(gpio_interrupt[pin_num].callback) { |     if(gpio_interrupt[pin_num].callback) { | ||||||
|         gpio_interrupt[pin_num].ready = true; |         gpio_interrupt[pin_num].ready = true; | ||||||
|     } |     } | ||||||
|     __enable_irq(); |     __enable_irq(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void hal_gpio_disable_int_callback(const GpioPin* gpio) { | void furi_hal_gpio_disable_int_callback(const GpioPin* gpio) { | ||||||
|     assert(gpio); |     assert(gpio); | ||||||
| 
 | 
 | ||||||
|     __disable_irq(); |     __disable_irq(); | ||||||
|     uint8_t pin_num = hal_gpio_get_pin_num(gpio); |     uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio); | ||||||
|     gpio_interrupt[pin_num].ready = false; |     gpio_interrupt[pin_num].ready = false; | ||||||
|     __enable_irq(); |     __enable_irq(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void hal_gpio_remove_int_callback(const GpioPin* gpio) { | void furi_hal_gpio_remove_int_callback(const GpioPin* gpio) { | ||||||
|     assert(gpio); |     assert(gpio); | ||||||
| 
 | 
 | ||||||
|     __disable_irq(); |     __disable_irq(); | ||||||
|     uint8_t pin_num = hal_gpio_get_pin_num(gpio); |     uint8_t pin_num = furi_hal_gpio_get_pin_num(gpio); | ||||||
|     gpio_interrupt[pin_num].callback = NULL; |     gpio_interrupt[pin_num].callback = NULL; | ||||||
|     gpio_interrupt[pin_num].context = NULL; |     gpio_interrupt[pin_num].context = NULL; | ||||||
|     gpio_interrupt[pin_num].ready = false; |     gpio_interrupt[pin_num].ready = false; | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "main.h" |  | ||||||
| #include "stdbool.h" | #include "stdbool.h" | ||||||
|  | #include "main.h" | ||||||
| #include <stm32wbxx_ll_gpio.h> | #include <stm32wbxx_ll_gpio.h> | ||||||
| #include <stm32wbxx_ll_system.h> | #include <stm32wbxx_ll_system.h> | ||||||
| #include <stm32wbxx_ll_exti.h> | #include <stm32wbxx_ll_exti.h> | ||||||
| @ -170,7 +170,7 @@ typedef struct { | |||||||
|  * @param gpio  GpioPin |  * @param gpio  GpioPin | ||||||
|  * @param mode  GpioMode |  * @param mode  GpioMode | ||||||
|  */ |  */ | ||||||
| void hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode); | void furi_hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * GPIO initialization function, normal version |  * GPIO initialization function, normal version | ||||||
| @ -179,7 +179,7 @@ void hal_gpio_init_simple(const GpioPin* gpio, const GpioMode mode); | |||||||
|  * @param pull  GpioPull |  * @param pull  GpioPull | ||||||
|  * @param speed GpioSpeed |  * @param speed GpioSpeed | ||||||
|  */ |  */ | ||||||
| void hal_gpio_init( | void furi_hal_gpio_init( | ||||||
|     const GpioPin* gpio, |     const GpioPin* gpio, | ||||||
|     const GpioMode mode, |     const GpioMode mode, | ||||||
|     const GpioPull pull, |     const GpioPull pull, | ||||||
| @ -193,7 +193,7 @@ void hal_gpio_init( | |||||||
|  * @param speed GpioSpeed |  * @param speed GpioSpeed | ||||||
|  * @param alt_fn GpioAltFn |  * @param alt_fn GpioAltFn | ||||||
|  */ |  */ | ||||||
| void hal_gpio_init_ex( | void furi_hal_gpio_init_ex( | ||||||
|     const GpioPin* gpio, |     const GpioPin* gpio, | ||||||
|     const GpioMode mode, |     const GpioMode mode, | ||||||
|     const GpioPull pull, |     const GpioPull pull, | ||||||
| @ -206,32 +206,32 @@ void hal_gpio_init_ex( | |||||||
|  * @param cb   GpioExtiCallback |  * @param cb   GpioExtiCallback | ||||||
|  * @param ctx  context for callback |  * @param ctx  context for callback | ||||||
|  */ |  */ | ||||||
| void hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx); | void furi_hal_gpio_add_int_callback(const GpioPin* gpio, GpioExtiCallback cb, void* ctx); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Enable interrupt |  * Enable interrupt | ||||||
|  * @param gpio GpioPin |  * @param gpio GpioPin | ||||||
|  */ |  */ | ||||||
| void hal_gpio_enable_int_callback(const GpioPin* gpio); | void furi_hal_gpio_enable_int_callback(const GpioPin* gpio); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Disable interrupt |  * Disable interrupt | ||||||
|  * @param gpio GpioPin |  * @param gpio GpioPin | ||||||
|  */ |  */ | ||||||
| void hal_gpio_disable_int_callback(const GpioPin* gpio); | void furi_hal_gpio_disable_int_callback(const GpioPin* gpio); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Remove interrupt |  * Remove interrupt | ||||||
|  * @param gpio GpioPin |  * @param gpio GpioPin | ||||||
|  */ |  */ | ||||||
| void hal_gpio_remove_int_callback(const GpioPin* gpio); | void furi_hal_gpio_remove_int_callback(const GpioPin* gpio); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * GPIO write pin |  * GPIO write pin | ||||||
|  * @param gpio  GpioPin |  * @param gpio  GpioPin | ||||||
|  * @param state true / false |  * @param state true / false | ||||||
|  */ |  */ | ||||||
| static inline void hal_gpio_write(const GpioPin* gpio, const bool state) { | static inline void furi_hal_gpio_write(const GpioPin* gpio, const bool state) { | ||||||
|     // writing to BSSR is an atomic operation
 |     // writing to BSSR is an atomic operation
 | ||||||
|     if(state == true) { |     if(state == true) { | ||||||
|         gpio->port->BSRR = gpio->pin; |         gpio->port->BSRR = gpio->pin; | ||||||
| @ -245,7 +245,7 @@ static inline void hal_gpio_write(const GpioPin* gpio, const bool state) { | |||||||
|  * @param gpio GpioPin |  * @param gpio GpioPin | ||||||
|  * @return true / false |  * @return true / false | ||||||
|  */ |  */ | ||||||
| static inline bool hal_gpio_read(const GpioPin* gpio) { | static inline bool furi_hal_gpio_read(const GpioPin* gpio) { | ||||||
|     if((gpio->port->IDR & gpio->pin) != 0x00U) { |     if((gpio->port->IDR & gpio->pin) != 0x00U) { | ||||||
|         return true; |         return true; | ||||||
|     } else { |     } else { | ||||||
| @ -257,7 +257,7 @@ static inline bool hal_gpio_read(const GpioPin* gpio) { | |||||||
|  * Get RFID IN level |  * Get RFID IN level | ||||||
|  * @return false = LOW, true = HIGH |  * @return false = LOW, true = HIGH | ||||||
|  */ |  */ | ||||||
| bool hal_gpio_get_rfid_in_level(); | bool furi_hal_gpio_get_rfid_in_level(); | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  | |||||||
| @ -60,13 +60,13 @@ void furi_hal_i2c_bus_handle_power_event( | |||||||
|     FuriHalI2cBusHandleEvent event) { |     FuriHalI2cBusHandleEvent event) { | ||||||
|     if(event == FuriHalI2cBusHandleEventActivate) { |     if(event == FuriHalI2cBusHandleEventActivate) { | ||||||
|         LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); |         LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             &gpio_i2c_power_sda, |             &gpio_i2c_power_sda, | ||||||
|             GpioModeAltFunctionOpenDrain, |             GpioModeAltFunctionOpenDrain, | ||||||
|             GpioPullNo, |             GpioPullNo, | ||||||
|             GpioSpeedLow, |             GpioSpeedLow, | ||||||
|             GpioAltFn4I2C1); |             GpioAltFn4I2C1); | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             &gpio_i2c_power_scl, |             &gpio_i2c_power_scl, | ||||||
|             GpioModeAltFunctionOpenDrain, |             GpioModeAltFunctionOpenDrain, | ||||||
|             GpioPullNo, |             GpioPullNo, | ||||||
| @ -95,11 +95,11 @@ void furi_hal_i2c_bus_handle_power_event( | |||||||
|         LL_I2C_Enable(handle->bus->i2c); |         LL_I2C_Enable(handle->bus->i2c); | ||||||
|     } else if(event == FuriHalI2cBusHandleEventDeactivate) { |     } else if(event == FuriHalI2cBusHandleEventDeactivate) { | ||||||
|         LL_I2C_Disable(handle->bus->i2c); |         LL_I2C_Disable(handle->bus->i2c); | ||||||
|         hal_gpio_write(&gpio_i2c_power_sda, 1); |         furi_hal_gpio_write(&gpio_i2c_power_sda, 1); | ||||||
|         hal_gpio_write(&gpio_i2c_power_scl, 1); |         furi_hal_gpio_write(&gpio_i2c_power_scl, 1); | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             &gpio_i2c_power_sda, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused); |             &gpio_i2c_power_sda, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused); | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             &gpio_i2c_power_scl, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused); |             &gpio_i2c_power_scl, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -113,9 +113,9 @@ void furi_hal_i2c_bus_handle_external_event( | |||||||
|     FuriHalI2cBusHandle* handle, |     FuriHalI2cBusHandle* handle, | ||||||
|     FuriHalI2cBusHandleEvent event) { |     FuriHalI2cBusHandleEvent event) { | ||||||
|     if(event == FuriHalI2cBusHandleEventActivate) { |     if(event == FuriHalI2cBusHandleEventActivate) { | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             &gpio_ext_pc0, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3); |             &gpio_ext_pc0, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3); | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             &gpio_ext_pc1, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3); |             &gpio_ext_pc1, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3); | ||||||
| 
 | 
 | ||||||
|         LL_I2C_InitTypeDef I2C_InitStruct = {0}; |         LL_I2C_InitTypeDef I2C_InitStruct = {0}; | ||||||
| @ -136,10 +136,12 @@ void furi_hal_i2c_bus_handle_external_event( | |||||||
|         LL_I2C_Enable(handle->bus->i2c); |         LL_I2C_Enable(handle->bus->i2c); | ||||||
|     } else if(event == FuriHalI2cBusHandleEventDeactivate) { |     } else if(event == FuriHalI2cBusHandleEventDeactivate) { | ||||||
|         LL_I2C_Disable(handle->bus->i2c); |         LL_I2C_Disable(handle->bus->i2c); | ||||||
|         hal_gpio_write(&gpio_ext_pc0, 1); |         furi_hal_gpio_write(&gpio_ext_pc0, 1); | ||||||
|         hal_gpio_write(&gpio_ext_pc1, 1); |         furi_hal_gpio_write(&gpio_ext_pc1, 1); | ||||||
|         hal_gpio_init_ex(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused); |         furi_hal_gpio_init_ex( | ||||||
|         hal_gpio_init_ex(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused); |             &gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused); | ||||||
|  |         furi_hal_gpio_init_ex( | ||||||
|  |             &gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow, GpioAltFnUnused); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,5 +1,4 @@ | |||||||
| #include "furi_hal_resources.h" | #include "furi_hal_resources.h" | ||||||
| #include "main.h" |  | ||||||
| 
 | 
 | ||||||
| const GpioPin vibro_gpio = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin}; | const GpioPin vibro_gpio = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin}; | ||||||
| const GpioPin ibutton_gpio = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin}; | const GpioPin ibutton_gpio = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin}; | ||||||
|  | |||||||
| @ -117,42 +117,42 @@ inline static void furi_hal_spi_bus_r_handle_event_callback( | |||||||
|     FuriHalSpiBusHandleEvent event, |     FuriHalSpiBusHandleEvent event, | ||||||
|     const LL_SPI_InitTypeDef* preset) { |     const LL_SPI_InitTypeDef* preset) { | ||||||
|     if(event == FuriHalSpiBusHandleEventInit) { |     if(event == FuriHalSpiBusHandleEventInit) { | ||||||
|         hal_gpio_write(handle->cs, true); |         furi_hal_gpio_write(handle->cs, true); | ||||||
|         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); |         furi_hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); | ||||||
|     } else if(event == FuriHalSpiBusHandleEventDeinit) { |     } else if(event == FuriHalSpiBusHandleEventDeinit) { | ||||||
|         hal_gpio_write(handle->cs, true); |         furi_hal_gpio_write(handle->cs, true); | ||||||
|         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |         furi_hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|     } else if(event == FuriHalSpiBusHandleEventActivate) { |     } else if(event == FuriHalSpiBusHandleEventActivate) { | ||||||
|         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); |         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||||
|         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); |         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||||
|         LL_SPI_Enable(handle->bus->spi); |         LL_SPI_Enable(handle->bus->spi); | ||||||
| 
 | 
 | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             handle->miso, |             handle->miso, | ||||||
|             GpioModeAltFunctionPushPull, |             GpioModeAltFunctionPushPull, | ||||||
|             GpioPullNo, |             GpioPullNo, | ||||||
|             GpioSpeedVeryHigh, |             GpioSpeedVeryHigh, | ||||||
|             GpioAltFn5SPI1); |             GpioAltFn5SPI1); | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             handle->mosi, |             handle->mosi, | ||||||
|             GpioModeAltFunctionPushPull, |             GpioModeAltFunctionPushPull, | ||||||
|             GpioPullNo, |             GpioPullNo, | ||||||
|             GpioSpeedVeryHigh, |             GpioSpeedVeryHigh, | ||||||
|             GpioAltFn5SPI1); |             GpioAltFn5SPI1); | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             handle->sck, |             handle->sck, | ||||||
|             GpioModeAltFunctionPushPull, |             GpioModeAltFunctionPushPull, | ||||||
|             GpioPullNo, |             GpioPullNo, | ||||||
|             GpioSpeedVeryHigh, |             GpioSpeedVeryHigh, | ||||||
|             GpioAltFn5SPI1); |             GpioAltFn5SPI1); | ||||||
| 
 | 
 | ||||||
|         hal_gpio_write(handle->cs, false); |         furi_hal_gpio_write(handle->cs, false); | ||||||
|     } else if(event == FuriHalSpiBusHandleEventDeactivate) { |     } else if(event == FuriHalSpiBusHandleEventDeactivate) { | ||||||
|         hal_gpio_write(handle->cs, true); |         furi_hal_gpio_write(handle->cs, true); | ||||||
| 
 | 
 | ||||||
|         hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |         furi_hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|         hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |         furi_hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|         hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |         furi_hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|         LL_SPI_Disable(handle->bus->spi); |         LL_SPI_Disable(handle->bus->spi); | ||||||
|     } |     } | ||||||
| @ -208,22 +208,22 @@ inline static void furi_hal_spi_bus_d_handle_event_callback( | |||||||
|     FuriHalSpiBusHandleEvent event, |     FuriHalSpiBusHandleEvent event, | ||||||
|     const LL_SPI_InitTypeDef* preset) { |     const LL_SPI_InitTypeDef* preset) { | ||||||
|     if(event == FuriHalSpiBusHandleEventInit) { |     if(event == FuriHalSpiBusHandleEventInit) { | ||||||
|         hal_gpio_write(handle->cs, true); |         furi_hal_gpio_write(handle->cs, true); | ||||||
|         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); |         furi_hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); | ||||||
| 
 | 
 | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             handle->miso, |             handle->miso, | ||||||
|             GpioModeAltFunctionPushPull, |             GpioModeAltFunctionPushPull, | ||||||
|             GpioPullNo, |             GpioPullNo, | ||||||
|             GpioSpeedVeryHigh, |             GpioSpeedVeryHigh, | ||||||
|             GpioAltFn5SPI2); |             GpioAltFn5SPI2); | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             handle->mosi, |             handle->mosi, | ||||||
|             GpioModeAltFunctionPushPull, |             GpioModeAltFunctionPushPull, | ||||||
|             GpioPullNo, |             GpioPullNo, | ||||||
|             GpioSpeedVeryHigh, |             GpioSpeedVeryHigh, | ||||||
|             GpioAltFn5SPI2); |             GpioAltFn5SPI2); | ||||||
|         hal_gpio_init_ex( |         furi_hal_gpio_init_ex( | ||||||
|             handle->sck, |             handle->sck, | ||||||
|             GpioModeAltFunctionPushPull, |             GpioModeAltFunctionPushPull, | ||||||
|             GpioPullNo, |             GpioPullNo, | ||||||
| @ -231,15 +231,15 @@ inline static void furi_hal_spi_bus_d_handle_event_callback( | |||||||
|             GpioAltFn5SPI2); |             GpioAltFn5SPI2); | ||||||
| 
 | 
 | ||||||
|     } else if(event == FuriHalSpiBusHandleEventDeinit) { |     } else if(event == FuriHalSpiBusHandleEventDeinit) { | ||||||
|         hal_gpio_write(handle->cs, true); |         furi_hal_gpio_write(handle->cs, true); | ||||||
|         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow); |         furi_hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow); | ||||||
|     } else if(event == FuriHalSpiBusHandleEventActivate) { |     } else if(event == FuriHalSpiBusHandleEventActivate) { | ||||||
|         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); |         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||||
|         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); |         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||||
|         LL_SPI_Enable(handle->bus->spi); |         LL_SPI_Enable(handle->bus->spi); | ||||||
|         hal_gpio_write(handle->cs, false); |         furi_hal_gpio_write(handle->cs, false); | ||||||
|     } else if(event == FuriHalSpiBusHandleEventDeactivate) { |     } else if(event == FuriHalSpiBusHandleEventDeactivate) { | ||||||
|         hal_gpio_write(handle->cs, true); |         furi_hal_gpio_write(handle->cs, true); | ||||||
|         LL_SPI_Disable(handle->bus->spi); |         LL_SPI_Disable(handle->bus->spi); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -185,8 +185,8 @@ void target_usb_wire_reset() { | |||||||
| 
 | 
 | ||||||
| void target_display_init() { | void target_display_init() { | ||||||
|     // Prepare gpio
 |     // Prepare gpio
 | ||||||
|     hal_gpio_init_simple(&gpio_display_rst, GpioModeOutputPushPull); |     furi_hal_gpio_init_simple(&gpio_display_rst, GpioModeOutputPushPull); | ||||||
|     hal_gpio_init_simple(&gpio_display_di, GpioModeOutputPushPull); |     furi_hal_gpio_init_simple(&gpio_display_di, GpioModeOutputPushPull); | ||||||
|     // Initialize
 |     // Initialize
 | ||||||
|     u8g2_t fb; |     u8g2_t fb; | ||||||
|     u8g2_Setup_st756x_flipper(&fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); |     u8g2_Setup_st756x_flipper(&fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); | ||||||
|  | |||||||
| @ -10,6 +10,6 @@ | |||||||
| 
 | 
 | ||||||
| void furi_hal_init(); | void furi_hal_init(); | ||||||
| 
 | 
 | ||||||
| void delay(float milliseconds); | void furi_hal_delay_ms(float milliseconds); | ||||||
| 
 | 
 | ||||||
| void delay_us(float microseconds); | void furi_hal_delay_us(float microseconds); | ||||||
|  | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Aleksandr Kutuzov
						Aleksandr Kutuzov