• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 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 next byte
49      */
50     virtual uint8_t onNextByte() = 0;
51 
52     /**
53      * Generate the next floating point sample.
54      * @return next float
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      */
onNextBit(bool)70     virtual void onNextBit(bool /* current */) {};
71 
advanceSample()72     void advanceSample() {
73         // Are we ready for a new bit?
74         if (++mCursor >= mSamplesPerPulse) {
75             mCursor = 0;
76             if (mBitsLeft == 0) {
77                 mCurrentByte = onNextByte();
78                 mBitsLeft = 8;
79             }
80             --mBitsLeft;
81             mCurrentBit = (mCurrentByte >> mBitsLeft) & 1;
82             onNextBit(mCurrentBit);
83         }
84     }
85 
getCurrentBit()86     bool getCurrentBit() {
87         return mCurrentBit;
88     }
89 
90     const int mSamplesPerPulse;
91     const int mSamplesPerPulseHalf;
92     int       mCursor;
93     int       mBitsLeft = 0;
94     uint8_t   mCurrentByte = 0;
95     bool      mCurrentBit = false;
96 };
97 #endif //ANALYZER_MANCHESTER_ENCODER_H
98