Skip to content

Conversation

@jaguilar
Copy link
Contributor

This pull request is just a heads up, so that y'all can tell me if I'm barking up the wrong tree. It's my intention to break these commits into separate requests as each parent commit gets approved. (I don't know if this is the style you all prefer to review code -- at work, we are told to make small, self-contained changes, and I intend to proceed in that mode unless told otherwise.)

I have a few questions about what I'm doing here:

  • In the uart block implementation, I am relying on the pbio uart interface rather than manipulating the uart directly as in the stm32 block. I felt this simplified the code quite a bit, and seems less error prone -- we've already written the uart manipulation code once, why write it again?
  • I noticed that the run loop for the existing btstack implementation polls data sources, but that seems unnecessary now that we have an easy-to-use RTOS. I was considering only copying the timer-handling portion of the runloop for the classic stack. Are y'all in agreement that that is the correct thing to do?
  • I have read the data sheets for the ti am1808 and the cc2560 as carefully as I know how, but I am not by training or experience an embedded programmer. Do the changes in platform.c look correct? I've tried to leave comments to explain why I'm doing what I'm doing.

I'll be on vacation from tomorrow to Monday, so I probably won't make any further progress until Tuesday next week.

@dlech
Copy link
Member

dlech commented Oct 23, 2025

at work, we are told to make small, self-contained changes

Keeping pull request under around 500 lines changed or so definitely makes them easier to review. 😄

  • I am relying on the pbio uart interface

You can thank Laurens for making it easy to use. So yes, use it, that is what it is there for.

  • I noticed that the run loop for the existing btstack implementation polls data sources,

Can you give an example of what you mean? We don't really have an RTOS, just cooperative multitasking using coroutines. Usually, the mechanism is that we receive an interrupt letting us know that data is ready. In the interrupt handler, we call a process poll function to let a "process" (just a coroutine) know that something change and that it should run to actually do something with the data that was received.

  • but I am not by training or experience an embedded programmer.

Could have fooled me. 😁

btstack may send us buffers longer than 256 bytes
to pass to the uart. It should be relatively low-cost
to increase the length of the read and write buffers
to accomodate this.
This commit creates a UART block implementation for btstack on the EV3.
This will allow us to communicate HCI commands from the btstack library
to the EV3's bluetooth module. The commit also contains necessary
changes to makefiles to allow compiling this module.
This adds the CTS and RTS pin definitions for UART2. It also configures
the "slow clock" input for the bluetooth module. Configures the BTnShutdn
gpio. Enables the ECAP functions in the PSC.
Adds the definitions for the platform data necessary
to hook btstack up to the ev3's bluetooth module.
@jaguilar jaguilar force-pushed the ev3-bluetooth-platform-data branch from ba10bc8 to f0565c5 Compare October 25, 2025 17:15
@coveralls
Copy link

coveralls commented Oct 25, 2025

Coverage Status

coverage: 59.78%. remained the same
when pulling cccb6ef on jaguilar:ev3-bluetooth-platform-data
into cff1933 on pybricks:master.

@jaguilar
Copy link
Contributor Author

at work, we are told to make small, self-contained changes

Keeping pull request under around 500 lines changed or so definitely makes them easier to review. 😄

So, for example, I was originally just posting this as an FYI, with the intention to eventually split it into 3 different requests. So what I'm wondering is whether this pull request already represents the right granularity, or if I should indeed go ahead and split it up. It sounds like you're saying this is already about the right granularity and we can just go forward with this. Anyway, going forward, if I send stuff that's hard for y'all to review please don't hesitate to correct me.

  • I noticed that the run loop for the existing btstack implementation polls data sources,

Can you give an example of what you mean? We don't really have an RTOS, just cooperative multitasking using coroutines. Usually, the mechanism is that we receive an interrupt letting us know that data is ready. In the interrupt handler, we call a process poll function to let a "process" (just a coroutine) know that something change and that it should run to actually do something with the data that was received.

I'm referring to this code. What it does is it adds a hook that the btstack run loop will poll to check if the DMA for the previous write is complete.

In this pull request, I instead do what you're describing e.g. in btstack_uart_block_ev3_receive_block, bypassing the data_source_handler mechanism in the btstack runloop. (And the interrupt to hear if the DMA is complete is handled by the pbio uart implementation, in the form of completing the child async op in do_write_process and do_read_process.)

  • but I am not by training or experience an embedded programmer.

