App accessor: init (#433)
This commit is contained in:
		
							
								
								
									
										176
									
								
								applications/accessor/accessor-app.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								applications/accessor/accessor-app.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | ||||
| #include "accessor-app.h" | ||||
| #include <furi.h> | ||||
| #include <api-hal.h> | ||||
| #include <stdarg.h> | ||||
|  | ||||
| void AccessorApp::run(void) { | ||||
|     AccessorEvent event; | ||||
|     bool consumed; | ||||
|     bool exit = false; | ||||
|  | ||||
|     notify_init(); | ||||
|  | ||||
|     wiegand.begin(); | ||||
|     onewire_master.start(); | ||||
|  | ||||
|     scenes[current_scene]->on_enter(this); | ||||
|  | ||||
|     while(!exit) { | ||||
|         view.receive_event(&event); | ||||
|  | ||||
|         consumed = scenes[current_scene]->on_event(this, &event); | ||||
|  | ||||
|         if(!consumed) { | ||||
|             if(event.type == AccessorEvent::Type::Back) { | ||||
|                 exit = switch_to_previous_scene(); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     scenes[current_scene]->on_exit(this); | ||||
| } | ||||
|  | ||||
| AccessorApp::AccessorApp() | ||||
|     : onewire_master{&ibutton_gpio} { | ||||
|     api_hal_power_insomnia_enter(); | ||||
| } | ||||
|  | ||||
| AccessorApp::~AccessorApp() { | ||||
|     api_hal_power_insomnia_exit(); | ||||
| } | ||||
|  | ||||
| AccessorAppViewManager* AccessorApp::get_view_manager() { | ||||
|     return &view; | ||||
| } | ||||
|  | ||||
| void AccessorApp::switch_to_next_scene(Scene next_scene) { | ||||
|     previous_scenes_list.push_front(current_scene); | ||||
|  | ||||
|     if(next_scene != Scene::Exit) { | ||||
|         scenes[current_scene]->on_exit(this); | ||||
|         current_scene = next_scene; | ||||
|         scenes[current_scene]->on_enter(this); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void AccessorApp::search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list) { | ||||
|     Scene previous_scene = Scene::Start; | ||||
|     bool scene_found = false; | ||||
|  | ||||
|     while(!scene_found) { | ||||
|         previous_scene = get_previous_scene(); | ||||
|         for(Scene element : scenes_list) { | ||||
|             if(previous_scene == element || previous_scene == Scene::Start) { | ||||
|                 scene_found = true; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     scenes[current_scene]->on_exit(this); | ||||
|     current_scene = previous_scene; | ||||
|     scenes[current_scene]->on_enter(this); | ||||
| } | ||||
|  | ||||
| bool AccessorApp::switch_to_previous_scene(uint8_t count) { | ||||
|     Scene previous_scene = Scene::Start; | ||||
|  | ||||
|     for(uint8_t i = 0; i < count; i++) { | ||||
|         previous_scene = get_previous_scene(); | ||||
|         if(previous_scene == Scene::Exit) break; | ||||
|     } | ||||
|  | ||||
|     if(previous_scene == Scene::Exit) { | ||||
|         return true; | ||||
|     } else { | ||||
|         scenes[current_scene]->on_exit(this); | ||||
|         current_scene = previous_scene; | ||||
|         scenes[current_scene]->on_enter(this); | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| AccessorApp::Scene AccessorApp::get_previous_scene() { | ||||
|     Scene scene = previous_scenes_list.front(); | ||||
|     previous_scenes_list.pop_front(); | ||||
|     return scene; | ||||
| } | ||||
|  | ||||
| /***************************** NOTIFY *******************************/ | ||||
|  | ||||
| void AccessorApp::notify_init() { | ||||
|     // TODO open record | ||||
|     const GpioPin* vibro_record = &vibro_gpio; | ||||
|     gpio_init(vibro_record, GpioModeOutputPushPull); | ||||
|     gpio_write(vibro_record, false); | ||||
|  | ||||
|     GPIO_InitTypeDef GPIO_InitStruct = {0}; | ||||
|  | ||||
|     GPIO_InitStruct.Pin = PB3_Pin; | ||||
|     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; | ||||
|     GPIO_InitStruct.Pull = GPIO_NOPULL; | ||||
|     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; | ||||
|     GPIO_InitStruct.Alternate = GPIO_AF1_TIM2; | ||||
|     HAL_GPIO_Init(PB3_GPIO_Port, &GPIO_InitStruct); | ||||
| } | ||||
|  | ||||
| void AccessorApp::notify_green_blink() { | ||||
|     api_hal_light_set(LightGreen, 0xFF); | ||||
|     delay(10); | ||||
|     api_hal_light_set(LightGreen, 0x00); | ||||
| } | ||||
|  | ||||
| void AccessorApp::notify_green_on() { | ||||
|     api_hal_light_set(LightGreen, 0xFF); | ||||
| } | ||||
|  | ||||
| void AccessorApp::notify_green_off() { | ||||
|     api_hal_light_set(LightGreen, 0x00); | ||||
| } | ||||
|  | ||||
| void AccessorApp::notify_success() { | ||||
|     api_hal_light_set(LightBacklight, 0xFF); | ||||
|  | ||||
|     hal_pwm_set(0.5, 1760 / 2, &htim2, TIM_CHANNEL_2); | ||||
|     notify_green_on(); | ||||
|     delay(100); | ||||
|     hal_pwm_stop(&htim2, TIM_CHANNEL_2); | ||||
|     notify_green_off(); | ||||
|  | ||||
|     delay(100); | ||||
|  | ||||
|     hal_pwm_set(0.5, 1760, &htim2, TIM_CHANNEL_2); | ||||
|     notify_green_on(); | ||||
|     delay(100); | ||||
|     hal_pwm_stop(&htim2, TIM_CHANNEL_2); | ||||
|     notify_green_off(); | ||||
| } | ||||
|  | ||||
| /*************************** TEXT STORE *****************************/ | ||||
|  | ||||
| char* AccessorApp::get_text_store() { | ||||
|     return text_store; | ||||
| } | ||||
|  | ||||
| uint8_t AccessorApp::get_text_store_size() { | ||||
|     return text_store_size; | ||||
| } | ||||
|  | ||||
| void AccessorApp::set_text_store(const char* text...) { | ||||
|     va_list args; | ||||
|     va_start(args, text); | ||||
|  | ||||
|     vsnprintf(text_store, text_store_size, text, args); | ||||
|  | ||||
|     va_end(args); | ||||
| } | ||||
|  | ||||
| /*************************** APP RESOURCES *****************************/ | ||||
|  | ||||
| WIEGAND* AccessorApp::get_wiegand() { | ||||
|     return &wiegand; | ||||
| } | ||||
|  | ||||
| OneWireMaster* AccessorApp::get_one_wire() { | ||||
|     return &onewire_master; | ||||
| } | ||||
							
								
								
									
										58
									
								
								applications/accessor/accessor-app.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								applications/accessor/accessor-app.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| #pragma once | ||||
| #include <map> | ||||
| #include <list> | ||||
| #include "accessor-view-manager.h" | ||||
|  | ||||
| #include "scene/accessor-scene-start.h" | ||||
|  | ||||
| #include "helpers/wiegand.h" | ||||
|  | ||||
| #include <one_wire_master.h> | ||||
|  | ||||
| class AccessorApp { | ||||
| public: | ||||
|     void run(void); | ||||
|  | ||||
|     AccessorApp(); | ||||
|     ~AccessorApp(); | ||||
|  | ||||
|     enum class Scene : uint8_t { | ||||
|         Exit, | ||||
|         Start, | ||||
|     }; | ||||
|  | ||||
|     AccessorAppViewManager* get_view_manager(); | ||||
|     void switch_to_next_scene(Scene index); | ||||
|     void search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list); | ||||
|     bool switch_to_previous_scene(uint8_t count = 1); | ||||
|     Scene get_previous_scene(); | ||||
|  | ||||
|     void notify_init(); | ||||
|     void notify_green_blink(); | ||||
|     void notify_green_on(); | ||||
|     void notify_green_off(); | ||||
|  | ||||
|     void notify_success(); | ||||
|  | ||||
|     char* get_text_store(); | ||||
|     uint8_t get_text_store_size(); | ||||
|     void set_text_store(const char* text...); | ||||
|  | ||||
|     WIEGAND* get_wiegand(); | ||||
|     OneWireMaster* get_one_wire(); | ||||
|  | ||||
| private: | ||||
|     std::list<Scene> previous_scenes_list = {Scene::Exit}; | ||||
|     Scene current_scene = Scene::Start; | ||||
|     AccessorAppViewManager view; | ||||
|  | ||||
|     std::map<Scene, AccessorScene*> scenes = { | ||||
|         {Scene::Start, new AccessorSceneStart()}, | ||||
|     }; | ||||
|  | ||||
|     static const uint8_t text_store_size = 128; | ||||
|     char text_store[text_store_size + 1]; | ||||
|  | ||||
|     WIEGAND wiegand; | ||||
|     OneWireMaster onewire_master; | ||||
| }; | ||||
							
								
								
									
										19
									
								
								applications/accessor/accessor-event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								applications/accessor/accessor-event.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| #pragma once | ||||
| #include <stdint.h> | ||||
|  | ||||
| class AccessorEvent { | ||||
| public: | ||||
|     // events enum | ||||
|     enum class Type : uint8_t { | ||||
|         Tick, | ||||
|         Back, | ||||
|     }; | ||||
|  | ||||
|     // payload | ||||
|     union { | ||||
|         uint32_t menu_index; | ||||
|     } payload; | ||||
|  | ||||
|     // event type | ||||
|     Type type; | ||||
| }; | ||||
							
								
								
									
										79
									
								
								applications/accessor/accessor-view-manager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								applications/accessor/accessor-view-manager.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| #include "accessor-view-manager.h" | ||||
| #include "accessor-event.h" | ||||
| #include <callback-connector.h> | ||||
|  | ||||
| AccessorAppViewManager::AccessorAppViewManager() { | ||||
|     event_queue = osMessageQueueNew(10, sizeof(AccessorEvent), NULL); | ||||
|  | ||||
|     view_dispatcher = view_dispatcher_alloc(); | ||||
|     auto callback = cbc::obtain_connector(this, &AccessorAppViewManager::previous_view_callback); | ||||
|  | ||||
|     // allocate views | ||||
|     submenu = submenu_alloc(); | ||||
|     add_view(ViewType::Submenu, submenu_get_view(submenu)); | ||||
|  | ||||
|     popup = popup_alloc(); | ||||
|     add_view(ViewType::Popup, popup_get_view(popup)); | ||||
|  | ||||
|     gui = static_cast<Gui*>(furi_record_open("gui")); | ||||
|     view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); | ||||
|  | ||||
|     // set previous view callback for all views | ||||
|     view_set_previous_callback(submenu_get_view(submenu), callback); | ||||
|     view_set_previous_callback(popup_get_view(popup), callback); | ||||
| } | ||||
|  | ||||
| AccessorAppViewManager::~AccessorAppViewManager() { | ||||
|     // remove views | ||||
|     view_dispatcher_remove_view( | ||||
|         view_dispatcher, static_cast<uint32_t>(AccessorAppViewManager::ViewType::Submenu)); | ||||
|     view_dispatcher_remove_view( | ||||
|         view_dispatcher, static_cast<uint32_t>(AccessorAppViewManager::ViewType::Popup)); | ||||
|  | ||||
|     // free view modules | ||||
|     submenu_free(submenu); | ||||
|     popup_free(popup); | ||||
|  | ||||
|     // free dispatcher | ||||
|     view_dispatcher_free(view_dispatcher); | ||||
|  | ||||
|     // free event queue | ||||
|     osMessageQueueDelete(event_queue); | ||||
| } | ||||
|  | ||||
| void AccessorAppViewManager::switch_to(ViewType type) { | ||||
|     view_dispatcher_switch_to_view(view_dispatcher, static_cast<uint32_t>(type)); | ||||
| } | ||||
|  | ||||
| Submenu* AccessorAppViewManager::get_submenu() { | ||||
|     return submenu; | ||||
| } | ||||
|  | ||||
| Popup* AccessorAppViewManager::get_popup() { | ||||
|     return popup; | ||||
| } | ||||
|  | ||||
| void AccessorAppViewManager::receive_event(AccessorEvent* event) { | ||||
|     if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) { | ||||
|         event->type = AccessorEvent::Type::Tick; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void AccessorAppViewManager::send_event(AccessorEvent* event) { | ||||
|     osStatus_t result = osMessageQueuePut(event_queue, event, 0, 0); | ||||
|     furi_check(result == osOK); | ||||
| } | ||||
|  | ||||
| uint32_t AccessorAppViewManager::previous_view_callback(void* context) { | ||||
|     if(event_queue != NULL) { | ||||
|         AccessorEvent event; | ||||
|         event.type = AccessorEvent::Type::Back; | ||||
|         send_event(&event); | ||||
|     } | ||||
|  | ||||
|     return VIEW_IGNORE; | ||||
| } | ||||
|  | ||||
| void AccessorAppViewManager::add_view(ViewType view_type, View* view) { | ||||
|     view_dispatcher_add_view(view_dispatcher, static_cast<uint32_t>(view_type), view); | ||||
| } | ||||
							
								
								
									
										39
									
								
								applications/accessor/accessor-view-manager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								applications/accessor/accessor-view-manager.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| #pragma once | ||||
| #include <furi.h> | ||||
| #include <gui/view_dispatcher.h> | ||||
| #include <gui/modules/submenu.h> | ||||
| #include <gui/modules/popup.h> | ||||
| #include "accessor-event.h" | ||||
|  | ||||
| class AccessorAppViewManager { | ||||
| public: | ||||
|     enum class ViewType : uint8_t { | ||||
|         Submenu, | ||||
|         Popup, | ||||
|         Tune, | ||||
|     }; | ||||
|  | ||||
|     osMessageQueueId_t event_queue; | ||||
|  | ||||
|     AccessorAppViewManager(); | ||||
|     ~AccessorAppViewManager(); | ||||
|  | ||||
|     void switch_to(ViewType type); | ||||
|  | ||||
|     void receive_event(AccessorEvent* event); | ||||
|     void send_event(AccessorEvent* event); | ||||
|  | ||||
|     Submenu* get_submenu(); | ||||
|     Popup* get_popup(); | ||||
|  | ||||
| private: | ||||
|     ViewDispatcher* view_dispatcher; | ||||
|     Gui* gui; | ||||
|  | ||||
|     uint32_t previous_view_callback(void* context); | ||||
|     void add_view(ViewType view_type, View* view); | ||||
|  | ||||
|     // view elements | ||||
|     Submenu* submenu; | ||||
|     Popup* popup; | ||||
| }; | ||||
							
								
								
									
										10
									
								
								applications/accessor/accessor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								applications/accessor/accessor.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| #include "accessor-app.h" | ||||
|  | ||||
| // app enter function | ||||
| extern "C" int32_t app_accessor(void* p) { | ||||
|     AccessorApp* app = new AccessorApp(); | ||||
|     app->run(); | ||||
|     delete app; | ||||
|  | ||||
|     return 255; | ||||
| } | ||||
							
								
								
									
										221
									
								
								applications/accessor/helpers/wiegand.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								applications/accessor/helpers/wiegand.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,221 @@ | ||||
| #include "wiegand.h" | ||||
| #include <furi.h> | ||||
| #include <api-hal.h> | ||||
|  | ||||
| volatile unsigned long WIEGAND::_cardTempHigh = 0; | ||||
| volatile unsigned long WIEGAND::_cardTemp = 0; | ||||
| volatile unsigned long WIEGAND::_lastWiegand = 0; | ||||
| unsigned long WIEGAND::_code = 0; | ||||
| unsigned long WIEGAND::_codeHigh = 0; | ||||
| volatile int WIEGAND::_bitCount = 0; | ||||
| int WIEGAND::_wiegandType = 0; | ||||
|  | ||||
| constexpr uint32_t clocks_in_ms = 64 * 1000; | ||||
|  | ||||
| WIEGAND::WIEGAND() { | ||||
| } | ||||
|  | ||||
| unsigned long WIEGAND::getCode() { | ||||
|     return _code; | ||||
| } | ||||
|  | ||||
| unsigned long WIEGAND::getCodeHigh() { | ||||
|     return _codeHigh; | ||||
| } | ||||
|  | ||||
| int WIEGAND::getWiegandType() { | ||||
|     return _wiegandType; | ||||
| } | ||||
|  | ||||
| bool WIEGAND::available() { | ||||
|     bool ret; | ||||
|     __disable_irq(); | ||||
|     ret = DoWiegandConversion(); | ||||
|     __enable_irq(); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| void input_isr(void* _pin, void* _ctx) { | ||||
|     // interrupt manager get us pin constant, so... | ||||
|     uint32_t pin = (uint32_t)_pin; | ||||
|     WIEGAND* _this = static_cast<WIEGAND*>(_ctx); | ||||
|  | ||||
|     if(pin == ext_pa6_gpio.pin) { | ||||
|         _this->ReadD0(); | ||||
|     } | ||||
|  | ||||
|     if(pin == ext_pa7_gpio.pin) { | ||||
|         _this->ReadD1(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void WIEGAND::begin() { | ||||
|     _lastWiegand = 0; | ||||
|     _cardTempHigh = 0; | ||||
|     _cardTemp = 0; | ||||
|     _code = 0; | ||||
|     _wiegandType = 0; | ||||
|     _bitCount = 0; | ||||
|  | ||||
|     const GpioPin* pinD0 = &ext_pa6_gpio; | ||||
|     const GpioPin* pinD1 = &ext_pa7_gpio; | ||||
|  | ||||
|     gpio_init(pinD0, GpioModeInterruptFall); // Set D0 pin as input | ||||
|     gpio_init(pinD1, GpioModeInterruptFall); // Set D1 pin as input | ||||
|  | ||||
|     api_interrupt_add( | ||||
|         input_isr, InterruptTypeExternalInterrupt, this); // Hardware interrupt - high to low pulse | ||||
| } | ||||
|  | ||||
| void WIEGAND::ReadD0() { | ||||
|     _bitCount++; // Increament bit count for Interrupt connected to D0 | ||||
|     if(_bitCount > 31) // If bit count more than 31, process high bits | ||||
|     { | ||||
|         _cardTempHigh |= ((0x80000000 & _cardTemp) >> 31); //	shift value to high bits | ||||
|         _cardTempHigh <<= 1; | ||||
|         _cardTemp <<= 1; | ||||
|     } else { | ||||
|         _cardTemp <<= 1; // D0 represent binary 0, so just left shift card data | ||||
|     } | ||||
|     _lastWiegand = DWT->CYCCNT; // Keep track of last wiegand bit received | ||||
| } | ||||
|  | ||||
| void WIEGAND::ReadD1() { | ||||
|     _bitCount++; // Increment bit count for Interrupt connected to D1 | ||||
|     if(_bitCount > 31) // If bit count more than 31, process high bits | ||||
|     { | ||||
|         _cardTempHigh |= ((0x80000000 & _cardTemp) >> 31); // shift value to high bits | ||||
|         _cardTempHigh <<= 1; | ||||
|         _cardTemp |= 1; | ||||
|         _cardTemp <<= 1; | ||||
|     } else { | ||||
|         _cardTemp |= 1; // D1 represent binary 1, so OR card data with 1 then | ||||
|         _cardTemp <<= 1; // left shift card data | ||||
|     } | ||||
|     _lastWiegand = DWT->CYCCNT; // Keep track of last wiegand bit received | ||||
| } | ||||
|  | ||||
| unsigned long WIEGAND::GetCardId( | ||||
|     volatile unsigned long* codehigh, | ||||
|     volatile unsigned long* codelow, | ||||
|     char bitlength) { | ||||
|     if(bitlength == 26) // EM tag | ||||
|         return (*codelow & 0x1FFFFFE) >> 1; | ||||
|  | ||||
|     if(bitlength == 24) return (*codelow & 0x7FFFFE) >> 1; | ||||
|  | ||||
|     if(bitlength == 34) // Mifare | ||||
|     { | ||||
|         *codehigh = *codehigh & 0x03; // only need the 2 LSB of the codehigh | ||||
|         *codehigh <<= 30; // shift 2 LSB to MSB | ||||
|         *codelow >>= 1; | ||||
|         return *codehigh | *codelow; | ||||
|     } | ||||
|  | ||||
|     if(bitlength == 32) { | ||||
|         return (*codelow & 0x7FFFFFFE) >> 1; | ||||
|     } | ||||
|  | ||||
|     return *codelow; // EM tag or Mifare without parity bits | ||||
| } | ||||
|  | ||||
| char translateEnterEscapeKeyPress(char originalKeyPress) { | ||||
|     switch(originalKeyPress) { | ||||
|     case 0x0b: // 11 or * key | ||||
|         return 0x0d; // 13 or ASCII ENTER | ||||
|  | ||||
|     case 0x0a: // 10 or # key | ||||
|         return 0x1b; // 27 or ASCII ESCAPE | ||||
|  | ||||
|     default: | ||||
|         return originalKeyPress; | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool WIEGAND::DoWiegandConversion() { | ||||
|     unsigned long cardID; | ||||
|     unsigned long sysTick = DWT->CYCCNT; | ||||
|  | ||||
|     if((sysTick - _lastWiegand) > | ||||
|        (25 * clocks_in_ms)) // if no more signal coming through after 25ms | ||||
|     { | ||||
|         if((_bitCount == 24) || (_bitCount == 26) || (_bitCount == 32) || (_bitCount == 34) || | ||||
|            (_bitCount == 37) || (_bitCount == 40) || (_bitCount == 8) || | ||||
|            (_bitCount == | ||||
|             4)) // bitCount for keypress=4 or 8, Wiegand 26=24 or 26, Wiegand 34=32 or 34 | ||||
|         { | ||||
|             _codeHigh = 0; | ||||
|             // shift right 1 bit to get back the real value - interrupt done 1 left shift in advance | ||||
|             _cardTemp >>= 1; | ||||
|             // bit count more than 32 bits, shift high bits right to make adjustment | ||||
|             if(_bitCount > 32) _cardTempHigh >>= 1; | ||||
|  | ||||
|             if(_bitCount == 8) // keypress wiegand with integrity | ||||
|             { | ||||
|                 // 8-bit Wiegand keyboard data, high nibble is the "NOT" of low nibble | ||||
|                 // eg if key 1 pressed, data=E1 in binary 11100001 , high nibble=1110 , low nibble = 0001 | ||||
|                 char highNibble = (_cardTemp & 0xf0) >> 4; | ||||
|                 char lowNibble = (_cardTemp & 0x0f); | ||||
|                 _wiegandType = _bitCount; | ||||
|                 _bitCount = 0; | ||||
|                 _cardTemp = 0; | ||||
|                 _cardTempHigh = 0; | ||||
|  | ||||
|                 if(lowNibble == | ||||
|                    (~highNibble & 0x0f)) // check if low nibble matches the "NOT" of high nibble. | ||||
|                 { | ||||
|                     _code = (int)translateEnterEscapeKeyPress(lowNibble); | ||||
|                     return true; | ||||
|                 } else { | ||||
|                     _lastWiegand = sysTick; | ||||
|                     _bitCount = 0; | ||||
|                     _cardTemp = 0; | ||||
|                     _cardTempHigh = 0; | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 // TODO: Handle validation failure case! | ||||
|             } else if(4 == _bitCount) { | ||||
|                 // 4-bit Wiegand codes have no data integrity check so we just | ||||
|                 // read the LOW nibble. | ||||
|                 _code = (int)translateEnterEscapeKeyPress(_cardTemp & 0x0000000F); | ||||
|  | ||||
|                 _wiegandType = _bitCount; | ||||
|                 _bitCount = 0; | ||||
|                 _cardTemp = 0; | ||||
|                 _cardTempHigh = 0; | ||||
|  | ||||
|                 return true; | ||||
|             } else if(40 == _bitCount) { | ||||
|                 _cardTempHigh >>= 1; | ||||
|  | ||||
|                 _code = _cardTemp; | ||||
|                 _codeHigh = _cardTempHigh; | ||||
|  | ||||
|                 _wiegandType = _bitCount; | ||||
|                 _bitCount = 0; | ||||
|                 _cardTemp = 0; | ||||
|                 _cardTempHigh = 0; | ||||
|  | ||||
|                 return true; | ||||
|             } else { | ||||
|                 // wiegand 26 or wiegand 34 | ||||
|                 cardID = GetCardId(&_cardTempHigh, &_cardTemp, _bitCount); | ||||
|                 _wiegandType = _bitCount; | ||||
|                 _bitCount = 0; | ||||
|                 _cardTemp = 0; | ||||
|                 _cardTempHigh = 0; | ||||
|                 _code = cardID; | ||||
|                 return true; | ||||
|             } | ||||
|         } else { | ||||
|             // well time over 25 ms and bitCount !=8 , !=26, !=34 , must be noise or nothing then. | ||||
|             _lastWiegand = sysTick; | ||||
|             _bitCount = 0; | ||||
|             _cardTemp = 0; | ||||
|             _cardTempHigh = 0; | ||||
|             return false; | ||||
|         } | ||||
|     } else | ||||
|         return false; | ||||
| } | ||||
							
								
								
									
										27
									
								
								applications/accessor/helpers/wiegand.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								applications/accessor/helpers/wiegand.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| #pragma once | ||||
|  | ||||
| class WIEGAND { | ||||
| public: | ||||
|     WIEGAND(); | ||||
|     void begin(); | ||||
|     bool available(); | ||||
|     unsigned long getCode(); | ||||
|     unsigned long getCodeHigh(); | ||||
|     int getWiegandType(); | ||||
|  | ||||
|     static void ReadD0(); | ||||
|     static void ReadD1(); | ||||
|  | ||||
| private: | ||||
|     static bool DoWiegandConversion(); | ||||
|     static unsigned long | ||||
|     GetCardId(volatile unsigned long* codehigh, volatile unsigned long* codelow, char bitlength); | ||||
|  | ||||
|     static volatile unsigned long _cardTempHigh; | ||||
|     static volatile unsigned long _cardTemp; | ||||
|     static volatile unsigned long _lastWiegand; | ||||
|     static volatile int _bitCount; | ||||
|     static int _wiegandType; | ||||
|     static unsigned long _code; | ||||
|     static unsigned long _codeHigh; | ||||
| }; | ||||
							
								
								
									
										13
									
								
								applications/accessor/scene/accessor-scene-generic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								applications/accessor/scene/accessor-scene-generic.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| #pragma once | ||||
| #include "../accessor-app.h" | ||||
|  | ||||
| class AccessorApp; | ||||
|  | ||||
| class AccessorScene { | ||||
| public: | ||||
|     virtual void on_enter(AccessorApp* app) = 0; | ||||
|     virtual bool on_event(AccessorApp* app, AccessorEvent* event) = 0; | ||||
|     virtual void on_exit(AccessorApp* app) = 0; | ||||
|  | ||||
| private: | ||||
| }; | ||||
							
								
								
									
										88
									
								
								applications/accessor/scene/accessor-scene-start.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								applications/accessor/scene/accessor-scene-start.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| #include "../accessor-app.h" | ||||
| #include "../accessor-view-manager.h" | ||||
| #include "../accessor-event.h" | ||||
| #include <callback-connector.h> | ||||
| #include "accessor-scene-start.h" | ||||
|  | ||||
| void AccessorSceneStart::on_enter(AccessorApp* app) { | ||||
|     AccessorAppViewManager* view_manager = app->get_view_manager(); | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|  | ||||
|     popup_set_header(popup, "Accessor App", 64, 16, AlignCenter, AlignBottom); | ||||
|     app->set_text_store("[??????]"); | ||||
|     popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop); | ||||
|  | ||||
|     view_manager->switch_to(AccessorAppViewManager::ViewType::Popup); | ||||
| } | ||||
|  | ||||
| bool AccessorSceneStart::on_event(AccessorApp* app, AccessorEvent* event) { | ||||
|     bool consumed = false; | ||||
|  | ||||
|     if(event->type == AccessorEvent::Type::Tick) { | ||||
|         WIEGAND* wiegand = app->get_wiegand(); | ||||
|         Popup* popup = app->get_view_manager()->get_popup(); | ||||
|         OneWireMaster* onewire = app->get_one_wire(); | ||||
|  | ||||
|         uint8_t data[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||||
|         uint8_t type = 0; | ||||
|  | ||||
|         if(wiegand->available()) { | ||||
|             type = wiegand->getWiegandType(); | ||||
|  | ||||
|             for(uint8_t i = 0; i < 4; i++) { | ||||
|                 data[i] = wiegand->getCode() >> (i * 8); | ||||
|             } | ||||
|  | ||||
|             for(uint8_t i = 4; i < 8; i++) { | ||||
|                 data[i] = wiegand->getCodeHigh() >> ((i - 4) * 8); | ||||
|             } | ||||
|         } else { | ||||
|             __disable_irq(); | ||||
|             if(onewire->reset()) { | ||||
|                 type = 255; | ||||
|                 onewire->write(0x33); | ||||
|                 for(uint8_t i = 0; i < 8; i++) { | ||||
|                     data[i] = onewire->read(); | ||||
|                 } | ||||
|  | ||||
|                 for(uint8_t i = 0; i < 7; i++) { | ||||
|                     data[i] = data[i + 1]; | ||||
|                 } | ||||
|             } | ||||
|             __enable_irq(); | ||||
|         } | ||||
|  | ||||
|         if(type > 0) { | ||||
|             if(type == 255) { | ||||
|                 app->set_text_store( | ||||
|                     "[%02X %02X %02X %02X %02X %02X DS]", | ||||
|                     data[5], | ||||
|                     data[4], | ||||
|                     data[3], | ||||
|                     data[2], | ||||
|                     data[1], | ||||
|                     data[0]); | ||||
|             } else { | ||||
|                 app->set_text_store( | ||||
|                     "[%02X %02X %02X %02X %02X %02X W%u]", | ||||
|                     data[5], | ||||
|                     data[4], | ||||
|                     data[3], | ||||
|                     data[2], | ||||
|                     data[1], | ||||
|                     data[0], | ||||
|                     type); | ||||
|             } | ||||
|             popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop); | ||||
|             app->notify_success(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return consumed; | ||||
| } | ||||
|  | ||||
| void AccessorSceneStart::on_exit(AccessorApp* app) { | ||||
|     Popup* popup = app->get_view_manager()->get_popup(); | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
| } | ||||
							
								
								
									
										9
									
								
								applications/accessor/scene/accessor-scene-start.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								applications/accessor/scene/accessor-scene-start.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| #pragma once | ||||
| #include "accessor-scene-generic.h" | ||||
|  | ||||
| class AccessorSceneStart : public AccessorScene { | ||||
| public: | ||||
|     void on_enter(AccessorApp* app) final; | ||||
|     bool on_event(AccessorApp* app, AccessorEvent* event) final; | ||||
|     void on_exit(AccessorApp* app) final; | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user