File: dvcontroller.h

package info (click to toggle)
serialdv 1.1.4-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 540 kB
  • sloc: cpp: 1,553; makefile: 2
file content (169 lines) | stat: -rw-r--r-- 7,805 bytes parent folder | download | duplicates (2)
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
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB.                                  //
//                                                                               //
// 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 as version 3 of the License, or                  //
//                                                                               //
// 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 V3 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/>.          //
///////////////////////////////////////////////////////////////////////////////////

#ifndef DVCONTROLLER_H_
#define DVCONTROLLER_H_

#include <string>

#include "serialdv_export.h"

namespace SerialDV
{

class DataController;

const unsigned int MBE_AUDIO_BLOCK_SIZE  = 160U;
const unsigned int MBE_AUDIO_BLOCK_BYTES = MBE_AUDIO_BLOCK_SIZE * 2U;
const unsigned int MBE_FRAME_MAX_LENGTH_BYTES = 18U;

const unsigned char DV3000_START_BYTE   = 0x61U;

const unsigned char DV3000_TYPE_CONTROL = 0x00U;
const unsigned char DV3000_TYPE_AMBE    = 0x01U;
const unsigned char DV3000_TYPE_AUDIO   = 0x02U;

const unsigned char DV3000_CONTROL_RATEP  = 0x0AU;
const unsigned char DV3000_CONTROL_GAIN   = 0x4BU;
const unsigned char DV3000_CONTROL_PRODID = 0x30U;
const unsigned char DV3000_CONTROL_READY  = 0x39U;

const unsigned char DV3000_REQ_PRODID[] = {DV3000_START_BYTE, 0x00U, 0x01U, DV3000_TYPE_CONTROL, DV3000_CONTROL_PRODID};
const unsigned int DV3000_REQ_PRODID_LEN = 5U;

const unsigned char DV3000_REQ_3600X2400_RATEP[]   = {DV3000_START_BYTE, 0x00U, 0x0DU, DV3000_TYPE_CONTROL, DV3000_CONTROL_RATEP, 0x01U, 0x30U, 0x07U, 0x63U, 0x40U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x48U};
const unsigned char DV3000_REQ_3600X2450_RATEP[]   = {DV3000_START_BYTE, 0x00U, 0x0DU, DV3000_TYPE_CONTROL, DV3000_CONTROL_RATEP, 0x04U, 0x31U, 0x07U, 0x54U, 0x24U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x6FU, 0x48U};

const unsigned char DV3000_REQ_7200X4400_1_RATEP[] = {DV3000_START_BYTE, 0x00U, 0x0DU, DV3000_TYPE_CONTROL, DV3000_CONTROL_RATEP, 0x00U, 0x58U, 0x08U, 0x87U, 0x30U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x44U, 0x90U};
const unsigned char DV3000_REQ_7200X4400_2_RATEP[] = {DV3000_START_BYTE, 0x00U, 0x0DU, DV3000_TYPE_CONTROL, DV3000_CONTROL_RATEP, 0x02U, 0x58U, 0x07U, 0x65U, 0x00U, 0x09U, 0x1EU, 0x0CU, 0x41U, 0x27U, 0x73U, 0x90U};
const unsigned char DV3000_REQ_7200X4400_3_RATEP[] = {DV3000_START_BYTE, 0x00U, 0x0DU, DV3000_TYPE_CONTROL, DV3000_CONTROL_RATEP, 0x04U, 0x58U, 0x09U, 0x86U, 0x80U, 0x20U, 0x00U, 0x00U, 0x00U, 0x00U, 0x73U, 0x90U};

const unsigned char DV3000_REQ_2450_RATEP[]        = {DV3000_START_BYTE, 0x00U, 0x0DU, DV3000_TYPE_CONTROL, DV3000_CONTROL_RATEP, 0x04U, 0x31U, 0x07U, 0x54U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x70U, 0x31U};
const unsigned char DV3000_REQ_4400_RATEP[]        = {DV3000_START_BYTE, 0x00U, 0x0DU, DV3000_TYPE_CONTROL, DV3000_CONTROL_RATEP, 0x04U, 0x58U, 0x09U, 0x86U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x44U, 0x58U};
const unsigned int DV3000_REQ_RATEP_LEN = 17U;

const unsigned char DV3000_REQ_GAIN[] = {DV3000_START_BYTE, 0x00U, 0x03U, DV3000_TYPE_CONTROL, DV3000_CONTROL_GAIN}; // followed by 1 byte input gain and 1 byte output gain
const unsigned int DV3000_REQ_GAIN_LEN = 5U;

const unsigned char DV3000_AUDIO_HEADER[] = {DV3000_START_BYTE, 0x01U, 0x42U, DV3000_TYPE_AUDIO, 0x00U, 0xA0U};
const unsigned char DV3000_AUDIO_HEADER_LEN = 6U;

const unsigned char DV3000_AMBE_HEADER[] = {DV3000_START_BYTE, 0x00U, 0x0BU, DV3000_TYPE_AMBE, 0x01U, 0x48U};
const unsigned char DV3000_AMBE_HEADER_LEN  = 6U;

const unsigned int DV3000_HEADER_LEN = 4U;

typedef enum
{
    DVRateNone,
    DVRate3600x2400, //!< D-Star
    DVRate3600x2450, //!< DMR, dPMR, YSF V/D type 1
    DVRate7200x4400,
    DVRate7100x4400,
    DVRate2400,
    DVRate2450,      //!< YSF V/D type 2 (does not use FEC in AMBE codec)
    DVRate4400
} DVRate;

class SERIALDV_API DVController
{
public:
	DVController();
	~DVController();

