ptrkrysik / gr-gsm

Gnuradio blocks and tools for receiving GSM transmissions
Other
1.35k stars 432 forks source link

Proposal: channel hopping #51

Closed rpp0 closed 9 years ago

rpp0 commented 9 years ago

Dear all,

I'm trying to implement real time channel hopping for gr-gsm. Here are some approaches that I considered:

In any case, I'm currently stuck with parsing the first hop to a SDCCH channel. I tried using the TCH/F demapper from this branch but I'm not getting any data in Wireshark. I was expecting to see some control data or occasional packets from phones hopping to the channel in question. Is decoding the SDCCH already supported? If not I would be happy to help :).

romankh commented 9 years ago

Hi @rpp0,

this is great to hear, as this is also a high priority feature for me.

I didn't test it yet, but @ptrkrysik already implemented capturing of multiple channels, so you wouldn't have to implement that again. Maybe it needs some improvements, @ptrkrysik can clarify.

In any case, I'm currently stuck with parsing the first hop to a SDCCH channel.

What do you mean, you have an Immediate Assignment, which assigns a hopping SDCCH ? Decoding of SDCCH is already working fine, but to tackle frequency hopping, it would be necessary to get the right bursts together.

I tried using the TCH/F demapper from this branch but I'm not getting any data in Wireshark.

Yes, the TCH decoder is missing. I am currently working on it, you can expect a pull request by the end of the week. However, it doesn't have any impact on SDCCH decoding. What you will get is the traffic channel TCH (contains speech data) and the corresponding SACCH and FACCH.

Using the TCH demapper, you can already get the SACCH messages by connecting the ACCH output to a control channel decoder.

I already was thinking about how to implement frequency hopping support, but didn't dig into the corresponding specifications so far. However my coarse idea would be a block, where the user can configure MAIO, HSN and other params for frequency hopping. The block would take the bursts from the involved channels, and put them together for decoding.

rpp0 commented 9 years ago

Hi @romankh,

Thank you for your fast reply!

I didn't test it yet, but @ptrkrysik already implemented capturing of multiple channels, so you wouldn't have to implement that again. Maybe it needs some improvements, @ptrkrysik can clarify.

Do you mean the d_cell_allocation parameter of the GSM Receiver block? I tried putting a list of ARFCNs in it and got a segfault after a few seconds (master branch, both absolute and relative ARFCNs), so I assumed it was some kind of experimental feature. Will do some more tests tonight to see why this happens. I can provide an example cfile so you can reproduce if you want.

What do you mean, you have an Immediate Assignment, which assigns a hopping SDCCH ? Decoding of SDCCH is already working fine, but to tackle frequency hopping, it would be necessary to get the right bursts together.

Ah I see, then I probably got the bursts wrong. Do you think it would be possible to hop fast enough using my method, i.e. directly set the frequency of the Source block? Though I agree that capturing multiple channels at a time and then putting the right bursts together is a better approach.

romankh commented 9 years ago

d_cell_allocation is part of it, also i believe Cx is supposed to deliver all other channels than C0. I didn't look so much into the receiver code, probably num streams also plays a role.

But I didn't try the feature yet, wait for ptrkrysik's response.

Ah I see, then I probably got the bursts wrong. Do you think it would be possible to hop fast enough using my method, i.e. directly set the frequency of the Source block? Though I agree that capturing multiple channels at a time and then putting the right bursts together is a better approach.

I am not 100% sure, but I dont think it would be easy in Gnuradio. I read a paper where the authors analyzed the ability of UHD with regards to frequency hopping, and stated it would be possible. But it didn't sound easy. I don't have much experience with Gnuradio, and I have no communication engineering background, so this is more a opinion.

The question is, do you (we) really need real-time processing ? For most of my use-cases a delay doesn't really matter.

rpp0 commented 9 years ago

Yes you're right, real time processing is not really required and it's probably easier to just capture all channels. I'll try to implement the hopping block you suggested in order to learn a bit more about GSM, but you'll probably beat me to it given your experience ;). Do you guys happen to have an IRC channel or Skype for discussing GSM perhaps?

ptrkrysik commented 9 years ago

I've started implementing receiver's side for the situation when there are all channels needed for frequency hopping available simultaneously. The feature is experimental but it worked for few test datasets that I tested it on. To configure the receiver to receive channels other than C0 you need to give number of channels (including C0) and list of ARFCNs (with C0 first). The list is used to set IDs in burst headers with intention to give information needed by a block that will reverse frequency hopping. The name of the parameter is "cell allocation" but I'm not sure if it has fully the same meaning as in 3gpp specs - here it's list of BTS ARFCNs needed to receive hoping channels. After these parameters are set connect all inputs with streams carrying different ARFCNs - the order should be the same as in "cell allocation".

If you don't set list of training sequences used on other channels ("TSEQ numbers") the receiver will try to discover training sequence for one of the channels and use it will use it for all channels other than C0 (for C0 it is set to BCC value read from SCH burst). This is not optimal - the best solution would be to read that training sequence number from somewhere, but I don't have a clean solution yet.

