Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bluetooth support (feature request, not an issue) #1

Open
amitv87 opened this issue Feb 16, 2023 · 3 comments
Open

Bluetooth support (feature request, not an issue) #1

amitv87 opened this issue Feb 16, 2023 · 3 comments

Comments

@amitv87
Copy link

amitv87 commented Feb 16, 2023

Hi, thanks for writing this elegant and minimal wifi driver in the first place.

Recently, bluetooth support was added in pico-sdk with relevant firmwares.
I tried the new wifi firmware with your driver, and it worked without any hassle. There's a patchram code that needs to be applied that enables an HCI transport layer over the same physical spi transport in a shared manner.

As I am very new to brcm/cyw devices, can you help implement a minimal HCI layer similar to the existing SDPCM layer?

@jbentham
Copy link
Owner

jbentham commented Feb 16, 2023 via email

@paulhamsh
Copy link

paulhamsh commented Dec 6, 2023

Hi
To @amitv87 there is good support for bluetooth in C/C++ and Micropython now - so is your request still needed?

@jbentham this is a very interesting project and your webpage on it is amazing! I have read it over and over to get an understanding of the SPI interface.

I am trying to write a basic bluetooth stack in Micropython for the Pico Pi W - just for my own interest. I can use the HCI layer provided by the Pico drivers, but also wanted to understand how this chip works - or at least how the Pico W talks to it.

So, now I'm writing a SPI bit-banging interface in Micropython, at the moment just to try and read the FEEDBEAD response - and it 'nearly' works but seems to by 4 bits out and I have no idea on mapping the command with the little-endian big-endian swapping.

I'm wondering if you could point me in the right direction for where I might be going wrong.
I can share the code, but this is what I am seeing.
I send 0x0A000400 (no idea why that works - I think I should be sending 0x4000A004 or some endian mangled version of that). And this is the response. It seems to be 4 bits out - but no idea how that could happen!
I guess the extra returned information is the 32 bit status, even though I think I am asking for 4 bytes only.
(I have no access to anything but the datasheet (which isn't too helpful) and the code I can find on github)

Even copies of your own bit-banging code would help - there are some bits not in your webpage or on here, I think.

0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0  0x0A000400

0 0 0 0 1 0 1 1 1 1 1 0 1 0 1 0 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 0  0x0BEADFEE
1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0xD0000000
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0x00400000
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0x00000000
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0x00000000
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0x00000000
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0x00000000
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0x00000000
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0x00000000
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  0x00000000
from machine import Pin
import time

cs = Pin(25, Pin.OUT)
clk = Pin(29, Pin.OUT)
pwr = Pin(23, Pin.OUT)

TIMING_DELAY = 1

def make_cmd(wr, inc, fn, addr, size):
    return (wr << 31) | (inc << 30) | (fn << 28) | ((addr & 0x1ffff) << 11) | (size & 0x3ff)

def swap_bytes(dat):
    return ((dat & 0xff000000) >> 8) | ((dat & 0xff0000) << 8) | ((dat & 0xff00) >>8) | ((dat & 0xff) << 8)

def write_cyw(dat):
    shift = 31
    data_pin = Pin(24, Pin.OUT)
    s = ""
    while shift >= 0:
        bit = (dat >> shift) & 1
        s = s + '{0:01b} '.format(bit)
        data_pin.value(bit)
        time.sleep_us(TIMING_DELAY)
        clk.value(1)
        time.sleep_us(TIMING_DELAY)
        clk.value(0)
        shift -= 1
    return s
    
def read_cyw():
    dat = 0
    shift = 31
    data_pin = Pin(24, Pin.IN)
    s = ""
    while shift >= 0:
        bit = data_pin.value()
        time.sleep_us(TIMING_DELAY)
        clk.value(1)
        time.sleep_us(TIMING_DELAY)
        dat += (bit << shift)
        s = s + '{0:01b} '.format(bit)
        clk.value(0)
        shift -= 1
    return dat, s

def init():
    clk.value(0)
    data_pin=Pin(24, Pin.OUT)
    data_pin.value(0)
    time.sleep_us(TIMING_DELAY)
    pwr.value(0)
    time.sleep_ms(20)
    pwr.value(1)
    time.sleep_ms(250)

def deinit():
    pwr.value(0)


init()

#cmd = make_cmd(0, 1, 0, 0x14, 4)
#swap_cmd = swap_bytes(cmd)

times = 1

while times > 0:
    cs.value(0)

    time.sleep_ms(10)
    times -= 1

    cmd = 0x0A000400
    s = write_cyw(cmd)    
    print(s, '0x{0:08X}'.format(cmd))

    v=[]
    s=[]
    #time.sleep_ms(0)
    print()
    for i in range(0, 10):
        val, st = read_cyw()
        v.append(val)
        s.append(st)

    for i in range(0, 10):
        print(s[i], '0x{0:08X}'.format(v[i]))
    print()
    time.sleep_ms(250)

    cs.value(1)
    
deinit()

@paulhamsh
Copy link

I discovered what was happening - this is why most code tries to read FEEDBEAD more than once - it seems the first write to the chip wants 4 extra bits at the start, which made my reads 4 bits shifted. If you make the first write 32+4 bits long, with the first 4 bits beings 0s, then it works fine - and subsequent write/reads are fine as well.
I still don't understand the high speed SPI mode or the description in the product specification.

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

No branches or pull requests

3 participants