summaryrefslogtreecommitdiffstats
path: root/lib/edioutput/TagItems.h
blob: 029681c1cbdd906672b4bc9ddb2453bf82cf5350 (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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*
   EDI output.
    This defines a few TAG items as defined ETSI TS 102 821 and
    ETSI TS 102 693

   Copyright (C) 2019
   Matthias P. Braendli, matthias.braendli@mpb.li

    http://www.opendigitalradio.org

   */
/*
   This file is part of the ODR-mmbTools.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as
   published by the Free Software Foundation, either version 3 of the
   License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <vector>
#include <array>
#include <chrono>
#include <string>
#include <cstdint>

namespace edi {

class TagItem
{
    public:
        virtual std::vector<uint8_t> Assemble() = 0;
};

// ETSI TS 102 693, 5.1.1 Protocol type and revision
class TagStarPTR : public TagItem
{
    public:
        TagStarPTR(const std::string& protocol);
        std::vector<uint8_t> Assemble();

    private:
        std::string m_protocol = "";
};

// ETSI TS 102 693, 5.1.3 DAB ETI(LI) Management (deti)
class TagDETI : public TagItem
{
    public:
        std::vector<uint8_t> Assemble();

        /***** DATA in intermediary format ****/
        // For the ETI Header: must be defined !
        uint8_t stat = 0;
        uint8_t mid = 0;
        uint8_t fp = 0;
        uint8_t rfa = 0;
        uint8_t rfu = 0; // MNSC is valid
        uint16_t mnsc = 0;
        uint16_t dlfc = 0; // modulo 5000 frame counter

        // ATST (optional)
        bool atstf = false; // presence of atst data

        /* UTCO: Offset (in seconds) between UTC and the Seconds value. The
         * value is expressed as an unsigned 8-bit quantity. As of February
         * 2009, the value shall be 2 and shall change as a result of each
         * modification of the number of leap seconds, as proscribed by
         * International Earth Rotation and Reference Systems Service (IERS).
         *
         * According to Annex F
         *  EDI = TAI - 32s (constant)
         *  EDI = UTC + UTCO
         * we derive
         *  UTCO = TAI-UTC - 32
         * where the TAI-UTC offset is given by the USNO bulletin using
         * the ClockTAI module.
         */
        uint8_t utco = 0;

        /* Update the EDI time. t is in UTC */
        void set_edi_time(const std::time_t t, int tai_utc_offset);

        /* The number of SI seconds since 2000-01-01 T 00:00:00 UTC as an
         * unsigned 32-bit quantity. Contrary to POSIX, this value also
         * counts leap seconds.
         */
        uint32_t seconds = 0;

        /* TSTA: Shall be the 24 least significant bits of the Time Stamp
         * (TIST) field from the STI-D(LI) Frame. The full definition for the
         * STI TIST can be found in annex B of EN 300 797 [4]. The most
         * significant 8 bits of the TIST field of the incoming STI-D(LI)
         * frame, if required, may be carried in the RFAD field.
         */
        uint32_t tsta = 0xFFFFFF;

        // the FIC (optional)
        bool ficf = false;
        const unsigned char* fic_data;
        size_t fic_length;

        // rfu
        bool rfudf = false;
        uint32_t rfud = 0;


};

// ETSI TS 102 693, 5.1.5 ETI Sub-Channel Stream <n>
class TagESTn : public TagItem
{
    public:
        std::vector<uint8_t> Assemble();

        // SSTCn
        uint8_t  scid;
        uint16_t sad;
        uint8_t  tpl;
        uint8_t  rfa;

        // Pointer to MSTn data
        uint8_t* mst_data;
        size_t mst_length; // STLn * 8 bytes

        uint8_t id;
};

// ETSI TS 102 693, 5.1.2 DAB STI-D(LI) Management
class TagDSTI : public TagItem
{
    public:
        std::vector<uint8_t> Assemble();

        // dsti Header
        bool stihf = false;
        bool atstf = false; // presence of atst data
        bool rfadf = false;
        uint16_t dlfc = 0; // modulo 5000 frame counter

        // STI Header (optional)
        uint8_t stat = 0;
        uint16_t spid = 0;

        /* UTCO: Offset (in seconds) between UTC and the Seconds value. The
         * value is expressed as an unsigned 8-bit quantity. As of February
         * 2009, the value shall be 2 and shall change as a result of each
         * modification of the number of leap seconds, as proscribed by
         * International Earth Rotation and Reference Systems Service (IERS).
         *
         * According to Annex F
         *  EDI = TAI - 32s (constant)
         *  EDI = UTC + UTCO
         * we derive
         *  UTCO = TAI-UTC - 32
         * where the TAI-UTC offset is given by the USNO bulletin using
         * the ClockTAI module.
         */
        uint8_t utco = 0;

        /* Update the EDI time. t is in UTC */
        void set_edi_time(const std::time_t t, int tai_utc_offset);

        /* The number of SI seconds since 2000-01-01 T 00:00:00 UTC as an
         * unsigned 32-bit quantity. Contrary to POSIX, this value also
         * counts leap seconds.
         */
        uint32_t seconds = 0;

        /* TSTA: Shall be the 24 least significant bits of the Time Stamp
         * (TIST) field from the STI-D(LI) Frame. The full definition for the
         * STI TIST can be found in annex B of EN 300 797 [4]. The most
         * significant 8 bits of the TIST field of the incoming STI-D(LI)
         * frame, if required, may be carried in the RFAD field.
         */
        uint32_t tsta = 0xFFFFFF;

        std::array<uint8_t, 9> rfad;

    private:
        int tai_offset_cache = 0;
        std::time_t tai_offset_cache_updated_at = 0;
};

// ETSI TS 102 693, 5.1.4 STI-D Payload Stream <m>
class TagSSm : public TagItem
{
    public:
        std::vector<uint8_t> Assemble();

        // SSTCn
        uint8_t rfa = 0;
        uint8_t tid = 0; // See EN 300 797, 5.4.1.1. Value 0 means "MSC sub-channel"
        uint8_t tidext = 0; // EN 300 797, 5.4.1.3, Value 0 means "MSC audio stream"
        bool crcstf = false;
        uint16_t stid = 0;

        // Pointer to ISTDm data
        const uint8_t *istd_data;
        size_t istd_length; // bytes

        uint16_t id = 0;
};

// ETSI TS 102 821, 5.2.2.2 Dummy padding
class TagStarDMY : public TagItem
{
    public:
        /* length is the TAG value length in bytes */
        TagStarDMY(uint32_t length) : length_(length) {}
        std::vector<uint8_t> Assemble();

    private:
        uint32_t length_;
};

// Custom TAG that carries version information of the EDI source
class TagODRVersion : public TagItem
{
    public:
        TagODRVersion(const std::string& version, uint32_t uptime_s);
        std::vector<uint8_t> Assemble();

    private:
        std::string m_version;
        uint32_t m_uptime;
};

// Custom TAG that carries audio level metadata
class TagODRAudioLevels : public TagItem
{
    public:
        TagODRAudioLevels(int16_t audiolevel_left, int16_t audiolevel_right);
        std::vector<uint8_t> Assemble();

    private:
        int16_t m_audio_left;
        int16_t m_audio_right;
};

}