Could have fooled me. 😁

Very kind of you to say.

- assert the result of pbdrv_uart_get_instance.
- Include stdbool.h.
- Remove some unnecessary locals in platform.c and add rounding.
@jaguilar
Copy link
Contributor Author

jaguilar commented Oct 25, 2025 via email

@dlech
Copy link
Member

dlech commented Oct 25, 2025

But I don’t know which pins are 51,78 and 87.

Oh, right. Yes, just do floor division by 16 to get the bank and the remainder is the pin. You can also verify on the schematic, e.g. PIC_EN is EMA_D11/GP3_3 on the schematic which matches bt-pic-en-hog with gpios = <51 ...> in the devicetree.

@dlech
Copy link
Member

dlech commented Oct 25, 2025

In this pull request, I instead do what you're describing e.g. in btstack_uart_block_ev3_receive_block, bypassing the data_source_handler mechanism in the btstack runloop. (And the interrupt to hear if the DMA is complete is handled by the pbio uart implementation, in the form of completing the child async op in do_write_process and do_read_process.)

If it works, then it sounds like a nice simplification. 👍

The new pins are copied from the old ev3dev sources.
These pins are responsible for enabling or disabling a
separate PIC microcontroller that is not needed for usual
bluetooth communication.
The PB_LIB_BTSTACK library has to be compiled
with different sources if it is being used to drive
a classic module vs. a dual or LE module.
Per PR feedback, adjust the PB_LIB_BTSTACK variable
to signal which state we are in, rather than using separate
PB_LIB_BTSTACK and PB_LIB_BTSTACK_CLASSIC variables.
@jaguilar jaguilar marked this pull request as ready for review October 26, 2025 22:36
@jaguilar
Copy link
Contributor Author

jaguilar commented Oct 26, 2025

In terms of verification, all I've done is upload this to my EV3 and ensure it can run "hello, world", which it can. And all the other bricks still build. In my next pull request I will install a classic-only run loop for btstack and ensure that we can do a basic hello-world operation with the bluetooth module.

Probably y'all will also want me to fix up the history a bit once the review is done. Let me know if that's desired.

@laurensvalk
Copy link
Member

Would it make sense to save this one for when we're closer to the end goal here? We can keep it open for now.

I'm not opposed to saving it until we're closer. That being said, the very next PR (the btstack uart block impl for ev3) uses this change.

I don't see a reason to delay the change.

I just returned from a short trip so probably I haven't followed this closely enough yet. We're very happy with contributions like this, so thanks for working on it!

Should I wait until I have something demonstrably working on an end-to-end basis before I send the pull requests for prerequisites?

Making submissions for feedback is fine, and some standalone changes like the UART size argument can be merged if they are tested independently. We may be a bit slower to merge driver code for something that might not get used, so here a demonstration would be great.

@jaguilar
Copy link
Contributor Author

We may be a bit slower to merge driver code for something that might not get used, so here a demonstration would be great.

Totally understandable. I feel I’m pretty close to having a working demo, so I will hold off on sending anything else until things are demonstrably working.

@laurensvalk
Copy link
Member

I feel I’m pretty close to having a working demo

This is awesome. If you'd asked me last year, I would never have imagined that the very first EV3 release might have anything Bluetooth related at all 😄

By the way, if you want some quick hooks from Python into C without learning all the API details just yet, you can modify experimental_hello_world as needed. It is used like this:

from pybricks.experimental import hello_world

result = hello_world(foo=5, bar="hi")

print("the square of foo is", result)

To add more functions, copy that function below and adjust as needed. Then add it to the table here.

@jaguilar
Copy link
Contributor Author

This is awesome. If you'd asked me last year, I would never have imagined that the very first EV3 release might have anything Bluetooth related at all 😄

Hah. Yeah, well, I'm to the point where if the code were all working correctly I would be able to get some basic local address info across the HCI interface all the way up to the Python layer. But, Pybricks is not starting up, so the code isn't all working.

So, it's time to do some printf debugging. We'll see where that gets us. Turns out I don't have a USB uart thingy, so I whipped one up with an ESP32 I had lying around. I'll try to hook it up and see what's being printed tonight.

@jaguilar
Copy link
Contributor Author

