Project

General

Profile

Actions

Feature #4396

closed

Circuit Switched Data (CSD) Support in osmocom-bb

Added by laforge about 4 years ago. Updated 2 months ago.

Status:
Resolved
Priority:
Normal
Assignee:
Category:
-
Target version:
-
Start date:
02/13/2020
Due date:
% Done:

100%

Resolution:
Spec Reference:
Tags:
CSD

Description

This would primarily entail:
  • permitting the related bearer types on the 04.08 CC side
  • configuring the DSP correctly to perform the 45.003 interleaving / coding for the respective bearer type
  • implementing the various rate adaptation functions to get to the individual sync/async characters. AFAIR there even was a hardware accelerator (maybe that was only MTK, not TI?). In any case, we want a software implementation on the host PC side, we don't care about an efficient implementation on the baseband chip.

Test/development could be done against Racal 6103, which supports both data + fax calls


Files

csd_v110_20231007_transp.dat csd_v110_20231007_transp.dat 46.4 KB fixeria, 11/07/2023 03:45 PM
csd_v110_20231007_rlp.dat csd_v110_20231007_rlp.dat 39.6 KB fixeria, 11/07/2023 03:45 PM

Checklist

  • CSD support in layer23
  • CSD support in the firmware
  • CSD support in trxcon
  • mobile: add VTY commands for configuring the Bearer Capability
  • mobile: support MO data calls
  • mobile: support MT data calls
  • mobile: expose the user plane
  • firmware: TCH/F2.4 support
  • libosmocore: complete Harald's soft-UART
  • libosmoisdn: complate Harald's V.110 FSM
  • mobile: support saving data call params to mobile.cfg
  • mobile: make async call params (parity, start/stop bits) configurable
  • wiki: document CSD support in osmocom-bb

Related issues

Related to OsmoBTS - Feature #1572: Circuit Switched Data (CSD) Support in osmo-btsResolvedfixeria02/23/2016

Actions
Related to OsmocomBB - Bug #6216: mobile: MT calls not working anymoreResolvedfixeria10/10/2023

Actions
Related to OsmocomBB - Feature #6346: mobile: support data calls @ 14400 bps (TCH/F14.4)New01/27/2024

Actions
Related to OsmocomBB - Feature #6347: mobile: support data calls @ 300 bps and 1200/75 bps (TCH/[FH]2.4)New01/27/2024

Actions
Related to OsmocomBB - Feature #6348: virtphy: add Circuit Switched Data (CSD) supportNew01/27/2024

Actions
Actions #1

Updated by laforge about 4 years ago

  • Tags set to CSD
Actions #2

Updated by laforge about 4 years ago

  • Related to Feature #1572: Circuit Switched Data (CSD) Support in osmo-bts added
Actions #3

Updated by fixeria over 3 years ago

configuring the DSP correctly to perform the 45.003 interleaving / coding for the respective bearer type

JFYI, here is an extract from include/calypso/l1_environment.h:

/* Channel mode definitions for DEDICATED mode */
#define SIG_ONLY_MODE      0    // signalling only
#define TCH_FS_MODE        1    // speech full rate
#define TCH_HS_MODE        2    // speech half rate
#define TCH_96_MODE        3    // data 9,6 kb/s
#define TCH_48F_MODE       4    // data 4,8 kb/s full rate
#define TCH_48H_MODE       5    // data 4,8 kb/s half rate
#define TCH_24F_MODE       6    // data 2,4 kb/s full rate
#define TCH_24H_MODE       7    // data 2,4 kb/s half rate
#define TCH_EFR_MODE       8    // enhanced full rate
#define TCH_144_MODE       9    // data 14,4 kb/s half rate
Actions #4

Updated by laforge over 1 year ago

  • Subject changed from Circuit Switched Data (CSD) Support to Circuit Switched Data (CSD) Support in osmocom-bb
Actions #5

Updated by laforge about 1 year ago

  • Priority changed from Low to Normal
Actions #7

Updated by fixeria 10 months ago

  • Checklist item CSD support in layer23 added
  • Checklist item CSD support in the firmware added
  • Checklist item CSD support in virtphy added
  • Checklist item CSD support in trxcon added
  • Status changed from New to In Progress
  • Assignee set to fixeria

I need CSD support in trxcon for testing the BTS side implementation #1572 in ttcn3-bts-test, so I'll be working on this part.

Actions #8

Updated by fixeria 10 months ago