When the receiver discovers bursts on channels other than C0 (on C0 there is constant stream of bursts on other channels only when some transmission occurs) - it puts them to the "CX" output.

When I was writing this my intention was to implement frequency hopping in the logical channels demapping block - it would have hopping sequence number as a parameter and separate outputs for all MAIOs (or selected ones).

As for the second proposition - it might be done but the requirement for the controllability of hardware used for the reception will be much higher. The delay in gnuradio flowgraph is not an issue once you have hardware accepting timed commands - there might be a gnuradio block that once configured to change frequency according to some pattern will issue in advance commands to switch frequency at precise moments. Another requirement is that for the speed of frequency switches by the hardware - it depends on how fast PLLs used in the analog frontend stabilise on a given frequency. Ettus's USRP might be good hardware for this, but I don't know how fast their analog fronends can switch frequencies.

rpp0 commented 9 years ago

Hi Piotr,

Thank you for clarifying and for the useful information regarding frequency switches. I will try receiving multiple channels simultaneously tomorrow, but this will not be easy to verify. In my case all channels but C0 appear to be hopping and there is a significant gap between them, so the easiest way to test seems to create seperate cfiles for all involved ARFCNs like in Bogdan's airprobe-hopping implementation, feed them to the GSM Receiver block and finally check the output of the control channel decoders.

ptrkrysik commented 9 years ago

This is how I did my tests also - first I extracted all needed channels into files and then I connected file sources to inputs of the receiver. I can dig this code and test data out if you like to see it or work on this functionality.

rpp0 commented 9 years ago

If you have the time to help me then sure, thanks! In the meantime I will create my own test data.

rpp0 commented 9 years ago

I had less time today than expected, but I created a channelized data set and managed to receive multiple streams simultaneously. SDCCH reception is working fine, but I'm still working on getting data from the hopping CX channels.

akibsayyed commented 9 years ago

Can u share your GRC for same On May 19, 2015 8:35 PM, "rpp0" notifications@github.com wrote:

I had less time today than expected, but I created a channelized data set and managed to receive multiple streams simultaneously. SDCCH reception is working fine, but I'm still working on getting data from the hopping CX channels.

— Reply to this email directly or view it on GitHub https://github.com/ptrkrysik/gr-gsm/issues/51#issuecomment-103539481.

ptrkrysik commented 9 years ago

The example for receiving hopping channels in a downlink: https://app.box.com/s/q54hi5vbe2oijo3fandabazxoj5id1t5

Associated files containing separated channels: https://app.box.com/s/9p8i59avdwhqt6domdet https://app.box.com/s/d43jwdf25boqnsx81usp https://app.box.com/s/6p37v08kgnd9n0th5axg https://app.box.com/s/b8aegzyq6mg3ma1eyd5r https://app.box.com/s/6wa2uz6q0fvm5pvjwjkt https://app.box.com/s/qq2gbrfjc5zdtv52h04p

A simple flowgraph for extracting given channel from wideband file: https://app.box.com/s/vkirr7t6s79a9gzvy758nwx8o13w4g45

rpp0 commented 9 years ago

My flowgraph for extracting a given channel from a wideband file looks similar to yours, except I used the xlating FIR filter. I was a bit confused by the clock offset corrector part (I understand the filtering) of the GSM Input Adapter block: why does it need the C0 frequency and not a CX frequency? Anyway, now comes the hard part: assembling the bursts. This might take me a while but I feel like I've already learned a lot, so thanks Piotr!

ptrkrysik commented 9 years ago

The aim of GSM Input Adaptor is to put together few functions that usually need to be done before the signal enters the receiver: -clock offset correction, -sampling rate adaptation to a integer multiply of symbol rate, -low pass filtering.

I've put this functions into one hierarchical block only because in multichannel receiver block realizing these functions would take too much space on the screen.

Regarding the question about why clock offset corrector needs C0 channel - I don't know what exactly you mean so I will just describe what this block do. The block receives on message input estimates of clock frequency offset and then corrects two effects of this offset: sampling frequency offset and carrier frequency offset. The measurements are done inside of the receiver by measuring carrier frequency offset for FCCH bursts (btw. the algorithm that is used for estimation of this offset can be improved). The receiver sends measurements to a simple controller that feeds corrections to the clock offset corrector.

rpp0 commented 9 years ago

I don't know what exactly you mean so I will just describe what this block do.

What I meant was that in your example, each GSM Input Adaptor block has the same fc setting even though the connected file sources contain different channels. I'm not sure why that is.

