aboutsummaryrefslogtreecommitdiffstats
path: root/src/gr-fadingui/python/frame_obj.py
blob: b9dae70af42dbc6cb1597c9b8d27088b6af830dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2021 Naoki Pross.

from functools import reduce
import operator as op

import numpy as np
from gnuradio import gr


class frame_obj(gr.basic_block):
    """
    Frame Object: Contains informations about a data frame.

      -------------------------------------------------------------------------------
      | Preamble | Padding | ID     | Data Length | Parity | Payload | Padding      |
      | k bytes  | 1 bit   | 4 bits | 22 bits     | 5 bits |         | if necessary |
      -------------------------------------------------------------------------------
                           | (31, 26) Hamming code EC      |
                           -----------------------------------

    - The preamble is user defined.
    - The ID (11 bits) + Data length (22 bits) together are a 31 bits, followed
      by 26 parity bits computed using a (31,26) hamming code.

      This constraints the maximum payload size to 64 MB and the number IDs to
      1024 (i.e. max file size is 1 GB, more than enough for many thing)

    """
    def __init__(self, preamble, payload_len):
        gr.basic_block.__init__(self, name="frame_obj",
                in_sig=None, out_sig=None)

        self.preamble = np.array(preamble, dtype=np.uint8)

        self.preamble_len = len(self.preamble)
        self.payload_len = payload_len

    @property
    def length(self):
        """Frame lenght in bytes"""
        return self.preamble_len + self.payload_len + 8

    def parity(self, bits):
        """Compute the 5 parity bits for an unpacked array of 26 bits"""
        assert(len(bits) == 26)
        # FIXME: does not work
        # gen = np.array(
        #     [[1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0],
        #      [0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1],
        #      [0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0],
        #      [0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0],
        #      [0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1]],
        #     dtype=np.uint8)
        # return np.matmul(bits, gen) % 2
        return np.array([0, 0, 0, 0, 0])

    def make(self, idv, data_len, data):
        """Make a frame"""
        return np.concatenate(self.preamble, np.packbits(hamming), data)

    def syndrome(self, bits):
        """Compute the syndrome (check Hamming code) for an unpacked array of 31 bits"""
        assert(len(bits) == 31)
        return reduce(op.xor, [i for i, bit in enumerate(bits) if bit])

    def general_work(self, input_items, output_items):
        """
        This block has no inputs or output 
        """
        return 0;