remote: https://gerrit.osmocom.org/c/osmocom-bb/+/32916 trxcon/l1sched: remove redundant TCH/[FH] prim length checks [NEW]
remote: https://gerrit.osmocom.org/c/osmocom-bb/+/32917 trxcon/l1sched: drop Tx prims for not supported TCH modes [NEW]
remote: https://gerrit.osmocom.org/c/osmocom-bb/+/32918 trxcon/l1sched: cosmetic: get rid of amr_is_cmr/fn_is_cmi [NEW]
remote: https://gerrit.osmocom.org/c/osmocom-bb/+/32919 trxcon/l1sched: use sched_tchh_dl_facch_map[] in rx_tchh_fn() [NEW]
remote: https://gerrit.osmocom.org/c/osmocom-bb/+/32920 trxcon/l1sched: use variable names like in osmo-bts-trx [NEW]
remote: https://gerrit.osmocom.org/c/osmocom-bb/+/32921 trxcon/l1sched: rework burst buffer shifting for TCH/[FH] [NEW]
remote: https://gerrit.osmocom.org/c/osmocom-bb/+/32922 trxcon/l1sched: implement CSD scheduling support [WIP]

Actions #9

Updated by fixeria 10 months ago

  • Status changed from In Progress to Stalled
Actions #10

Updated by fixeria 9 months ago

  • Status changed from Stalled to In Progress
Actions #11

Updated by fixeria 9 months ago

  • Checklist item CSD support in trxcon set to Done
  • Status changed from In Progress to Feedback
  • % Done changed from 0 to 30

Implementing CSD support for trxcon required some refactoring, mostly bringing its l1sched closer to the state of osmo-bts-trx:

https://gerrit.osmocom.org/c/osmocom-bb/+/33708 trxcon/l1sched: rework dequeueing of Tx prims
https://gerrit.osmocom.org/c/osmocom-bb/+/33709 trxcon/l1sched: peoperly prioritize FACCH/H over TCH
https://gerrit.osmocom.org/c/osmocom-bb/+/33710 trxcon/l1sched: simplify and unify prim_dequeue_tchf()
https://gerrit.osmocom.org/c/osmocom-bb/+/33711 trxcon/l1sched: do not craft artificial BFI frames on TCH
https://gerrit.osmocom.org/c/osmocom-bb/+/33712 trxcon/l1sched: transmit dummy speech blocks with inverted CRC3

I also noticed a regression introduced by https://gerrit.osmocom.org/c/osmocom-bb/+/32916 and fixed it:

https://gerrit.osmocom.org/c/osmocom-bb/+/33706 trxcon/l1sched: fix handling of UL FACCH on TCH/A[FH]S
https://gerrit.osmocom.org/c/osmocom-bb/+/33707 trxcon/l1sched: remove unused vars in l1sched_lchan_amr_prim_is_valid()

There is one additional change that changes the logic of sending DATA.cnf, but simplifies everything a lot:

https://gerrit.osmocom.org/c/osmocom-bb/+/33749 trxcon/l1sched: emit DATA.cnf early (on bid=0)

Finally, here is a patch implementing CSD specific channel coding (including FACCH support):

https://gerrit.osmocom.org/c/osmocom-bb/+/32922 trxcon/l1sched: implement CSD scheduling support

Actions #12

Updated by fixeria 7 months ago

  • Status changed from Feedback to New
  • Assignee deleted (fixeria)
Actions #13

Updated by laforge 7 months ago

  • Status changed from New to Stalled
  • Assignee set to fixeria
Actions #14

Updated by fixeria 6 months ago

  • Status changed from Stalled to In Progress

As discussed with Harald, I will be working on adding CSD support to the firmware, so that a Calypso based phone can be used to make data calls.
This also includes adding CSD support to the upper layers (layer23) and exposing the user plane via some interface.

Actions #15

Updated by fixeria 6 months ago

  • Related to Bug #6216: mobile: MT calls not working anymore added
Actions #16

Updated by fixeria 5 months ago

  • Checklist item CSD support in the firmware set to Done
  • % Done changed from 30 to 60

Here is a patch adding CSD support to the firmware:

https://gerrit.osmocom.org/c/osmocom-bb/+/34694 firmware/layer1: handle CSD related channel modes [NEW]

plus several improvements to the TCH scheduling:

https://gerrit.osmocom.org/c/osmocom-bb/+/34751 firmware/layer1: mute UL/DL vocodec if it's not needed [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/34752 firmware/layer1: clean up l1s_tch_cmd(): reduce nesting [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/34753 firmware/layer1: clean up l1s_tch_resp() [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/34754 firmware/layer1: fix l1s_tch_resp(): use the right A_DD header [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/34755 firmware/layer1: fill-in DL info for L1CTL TRAFFIC.ind [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/34756 firmware/layer1: emit TRAFFIC.ind even if B_BFI is set [NEW]