    bool open(const std::string& device, bool halfSpeed=false);
    void close();
    bool isOpen() const { return m_open; }

	/** Encoding process of one audio frame to one AMBE frame
	 * Buffers are supposed to be allocated with the correct size. That is
	 * - 320 bytes (160 short samples) for the audio frame.
	 *   - SerialDV::MBE_AUDIO_BLOCK_BYTES constant is the number of bytes (320)
	 *   - SerialDV::MBE_AUDIO_BLOCK_SIZE constant is the number of short samples (160)
	 * - 9 or 18 bytes (72 or 144 bits) for the AMBE frame.
	 *   - SerialDV::VOICE_FRAME_MAX_LENGTH_BYTES constant is the maximum number of bytes (18)
	 */
	bool encode(const short *audioFrame, unsigned char *mbeFrame, DVRate rate, int gain = 0);

	/** Encoding process of one AMBE frame to one audio frame
	 * Buffers are supposed to be allocated with the correct size. That is
	 * - 320 bytes (160 short samples) for the audio frame.
	 *   - SerialDV::MBE_AUDIO_BLOCK_BYTES constant is the number of bytes (320)
	 *   - SerialDV::MBE_AUDIO_BLOCK_SIZE constant is the number of short samples (160)
	 * - 9 or 18 bytes (72 or 144 bits) for the AMBE frame.
     *   - SerialDV::VOICE_FRAME_MAX_LENGTH_BYTES constant is the maximum number of bytes (18)
	 */
	bool decode(short *audioFrame, const unsigned char *mbeFrame, DVRate rate, int gain = 0);

	/** Returns the number of bytes in a MBE frame given the MBE rate
	 */
	static unsigned short getNbMbeBytes(DVRate mbeRate);

    /** Returns the number of bits in a MBE frame given the MBE rate
     */
    static unsigned char getNbMbeBits(DVRate mbeRate);

private:

    enum RESP_TYPE {
        RESP_NONE,
        RESP_ERROR,
        RESP_RATEP,
        RESP_NAME,
        RESP_AMBE,
        RESP_AUDIO,
        RESP_GAIN,
        RESP_UNKNOWN
    };

    DataController *m_serial;
    bool m_open; //!< True if the serial DV device has been correctly opened
    DVRate m_currentRate;
    int m_currentGainIn;
    int m_currentGainOut;
    unsigned char m_currentNbMbeBits;
    unsigned short m_currentNbMbeBytes;
    bool m_littleEndian;

    bool isLittleEndian()
    {
        short int number = 0x1;
        char *numPtr = (char*)&number;
        return (numPtr[0] == 1);
    }

    void encodeIn(const short* audio, unsigned int length);
    bool encodeOut(unsigned char* ambe, unsigned int length);

    void decodeIn(const unsigned char* ambe, unsigned char nbBits, unsigned short nbBytes);
    bool decodeOut(short* audio, unsigned int length);

    bool setRate(DVRate rate);

    /** Set input and output gain in dB (-90 to +90 dB)
     * If the input gain is < 0 dB then the input speech samples are attenuated prior to encoding.
     * If the input gain is > 0 dB then the input speech samples are amplified prior to encoding.
     * If the output gain is < 0 dB then the output speech samples are attenuated after decoding.
     * If the output gain is > 0 dB then the output speech samples are amplified after decoding.
     */
    bool setGain(signed char dBGainIn, signed char dBGainOut);

    RESP_TYPE getResponse(unsigned char* buffer, unsigned int length);
};

} // namespace SerialDV

#endif /* DVCONTROLLER_H_ */