• Home
  • History
  • Annotate
  • 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_ROUNDED_MANCHESTER_ENCODER_H
18  #define ANALYZER_ROUNDED_MANCHESTER_ENCODER_H
19  
20  #include <math.h>
21  #include <memory.h>
22  #include <stdlib.h>
23  #include "ManchesterEncoder.h"
24  
25  /**
26   * Encode bytes using Manchester Code.
27   * Round the edges using a half cosine to reduce ringing caused by a hard edge.
28   */
29  
30  class RoundedManchesterEncoder : public ManchesterEncoder {
31  public:
RoundedManchesterEncoder(int samplesPerPulse)32      RoundedManchesterEncoder(int samplesPerPulse)
33              : ManchesterEncoder(samplesPerPulse) {
34          int rampSize = samplesPerPulse / 4;
35          mZeroAfterZero = std::make_unique<float[]>(samplesPerPulse);
36          mZeroAfterOne = std::make_unique<float[]>(samplesPerPulse);
37  
38          int sampleIndex = 0;
39          for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
40              float phase = (rampIndex + 1) * M_PI / rampSize;
41              float sample = -cosf(phase);
42              mZeroAfterZero[sampleIndex] = sample;
43              mZeroAfterOne[sampleIndex] = 1.0f;
44              sampleIndex++;
45          }
46          for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
47              mZeroAfterZero[sampleIndex] = 1.0f;
48              mZeroAfterOne[sampleIndex] = 1.0f;
49              sampleIndex++;
50          }
51          for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
52              float phase = (rampIndex + 1) * M_PI / rampSize;
53              float sample = cosf(phase);
54              mZeroAfterZero[sampleIndex] = sample;
55              mZeroAfterOne[sampleIndex] = sample;
56              sampleIndex++;
57          }
58          for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
59              mZeroAfterZero[sampleIndex] = -1.0f;
60              mZeroAfterOne[sampleIndex] = -1.0f;
61              sampleIndex++;
62          }
63      }
64  
onNextBit(bool current)65      void onNextBit(bool current) override {
66          // Do we need to use the rounded edge?
67          mCurrentSamples = (current ^ mPreviousBit)
68                            ? mZeroAfterOne.get()
69                            : mZeroAfterZero.get();
70          mPreviousBit = current;
71      }
72  
nextFloat()73      float nextFloat() override {
74          advanceSample();
75          float output = mCurrentSamples[mCursor];
76          if (getCurrentBit()) output = -output;
77          return output;
78      }
79  
80  private:
81  
82      bool mPreviousBit = false;
83      float *mCurrentSamples = nullptr;
84      std::unique_ptr<float[]> mZeroAfterZero;
85      std::unique_ptr<float[]> mZeroAfterOne;
86  };
87  
88  #endif //ANALYZER_ROUNDED_MANCHESTER_ENCODER_H
89