jaguilar commented Oct 29, 2025

Status report:

  • Fixed a bunch of busted things about the commits in this PR which will have to be separated out into clean deltas and added.
  • Got the debug uart stuff working and added a blocking mode to it because I was seeing some crashes and wanted to printf debug them without other stuff happening.
  • Where I'm currently stuck is that the stuff coming out of UART2 doesn't seem to make much sense to the btstack HCI subsystem. See log at the bottom of this comment.

What seems to be the problem is that UART2 is reporting buffers containing zero in response to pbdrv_uart_read. From what I can research online, this probably means the module isn't starting up properly or there's something wrong with the pin configuration or UART configuration. Could also be that the sequence for reading the UART's FIFO isn't being followed correctly w.r.t. flow control, I'll have to double check that as well.

Fortunately, the manual for the CC2560 has a detailed startup sequence and I guess I can use it to figure out if the thing is turned on properly. I'm going to try that tomorrow. Any helpful insights for further debugging would be welcome.

My janky UART->PC setup:

IMG_1565

Logfile:

SF: Detected n25q128a13 with page size 256 Bytes, erase size 4 KiB, total 16 MiB
device 0 offset 0x50000, size 0x100000
SF: 1048576 bytes @ 0x50000 Read: OK
Starting btstack classic ...
Starting btstack classic HCI...
btstack_chipset_cc256x.c.167: cc256x: using default init script
HCI process started.
Reset BT controller
hci.c.5055: hci_power_control: 0, current mode 0
hci.c.7436: BTSTACK_EVENT_STATE 0
HCI in packet type: 04, len: 3
Initialize BT controller
hci.c.5055: hci_power_control: 1, current mode 0
btstack_chipset_cc256x.c.167: cc256x: using default init script
UART CONFIG: baudrate=115200, flowcontrol=1, device_name=NULL, parity=0
Starting UART read/write processes
UART read 1 bytes started
hci.c.7436: BTSTACK_EVENT_STATE 1
HCI in packet type: 04, len: 3
hci.c.1777: hci_initializing_run: substate 0, can send 1
HCI out packet type: 01, len: 3
UART write 4 bytes started
UART write thread
UART write 4 bytes
UART read thread
UART read 1 bytes
UART read OK
UART write done
HCI in packet type: 04, len: 2
hci.c.1777: hci_initializing_run: substate 1, can send 0
hci_transport_h4.c.263: hci_transport_h4: invalid packet type 0x00
UART read 1 bytes started
UART read 1 bytes
UART read OK
hci_transport_h4.c.263: hci_transport_h4: invalid packet type 0x00
UART read 1 bytes started
UART read 1 bytes
UART read OK
hci_transport_h4.c.263: hci_transport_h4: invalid packet type 0x00
UART read 1 bytes started
UART read 1 bytes
UART read OK
hci.c.1718: Resend HCI Reset
hci.c.1777: hci_initializing_run: substate 0, can send 1
HCI out packet type: 01, len: 3
UART write 4 bytes started
UART write 4 bytes
hci_transport_h4.c.263: hci_transport_h4: invalid packet type 0x00
UART read 1 bytes started
UART read 1 bytes
UART read OK
UART write done
HCI in packet type: 04, len: 2
hci.c.1777: hci_initializing_run: substate 1, can send 0
hci_transport_h4.c.263: hci_transport_h4: invalid packet type 0x00
UART read 1 bytes started
UART read 1 bytes
UART read OK
hci_transport_h4.c.263: hci_transport_h4: invalid packet type 0x00
UART read 1 bytes started
UART read 1 bytes
UART read OK
hci_transport_h4.c.263: hci_transport_h4: invalid packet type 0x00
UART read 1 bytes started
UART read 1 bytes
UART read OK
hci_transport_h4.c.263: hci_transport_h4: invalid packet type 0x00
UART read 1 bytes started
UART read 1 bytes
UART read OK
hci_transport_h4.c.263: hci_transport_h4: invalid packet type 0x00
UART read 1 bytes started
UART read 1 bytes
UART read OK
hci.c.1718: Resend HCI Reset
hci.c.1777: hci_initializing_run: substate 0, can send 1
HCI out packet type: 01, len: 3
UART write 4 bytes started
UART write 4 bytes
UART write done
HCI in packet type: 04, len: 2
hci.c.1777: hci_initializing_run: substate 1, can send 0
hci_transport_h4.c.263: hci_transport_h4: invalid packet type 0x00
UART read 1 bytes started
UART read 1 bytes
UART read OK
...

