App accessor: init (#433)
This commit is contained in:
parent
dfcf0ea0eb
commit
c3350990c2
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;
|
||||||
|
};
|
@ -35,6 +35,7 @@ int32_t gui_test(void* p);
|
|||||||
int32_t keypad_test(void* p);
|
int32_t keypad_test(void* p);
|
||||||
int32_t scene_app(void* p);
|
int32_t scene_app(void* p);
|
||||||
int32_t passport(void* p);
|
int32_t passport(void* p);
|
||||||
|
int32_t app_accessor(void* p);
|
||||||
|
|
||||||
const FlipperApplication FLIPPER_SERVICES[] = {
|
const FlipperApplication FLIPPER_SERVICES[] = {
|
||||||
#ifdef APP_CLI
|
#ifdef APP_CLI
|
||||||
@ -149,6 +150,10 @@ const FlipperApplication FLIPPER_SERVICES[] = {
|
|||||||
{.app = keypad_test, .name = "keypad_test", .icon = A_Plugins_14},
|
{.app = keypad_test, .name = "keypad_test", .icon = A_Plugins_14},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef APP_ACCESSOR
|
||||||
|
{.app = app_accessor, .name = "accessor", .stack_size = 4096, .icon = A_Plugins_14},
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t FLIPPER_SERVICES_COUNT = sizeof(FLIPPER_SERVICES) / sizeof(FlipperApplication);
|
const size_t FLIPPER_SERVICES_COUNT = sizeof(FLIPPER_SERVICES) / sizeof(FlipperApplication);
|
||||||
@ -230,6 +235,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = {
|
|||||||
{.app = keypad_test, .name = "keypad_test", .icon = A_Plugins_14},
|
{.app = keypad_test, .name = "keypad_test", .icon = A_Plugins_14},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUILD_ACCESSOR
|
||||||
|
{.app = app_accessor, .name = "accessor", .stack_size = 4096, .icon = A_Plugins_14},
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t FLIPPER_DEBUG_APPS_COUNT = sizeof(FLIPPER_DEBUG_APPS) / sizeof(FlipperApplication);
|
const size_t FLIPPER_DEBUG_APPS_COUNT = sizeof(FLIPPER_DEBUG_APPS) / sizeof(FlipperApplication);
|
||||||
|
@ -25,6 +25,7 @@ BUILD_GPIO_DEMO = 1
|
|||||||
BUILD_MUSIC_PLAYER = 1
|
BUILD_MUSIC_PLAYER = 1
|
||||||
BUILD_FLOOPPER_BLOOPPER = 1
|
BUILD_FLOOPPER_BLOOPPER = 1
|
||||||
BUILD_IBUTTON = 1
|
BUILD_IBUTTON = 1
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
APP_DEBUG ?=0
|
APP_DEBUG ?=0
|
||||||
@ -32,6 +33,7 @@ ifeq ($(APP_DEBUG), 1)
|
|||||||
CFLAGS += -DAPP_DEBUG
|
CFLAGS += -DAPP_DEBUG
|
||||||
BUILD_GUI_TEST = 1
|
BUILD_GUI_TEST = 1
|
||||||
BUILD_KEYPAD_TEST = 1
|
BUILD_KEYPAD_TEST = 1
|
||||||
|
BUILD_ACCESSOR = 1
|
||||||
BUILD_SD_TEST = 1
|
BUILD_SD_TEST = 1
|
||||||
BUILD_VIBRO_DEMO = 1
|
BUILD_VIBRO_DEMO = 1
|
||||||
BUILD_SPEAKER_DEMO = 1
|
BUILD_SPEAKER_DEMO = 1
|
||||||
@ -209,6 +211,17 @@ CFLAGS += -DBUILD_KEYPAD_TEST
|
|||||||
BUILD_KEYPAD_TEST = 1
|
BUILD_KEYPAD_TEST = 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
APP_ACCESSOR ?= 0
|
||||||
|
ifeq ($(APP_ACCESSOR), 1)
|
||||||
|
CFLAGS += -DAPP_ACCESSOR
|
||||||
|
BUILD_ACCESSOR = 1
|
||||||
|
endif
|
||||||
|
BUILD_ACCESSOR ?= 0
|
||||||
|
ifeq ($(BUILD_ACCESSOR), 1)
|
||||||
|
CFLAGS += -DBUILD_ACCESSOR
|
||||||
|
BUILD_ACCESSOR = 1
|
||||||
|
endif
|
||||||
|
|
||||||
APP_GPIO_DEMO ?= 0
|
APP_GPIO_DEMO ?= 0
|
||||||
ifeq ($(APP_GPIO_DEMO), 1)
|
ifeq ($(APP_GPIO_DEMO), 1)
|
||||||
CFLAGS += -DAPP_GPIO_DEMO
|
CFLAGS += -DAPP_GPIO_DEMO
|
||||||
|
@ -42,3 +42,13 @@ const GpioPin gpio_spi_d_sck = { .port=SPI_D_SCK_GPIO_Port, .pin=SPI_D_SCK_Pin }
|
|||||||
const GpioPin gpio_spi_r_miso = { .port=SPI_R_MISO_GPIO_Port, .pin=SPI_R_MISO_Pin };
|
const GpioPin gpio_spi_r_miso = { .port=SPI_R_MISO_GPIO_Port, .pin=SPI_R_MISO_Pin };
|
||||||
const GpioPin gpio_spi_r_mosi = { .port=SPI_R_MOSI_GPIO_Port, .pin=SPI_R_MOSI_Pin };
|
const GpioPin gpio_spi_r_mosi = { .port=SPI_R_MOSI_GPIO_Port, .pin=SPI_R_MOSI_Pin };
|
||||||
const GpioPin gpio_spi_r_sck = { .port=SPI_R_SCK_GPIO_Port, .pin=SPI_R_SCK_Pin };
|
const GpioPin gpio_spi_r_sck = { .port=SPI_R_SCK_GPIO_Port, .pin=SPI_R_SCK_Pin };
|
||||||
|
|
||||||
|
// external gpio's
|
||||||
|
const GpioPin ext_pc0_gpio = {.port = GPIOC, .pin = GPIO_PIN_0};
|
||||||
|
const GpioPin ext_pc1_gpio = {.port = GPIOC, .pin = GPIO_PIN_1};
|
||||||
|
const GpioPin ext_pc3_gpio = {.port = GPIOC, .pin = GPIO_PIN_3};
|
||||||
|
const GpioPin ext_pb2_gpio = {.port = GPIOB, .pin = GPIO_PIN_2};
|
||||||
|
const GpioPin ext_pb3_gpio = {.port = GPIOB, .pin = GPIO_PIN_3};
|
||||||
|
const GpioPin ext_pa4_gpio = {.port = GPIOA, .pin = GPIO_PIN_4};
|
||||||
|
const GpioPin ext_pa6_gpio = {.port = GPIOA, .pin = GPIO_PIN_6};
|
||||||
|
const GpioPin ext_pa7_gpio = {.port = GPIOA, .pin = GPIO_PIN_7};
|
@ -74,6 +74,14 @@ extern const GpioPin gpio_spi_r_miso;
|
|||||||
extern const GpioPin gpio_spi_r_mosi;
|
extern const GpioPin gpio_spi_r_mosi;
|
||||||
extern const GpioPin gpio_spi_r_sck;
|
extern const GpioPin gpio_spi_r_sck;
|
||||||
|
|
||||||
|
extern const GpioPin ext_pc0_gpio;
|
||||||
|
extern const GpioPin ext_pc1_gpio;
|
||||||
|
extern const GpioPin ext_pc3_gpio;
|
||||||
|
extern const GpioPin ext_pb2_gpio;
|
||||||
|
extern const GpioPin ext_pb3_gpio;
|
||||||
|
extern const GpioPin ext_pa4_gpio;
|
||||||
|
extern const GpioPin ext_pa6_gpio;
|
||||||
|
extern const GpioPin ext_pa7_gpio;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user