Skip to content

Commit

Permalink
PicoW: working Ok
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardoquesada committed Nov 9, 2023
1 parent 1c183db commit 11b4f11
Show file tree
Hide file tree
Showing 7 changed files with 282 additions and 24 deletions.
3 changes: 3 additions & 0 deletions src/components/bluepad32/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ if(IDF_TARGET)
"uni_gpio.c"
"uni_mouse_quadrature.c"
"uni_property_nvs.c")
elseif(PICO_SDK_VERSION_STRING)
list(APPEND srcs
"uni_property_mem.c")
endif()

if(CONFIG_IDF_TARGET_ESP32)
Expand Down
3 changes: 2 additions & 1 deletion src/components/bluepad32/uni_bt_le.c
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,8 @@ void uni_bt_le_setup(void) {

gatt_client_init();
hids_client_init(hid_descriptor_storage, sizeof(hid_descriptor_storage));
scan_parameters_service_client_init();
// FIXME: this is an empty function and PicoW toolchain is removing empty function (?)
// scan_parameters_service_client_init();
device_information_service_client_init();

gap_set_scan_parameters(0 /* type: passive */, 48 /* interval */, 48 /* window */);
Expand Down
18 changes: 9 additions & 9 deletions src/components/bluepad32/uni_property.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,25 @@ const char* UNI_PROPERTY_KEY_UNI_VENDOR = "bp.uni.vendor";
// TODO: Implement "property interface" instead of doing #ifdef

void uni_property_set(const char* key, uni_property_type_t type, uni_property_value_t value) {
#if defined(CONFIG_BLUEPAD32_PLATFORM_PC_DEBUG)
uni_property_mem_set(key, type, value);
#else
#if defined(CONFIG_IDF_TARGET)
uni_property_nvs_set(key, type, value);
#else
uni_property_mem_set(key, type, value);
#endif
}

uni_property_value_t uni_property_get(const char* key, uni_property_type_t type, uni_property_value_t def) {
#if defined(CONFIG_BLUEPAD32_PLATFORM_PC_DEBUG)
return uni_property_mem_get(key, type, def);
#else
#if defined(CONFIG_IDF_TARGET)
return uni_property_nvs_get(key, type, def);
#else
return uni_property_mem_get(key, type, def);
#endif
}

void uni_property_init(void) {
#if defined(CONFIG_BLUEPAD32_PLATFORM_PC_DEBUG)
return uni_property_mem_init();
#else
#if defined(CONFIG_IDF_TARGET)
return uni_property_nvs_init();
#else
return uni_property_mem_init();
#endif
}
25 changes: 15 additions & 10 deletions tools/pico/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,38 @@ include(pico_sdk_import.cmake)

set(BTSTACK_ROOT ${PICO_SDK_PATH}/lib/btstack)

project(Bluepad32_PicoW C CXX ASM)
project(bluepad32_picow_app C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

# initialize the Raspberry Pi Pico SDK
pico_sdk_init()

add_executable(Bluepad32_PicoW
src/main.cpp
add_executable(bluepad32_picow_app
main.c
my_platform.c
)

target_include_directories(Bluepad32_PicoW PRIVATE
target_include_directories(bluepad32_picow_app PRIVATE
src
../../src/components/bluepad32/include)
include_directories(Bluepad32_PicoW .)
target_link_libraries(Bluepad32_PicoW

# Needed for btstack_config.h / sdkconfig.h
# so that libblupad32 can include them
include_directories(bluepad32_picow_app .)

target_link_libraries(bluepad32_picow_app
pico_stdlib
pico_cyw43_arch_none
pico_btstack_classic
pico_btstack_cyw43
bluepad32
)

add_subdirectory(../../src/components/bluepad32 bluepad32_bin)
add_subdirectory(../../src/components/bluepad32 libbluepad32)

pico_enable_stdio_usb(Bluepad32_PicoW 1)
pico_enable_stdio_uart(Bluepad32_PicoW 0)
pico_enable_stdio_usb(bluepad32_picow_app 1)
pico_enable_stdio_uart(bluepad32_picow_app 0)

# create map/bin/hex/uf2 file in addition to ELF.
pico_add_extra_outputs(Bluepad32_PicoW)
pico_add_extra_outputs(bluepad32_picow_app)
2 changes: 1 addition & 1 deletion tools/pico/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ rm -rf build
mkdir build
cd build
cmake .. -DPICO_BOARD=pico_w
make -j4
make -j
36 changes: 33 additions & 3 deletions tools/pico/main.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,39 @@
/****************************************************************************
http://retro.moe/unijoysticle2
Copyright 2019 Ricardo Quesada
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
****************************************************************************/

#include <pico/stdlib.h>

#include "uni_main.h"

int main(int argc, const char* argv[]) {
int main()
{
stdio_init_all();

// initialize CYW43 driver architecture (will enable BT if/because CYW43_ENABLE_BLUETOOTH == 1)
if (cyw43_arch_init()) {
printf("failed to initialise cyw43_arch\n");
return -1;
}

cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);

// Initialize Bluepad32. Does not return.
uni_main(argc, argv);
// Does not return
uni_main(0, NULL);

return 0;
}
219 changes: 219 additions & 0 deletions tools/pico/my_platform.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
/****************************************************************************
http://retro.moe/unijoysticle2
Copyright 2023 Ricardo Quesada
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
****************************************************************************/

#include <stdio.h>
#include <string.h>

#include "sdkconfig.h"
#include "uni_bt.h"
#include "uni_gamepad.h"
#include "uni_hid_device.h"
#include "uni_log.h"
#include "uni_platform.h"

//
// Only used when CONFIG_BLUEPAD32_PLATFORM_CUSTOM is selected.
//

//
// Globals
//
static int g_delete_keys = 0;

// Custom-1 "instance"
typedef struct my_platform_instance_s {
uni_gamepad_seat_t gamepad_seat; // which "seat" is being used
} my_platform_instance_t;

// Declarations
static void trigger_event_on_gamepad(uni_hid_device_t* d);
static my_platform_instance_t* get_my_platform_instance(uni_hid_device_t* d);

//
// Platform Overrides
//
static void my_platform_init(int argc, const char** argv) {
ARG_UNUSED(argc);
ARG_UNUSED(argv);

logi("custom: init()\n");

#if 0
uni_gamepad_mappings_t mappings = GAMEPAD_DEFAULT_MAPPINGS;

// Inverted axis with inverted Y in RY.
mappings.axis_x = UNI_GAMEPAD_MAPPINGS_AXIS_RX;
mappings.axis_y = UNI_GAMEPAD_MAPPINGS_AXIS_RY;
mappings.axis_ry_inverted = true;
mappings.axis_rx = UNI_GAMEPAD_MAPPINGS_AXIS_X;
mappings.axis_ry = UNI_GAMEPAD_MAPPINGS_AXIS_Y;

// Invert A & B
mappings.button_a = UNI_GAMEPAD_MAPPINGS_BUTTON_B;
mappings.button_b = UNI_GAMEPAD_MAPPINGS_BUTTON_A;

uni_gamepad_set_mappings(&mappings);
#endif
}

static void my_platform_on_init_complete(void) {
logi("custom: on_init_complete()\n");
}

static void my_platform_on_device_connected(uni_hid_device_t* d) {
logi("custom: device connected: %p\n", d);
}

static void my_platform_on_device_disconnected(uni_hid_device_t* d) {
logi("custom: device disconnected: %p\n", d);
}

static uni_error_t my_platform_on_device_ready(uni_hid_device_t* d) {
logi("custom: device ready: %p\n", d);
my_platform_instance_t* ins = get_my_platform_instance(d);
ins->gamepad_seat = GAMEPAD_SEAT_A;

trigger_event_on_gamepad(d);
return UNI_ERROR_SUCCESS;
}

static void my_platform_on_controller_data(uni_hid_device_t* d, uni_controller_t* ctl) {
static uint8_t leds = 0;
static uint8_t enabled = true;
static uni_controller_t prev = {0};
uni_gamepad_t* gp;

if (memcmp(&prev, ctl, sizeof(*ctl)) == 0) {
return;
}
prev = *ctl;
// Print device Id before dumping gamepad.
logi("(%p) ", d);
uni_controller_dump(ctl);

switch (ctl->klass) {
case UNI_CONTROLLER_CLASS_GAMEPAD:
gp = &ctl->gamepad;

// Debugging
// Axis ry: control rumble
if ((gp->buttons & BUTTON_A) && d->report_parser.set_rumble != NULL) {
d->report_parser.set_rumble(d, 128, 128);
}
// Buttons: Control LEDs On/Off
if ((gp->buttons & BUTTON_B) && d->report_parser.set_player_leds != NULL) {
d->report_parser.set_player_leds(d, leds++ & 0x0f);
}
// Axis: control RGB color
if ((gp->buttons & BUTTON_X) && d->report_parser.set_lightbar_color != NULL) {
uint8_t r = (gp->axis_x * 256) / 512;
uint8_t g = (gp->axis_y * 256) / 512;
uint8_t b = (gp->axis_rx * 256) / 512;
d->report_parser.set_lightbar_color(d, r, g, b);
}

// Toggle Bluetooth connections
if ((gp->buttons & BUTTON_SHOULDER_L) && enabled) {
logi("*** Disabling Bluetooth connections\n");
uni_bt_enable_new_connections_safe(false);
enabled = false;
}
if ((gp->buttons & BUTTON_SHOULDER_R) && !enabled) {
logi("*** Enabling Bluetooth connections\n");
uni_bt_enable_new_connections_safe(true);
enabled = true;
}
break;
default:
break;
}
}

static int32_t my_platform_get_property(uni_platform_property_t key) {
logi("custom: get_property(): %d\n", key);
if (key != UNI_PLATFORM_PROPERTY_DELETE_STORED_KEYS)
return -1;
return g_delete_keys;
}

static void my_platform_on_oob_event(uni_platform_oob_event_t event, void* data) {
logi("custom: on_device_oob_event(): %d\n", event);

if (event != UNI_PLATFORM_OOB_GAMEPAD_SYSTEM_BUTTON) {
logi("my_platform_on_device_gamepad_event: unsupported event: 0x%04x\n", event);
return;
}

uni_hid_device_t* d = data;

if (d == NULL) {
loge("ERROR: my_platform_on_device_gamepad_event: Invalid NULL device\n");
return;
}

my_platform_instance_t* ins = get_my_platform_instance(d);
ins->gamepad_seat = ins->gamepad_seat == GAMEPAD_SEAT_A ? GAMEPAD_SEAT_B : GAMEPAD_SEAT_A;

trigger_event_on_gamepad(d);
}

//
// Helpers
//
static my_platform_instance_t* get_my_platform_instance(uni_hid_device_t* d) {
return (my_platform_instance_t*)&d->platform_data[0];
}

static void trigger_event_on_gamepad(uni_hid_device_t* d) {
my_platform_instance_t* ins = get_my_platform_instance(d);

if (d->report_parser.set_rumble != NULL) {
d->report_parser.set_rumble(d, 0x80 /* value */, 15 /* duration */);
}

if (d->report_parser.set_player_leds != NULL) {
d->report_parser.set_player_leds(d, ins->gamepad_seat);
}

if (d->report_parser.set_lightbar_color != NULL) {
uint8_t red = (ins->gamepad_seat & 0x01) ? 0xff : 0;
uint8_t green = (ins->gamepad_seat & 0x02) ? 0xff : 0;
uint8_t blue = (ins->gamepad_seat & 0x04) ? 0xff : 0;
d->report_parser.set_lightbar_color(d, red, green, blue);
}
}

//
// Entry Point
//
struct uni_platform* uni_platform_custom_create(void) {
static struct uni_platform plat = {
.name = "custom",
.init = my_platform_init,
.on_init_complete = my_platform_on_init_complete,
.on_device_connected = my_platform_on_device_connected,
.on_device_disconnected = my_platform_on_device_disconnected,
.on_device_ready = my_platform_on_device_ready,
.on_oob_event = my_platform_on_oob_event,
.on_controller_data = my_platform_on_controller_data,
.get_property = my_platform_get_property,
};

return &plat;
}

0 comments on commit 11b4f11

Please sign in to comment.