1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANALYZER_MANCHESTER_ENCODER_H
18 #define ANALYZER_MANCHESTER_ENCODER_H
19 
20 #include <cstdint>
21 
22 /**
23  * Encode bytes using Manchester Coding scheme.
24  *
25  * Manchester Code is self clocking.
26  * There is a transition in the middle of every bit.
27  * Zero is high then low.
28  * One is low then high.
29  *
30  * This avoids having long DC sections that would droop when
31  * passed though analog circuits with AC coupling.
32  *
33  * IEEE 802.3 compatible.
34  */
35 
36 class ManchesterEncoder {
37 public:
ManchesterEncoder(int samplesPerPulse)38     ManchesterEncoder(int samplesPerPulse)
39             : mSamplesPerPulse(samplesPerPulse)
40             , mSamplesPerPulseHalf(samplesPerPulse / 2)
41             , mCursor(samplesPerPulse) {
42     }
43 
44     virtual ~ManchesterEncoder() = default;
45 
46     /**
47      * This will be called when the next byte is needed.
48      * @return
49      */
50     virtual uint8_t onNextByte() = 0;
51 
52     /**
53      * Generate the next floating point sample.
54      * @return
55      */
nextFloat()56     virtual float nextFloat() {
57         advanceSample();
58         if (mCurrentBit) {
59             return (mCursor < mSamplesPerPulseHalf) ? -1.0f : 1.0f; // one
60         } else {
61             return (mCursor < mSamplesPerPulseHalf) ? 1.0f : -1.0f; // zero
62         }
63     }
64 
65 protected:
66     /**
67      * This will be called when a new bit is ready to be encoded.
68      * It can be used to prepare the encoded samples.
69      * @param current
70      */
onNextBit(bool)71     virtual void onNextBit(bool /* current */) {};
72 
advanceSample()73     void advanceSample() {
74         // Are we ready for a new bit?
75         if (++mCursor >= mSamplesPerPulse) {
76             mCursor = 0;
77             if (mBitsLeft == 0) {
78                 mCurrentByte = onNextByte();
79                 mBitsLeft = 8;
80             }
81             --mBitsLeft;
82             mCurrentBit = (mCurrentByte >> mBitsLeft) & 1;
83             onNextBit(mCurrentBit);
84         }
85     }
86 
getCurrentBit()87     bool getCurrentBit() {
88         return mCurrentBit;
89     }
90 
91     const int mSamplesPerPulse;
92     const int mSamplesPerPulseHalf;
93     int       mCursor;
94     int       mBitsLeft = 0;
95     uint8_t   mCurrentByte = 0;
96     bool      mCurrentBit = false;
97 };
98 #endif //ANALYZER_MANCHESTER_ENCODER_H
99