I also extended the MNCCMS logic and added a VTY command for making data calls:

https://gerrit.osmocom.org/c/osmocom-bb/+/34758 mobile: mncc_recv_internal(): make struct gsm_mncc ptr const [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/34759 mobile: mncc_call(): make *number argument const [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/34760 mobile: separate 'call MS_NAME NUMBER' command [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/34761 mobile: clean up call related VTY commands [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/34762 mobile: add support for Circuit Switched Data calls [NEW]

Here is a fix for currently broken TCH loopback mode:

https://gerrit.osmocom.org/c/osmocom-bb/+/34757 mobile: fix AUDIO_IOH_LOOPBACK mode: pull DL info header [NEW]

With this patchset applied and the TCH loopback mode enabled, I can make transparent data calls to Sony Ericsson K200i and getting everything I type echoed back.

  +----------+   HELLO    +---------+    HELLO   +-------------+            +----------------+
  |          | ---------> |         | ---------> |             | ---------> |                | -------+
  | SE K200i |     Um     |   BTS   |     Um     | Calypso DSP |    L1CTL   | layer23/mobile |        | TCH loopback
  |          | <--------- |         | <--------- |             | <--------- |                | <------+
  +----------+   HELLO    +---------+    HELLO   +-------------+            +----------------+
Actions #17

Updated by fixeria 5 months ago

  • Checklist item mobile: add VTY commands for configuring the Bearer Capability added
  • Checklist item mobile: support MO data calls added
  • Checklist item mobile: support MT data calls added
  • Checklist item mobile: expose the user plane added
  • Checklist item firmware: TCH/F2.4 support added

fixeria wrote in #note-16:

With this patchset applied and the TCH loopback mode enabled, I can make transparent data calls to Sony Ericsson K200i and getting everything I type echoed back.

So far I tested only full-rate channels, and confirmed both TCH/F9.6 and TCH/F4.8 to work (loopback worked).
TCH/F2.4 didn't work for me, so it's still to be investigated why. I need to do more tests.

Actions #18

Updated by fixeria 5 months ago

  • Checklist item mobile: add VTY commands for configuring the Bearer Capability set to Done
  • Checklist item mobile: support MT data calls set to Done
  • % Done changed from 60 to 70

All patches except this one:

https://gerrit.osmocom.org/c/osmocom-bb/+/34762 mobile: add support for Circuit Switched Data calls

have been merged. Meanwhile, I reworked this only remaining patch to support MT calls and added VTY commands for configuring the Bearer Capability.

I am now shifting my focus towards the user plane interface. As was discussed with laforge and jolly, we have several options here:

  • a UNIX domain socket - quick and dirty solution (I will likely implement it first for early development and testing);
  • interfacing with a physical serial port connected to the machine running osmocom-bb/mobile;
  • emulating a virtual serial device using the CUSE (Character devices in user space): https://lwn.net/Articles/308445/
    • jolly has a project making use of this API, but IIRC he said that using it requires using threads?
Actions #19

Updated by laforge 5 months ago

Hi Vadim,

On Fri, Oct 20, 2023 at 01:54:53PM +0000, wrote:

  • a UNIX domain socket - quick and dirty solution (I will likely implement it first for early development and testing);
  • interfacing with a physical serial port connected to the machine running osmocom-bb/mobile;

ack. Either of those two is sufficient to complete this issue/task.

  • emulating a virtual serial device using the CUSE (Character devices in user space): https://lwn.net/Articles/308445/
    • jolly has a project making use of this API, but IIRC he said that using it requires using threads?

This CUSE based approach is a nice project, but not to be implemented here. It is also needed by soft-modems and the like in the retronetworking projects I'm working on with @manawrym. The best approach is probably to move some general "CUSE driver side implementation" into libosmo* and then use it for various projects.

However, this is out of the scope of this current project/task here, we do not have funding for that within
this project.

Actions #20

Updated by fixeria 5 months ago

Harald pointed me out to his libosmocore branch implementing the soft-UART:

https://cgit.osmocom.org/libosmocore/log/?h=laforge/libosmoisdn

I am currently working on integrating soft-UART into the mobile app. The goal is to get async characters from the other phone/modem decoded and printed.
The progress was slowed down by #6247 (problems with USRP B210), but in the end I managed to do some testing and recorded two dumps containing TRAFFIC.ind received from the PHY:

  • csd_v110_20231007_transp.dat - transparent data call, TCH/F9.6, 8-N-1;
  • csd_v110_20231007_rlp.dat - non-transparent data call, TCH/F9.6, RLP.

