diff --git a/applications/accessor/accessor-app.cpp b/applications/accessor/accessor-app.cpp new file mode 100644 index 00000000..9a3b4c8e --- /dev/null +++ b/applications/accessor/accessor-app.cpp @@ -0,0 +1,176 @@ +#include "accessor-app.h" +#include +#include +#include + +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 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; +} \ No newline at end of file diff --git a/applications/accessor/accessor-app.h b/applications/accessor/accessor-app.h new file mode 100644 index 00000000..7d880ed4 --- /dev/null +++ b/applications/accessor/accessor-app.h @@ -0,0 +1,58 @@ +#pragma once +#include +#include +#include "accessor-view-manager.h" + +#include "scene/accessor-scene-start.h" + +#include "helpers/wiegand.h" + +#include + +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 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 previous_scenes_list = {Scene::Exit}; + Scene current_scene = Scene::Start; + AccessorAppViewManager view; + + std::map 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; +}; \ No newline at end of file diff --git a/applications/accessor/accessor-event.h b/applications/accessor/accessor-event.h new file mode 100644 index 00000000..64712bad --- /dev/null +++ b/applications/accessor/accessor-event.h @@ -0,0 +1,19 @@ +#pragma once +#include + +class AccessorEvent { +public: + // events enum + enum class Type : uint8_t { + Tick, + Back, + }; + + // payload + union { + uint32_t menu_index; + } payload; + + // event type + Type type; +}; diff --git a/applications/accessor/accessor-view-manager.cpp b/applications/accessor/accessor-view-manager.cpp new file mode 100644 index 00000000..bb503898 --- /dev/null +++ b/applications/accessor/accessor-view-manager.cpp @@ -0,0 +1,79 @@ +#include "accessor-view-manager.h" +#include "accessor-event.h" +#include + +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(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(AccessorAppViewManager::ViewType::Submenu)); + view_dispatcher_remove_view( + view_dispatcher, static_cast(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(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(view_type), view); +} \ No newline at end of file diff --git a/applications/accessor/accessor-view-manager.h b/applications/accessor/accessor-view-manager.h new file mode 100644 index 00000000..e9aad871 --- /dev/null +++ b/applications/accessor/accessor-view-manager.h @@ -0,0 +1,39 @@ +#pragma once +#include +#include +#include +#include +#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; +}; \ No newline at end of file diff --git a/applications/accessor/accessor.cpp b/applications/accessor/accessor.cpp new file mode 100644 index 00000000..25215827 --- /dev/null +++ b/applications/accessor/accessor.cpp @@ -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; +} \ No newline at end of file diff --git a/applications/accessor/helpers/wiegand.cpp b/applications/accessor/helpers/wiegand.cpp new file mode 100644 index 00000000..5cf6f683 --- /dev/null +++ b/applications/accessor/helpers/wiegand.cpp @@ -0,0 +1,221 @@ +#include "wiegand.h" +#include +#include + +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(_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; +} \ No newline at end of file diff --git a/applications/accessor/helpers/wiegand.h b/applications/accessor/helpers/wiegand.h new file mode 100644 index 00000000..782eec77 --- /dev/null +++ b/applications/accessor/helpers/wiegand.h @@ -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; +}; \ No newline at end of file diff --git a/applications/accessor/scene/accessor-scene-generic.h b/applications/accessor/scene/accessor-scene-generic.h new file mode 100644 index 00000000..641d55f0 --- /dev/null +++ b/applications/accessor/scene/accessor-scene-generic.h @@ -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: +}; \ No newline at end of file diff --git a/applications/accessor/scene/accessor-scene-start.cpp b/applications/accessor/scene/accessor-scene-start.cpp new file mode 100644 index 00000000..6fc0bddb --- /dev/null +++ b/applications/accessor/scene/accessor-scene-start.cpp @@ -0,0 +1,88 @@ +#include "../accessor-app.h" +#include "../accessor-view-manager.h" +#include "../accessor-event.h" +#include +#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); +} \ No newline at end of file diff --git a/applications/accessor/scene/accessor-scene-start.h b/applications/accessor/scene/accessor-scene-start.h new file mode 100644 index 00000000..442c2db7 --- /dev/null +++ b/applications/accessor/scene/accessor-scene-start.h @@ -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; +}; \ No newline at end of file diff --git a/applications/applications.c b/applications/applications.c index c8a02965..b8109f28 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -35,6 +35,7 @@ int32_t gui_test(void* p); int32_t keypad_test(void* p); int32_t scene_app(void* p); int32_t passport(void* p); +int32_t app_accessor(void* p); const FlipperApplication FLIPPER_SERVICES[] = { #ifdef APP_CLI @@ -149,6 +150,10 @@ const FlipperApplication FLIPPER_SERVICES[] = { {.app = keypad_test, .name = "keypad_test", .icon = A_Plugins_14}, #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); @@ -230,6 +235,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = { {.app = keypad_test, .name = "keypad_test", .icon = A_Plugins_14}, #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); diff --git a/applications/applications.mk b/applications/applications.mk index 57999d2b..075031f7 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -25,6 +25,7 @@ BUILD_GPIO_DEMO = 1 BUILD_MUSIC_PLAYER = 1 BUILD_FLOOPPER_BLOOPPER = 1 BUILD_IBUTTON = 1 + endif APP_DEBUG ?=0 @@ -32,6 +33,7 @@ ifeq ($(APP_DEBUG), 1) CFLAGS += -DAPP_DEBUG BUILD_GUI_TEST = 1 BUILD_KEYPAD_TEST = 1 +BUILD_ACCESSOR = 1 BUILD_SD_TEST = 1 BUILD_VIBRO_DEMO = 1 BUILD_SPEAKER_DEMO = 1 @@ -209,6 +211,17 @@ CFLAGS += -DBUILD_KEYPAD_TEST BUILD_KEYPAD_TEST = 1 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 ifeq ($(APP_GPIO_DEMO), 1) CFLAGS += -DAPP_GPIO_DEMO diff --git a/firmware/targets/f5/api-hal/api-hal-resources.c b/firmware/targets/f5/api-hal/api-hal-resources.c index 5b53e29c..2d0dcf93 100644 --- a/firmware/targets/f5/api-hal/api-hal-resources.c +++ b/firmware/targets/f5/api-hal/api-hal-resources.c @@ -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_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 }; + +// 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}; \ No newline at end of file diff --git a/firmware/targets/f5/api-hal/api-hal-resources.h b/firmware/targets/f5/api-hal/api-hal-resources.h index 297a79a4..92f01b96 100644 --- a/firmware/targets/f5/api-hal/api-hal-resources.h +++ b/firmware/targets/f5/api-hal/api-hal-resources.h @@ -74,6 +74,14 @@ extern const GpioPin gpio_spi_r_miso; extern const GpioPin gpio_spi_r_mosi; 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 }