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_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