Each record in these files is 33 bytes long - this is what the layer1 firmware emits in L1CTL TRAFFIC.ind.

Non-transparent data call, TCH/F9.6, RLP

Luckily for us, SE K200i (the other phone I am using as a reference implementation) emits RLP frames with an easily recognizable sequence of characters in padding.

>>> f = open('csd_v110_20231007_rlp.dat', 'rb')
>>> while True:
...     data = f.read(33)
...     if data == b'':
...             break
...     print(data)
... 
b'\x05\xf1DCFEHGJILKNMPORQTSVUXWZY\xcd[Fa\x00\x00\x00'
b'\x05\xf1DCFEHGJILKNMPORQTSVUXWZY\xcd[Fa\x00\x00\x00'
b'\x05\xf1DCFEHGJILKNMPORQTSVUXWZY\xcd[Fa\x00\x00\x00'
b'\x05\xf1DCFEHGJILKNMPORQTSVUXWZY\xcd[Fa\x00\x00\x00'
b'\x05\xf1DCFEHGJILKNMPORQTSVUXWZY\xcd[Fa\x00\x00\x00'
b'\x05\xf1DCFEHGJILKNMPORQTSVUXWZY\xcd[Fa\x00\x00\x00'
b'\x05\xf1DCFEHGJILKNMPORQTSVUXWZY\xcd[Fa\x00\x00\x00'
b'\x05\xf1DCFEHGJILKNMPORQTSVUXWZY\xcd[Fa\x00\x00\x00'

As can be seen, bytes are swapped in words. With a small correction I am getting better looking results:

>>> f = open('csd_v110_20231007_rlp.dat', 'rb')
>>> while True:
...     data = f.read(33)
...     if data == b'':
...             break
...     data = bytearray(data[:-3]) # strip 3 dummy tail bytes
...     data[0::2], data[1::2] = data[1::2], data[0::2] # swap bytes in words
...     print(data)
... 
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')
bytearray(b'\xf1\x05CDEFGHIJKLMNOPQRSTUVWXYZ[\xcdaF')

