// File: ke6jjj[P]r-dat/RDATSlopeDecoder.cc
// Function: RDATSlopeDecoder::Process(float*, unsigned long)
void
RDATSlopeDecoder::Process(float *samples, size_t count)
{
  size_t i;
  float signal;
  
  for (i = 0; i < count; i++) {
    //
    // Look at the sample.
    //
    signal = samples[i];
    mSampleNumber++;

    //
    // Update the overall signal level.
    //
    mOverallSignalLevel *= mAlpha;
    mOverallSignalLevel += (1.0 - mAlpha) * fabs(signal);

    //
    // Store the new sample in the symbol window
    //
    mSymbolWindow.Add(signal);

    //
    // Ask the clock detector if now is a good time to sample the signal.
    //
    // This clock detection algorithm needs to be 180 degrees out of phase
    // with the symbol period so that any magnetic pulse picked up by the
    // read head will be centered within the sample period.
    //
    if (mClockDetector.AddAndDetect(signal)) {
      //
      // Evaluate all the samples in the sample window to determine the
      // average slope amonst them.
      //
      float slope = mSymbolWindow.Slope();

      bool zeroCrossed = mSymbolWindow.CrossesZero();

      //
      // If the slope exceeds the detection threshold, mark that we've found
      // a pulse.
      //
      float threshold;
      if (zeroCrossed) {
        threshold = mOverallSignalLevel / mkSamplesPerSymbol * 0.72;
      } else {
        threshold = mOverallSignalLevel / mkSamplesPerSymbol * 3;
      }

      bool pulse = fabs(slope) > threshold;

#if 1
      if (mSampleNumber > 87387) {
#if 0
        printf("%zd overall %g, slope %g, target %g\n",
          mSampleNumber,
          mOverallSignalLevel,
          fabs(slope),
          threshold
        );
#endif
#if 1
        printf(" %zd pulse %d", mSampleNumber, pulse ? 1 : 0);
#endif
      }
#endif
     
      //
      // Signal the decision.
      //
      if (mDecoder != NULL)
        mDecoder->ReceiveBit(pulse);
    }

    //
    // If there's no track in progress, see if a new one has perhaps
    // started.
    //
    if (!mTrackInProgress) {
      //
      // We're in the idle time between tracks. Check if a track has started.
      //
      if (mDecoder != NULL && mDecoder->PreambleDetected()) {
        //
        // A track appears to have started. Start the track progress timer.
        //
        mTrackInProgress = true;
        mTrackSampleCount = mTrackDuration;

        //
        // Notify the downstream decoder.
        //
        mDecoder->TrackDetected(true);
#if 1
        printf("%zd Track started\n", mSampleNumber);
#endif
      }
    } else {
      //
      // There's a track in progress. See if the track timer has expired.
      //
      mTrackSampleCount--;
      if (mTrackSampleCount == 0) {
        //
        // The track should have ended by now. Declare it over.
        //
        mTrackInProgress = false;
        if (mDecoder != NULL)
          mDecoder->TrackDetected(false);
#if 1
        printf("%zd Track stopped\n", mSampleNumber);
#endif
      }
    }
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x40(%rbp)
movq $0x0, -0x20(%rbp)
movq -0x20(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0xd7ca
movq -0x40(%rbp), %rax
movq -0x10(%rbp), %rcx
movq -0x20(%rbp), %rdx
movss (%rcx,%rdx,4), %xmm0
movss %xmm0, -0x24(%rbp)
movq (%rax), %rcx
addq $0x1, %rcx
movq %rcx, (%rax)
movss 0x84(%rax), %xmm0
mulss 0x88(%rax), %xmm0
movss %xmm0, 0x88(%rax)
movss 0x84(%rax), %xmm0
cvtss2sd %xmm0, %xmm1
movsd 0xe0a(%rip), %xmm0      # 0xe318
subsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movss -0x24(%rbp), %xmm0
callq 0x3190
movq -0x40(%rbp), %rdi
movaps %xmm0, %xmm1
movsd -0x48(%rbp), %xmm0
cvtss2sd %xmm1, %xmm2
movss 0x88(%rdi), %xmm1
cvtss2sd %xmm1, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x88(%rdi)
addq $0x58, %rdi
movss -0x24(%rbp), %xmm0
callq 0xd8f0
movq -0x40(%rbp), %rdi
addq $0x10, %rdi
movss -0x24(%rbp), %xmm0
callq 0xcfc0
testb $0x1, %al
jne 0xd57a
jmp 0xd6f3
movq -0x40(%rbp), %rdi
addq $0x58, %rdi
callq 0xd930
movq -0x40(%rbp), %rdi
movss %xmm0, -0x28(%rbp)
addq $0x58, %rdi
callq 0xd9c0
andb $0x1, %al
movb %al, -0x29(%rbp)
testb $0x1, -0x29(%rbp)
je 0xd617
movq -0x40(%rbp), %rax
movss 0x88(%rax), %xmm0
movss %xmm0, -0x54(%rbp)
movq 0x8(%rax), %rax
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x50(%rbp)
testq %rax, %rax
movss %xmm0, -0x4c(%rbp)
js 0xd5ee
movss -0x50(%rbp), %xmm0
movss %xmm0, -0x4c(%rbp)
movss -0x54(%rbp), %xmm0
movss -0x4c(%rbp), %xmm1
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x2638(%rip), %xmm1     # 0xfc40
mulsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, -0x30(%rbp)
jmp 0xd680
movq -0x40(%rbp), %rax
movss 0x88(%rax), %xmm0
movss %xmm0, -0x60(%rbp)
movq 0x8(%rax), %rax
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x5c(%rbp)
testq %rax, %rax
movss %xmm0, -0x58(%rbp)
js 0xd661
movss -0x5c(%rbp), %xmm0
movss %xmm0, -0x58(%rbp)
movss -0x60(%rbp), %xmm0
movss -0x58(%rbp), %xmm1
divss %xmm1, %xmm0
movss 0x2589(%rip), %xmm1     # 0xfc00
mulss %xmm1, %xmm0
movss %xmm0, -0x30(%rbp)
movss -0x28(%rbp), %xmm0
callq 0x3190
movq -0x40(%rbp), %rax
ucomiss -0x30(%rbp), %xmm0
seta %cl
andb $0x1, %cl
movb %cl, -0x31(%rbp)
cmpq $0x1555b, (%rax)        # imm = 0x1555B
jbe 0xd6c9
movq -0x40(%rbp), %rax
movq (%rax), %rsi
movb -0x31(%rbp), %cl
xorl %edx, %edx
movl $0x1, %eax
testb $0x1, %cl
cmovnel %eax, %edx
leaq 0x2586(%rip), %rdi      # 0xfc48
movb $0x0, %al
callq 0x2040
movq -0x40(%rbp), %rax
cmpq $0x0, 0x90(%rax)
je 0xd6f1
movq -0x40(%rbp), %rax
movq 0x90(%rax), %rdi
movb -0x31(%rbp), %cl
movq (%rdi), %rax
andb $0x1, %cl
movzbl %cl, %esi
callq *0x10(%rax)
jmp 0xd6f3
movq -0x40(%rbp), %rax
testb $0x1, 0x80(%rax)
jne 0xd761
movq -0x40(%rbp), %rax
cmpq $0x0, 0x90(%rax)
je 0xd75f
movq -0x40(%rbp), %rax
movq 0x90(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
testb $0x1, %al
jne 0xd725
jmp 0xd75f
movq -0x40(%rbp), %rax
movb $0x1, 0x80(%rax)
movq 0x70(%rax), %rcx
movq %rcx, 0x78(%rax)
movq 0x90(%rax), %rdi
movq (%rdi), %rax
movl $0x1, %esi
callq *0x20(%rax)
movq -0x40(%rbp), %rax
movq (%rax), %rsi
leaq 0x24fe(%rip), %rdi      # 0xfc56
movb $0x0, %al
callq 0x2040
jmp 0xd7b7
movq -0x40(%rbp), %rax
movq 0x78(%rax), %rcx
addq $-0x1, %rcx
movq %rcx, 0x78(%rax)
cmpq $0x0, 0x78(%rax)
jne 0xd7b5
movq -0x40(%rbp), %rax
movb $0x0, 0x80(%rax)
cmpq $0x0, 0x90(%rax)
je 0xd7a0
movq -0x40(%rbp), %rax
movq 0x90(%rax), %rdi
movq (%rdi), %rax
xorl %esi, %esi
callq *0x20(%rax)
movq -0x40(%rbp), %rax
movq (%rax), %rsi
leaq 0x24bb(%rip), %rdi      # 0xfc69
movb $0x0, %al
callq 0x2040
jmp 0xd7b7
jmp 0xd7b9
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0xd4b4
addq $0x60, %rsp
popq %rbp
retq