@laurensvalk
Copy link
Member

To start simple, is there some kind of basic command we can send/receive to verify that UART is working at that the Bluetooth chip is up and running? Like some HCI command to read a vendor string. That might help test the basics before hooking it all up to btstack.

For additional debugging, we could expose this UART to the user code (just like the UARTs on S1 through S4 can be used) so you can poke at it from Python. Let me know if I should set this up.

My janky UART->PC setup:

If it works, it works! But if you want to buy this one, we would gladly refund the expense.

@jaguilar
Copy link
Contributor Author

Like some HCI command to read a vendor string. That might help test the basics before hooking it all up to btstack.

Yep, that's ultimately what I'm trying to get set up as my hello world demo for this pull request or the next one. The simplest HCI command is read_local_version_information, I think, and I have that command wired all the way through to Python. However, we don't even get that far. In the log, the problem is more fundamental. We are sending the initial HCI power-on packet, and we can't get back a single valid packet from the bluetooth module. I'm assuming that either I've configured some pin wrong, the UART is configured wrong, or the startup sequence is busted somehow.

If you look at the cc2560 manual, section 5.7.1.2, it seems there's a very specific order things need to happen. My next goal is to make sure things are happening in this order and ensure that the RTS wire is being pulled low before continuing with startup.

we would gladly refund the expense

Hah, thank you, but there's no need now that I have this thing working.

@jaguilar
Copy link
Contributor Author

Okay, actually, no worries. I've found the bts files that @dlech originally uploaded to the linux firmware git repo. I have also found the convert_bts_init_scripts.py file in the btstack library. I think I can bump these two things together until something good comes out.

@jaguilar jaguilar marked this pull request as draft October 30, 2025 02:30
It's useful to have a vprintf version of
the uart_debug functions. This will be used
in a later change to assist with logging
messages originating in BTStack.

Also, there was a bug where the error from
writing to the UART was not captured. This
fixes that bug and logs the error on
the next attempt to use the port.
@jaguilar
Copy link
Contributor Author

hci.c.1777: hci_initializing_run: substate 40, can send 0
HCI in packet type: 04, len: 6
HCI in packet type: 04, len: 4
hci.c.2226: Command complete for expected opcode 0c1a at substate 40
hci.c.1777: hci_initializing_run: substate 40, can send 1
hci.c.1770: hci_init_done -> HCI_STATE_WORKING
hci.c.7436: BTSTACK_EVENT_STATE 2
HCI in packet type: 04, len: 3
BT controller initialized. Awaiting shutdown.

Cleared the final bug to get the HCI interface up and running. The baudrate was too high!

During debugging, found a bunch of errors with the EV3 UART block impl.

- `block_received` and `block_sent` are written before open, therefore,
  we have to set them in init, not in open.
- Read thread passed wrong state to pbdrv_uart_read.
- Safer shutdown sequence.
@jaguilar jaguilar force-pushed the ev3-bluetooth-platform-data branch from f7fde9e to fac4394 Compare October 30, 2025 06:03
The EV3 was released with two different revisions of the CC2560
bluetooth module. Therefore we cannot rely on a statically compiled
bluetooth init script. We include both init scripts in the firmware
to be selected dynamically at module startup time.
The classic runloop is separated from the LE one because little code
will be shared between them. For now, it's just a skeleton.
@jaguilar jaguilar force-pushed the ev3-bluetooth-platform-data branch from fac4394 to 98c13bf Compare October 30, 2025 06:07
@laurensvalk
Copy link
Member

laurensvalk commented Oct 30, 2025

I'm kicking myself for not remembering this sooner, but once upon a time we tried running Pybricks on ev3rt, with this library. We ended up not using it for various reasons but it is still a useful inspiration for some driver configurations. Notably, it uses BTstack. Some pointers include:

A note of caution with this code base: Just because something is there, doesn't mean it is used/included/built. There are two different versions of run_loop_toppers.c in totally different places, for example. It looks like there are also two versions of the SPP code.

That said, it did work. So another insightful approach could be to build it and see what the UART is sending and reporting, to verify your own work.