This matches what I see in wireshark (using a hack https://gerrit.osmocom.org/c/osmo-bts/+/34014).

Actions #21

Updated by fixeria 5 months ago

Transparent data call, TCH/F9.6, 8-N-1

I am working on a small tool to decode this capture. The capture contains "Hello world" and then a sequence of repeating character 'B'.

This is what I am getting with the above-mentioned python script:

bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x99\xf0\xe0\xc9\x1d3\xf29FHOb\xaa\x92\xe2\x0b\xb0\x00\x1e\xbf\xe4\xa3\x91\x1eU\xc9\xd1\x91\xb3.')
bytearray(b'\xabb\x1d\xc9\x1d\xb3\xe3\xb6#\x93\xe58\xc7\x8f9:"\x1c\x8e\x0e\x00\xa0\x8eG\x12\x00 \x00?\n')
bytearray(b'\x00|$\xc9\x1d\x01\x00\x00\x80\x1e\x01\xf0\xe3\x88\xab\x1e?\xc9\x01\x02\x00\xa0#\x00\x00\x00 \x80#?')
bytearray(b'\x00$9\x80\x03\x00\x00\x00@\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00 \x00\x00\x00')
bytearray(b'\x80#\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8xdr$G\x90$\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00H\x06\x00\x00\x00\x00\x00\x00\xc7q$\x01\x00\xc7\x8f\xe4\x00\x009$\t\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00p$\x00H\x12\x00\x00Z\x91\x04\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8e\x04')
bytearray(b'\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x11\x00\x00')
bytearray(b'\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00p$\x00\x00\x00\x90$\x00\x00\x00\x00\x00\x00\x00\x00\x00@')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x01\x00\x00\x00$\x03\x00\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00H\x06\x00\x00\x00\xc8\x00\x00\x00\x00\x00\x01\x00\xc7\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x92\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
...
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\x04\xdd\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
bytearray(b'\xbf\xdf\xefw\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~\xbf\xdf\xef\xf7\xbf\xdf\xef\xf7\xfb\xfd~\xff\xfb\xfd~')
...
Actions #22

Updated by fixeria 5 months ago

fixeria wrote in #note-21:

Transparent data call, TCH/F9.6, 8-N-1

I am working on a small tool to decode this capture. The capture contains "Hello world" and then a sequence of repeating character 'B'.

I just pushed a WIP version of this tool to a branch (partly based on laforge/libosmoisdn):

https://cgit.osmocom.org/libosmocore/log/?h=fixeria/suart

At the beginning of the capture we have some garbage (all bits set to 0):

S: 000000000
X: 00
E: 0000000
D: 000000000000000000000000000000000000000000000000
framing error: stop bit 10 != 1
framing error: stop bit 10 != 1
framing error: stop bit 10 != 1
framing error: stop bit 10 != 1
framing error: stop bit 10 != 1

This is likely happening because osmo-bts-trx is transmitting zeroes when there is nothing to send. We should fix this and make it send ones instead.

Most of the records are dummy UART frames filled with stop bits:

S: 101101011
X: 11
E: 0001111
D: 111111111111111111111111111111111111111111111111
S: 101101011
X: 11
E: 0001111
D: 111111111111111111111111111111111111111111111111
S: 101101011
X: 11
E: 0001111
D: 111111111111111111111111111111111111111111111111
S: 101101011
X: 11
E: 0001111
D: 111111111111111111111111111111111111111111111111

Closer to the end of the capture comes the content I was expecting to recover:

uart_rx_cb(): 00 e0 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 0d 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 5c 
�Hello, world!
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\
Actions #23

Updated by fixeria 4 months ago

  • % Done changed from 70 to 80

During the last week I was working on completing Harald's soft-UART and eventually getting it merged to master:

https://gerrit.osmocom.org/c/libosmocore/+/30763 core: Add software UART implementation
https://gerrit.osmocom.org/c/libosmocore/+/35018 soft_uart: add osmo_soft_uart_free() [NEW]
https://gerrit.osmocom.org/c/libosmocore/+/35019 soft_uart: add doxygen documentation [NEW]
https://gerrit.osmocom.org/c/libosmocore/+/35020 soft_uart: split osmo_soft_uart_enable() [NEW]
https://gerrit.osmocom.org/c/libosmocore/+/35021 soft_uart: make osmo_soft_uart_alloc() accept *cfg [NEW]
https://gerrit.osmocom.org/c/libosmocore/+/35022 soft_uart: rework osmo_uart_rx_bit() to use flow state [NEW]
https://gerrit.osmocom.org/c/libosmocore/+/35023 soft_uart: implement parity checking for the receiver [NEW]
https://gerrit.osmocom.org/c/libosmocore/+/35044 soft_uart: implement the transmitter [NEW]
https://gerrit.osmocom.org/c/libosmocore/+/35045 [WIP] soft_uart: implement OSMO_SUART_RX_MODE_N_FRAMES [NEW]
https://gerrit.osmocom.org/c/libosmocore/+/35046 soft_uart: add unit tests for the receiver and transmitter [NEW]

I had implemented the missing parity checking and added the missing transmitter, plus the unit test coverage of course.
There is still room for improvements and additional features (like the software flow control), but overall it's already usable.

Actions #24

Updated by fixeria 4 months ago

  • Checklist item libosmocore: complete Harald's soft-UART added

fixeria wrote in #note-23:

I had implemented the missing parity checking and added the missing transmitter, plus the unit test coverage of course.
There is still room for improvements and additional features (like the software flow control), but overall it's already usable.

All patches have been merged to master. I submitted a new patchset fixing bugs and implementing the "hardware" flow control:

remote: https://gerrit.osmocom.org/c/libosmocore/+/35169 soft_uart: add osmo_soft_uart_{get,set}_name() [NEW]
remote: https://gerrit.osmocom.org/c/libosmocore/+/35170 soft_uart: fix doxygen doc for osmo_soft_uart_tx_ubits() [NEW]
remote: https://gerrit.osmocom.org/c/libosmocore/+/35171 soft_uart: check Rx/Tx state once in osmo_soft_uart_{rx,tx}_ubits() [NEW]
remote: https://gerrit.osmocom.org/c/libosmocore/+/35172 soft_uart: implement modem status lines and flow control [NEW]

The soft-UART can now be considered completed.

Actions #25

Updated by fixeria 4 months ago

A Work-in-Progress integration of the soft-UART as well as the user plane (UNIX domain socket) implementation can be found in this branch:

https://cgit.osmocom.org/osmocom-bb/log/?h=fixeria/csd_demo

Patches need to be reworked and submitted to Gerrit for review.

Actions #26

Updated by fixeria 4 months ago

  • Checklist item libosmoisdn: complate Harald's V.110 FSM added
  • % Done changed from 80 to 70

We're also missing to implement handling of the S-/X-bits in the V.110 frames. Without this, we cannot establish a data call between osmocom-bb/mobile and some other phone/modem. Only mobile-to-mobile calls are working at the moment.

Here is Harald's unfinished V.110 code that I need to take and complete:

https://cgit.osmocom.org/libosmocore/commit/?h=laforge/libosmoisdn&id=a700be4f147fbfac9d780ce38fdb2efa0198d6df

Actions #27

Updated by fixeria 3 months ago

  • % Done changed from 70 to 80

fixeria wrote in #note-26:

We're also missing to implement handling of the S-/X-bits in the V.110 frames. [...]
Here is Harald's unfinished V.110 code that I need to take and complete:

https://cgit.osmocom.org/libosmocore/commit/?h=laforge/libosmoisdn&id=a700be4f147fbfac9d780ce38fdb2efa0198d6df

During the last few weeks I have been working on completing Harald's V.110 Terminal Adapter FSM.
Took me a while to wrap my head around the concepts described in V.110, but in the end it's not that hard to implement.

Here is current WIP patch:

https://gerrit.osmocom.org/c/libosmocore/+/35444 isdn: initial implementation of the V.110 TA

There are still missing bits here and there, but the unit tests prove it's already mature enough to be used for CSD.
I will be focusing on completing the most important missing parts and then integrating it into osmocom-bb/mobile.

Actions #28

Updated by fixeria 3 months ago

  • Checklist item libosmoisdn: complate Harald's V.110 FSM set to Done
  • % Done changed from 80 to 90

fixeria wrote in #note-27:

https://gerrit.osmocom.org/c/libosmocore/+/35444 isdn: initial implementation of the V.110 TA

There are still missing bits here and there, but the unit tests prove it's already mature enough to be used for CSD.
I will be focusing on completing the most important missing parts and then integrating it into osmocom-bb/mobile.

I have been working on completing the most important missing bits, and today have finally unset the Work-in-Progress flag.
I also updated the Work-in-Progress osmocom-bb/mobile code to use the new V.110 TA and finally got transparent calls to work with a real MS (SE K200).

  +----------+            +---------+            +-------------+            +----------------+            +------------+            +-------------+            +------------+
  |          | ---------> |         | ---------> |             | ---------> |                | ---------> |            | ---------> |             | ---------> |            |
  | SE K200i |     Um     |   BTS   |     Um     | Calypso DSP |    L1CTL   | layer23/mobile |   V.110    |  V.110 TA  |    chars   |  soft-UART  |  UNIX sock |  ext. app  |
  |          | <--------- |         | <--------- |             | <--------- |                | <--------- |            | <--------- |             | <--------- |            |
  +----------+            +---------+            +-------------+            +----------------+            +------------+            +-------------+            +------------+

I will now be focusing on cleaning up the code in osmocom-bb/mobile and eventually getting it merged.

Actions #29

Updated by fixeria 2 months ago

  • Checklist item CSD support in layer23 set to Done
  • Checklist item mobile: expose the user plane set to Done

fixeria wrote in #note-28:

I will now be focusing on cleaning up the code in osmocom-bb/mobile and eventually getting it merged.

This patchset integrates the V.110 TA and soft-UART from libosmocore and exposes the user plane via a UNIX socket:

https://gerrit.osmocom.org/c/osmocom-bb/+/35577 mobile: add generic signals for CC/SS/SM transactions [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/35578 mobile: store MNCC Bearer Capability in CC transaction [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/35579 mobile: init/deinit GAPK I/O based on CC transaction events [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/35580 mobile: rename tch_send_voice_{msg,frame}() functions [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/35581 mobile: split voice specific TCH handling into its own file [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/35582 mobile: integrate V.110 TA & soft-UART from libosmocore [NEW]
https://gerrit.osmocom.org/c/osmocom-bb/+/35583 mobile: implement sending CSD data over UNIX socket [NEW]

There are still some TODOs, but in general it should be enough to make sync/async transparent calls.

Actions #30

Updated by fixeria 2 months ago

fixeria wrote in #note-29:

There are still some TODOs, but in general it should be enough to make sync/async transparent calls.

I confirmed both user data rates 9600 and 4800 (TCH/F9.6 and TCH/F4.8, respectively) to work reliably in the following scenarios:

  • against a reference implementation (Calypso based SE K200),
  • against our own implementation - another phone running osmocom-bb/mobile.

However, I could not get 2400 (TCH/F2.4) to work in either of the two scenarios.
There problem must be somewhere in the firmware, because the V.110 frames I am receiving look like garbage (expected all '1'):

    E-bits: 1100100
    S-bits: 111110
    X-bits: 11
    D-bits: 110000110011000000000011110000110011000000111111
DLGLOBAL DEBUG v110_ta.c:758 V110-TA(csd_v110_ta)[0x61200000dba0]{IDLE_READY}: Received Event RX_FRAME_IND
    E-bits: 1101110                        
    S-bits: 001001
    X-bits: 11
    D-bits: 001100110000111111110000001100110000001100110000
DLGLOBAL DEBUG v110_ta.c:758 V110-TA(csd_v110_ta)[0x61200000dba0]{IDLE_READY}: Received Event RX_FRAME_IND
    E-bits: 1100111
    S-bits: 011110
    X-bits: 10             
    D-bits: 111100000011001111110000110000000011001111000011
DLGLOBAL DEBUG v110_ta.c:758 V110-TA(csd_v110_ta)[0x61200000dba0]{IDLE_READY}: Received Event RX_FRAME_IND    
    E-bits: 1100010                                      
    S-bits: 101111
    X-bits: 11                    
    D-bits: 001111110000000011110000001111110000001111110000
DLGLOBAL DEBUG v110_ta.c:758 V110-TA(csd_v110_ta)[0x61200000dba0]{IDLE_READY}: Received Event RX_FRAME_IND
    E-bits: 1100100            
    S-bits: 111100                       
    X-bits: 10                                     
    D-bits: 111100111111001100001111110000111111001100111111 
DLGLOBAL DEBUG v110_ta.c:758 V110-TA(csd_v110_ta)[0x61200000dba0]{IDLE_READY}: Received Event RX_FRAME_IND
    E-bits: 1101110
    S-bits: 001001          
    X-bits: 11                        
    D-bits: 001100110000111111110000001100110000001100110000
DLGLOBAL DEBUG v110_ta.c:758 V110-TA(csd_v110_ta)[0x61200000dba0]{IDLE_READY}: Received Event RX_FRAME_IND  
    E-bits: 1100100
    S-bits: 111100    
    X-bits: 10                  
    D-bits: 001111111100001111111111110000111111001100111111
DLGLOBAL DEBUG v110_ta.c:758 V110-TA(csd_v110_ta)[0x61200000dba0]{IDLE_READY}: Received Event RX_FRAME_IND
    E-bits: 1101110                                           
    S-bits: 001001
    X-bits: 11     
    D-bits: 001100110000111111110000001100110000001100110000
DLGLOBAL DEBUG v110_ta.c:758 V110-TA(csd_v110_ta)[0x61200000dba0]{IDLE_READY}: Received Event RX_FRAME_IND
    E-bits: 1100100
    S-bits: 110100
    X-bits: 00            
    D-bits: 111100110011000000000011110000111111001100111111
DLGLOBAL DEBUG v110_ta.c:758 V110-TA(csd_v110_ta)[0x61200000dba0]{IDLE_READY}: Received Event RX_FRAME_IND
    E-bits: 1101110
    S-bits: 001001
    X-bits: 11
    D-bits: 001100110000111111110000001100110000001100110000
DLGLOBAL DEBUG v110_ta.c:758 V110-TA(csd_v110_ta)[0x61200000dba0]{IDLE_READY}: Received Event RX_FRAME_IND
Actions #31

Updated by fixeria 2 months ago

fixeria wrote in #note-30:

There problem must be somewhere in the firmware, because the V.110 frames I am receiving look like garbage (expected all '1'): [...]

After hours of debugging, I think I finally found the problem:

  • The firmware is built against an old outdated copy of libosmocore,
    • ... which defines GSM48_CMODE_DATA_3k6 = 0x23 (incorrect).
  • Recent libosmocore defines GSM48_CMODE_DATA_3k6 = 0x13 (correct).
  • The mobile app requests chan_mode=0x13, as expected,
  • The layer1 firmware does not recognize this mode and falls-back to GSM48_CMODE_SIGN.

Below is a related fix, which was merged back in 2013 (!):

commit 31e844bfe2756e36dd50f8bed9fa8b087ee6a1d9
Author: Bhaskar <niceguy108@gmail.com>
Date:   Thu May 16 17:06:35 2013 +0530

    gsm_04_08.h: Fix GSM48_CMODE_DATA_3k6 as per 3GPP TS 04.08 / 10.5.2.6.

diff --git a/include/osmocom/gsm/protocol/gsm_04_08.h b/include/osmocom/gsm/protocol/gsm_04_08.h
index 172ef678..e5d129ed 100644
--- a/include/osmocom/gsm/protocol/gsm_04_08.h
+++ b/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -345,7 +345,7 @@ enum gsm48_chan_mode {
        GSM48_CMODE_DATA_14k5   = 0x0f,
        GSM48_CMODE_DATA_12k0   = 0x03,
        GSM48_CMODE_DATA_6k0    = 0x0b,
-       GSM48_CMODE_DATA_3k6    = 0x23,
+       GSM48_CMODE_DATA_3k6    = 0x13,
 };

 /* Chapter 9.1.2 */

Applying this patch makes 2400 bps (and lower) rates work.
This is another reason we should finally get rid of that outdated copy and start building against recent libosmocore.git.

Actions #32

Updated by fixeria 2 months ago

  • Checklist item firmware: TCH/F2.4 support set to Done

https://gerrit.osmocom.org/c/osmocom-bb/+/35637 firmware (libosmocore): fix gsm48_chan_mode for TCH/[FH]2.4 [NEW]

Actions #33

Updated by fixeria 2 months ago

  • Checklist item mobile: support 300 bps (pad to 600 bps using stop bits) added
Actions #34

Updated by fixeria 2 months ago

  • Checklist item mobile: support saving data call params to mobile.cfg added
  • Checklist item mobile: make async call params (parity, start/stop bits) configurable added
Actions #35

Updated by fixeria 2 months ago

Some more testing results. I was able to send the GPLv2 license text from one osmocom-bb/mobile instance to another using xyzmodem.

Tested rates:

  • 9600 bps
  • 4800 bps
  • 2400 bps

Receiving side

$ socat UNIX-CONNECT:/tmp/ms_data.1 EXEC:"/tmp/install/bin/lrx -vv GPL-2.0-or-later.$RATE.txt" 

lrx: ready to receive GPL-2.0-or-later.$RATE.txt
Bytes received:   17408   BPS:115                   

Transfer complete

Sending side

$ socat UNIX-CONNECT:/tmp/ms_data.2 EXEC:"/tmp/install/bin/lsx -vv /usr/share/licenses/spdx/GPL-2.0-or-later.txt" 
Sending /usr/share/licenses/spdx/GPL-2.0-or-later.txt, 135 blocks: Give your local XMODEM receive command now.
Xmodem sectors/kbytes sent: 135/16k^Clsx: caught signal 2; exiting

Summary

$ md5sum GPL-2.0-or-later.*
15e2bdb38269aa11e75aeae879dace02  GPL-2.0-or-later.2400.txt
15e2bdb38269aa11e75aeae879dace02  GPL-2.0-or-later.4800.txt
15e2bdb38269aa11e75aeae879dace02  GPL-2.0-or-later.9600.txt
Actions #36

Updated by fixeria 2 months ago

  • Checklist item mobile: make async call params (parity, start/stop bits) configurable set to Done

https://gerrit.osmocom.org/c/osmocom-bb/+/35661 mobile: VTY: use 'enum gsm48_bcap_transp' from libosmogsm
https://gerrit.osmocom.org/c/osmocom-bb/+/35662 mobile: VTY: make soft-UART parameters configurable

I also reworked the call type/rate configuration, which had some design flaws:

https://gerrit.osmocom.org/c/osmocom-bb/+/35663 mobile: VTY: rework data type/rate configuration commands

Actions #37

Updated by fixeria 2 months ago

  • Checklist item mobile: support saving data call params to mobile.cfg set to Done

https://gerrit.osmocom.org/c/osmocom-bb/+/35699 mobile: VTY: store/read data call params to/from config file

Actions #38

Updated by fixeria 2 months ago

  • Checklist item wiki: document CSD support in osmocom-bb added

I documented CSD support here: CSD. News announcement is planned.

Actions #39

Updated by fixeria 2 months ago

  • Related to Feature #6346: mobile: support data calls @ 14400 bps (TCH/F14.4) added
Actions #40

Updated by fixeria 2 months ago

  • Related to Feature #6347: mobile: support data calls @ 300 bps and 1200/75 bps (TCH/[FH]2.4) added
Actions #41

Updated by fixeria 2 months ago

  • Related to Feature #6348: virtphy: add Circuit Switched Data (CSD) support added
Actions #42

Updated by fixeria 2 months ago

  • Checklist item deleted (CSD support in virtphy)
  • Checklist item deleted (mobile: support 300 bps (pad to 600 bps using stop bits))
  • Status changed from In Progress to Resolved
  • % Done changed from 90 to 100

I created tickets for the missing checklist items. This ticket can be closed now.

Actions

Also available in: Atom PDF

Add picture from clipboard (Maximum size: 48.8 MB)