aboutsummaryrefslogtreecommitdiff
path: root/apps/OboeTester/app/src/main/cpp/analyzer/ManchesterEncoder.h
blob: b3d12b313e23bed401749cba44d7a3dcea7c3e6a (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
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANALYZER_MANCHESTER_ENCODER_H
#define ANALYZER_MANCHESTER_ENCODER_H

#include <cstdint>

/**
 * Encode bytes using Manchester Coding scheme.
 *
 * Manchester Code is self clocking.
 * There is a transition in the middle of every bit.
 * Zero is high then low.
 * One is low then high.
 *
 * This avoids having long DC sections that would droop when
 * passed though analog circuits with AC coupling.
 *
 * IEEE 802.3 compatible.
 */

class ManchesterEncoder {
public:
    ManchesterEncoder(int samplesPerPulse)
            : mSamplesPerPulse(samplesPerPulse)
            , mSamplesPerPulseHalf(samplesPerPulse / 2)
            , mCursor(samplesPerPulse) {
    }

    /**
     * This will be called when the next byte is needed.
     * @return
     */
    virtual uint8_t onNextByte() = 0;

    /**
     * Generate the next floating point sample.
     * @return
     */
    virtual float nextFloat() {
        advanceSample();
        if (mCurrentBit) {
            return (mCursor < mSamplesPerPulseHalf) ? -1.0f : 1.0f; // one
        } else {
            return (mCursor < mSamplesPerPulseHalf) ? 1.0f : -1.0f; // zero
        }
    }

protected:
    /**
     * This will be called when a new bit is ready to be encoded.
     * It can be used to prepare the encoded samples.
     * @param current 
     */
    virtual void onNextBit(bool current) {};
    
    void advanceSample() {
        // Are we ready for a new bit?
        if (++mCursor >= mSamplesPerPulse) {
            mCursor = 0;
            if (mBitsLeft == 0) {
                mCurrentByte = onNextByte();
                mBitsLeft = 8;
            }
            --mBitsLeft;
            mCurrentBit = (mCurrentByte >> mBitsLeft) & 1;
            onNextBit(mCurrentBit);
        }
    }

    bool getCurrentBit() {
        return mCurrentBit;
    }

    const int mSamplesPerPulse;
    const int mSamplesPerPulseHalf;
    int       mCursor;
    int       mBitsLeft = 0;
    uint8_t   mCurrentByte = 0;
    bool      mCurrentBit = false;
};
#endif //ANALYZER_MANCHESTER_ENCODER_H