Here's what I experimented with today; I hope you don't mind if I update my progress here. Based on the airprobe-hopping code, I made a hacky implementation of channel hopping, but it's not working yet. I must be missing something so I need to check the standard once more in order to make progress. Instead of reading bursts sequentially from each input item / channel, I changed the receiver to only read from C0 (https://github.com/rpp0/gr-gsm/blob/test/lib/receiver/receiver_impl.cc#L292) and hop to a CX channel based on the HSN, MAIO and T1 T2 T3 parameters (https://github.com/rpp0/gr-gsm/blob/test/lib/receiver/receiver_impl.cc#L376). In my case, the MA list is identical to the CA list (so each channel is used to hop except the BCCH).

ptrkrysik commented 9 years ago

W dniu 21.05.2015 o 17:18, rpp0 pisze:

I don't know what exactly you mean so I will just describe what this
block do.

What I meant was that in your example, each GSM Input Adaptor block has the same fc setting even though the connected file sources contain different channels. I'm not sure why that is.

The GSM Input Adaptor should get channel frequency - it is needed to compute carrier frequency offset. What I did there is generally not correct, but as clock and frequency correction function of these blocks is not used in that example - it doesn't matter that the value isn't right.

Here's what I experimented with today; I hope you don't mind if I update my progress here. Based on the airprobe-hopping code, I made a hacky implementation of channel hopping, but it's not working yet. I must be missing something so I need to check the standard once more in order to make progress. Instead of reading bursts sequentially from each input item / channel, I changed the receiver to only read from C0 (https://github.com/rpp0/gr-gsm/blob/test/lib/receiver/receiver_impl.cc#L292) and hop to a CX channel based on the HSN, MAIO and T1 T2 T3 parameters (https://github.com/rpp0/gr-gsm/blob/test/lib/receiver/receiver_impl.cc#L376). In my case, the MA list is identical to the CA list (so each channel is used to hop except the BCCH).

Of course you can writes updates here especially that your work is perfectly aligned with development of gr-gsm.

As I said I was considering implementing channel hopping. Simple and clean way to implement it would be outside of the receiver. The block doing this would take MA and HSN. It would also have separate output for each MAIO (hopping channel). Based on hopping parameters it would just copy bursts from input to the right output or discard them if they are from channels outside of MA.

rpp0 commented 9 years ago

Ok, I made a seperate "Hopping" block with as input all bursts from the CX channels. If I understood correctly, all I have to do is calculate the hopping sequence (using the algorithm from GSM 5.02) and forward the bursts in the correct order to the demapper blocks. For now, I used a fixed MAIO and HSN (which I observed from a Wireshark trace of my test set; the MAIO and HSN seem to be identical for each Immediate Assignment). My debug output seems correct, for example frame 1842282 shows I have to hop to CA 991, and the next burst indeed has CA 991 in its GSMTAP header. However, I'm not able to decode any frames. Any ideas what I could be doing wrong (https://github.com/rpp0/gr-gsm/blob/test/lib/hopping_impl.cc)?

output from my Hopper block:
got frame nr 1842282 from CA 1022 -> CA 991
1842282:0001000000111001000110111100000111000110001101100111000000001101001111101100010100111111010000011110011100110110101001100110010001110011111100001000
got frame nr 1842283 from CA 991 -> CA 994
1842283:0001100111110101111011000011001111011001011101001010101011111101001111101100010100111111000101011101111011100110001101010110011001101110000000011000
got frame nr 1842284 from CA 994 -> CA 993
1842284:0001010000110000011011101011100101011000001000100000100011001101001111101100010100111111001011000100001111110001000011011110010101011101100110010000
got frame nr 1842285 from CA 993 -> CA 993
1842285:0000011010100101011011011001101001000011101001000001010000111101001111101100010100111111111010011100110011010001111010101001111011001001110001111000
got frame nr 1842326 from CA 1019 -> CA 1019
got frame nr 1842327 from CA 1019 -> CA 995
got frame nr 1842328 from CA 995 -> CA 1019
got frame nr 1842333 from CA 1021 -> CA 995
got frame nr 1842334 from CA 995 -> CA 993
got frame nr 1842335 from CA 993 -> CA 992
romankh commented 9 years ago

Can you describe your test data, or did you use @ptrkrysik 's data ? If you provide your flowgraph, I can take a look, maybe two more eyes are helpful.

rpp0 commented 9 years ago

Thanks, and sorry if it's something stupid. I'm learning about GSM every day but it's still quite hard to figure things out from the standard. Here is the flowgraph I made: https://github.com/rpp0/gr-gsm/blob/test/apps/airprobe_rtlsdr_multi.grc. I used my own data. The test data properties are shown below. The main ARFCN (non hopping) is channel 975. All other channels are hopping. ma arfcn

romankh commented 9 years ago

I don't think you need all those demappers, if I understood you right.

You need only one, where you set the timeslot according to your immediate assignment, in case of the screenshot it's timeslot 7. In this case you have SDCCH/8, so your starts_fn_mod51 should be [0,4,8,12,16,20,24,28,32,36,40,44], and channeltypes is [SDCCH, SDCCH, SDCCH, SDCCH, SDCCH, SDCCH, SDCCH, SDCCH,SACCH,SACCH,SACCH,SACCH]