Also, please see this article. There are different EV3 brick versions containing different Bluetooth chips. @dlech probably remembers this better, but I thought the EV3 brick hardware version was still the same, so maybe we can determine the variant based on what the chip is saying.


EDIT: I hadn't seen your latest replies when I wrote this. Looks like you have found some resources already. Nice work!

@laurensvalk
Copy link
Member

laurensvalk commented Oct 30, 2025

Possibly worth spinning off to a separate discussion... But there are some chips CC2560 chips out there that can run CC2564 firmware, which is BLE enabled. Now there's a challenge for @dlech 😄 Looks like we have a different PAN version though. But to try it, I guess we could just use the 2564 bts file?

This happened with the Pebble smartwatch:

The Bluetooth chips TI sent to Panasonic were labeled CC2560 but have been flashed with the firmware (and BT LE support) of a CC2564. That's why the module was labeled PAN1316.

Many chip vendors make silicon consistent between product lines but simply flash different firmware to enable features. Our chips were labeled CC2560 because TI asked us if we wouldn't mind using them with CC2564 firmware to speed up our order. Pebble most definitely has Bluetooth LE support, though it has not yet been enabled in our operating system.

@jaguilar
Copy link
Contributor Author

so maybe we can determine the variant based on what the chip is saying.

Yep, this is implemented in the code as it stands. Have a gander at bluetooth_btstack_classic.cc around where we test if lmp_subversion == 0.

inspiration for some driver configurations

That's very helpful! I will read the rfcomm and spp code especially. Now that we have communication with the chip up getting things working should be much simpler, but it's always nice to have a well let trail.

@jaguilar
Copy link
Contributor Author

But to try it, I guess we could just use the 2564 bts file?

FWIW, my 2560 could not load the firmware for the 2560a. At least, BTStack choked on it. Maybe there was a way to bypass the btstack objection, but I didn't look further, since I only really care about EV3<->EV3 communication at the moment.

@laurensvalk
Copy link
Member

laurensvalk commented Oct 30, 2025

my 2560 could not load the firmware for the 2560a.

To clarify, EV3 variants with 2560 and 2560a both exist and would eventually need to be tested and supported. We can start with the one you have, and we can dust off our collection to find and test the other one.

(It is the 2564 hack I was curious about, but this can be saved for another time. If at all, it would only work on the 2560a, as per the reference above. It is probably confusing to have different end-user experiences anyway, so we will probably not do this even if it worked.)

@dlech
Copy link
Member

dlech commented Oct 30, 2025

The two version of the chip in EV3 are CC2560 and CC2560A. Only the later is Bluetooth 4.0. And the "firmware" files are really only patch files, not full firmware - that is why the chips have a "ROM version". I have only seen BLE enabled firmware for CC2560B and CC2560C, so I still have some doubts that it could work on CC2560A because of that.

Reference: https://git.ti.com/cgit/ti-bt/service-packs/about/

@jaguilar
Copy link
Contributor Author

jaguilar commented Nov 5, 2025

Status update:

Demo code:

from pybricks.hubs import EV3Brick
from pybricks.tools import run_task

print("Hello, World!")

brick = EV3Brick()
print("EV3Brick fields: ", dir(brick))
print("Brick.btc fields: ", dir(brick.btc))
print("Scan function: ", dir(brick.btc.scan))


async def scan():
    print("Start bluetooth scan...")
    devices = await brick.btc.scan()
    print("Scan complete, devices found: ")
    for device in devices:
        print(device)


run_task(scan())
(pybricksdev-py3.12) jaguilar@DESKTOP-2GF79BV:~/projects/pybricksdev$ pybricksdev run usb demo/hello_bluetooth_classic.py 
100%|██████████████████████████████████████| 420/420 [00:00<00:00, 922kB/s]
Hello, World!
EV3Brick fields:  ['battery', 'btc', 'buttons', 'light', 'screen', 'speaker', 'system']
Brick.btc fields:  ['__del__', 'scan', 'version']
Scan function:  []
Start bluetooth scan...
Scan complete, devices found: 
{'rssi': -36, 'class_of_device': 7995916, 'name': '', 'address': 'e6:54:41:50:81:ec'}

This is just my iphone in discoverable mode. I don't really know what's up with the CoD here -- it seems wrong. And the name field should be populated unless I'm missing something. More work and debugging to do, but we are making progress.

