various improvements
This commit is contained in:
@@ -5,18 +5,18 @@ from dataclasses import dataclass
|
|||||||
# Define some base dataclasses to hold the relevant parameters
|
# Define some base dataclasses to hold the relevant parameters
|
||||||
@dataclass
|
@dataclass
|
||||||
class AuracastQoSConfig:
|
class AuracastQoSConfig:
|
||||||
iso_interval_us: int = 10000
|
iso_int_multiple_10ms: int = 1
|
||||||
number_of_retransmissions:int = 4
|
number_of_retransmissions:int = 4 #4
|
||||||
max_transport_latency_ms:int = 43 # TODO: varies from the default value in bumble (was 65)
|
max_transport_latency_ms:int = 43 #varies from the default value in bumble (was 65)
|
||||||
|
|
||||||
qos_config_mono_high_rel = AuracastQoSConfig() #highest rel + lowest latency
|
qos_config_mono_high_rel = AuracastQoSConfig() #highest rel + lowest latency
|
||||||
qos_config_mono_medium_rel = AuracastQoSConfig(
|
qos_config_mono_medium_rel = AuracastQoSConfig(
|
||||||
iso_interval_us = 10000,
|
iso_int_multiple_10ms = 2,
|
||||||
number_of_retransmissions = 3,
|
number_of_retransmissions = 3,
|
||||||
max_transport_latency_ms = 65
|
max_transport_latency_ms = 65
|
||||||
)
|
)
|
||||||
qos_config_mono_low_rel = AuracastQoSConfig( #highest latency
|
qos_config_mono_low_rel = AuracastQoSConfig( #highest latency
|
||||||
iso_interval_us = 10000,
|
iso_int_multiple_10ms = 3,
|
||||||
number_of_retransmissions = 2,
|
number_of_retransmissions = 2,
|
||||||
max_transport_latency_ms = 65
|
max_transport_latency_ms = 65
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ async def create_device(config: auracast_config.AuracastGlobalConfig) -> AsyncGe
|
|||||||
name=config.device_name,
|
name=config.device_name,
|
||||||
address=config.auracast_device_address,
|
address=config.auracast_device_address,
|
||||||
keystore='JsonKeyStore',
|
keystore='JsonKeyStore',
|
||||||
#le_simultaneous_enabled=True #TODO: needed ?
|
#le_simultaneous_enabled=True #TODO: What is this doing ?
|
||||||
)
|
)
|
||||||
|
|
||||||
device = bumble.device.Device.from_config_with_hci(
|
device = bumble.device.Device.from_config_with_hci(
|
||||||
@@ -141,7 +141,10 @@ async def run_broadcast(
|
|||||||
frames = list[bytes]()
|
frames = list[bytes]()
|
||||||
while pcm := wav.readframes(encoder.get_frame_samples()):
|
while pcm := wav.readframes(encoder.get_frame_samples()):
|
||||||
frames.append(
|
frames.append(
|
||||||
encoder.encode(pcm, num_bytes=global_config.octets_per_frame, bit_depth=wav.getsampwidth() * 8)
|
encoder.encode(
|
||||||
|
pcm,
|
||||||
|
num_bytes=global_config.octets_per_frame,
|
||||||
|
bit_depth=wav.getsampwidth() * 8)
|
||||||
)
|
)
|
||||||
del encoder
|
del encoder
|
||||||
logger.info('Encoding complete.')
|
logger.info('Encoding complete.')
|
||||||
@@ -220,17 +223,23 @@ async def run_broadcast(
|
|||||||
await bigs[f'big{i}']['advertising_set'].start_periodic()
|
await bigs[f'big{i}']['advertising_set'].start_periodic()
|
||||||
|
|
||||||
logging.info('Setup BIG')
|
logging.info('Setup BIG')
|
||||||
|
if global_config.qos_config.iso_int_multiple_10ms == 1:
|
||||||
|
frame_enable = 0
|
||||||
|
else:
|
||||||
|
frame_enable = 1
|
||||||
|
|
||||||
big = await device.create_big(
|
big = await device.create_big(
|
||||||
bigs[f'big{i}']['advertising_set'] ,
|
bigs[f'big{i}']['advertising_set'] ,
|
||||||
parameters=bumble.device.BigParameters(
|
parameters=bumble.device.BigParameters(
|
||||||
num_bis=1,
|
num_bis=1,
|
||||||
sdu_interval=global_config.qos_config.iso_interval_us,
|
sdu_interval=global_config.qos_config.iso_int_multiple_10ms*10000, # Is the same as iso interval
|
||||||
max_sdu=global_config.octets_per_frame, # is this octets per frame ?
|
max_sdu=global_config.octets_per_frame,
|
||||||
max_transport_latency=global_config.qos_config.max_transport_latency_ms,
|
max_transport_latency=global_config.qos_config.max_transport_latency_ms,
|
||||||
rtn=global_config.qos_config.number_of_retransmissions,
|
rtn=global_config.qos_config.number_of_retransmissions,
|
||||||
broadcast_code=(
|
broadcast_code=(
|
||||||
bytes.fromhex(conf.broadcast_code) if conf.broadcast_code else None
|
bytes.fromhex(conf.broadcast_code) if conf.broadcast_code else None
|
||||||
),
|
),
|
||||||
|
framing=frame_enable # needed if iso interval is not frame interval of codedc
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
bigs[f'big{i}']['big'] = big
|
bigs[f'big{i}']['big'] = big
|
||||||
@@ -261,8 +270,12 @@ async def run_broadcast(
|
|||||||
event_found = False
|
event_found = False
|
||||||
for big in bigs.values():
|
for big in bigs.values():
|
||||||
if big['big'].bis_links[0].handle == event_handle:
|
if big['big'].bis_links[0].handle == event_handle:
|
||||||
frame = next(big['frames_iterator'])
|
frame = b''
|
||||||
|
for _ in range(0, global_config.qos_config.iso_int_multiple_10ms):
|
||||||
|
# loop is nececarry if iso interval is not frame interval of codec
|
||||||
|
frame += next(big['frames_iterator'])
|
||||||
big['big'].bis_links[0].write(frame)
|
big['big'].bis_links[0].write(frame)
|
||||||
|
|
||||||
event_found = True
|
event_found = True
|
||||||
if not event_found:
|
if not event_found:
|
||||||
logging.warning('unknown event on packet complete with handle: %s', event_handle)
|
logging.warning('unknown event on packet complete with handle: %s', event_handle)
|
||||||
@@ -274,7 +287,7 @@ async def run_broadcast(
|
|||||||
|
|
||||||
# Send the first packet for each big, to get the event loop running
|
# Send the first packet for each big, to get the event loop running
|
||||||
for big in bigs.values():
|
for big in bigs.values():
|
||||||
frame = next(big['frames_iterator'] )
|
frame = next(big['frames_iterator'])
|
||||||
big['big'].bis_links[0].write(frame)
|
big['big'].bis_links[0].write(frame)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@@ -298,7 +311,7 @@ def broadcast(global_conf: auracast_config.AuracastGlobalConfig, big_conf: List[
|
|||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=logging.INFO,
|
level=logging.DEBUG,
|
||||||
format='%(module)s.py:%(lineno)d %(levelname)s: %(message)s'
|
format='%(module)s.py:%(lineno)d %(levelname)s: %(message)s'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -310,28 +323,37 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
#global_conf.transport='serial:/dev/serial/by-id/usb-SEGGER_J-Link_001057705357-if02,1000000,rtscts' # transport for nrf54l15dk
|
#global_conf.transport='serial:/dev/serial/by-id/usb-SEGGER_J-Link_001057705357-if02,1000000,rtscts' # transport for nrf54l15dk
|
||||||
|
|
||||||
global_conf.transport='serial:/dev/ttyACM1,115200,rtscts'
|
global_conf.transport='serial:/dev/serial/by-id/usb-ZEPHYR_Zephyr_HCI_UART_sample_81BD14B8D71B5662-if02,115200,rtscts' #nrf52dongle usb cdc uart
|
||||||
|
|
||||||
global_conf.qos_config = auracast_config.qos_config_mono_high_rel # TODO: low rel, actually advertising seems to work again- maybe then the problem is hci->controler
|
# TODO use nrf52dongle with hci over usb
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: How can we use other iso interval than 10ms ?(medium or low rel) ? - nrf53audio receiver repports I2S tx underrun
|
||||||
|
global_conf.qos_config = auracast_config.qos_config_mono_medium_rel
|
||||||
|
|
||||||
|
global_conf.qos_config = auracast_config.qos_config_mono_high_rel
|
||||||
|
|
||||||
bigs = [
|
bigs = [
|
||||||
auracast_config.broadcast_de,
|
auracast_config.broadcast_de,
|
||||||
auracast_config.broadcast_en,
|
auracast_config.broadcast_en,
|
||||||
auracast_config.broadcast_fr,
|
auracast_config.broadcast_fr,
|
||||||
auracast_config.broadcast_es, #TODO: spanish not appearing as auracast
|
auracast_config.broadcast_es,
|
||||||
# auracast_config.broadcast_it, #TODO: with more than three broadcasts, not advertising at all is present, regardless the adv. interval
|
# auracast_config.broadcast_it, #TODO: with more than three broadcasts, not advertising at all is present, regardless the adv. interval
|
||||||
]
|
] # TODO: more than three broadcasters lead to some buffer overflow on hci side- try to increase some buffer lengths
|
||||||
global_conf.auracast_sampling_rate_hz = 16000
|
global_conf.auracast_sampling_rate_hz = 16000
|
||||||
global_conf.octets_per_frame = 40 # 32kbps@16kHz
|
global_conf.octets_per_frame = 40 # 32kbps@16kHz
|
||||||
|
|
||||||
# Note: 24kHz is only working with 2 streams - so this may be a host->controller interface bottleneck
|
# Note: 24kHz is only working with 2 streams - so this may be a host->controller interface bottleneck - probably airtime constraint
|
||||||
|
# 16kHz works reliably with 3 streams
|
||||||
# use thread usage debugger on controller to check actual cpu load - not much load
|
# use thread usage debugger on controller to check actual cpu load - not much load
|
||||||
|
|
||||||
# TODO; I dont think hci is really the bottleneck. probably limited airtime is the problem. Analyze this somehow.
|
# TODO; I dont think hci is really the bottleneck. probably limited airtime is the problem. Analyze this somehow.
|
||||||
# Advertising is still 1Mbit phy - use 2Mbit
|
# Advertising is still 1Mbit phy - use 2Mbit
|
||||||
# Check is the sdu interval (iso interval?) may really be varied - does not seem to work really
|
# Check is the sdu interval (iso interval?) may really be varied - does not seem to work really
|
||||||
# # sdu per frame also needs to be adjusted somehow? is this even compatible with lc3?
|
# # sdu per frame also needs to be adjusted somehow? is this even compatible with lc3?
|
||||||
|
|
||||||
|
# TODO: analyze the airtime somehow!
|
||||||
|
|
||||||
broadcast(
|
broadcast(
|
||||||
global_conf,
|
global_conf,
|
||||||
bigs
|
bigs
|
||||||
|
|||||||
Reference in New Issue
Block a user