You can then just feed the re-assembled bursts from your block to the demapper, and then as you already have it, to decryption and then decoder.

Also, if you are not sure about the decryption key, you could omit the decryption, there should be some messages before authentication is requested.

rpp0 commented 9 years ago

Thank you, I had a disabled demapper for SDCCH/8 at the bottom of my flowgraph which I tried at some point, but I noticed now that it contains too much SACCH entries. Unfortunately it still doesn't work after the corrections so my assumptions about how hopping works are probably wrong. I'll study some more :)

ptrkrysik commented 9 years ago

As @romankh noticed - there is Immediate Assignment that points that there is some SDCCH/8 channel with hoping in timeslot 7. All demappers have parameter timeslot_nr set to 0. You can leave one and change timeslot_nr to 7. If you leave decryption block without key - it just passes bursts from input to the output.

Another thing is to be sure that the receiver detected all bursts needed to decode at leas one message. The feature is experimental and it was never tested to the point you are now at. You can look at the output of your hopping block and see how continuous is the stream of bursts in timeslot 7.

rpp0 commented 9 years ago

All demappers have parameter timeslot_nr set to 0.

Hmm that's strange, I have the bottom two demappers set to timeslot 7 in my file.

Another thing is to be sure that the receiver detected all bursts needed to decode at leas one message.

That's probably why it's not working yet, I'll try out some new ideas soon :).

rpp0 commented 9 years ago

The GSM receiver block only detects normal bursts for the CX channels at timeslot 0 for my test data (the rest is noise?), but the Immediate Assignments from my test data only assign stations to timeslot 7. Does anyone know why I'm not seeing any frames in timeslot 7? @romankh , @ptrkrysik ?

ptrkrysik commented 9 years ago

It might be hard to say without the test data and your flowgraph. Is it possible for you to make it public or at leas available to me?

rpp0 commented 9 years ago

Sure, I've sent an email to your Gmail address.

rpp0 commented 9 years ago

I finally managed to decode some SDCCH frames on the hopping channels. The problem appears to be that the chans demapper block assumes that all frame numbers are consecutive. However, on p32 of GSM 05.02 it appears that for hopping this is not necessarily true. Below is some example debug output of my solution where I manually assign my own frame number instead of the real frame number. This solution is unreliable however, because the offset in "fn mod 51" will most likely be incorrect; you need to be lucky in order to see frames. If anyone has a suggestion for calculating fn mod 51 offset correctly given that the frame number is non-consecutive, please let me know :)!

got frame nr 1840903 (ts 0, type 6) from CA 1022 -> CA 1022
1840903:0000000000101111101000101000010100100000111110101000000000011101001111101100010100111111000000101011101010100001010000001000101110101010001001010000
got frame nr 1840904 (ts 0, type 6) from CA 1022 -> CA 991
1840904:0000001000000000010101011111111000101000000001011111101111101101001111101100010100111111100010010001010111011111101010100010000101011101101011101000
got frame nr 1840933 (ts 0, type 6) from CA 1020 -> CA 1023
got frame nr 1840934 (ts 0, type 6) from CA 1023 -> CA 1023
got frame nr 1840935 (ts 0, type 6) from CA 1023 -> CA 991
got frame nr 1840936 (ts 0, type 6) from CA 991 -> CA 1022
1840905:0000111111111010100110101100001110000011110100011000011110001101001111101100010100111111011010001111111001001001100100010101001010011011011111011000
got frame nr 1840937 (ts 0, type 6) from CA 1022 -> CA 994
1840906:0001110001010011001011111000111111000001100111001010111010111101001111101100010100111111010000001000000101110100001001010100000001011111111000101000
got frame nr 1840938 (ts 0, type 6) from CA 994 -> CA 992
1840907:0000010101010001011011001011010001001111111001101010100011011101001111101100010100111111010101111111110110101000001110000101110101111011010011001000
got frame nr 1840939 (ts 0, type 6) from CA 992 -> CA 990
1840908:0000011000100101101101100000110101000000010010111010101110001101001111101100010100111111001110000101001110001010000000000100000001101111100111010000
got frame nr 1840952 (ts 0, type 6) from CA 1023 -> CA 990
got frame nr 1840954 (ts 0, type 6) from CA 1021 -> CA 1021
got frame nr 1840955 (ts 0, type 6) from CA 1021 -> CA 995
got frame nr 1840956 (ts 0, type 6) from CA 995 -> CA 993
got frame nr 1840957 (ts 0, type 6) from CA 993 -> CA 992
got frame nr 1840958 (ts 0, type 6) from CA 992 -> CA 991
got frame nr 1841003 (ts 0, type 6) from CA 1022 -> CA 1023
got frame nr 1841004 (ts 0, type 6) from CA 1023 -> CA 991
got frame nr 1841006 (ts 0, type 6) from CA 1020 -> CA 994
got frame nr 1841007 (ts 0, type 6) from CA 994 -> CA 991
got frame nr 1841009 (ts 0, type 6) from CA 995 -> CA 990
got frame nr 1841036 (ts 0, type 6) from CA 1021 -> CA 1021
got frame nr 1841037 (ts 0, type 6) from CA 1021 -> CA 1023
got frame nr 1841038 (ts 0, type 6) from CA 1023 -> CA 1020
got frame nr 1841039 (ts 0, type 6) from CA 1020 -> CA 992
got frame nr 1841041 (ts 0, type 6) from CA 994 -> CA 1022
got frame nr 1841042 (ts 0, type 6) from CA 1022 -> CA 990
got frame nr 1841054 (ts 0, type 6) from CA 1021 -> CA 1022
got frame nr 1841055 (ts 0, type 6) from CA 1022 -> CA 990
got frame nr 1841057 (ts 0, type 6) from CA 1019 -> CA 993
got frame nr 1841059 (ts 0, type 6) from CA 990 -> CA 1023
1840909:0001010111010111101010000001010001010111111110101010101001001101001111101100010100111111000101110111101110100000010000010101111011111010001001010000
got frame nr 1841060 (ts 0, type 6) from CA 1023 -> CA 1023
1840910:0000000000101111101000101000010100100000111110101000000000011101001111101100010100111111000000101011101010100001010000001000101110101010001001010000
got frame nr 1841061 (ts 0, type 6) from CA 1023 -> CA 1019
1840911:0000001000000000010101011111111000101000000001011111101111101101001111101100010100111111100010010001010111011111101010100010000101011101101011101000
 03 20 0d 06 35 11 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
 03 20 0d 06 35 11 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
got frame nr 1841105 (ts 0, type 6) from CA 1020 -> CA 1021
ptrkrysik commented 9 years ago

Do you mean that bursts oming to the input of the demapper are not coming in order of growing frame numbers?

The demapper block has support for missing bursts - it just don't send message in this situation further. This is not 100% optimal as the decoder could decode correctly when one bursts is missing but at this stage of project I think it's not most important issue.

However bursts that are not coming in the right order... do you know why this happens? Does the MA include C0 frequency?

rpp0 commented 9 years ago

The frame numbers are growing, but for example:

got frame nr 1840903 (ts 0, type 6) from CA 1022 -> CA 1022
1840903:0000000000101111101000101000010100100000111110101000000000011101001111101100010100111111000000101011101010100001010000001000101110101010001001010000
got frame nr 1840904 (ts 0, type 6) from CA 1022 -> CA 991
1840904:0000001000000000010101011111111000101000000001011111101111101101001111101100010100111111100010010001010111011111101010100010000101011101101011101000
got frame nr 1840933 (ts 0, type 6) from CA 1020 -> CA 1023
got frame nr 1840934 (ts 0, type 6) from CA 1023 -> CA 1023
got frame nr 1840935 (ts 0, type 6) from CA 1023 -> CA 991
got frame nr 1840936 (ts 0, type 6) from CA 991 -> CA 1022
1840905:0000111111111010100110101100001110000011110100011000011110001101001111101100010100111111011010001111111001001001100100010101001010011011011111011000

Here, we see a couple of hopping normal bursts in timeslot 0, namely one for frame 1840903 and 1840904. These get forwarded to the demapper. So far so good, but then the next normal burst for the hopping channel arrives in frame 1840936. The demapper would not forward these bursts to the next block because of:

                for(int jj=1; jj<4; jj++)
                {
                    if((d_frame_numbers[jj]-d_frame_numbers[jj-1])!=1)
                    {
                        frames_are_consecutive = false;
                    }
                }

Then what I did is rewrite 1840936 to 1840905, which fixes the problem. But it's quite hacky, so I'm thinking about a better approach. C0 is not included in the MA list, and I noticed that in the gap between frame 1840904 and 1840936 there are only bursts coming from C0 (fcch, sch, dummy or normal).

romankh commented 9 years ago

The problem appears to be that the chans demapper block assumes that all frame numbers are consecutive. However, on p32 of GSM 05.02 it appears that for hopping this is not necessarily true. Below is some example debug output of my solution where I manually assign my own frame number instead of the real frame number.

Hmm, this would really be surprising to me. It would result in a significant loss of bandwidth for the concerned channels. In figure 5 of GSM 05.02, which you mentioned, they don't describe precisely, what kind of hopping channel is shown. It may also be a SACCH channel, where this behaviour is normal. Search function didn't show me any reference to the figure.

Are you still testing the Immediate Assignment from the screenshot above ? If so, you have an assignment to subslot 1 (in wireshark subchannel 1) in SDCCH/8 channel, which means the bursts where fn_mod51 >= 4 and fn_mod51 <= 7 represent the bursts for the assigned SDCCH-subslot.

FN 1840903 is the last of 4 bursts, and 1840904 % 51 = 8, it should be the first burst of subslot 2, and not part of your message any more.

If you were right that in hopping channels don't have to be consecutive, you could easily verify this by disabling the check in the demapper. However, I believe you may have got a few messages decoded falsely, where some bursts that don't belong together were assembled. Frankenstein-messages :)

I haven't read the whole specification that could apply to frequency hopping, I would expect it to work like that:

As you know, which subslot is assigned in the immediate assignment, you can calculate the framenumbers of the involved 4 bursts for every message. Now try to get the bursts together by taking the right bursts with the right framenumbers from different channels, according to your mai calculation. Then send them to the demapper, preserving order (framenumbers ascending)

ptrkrysik commented 9 years ago

W dniu 28.05.2015 o 09:37, rpp0 pisze:

The frame numbers are growing, but for example:

got frame nr 1840903 (ts 0, type 6) from CA 1022 -> CA 1022 1840903:0000000000101111101000101000010100100000111110101000000000011101001111101100010100111111000000101011101010100001010000001000101110101010001001010000 got frame nr 1840904 (ts 0, type 6) from CA 1022 -> CA 991 1840904:0000001000000000010101011111111000101000000001011111101111101101001111101100010100111111100010010001010111011111101010100010000101011101101011101000 got frame nr 1840933 (ts 0, type 6) from CA 1020 -> CA 1023 got frame nr 1840934 (ts 0, type 6) from CA 1023 -> CA 1023 got frame nr 1840935 (ts 0, type 6) from CA 1023 -> CA 991 got frame nr 1840936 (ts 0, type 6) from CA 991 -> CA 1022 1840905:0000111111111010100110101100001110000011110100011000011110001101001111101100010100111111011010001111111001001001100100010101001010011011011111011000

Here, we see a couple of hopping normal bursts in timeslot 0, namely one for frame 1840903 and 1840904. These get forwarded to the demapper. So far so good, but then the next normal burst for the hopping channel arrives in frame 1840936. The demapper would not forward these bursts to the next block because of:

for(int jj=1; jj<4; jj++) { if((d_frame_numbers[jj]-d_frame_numbers[jj-1])!=1) { frames_are_consecutive = false; } }

Then what I did is rewrite 1840936 to 1840905, which fixes the problem. But it's quite hacky, so I'm thinking about a better approach. C0 is not included in the MA list, and I noticed that in the gap between frame 1840904 and 1840936 there are only bursts coming from C0 (fcch, sch, dummy or normal).

To use the data for testing new software you will need to know as much as possible about it: which timeslots are in use, when, what training sequences are used - at least for a short part of it. Then it will be possible to compare if what you see at the output of the receiver is what you would expect. It is possible that some corrections are needed in the receiver.

It would be good to tell the receiver which training sequences are in use for each channel - so they are not auto-detected (probably they are the same for channels other than C0 - then you can give just one value).

What you are observing that after rewriting 1840936 to 1840905 you get some result - might be just coincidence.

rpp0 commented 9 years ago

Hmm, this would really be surprising to me. It would result in a significant loss of bandwidth for the concerned channels. In figure 5 of GSM 05.02, which you mentioned, they don't describe precisely, what kind of hopping channel is shown.

@romankh After some more testing I found that the "gaps" were indeed unrelated, so I was wrong, sorry about that :(.

Are you still testing the Immediate Assignment from the screenshot above ?

No, I'm trying to decode a different one now. Here's what happens: 1) On C0, FN 1841187 I receive an Immediate Assignment message to subchannel 0, timeslot 7 using tseq 6. Same MAIO etc as before. 2) The next "normal or noise" frame I get is FN 1841203, followed by 1841204, 1841205, 1841206. However, 1841203 % 51 = 1, so this is where I am confused. Where did 1841202 go? Am I not supposed to see this frame given that the assigned subslot is 0? If I use my rewrite trick to set 1841203 -> 1841202 so that 1841202 % 51 = 0, the message successfully decodes. Any subsequent frames however, do not. Am I supposed to wait until I see a normal frame x where x % 51 = 0?

Example without rewrite:

got frame nr 1841203 (ts 0, type 6) from CA 990 -> CA 1023
1841203:0001000000100011101010100000000101000000001111111010100000011101001111101100010100111111010000100010111010100000000101000010000010101010100000010000
got frame nr 1841204 (ts 0, type 6) from CA 1023 -> CA 1021
1841204:0001010101111111111010000001010101011111111111101000000001001101001111101100010100111111010111111111111010101000000001010101011011101010000001000000
got frame nr 1841205 (ts 0, type 6) from CA 1021 -> CA 1021
1841205:0000000000111110101010100001000000100010101110101010000101001101001111101100010100111111001010001111101010001000010000000000101110101010100000010000
got frame nr 1841206 (ts 0, type 6) from CA 1021 -> CA 995
1841206:0000001000010101010101111011101010100000000101011101111110101101001111101100010100111111100010000001010101011011101010001000010001011101111010101000
got frame nr 1841212 (ts 0, type 6) from CA 1021 -> CA 1020
got frame nr 1841213 (ts 0, type 6) from CA 1020 -> CA 1019
got frame nr 1841214 (ts 0, type 6) from CA 1019 -> CA 1020

And with rewrite:

got frame nr 1841203 (ts 0, type 6) from CA 990 -> CA 1023
1841202:0001000000100011101010100000000101000000001111111010100000011101001111101100010100111111010000100010111010100000000101000010000010101010100000010000
got frame nr 1841204 (ts 0, type 6) from CA 1023 -> CA 1021
1841203:0001010101111111111010000001010101011111111111101000000001001101001111101100010100111111010111111111111010101000000001010101011011101010000001000000
got frame nr 1841205 (ts 0, type 6) from CA 1021 -> CA 1021
1841204:0000000000111110101010100001000000100010101110101010000101001101001111101100010100111111001010001111101010001000010000000000101110101010100000010000
got frame nr 1841206 (ts 0, type 6) from CA 1021 -> CA 995
 03 03 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
1841205:0000001000010101010101111011101010100000000101011101111110101101001111101100010100111111100010000001010101011011101010001000010001011101111010101000
got frame nr 1841212 (ts 0, type 6) from CA 1021 -> CA 1020
got frame nr 1841213 (ts 0, type 6) from CA 1020 -> CA 1019
got frame nr 1841214 (ts 0, type 6) from CA 1019 -> CA 1020

To use the data for testing new software you will need to know as much as possible about it: which timeslots are in use, when, what training sequences are used - at least for a short part of it. Then it will be possible to compare if what you see at the output of the receiver is what you would expect. It is possible that some corrections are needed in the receiver.

Thanks, this is a good tip.

romankh commented 9 years ago

Am I not supposed to see this frame given that the assigned subslot is 0? Yes, as long as this channel and subslot is assigned, the burst where fn_mod51 is between 0 and 3 are yours.

If I use my rewrite trick to set 1841203 -> 1841202 so that 1841202 % 51 = 0, the message successfully decodes.

Still could be coincidence.

It would be easier, if you use @ptrkrysik 's dataset for development, so at least someone could take a closer look on it. This way it is more guessing.

ptrkrysik commented 9 years ago

I started the flowgraph on your test data @rpp0. You can pull one fix from main branch - there was a bug in gsm_input.py - it didn't pass ppm and fc parameter to the clock offset corrector. I also changed fc parameters in gsm_input blocks in your flowgraph to match frequency of your channels. It didn't help much - it seems that the receiver don't detect some of the bursts - hence the gaps that you observe. What is needed is to look at the signal, see where are bursts and which ones are not detected by the receiver. I currently don't have too much time for this. If you don't want to wait till I will find some moment to look at the issue - the reception of hopping channels is implemented in this part of the receiver_impl.cc:

            case normal_or_noise:
            {
                unsigned int burst_start;
                float normal_corr_max_tmp;
                float normal_corr_max=-1e6;
                int max_tn;
                std::vector<gr_complex> v(input, input + noutput_items);
                if(d_signal_dbm>=d_c0_signal_dbm-13) //initial detection of bursts based on received power - the threshold is power_of_c0 signal minus 13dB
                {
                    if(d_tseq_nums.size()==0)              //there is no information about training sequence
                    {                                      //however the receiver can detect it
                        get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, 0);
                        float ts_max=normal_corr_max;     //with use of a very simple algorithm based on finding
                        int ts_max_num=0;                 //maximum correlation
                        for(int ss=1; ss<=7; ss++)
                        {
                            get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, ss);
                            if(ts_max<normal_corr_max)
                            {
                                ts_max = normal_corr_max;
                                ts_max_num = ss;
                            }
                        }
                        d_tseq_nums.push_back(ts_max_num);
                    }
                    int tseq_num;
                    if(input_nr<=d_tseq_nums.size()){
                        tseq_num = d_tseq_nums[input_nr-1];
                    } else {
                        tseq_num = d_tseq_nums.back();
                    }
                    burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, tseq_num);
//                  if(abs(d_c0_burst_start-burst_start)<=2){ //unused check/filter based on timing
                    if((normal_corr_max/sqrt(signal_pwr))>=0.9){ //more precise detection based ratio of signal amplitude and maximum value of correlation of training sequence with the burst
                        detect_burst(input, &channel_imp_resp[0], burst_start, output_binary);
                        send_burst(d_burst_nr, output_binary, GSMTAP_BURST_NORMAL, input_nr);
                    }
                }
                break;
            }

You can for example ease thresholds for detection of bursts and see what happens. You can also plot content of input samples (amplitude of vector v) after detection of a burst, and see if the receiver detects all bursts that you see. I have written few functions for plotting amplitude of a complex vector in "plotting/plotting.hpp" which requires gnuplot-iostream.

rpp0 commented 9 years ago

Thanks for the fix! I'll take a look at the amplitude of the input samples and see if I can visually identify the normal bursts. If the receiver missed some frames I will see what I can do to improve. Maybe tweaking the threshold is enough, I'll test this soon.

ptrkrysik commented 9 years ago

Hi @rpp0,

I reviewed the code of hopping_impl.cc. In the function processing bursts there is this part:

if(next_hop == (int)frame_ca || frame_nr == 1842172) {
        message_port_pub(pmt::mp("bursts"), msg);
        next_hop = ma_list[mai];
}

The block at this point has state and the state is dependent on next_hop. I think it is not necessary - based on hopping parameters and frame number of the bursts that arrived you can compute arfcn of a burst that can be passed at given moment. If this agrees with arfcn of the burst that arrived - the block should pass the burst it received to the output. Or I'm missing something?

ptrkrysik commented 9 years ago

I suppose this might be the right version:

if(ma_list[mai] == (int)frame_ca) {
     message_port_pub(pmt::mp("bursts"), msg);
}

with next_hop removed.

rpp0 commented 9 years ago

Updating here as well besides some results I discussed with @ptrkrysik via email:

romankh commented 9 years ago

Hi @rpp0,

I believe you may overestimate my knowledge of gsm, I don't have as much experience as you may think. This is specially true for the radio part.

I lost track of your current status, here just a few thoughts:

rpp0 commented 9 years ago

Hi @romankh, no problem and thanks for these tips! I will update this thread when I have some more results.

rpp0 commented 9 years ago

Hi all, thanks to a bugfix in the receiver block by @ptrkrysik, I was able to get the channel hopping block working now! Thank you for all the help. I've created pull request https://github.com/ptrkrysik/gr-gsm/pull/64. Please let me know if anything needs to be modified. Next, I can add some documentation or extra error checks (for example that MAI may not be >= d_narfcn) if you'd like :-).

ptrkrysik commented 9 years ago

It's great to hear that you have done the block so quickly. The code looks good and it works on my test datasets. You can add the checks. As for the GRC documentation - probably it will be the FIRST gr-gsm blocks that would have one.

romankh commented 9 years ago

Congrats also from me, I am looking forward to make use of it.

chopengauer commented 9 years ago

Excuse me for offtop. Can anyone explain how to use block with hopping? I make flowgraph for gr, and connect "CX channel hopper" with input from "GSM Receiver", and as output - "Burst printer", and see nothing.

In "CX channel hopper" MA - list of arfcn channels from "System Information 1" (or list of the frequences) MAIO and HSN - from "Immediate Assignment".

Is it enough one GSM Receiver / GSM Input adaptor for hopping ? Can anyone share sample grc file? Thanks!

rpp0 commented 9 years ago

You seem to have configured the block correctly: MA list of hopping ARFCN channels like [990, 991, ...] excluding the main ARFCN, then MAIO and HSN from the Immediate Assignment. However, you need to place the block after the receiver (so connect the output of GSM Receiver CX to the hopper block). Did you configure multiple inputs for the GSM Receiver block?

As for the example grc: I'm working on one, but it's not finished yet unfortunately.

chopengauer commented 9 years ago

No. I have made only one GSM input. Sample - http://rghost.ru/8Frwhxc2L I'll try to make few GSM Inputs. But how i should be with "GSM clock offset control"?

rpp0 commented 9 years ago

Here is an example I made: you need to create a capture file for each channel and feed them to the GSM Receiver inputs.

http://rghost.net/private/8bNswS6LL/745462b31d478c567b56aa8ebf393cd3

bluelightvision commented 9 years ago

It seems that you guys have done a great work! Can someone tell me how to obtain the different input files that should be fed to the GSM Receiver block ?

ptrkrysik commented 9 years ago

There are many steps currently:

  1. capture all frequency channels to a file,
  2. process C0 channel of a BTS with Wireshark listening on local interface,
  3. from System Information messages read in Wireshark Cell Allocation (list of channels assigned to given BTS),
  4. extract all needed channels for example with this program: https://app.box.com/s/vkirr7t6s79a9gzvy758nwx8o13w4g45 (source in get_channel.grc migh require editing depending on format of samples in your capture file)
  5. configure the receiver (cell allocation with C0 channel first and number of inputs),
  6. configure file source block with your channels connected in the same order as in cell allocation,
  7. configure hopping channel block with MA, MAIO and HSN taken from some Immediate Assignment or Assignment command,
  8. configure demapper block with timeslot number taken from these commands

We want to make easier demonstration and then an application that support hopping without having to edit GRC flowgraph.

bluelightvision commented 9 years ago

I am stuck on step 4, the cfile that I receive at the end does not decode correctly. Can you please give some explanations of how tp use the get_channel.grc flowgraph.

ptrkrysik commented 9 years ago

get_channel.grc is for files with signal in interleaved complex int16 format. You probably have file with samples in complex float format so you will have to change in file source output format to complex and remove the next block that converts complex integers to complex floats.