Question: at what feature-point should this pull request be wrapped and polished? I was thinking that of implementing btc.connect(bdaddr), btc.accept(bdaddr), which would return something like RFCOMMStream. The streams themselves would have async read, write, and close methods, along with __aenter__ and __aexit__. I think the PR would already be pretty huge at that point, so it would be a good stopping point. After that I could implement the mailbox protocol in Python in terms of these primitives.

If at any point there is an error in the UART layer, we can't continue
using the connection. For now, just return the error. In the future, we
need to reset the bluetooth module if this happens.
The classic driver now has a single packet handler that deals with
all events from the module. We also implement a scan API.

As of this commit, there still appear to be some bugs with the scan
correctly picking up the name of the scanned devices.
The bluetooth classic object currently only supports scanning for
devices. A future commit will add RFCOMM connection support.
Copy link
Member

@dlech dlech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made 2 inline comments of some things I think we should do first. (And of course, we need to rebase this to fix the merge conflicts.)

Then I would be OK with merging this with just one basic function to read e.g. the version info from the chip so we can see that it is working.

Figuring out what we will want the actual Python API to be will take some thought, but ideally it would be (mostly) compatible with https://pybricks.com/ev3-micropython/messaging.html. That can be a discussion for another day.

And we will need to figure out a user interface for the EV3 so that we can do things like turn Bluetooth on and off. (That is being discussed elsewhere.)

Copy link
Member

@dlech dlech Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file name should not have x in it. It won't work with CC2560A. We will need a 2nd init script for that one based on TIInit_6.6.15.bts. And we will have to find a way to read info from the chip to pick the right one at runtime.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will work with the CC2560A, scroll down to cc2560a_init_script and cc2560a_init_script_size. pbdrv_bluetooth_get_init_script selects the correct init script given the lmp subversion.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah-ha! I missed that detail.

typedef struct _hubs_EV3Brick_obj_t {
mp_obj_base_t base;
mp_obj_t battery;
#if PYBRICKS_PY_COMMON_BTC
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not put this in EV3Brick yet until we figure out what the actual API is going to be. Instead, let's just use pybricks.experimental with just functions, no objects yet, for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

@jaguilar
Copy link
Contributor Author

jaguilar commented Nov 5, 2025

Figuring out what we will want the actual Python API to be will take some thought, but ideally it would be (mostly) compatible with https://pybricks.com/ev3-micropython/messaging.html. That can be a discussion for another day.

Sure. My thinking was that we could implement in C only what is needed to make the RFCOMM connections, and then in Python it would be pretty trivial to implement the mailbox API on top of the lower level RFCOMM API.

And we will need to figure out a user interface for the EV3 so that we can do things like turn Bluetooth on and off. (That is being discussed elsewhere.)

Where is elsewhere? I don't necessarily desire to have a say, but I'd like to know what is being discussed so that I can make sure not to design a huge problem into the API I'm working on.

@dlech
Copy link
Member

dlech commented Nov 5, 2025

Where is elsewhere?

EV3 UI design/planning: pybricks/support#2360

@laurensvalk
Copy link
Member

laurensvalk commented Nov 7, 2025

And we will need to figure out a user interface for the EV3 so that we can do things like turn Bluetooth on and off. (That is being discussed elsewhere.)

Where is elsewhere? I don't necessarily desire to have a say, but I'd like to know what is being discussed so that I can make sure not to design a huge problem into the API I'm working on.

Wherever it makes sense, we often start making it available through Python code. This usually helps us figure out what the best way is to split between user code and system code.

So I wouldn't worry about future UIs for now. Code isn't all that rigid as it might seem, and we tend to refactor things over time (we really do tend to get to those //TODO and //FIXME sticking points, even if that is a few years later 😄)

But I appreciate that some guidance would help. Will try and brainstorm some suggestions for APIs.

@laurensvalk
Copy link
Member

laurensvalk commented Nov 8, 2025

I've been thinking about APIs a bit. I was typing a message here, but we can probably discuss it in pybricks/support#2274 (comment) instead and keep this PR more about the initial proof of concept of RFCOMM. Feedback and ideas welcome!

I think the API proposed there could also be the backbone of the old Mailbox API, which we could implement as a Python wrapper.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants