
#include "stdio.h"
#include "assert.h"
#include "windows.h"
#include "math.h"
#include "Shared.h"

// #define VC20

//################################################### Mode0_ProcessLine
void Mode0_ProcessLine(TUSBItem_Line* USBItem)
{
  if(Blit==NULL)
  {
    int Size_nx = _nSample*_nSub/1;
    int Size_ny = 288*2;
    // 32*2 Vollbilder -> 2.56s
    Blit = new TBlit(Size_nx, Size_ny, "2.56 s");
  }

  int iFrame = _State.VSyncCnt&ImgMsk;

  AddToImgArr(USBItem, iFrame);

  int iLine = _iLine;
  iFrame = (iFrame-12)&ImgMsk;

  if(iLine-22>=0 && iLine-22<288 && (iFrame&4)==0)
  {
     // SubImageOfs für aufeinanderfolgende Halbbilder
     // - Mode 0
     //   0  0  1  1
     //   0  0  1  1
     //   2  2  3  3
     //   2  2  3  3
     //   4  4  5  5
     //   ...
    TUSBItem_LineEx* Line0 = ImgArr[(iFrame+ 0 + 0*4)&ImgMsk].Img+iLine;
    TUSBItem_LineEx* Line1 = ImgArr[(iFrame+ 0 + 2*4)&ImgMsk].Img+iLine;
    TUSBItem_LineEx* Line2 = ImgArr[(iFrame+ 4 + 0*4)&ImgMsk].Img+iLine;
    TUSBItem_LineEx* Line3 = ImgArr[(iFrame+ 4 + 2*4)&ImgMsk].Img+iLine;
    #ifdef VC20
    {
      // Beim VC20 ist die PAL-Phase (entgegen dem Standard) über alle Frames
      // gleich (für PAL ist eigentlich 90° pro Frame definiert). Die Meßwerte
      // für die 90° (bzw. 270°) Farbphase muss von einem anderen Orten
      // genommen werden. Falls dort die Farbe oder Helligkeit anders ist, 
      // führt das unvermeidlich zu Farb- und Helligkeitsfehlern. Folge sind
      // farbige Ränder um Konturen.
      // (Außerdem ist beim VC20 anscheinend ein "_dphiColor_degree = 22;" 
      // sinnvoll - aber warum?)
      Line2 = ImgArr[(iFrame+ 0 - 4*4)&ImgMsk].Img+iLine; // -180°
      Line3 = ImgArr[(iFrame+ 0 - 2*4)&ImgMsk].Img+iLine; //  -90°
    }
    #endif
    InitLine(Line0, Line0);
    InitLine(Line0, Line1);
    InitLine(Line0, Line2);
    InitLine(Line0, Line3);

    if(_iLine==100 && (iFrame&1)==0 && 1==2)
    {
      printf("%5i - %i%i%i%i - %2i %2i %2i %2i- %5i %5i %5i %5i\n",
             iFrame,
             Line0->Odd, // 0 oder 1
             Line1->Odd, // +0
             Line2->Odd, // +0
             Line3->Odd, // +0
             Line0->SubImageOfs, // 0..31
             Line1->SubImageOfs, // +2
             Line2->SubImageOfs, // +0
             Line3->SubImageOfs, // +2
             int8_t((Line0->BurstPhi-Line2->BurstPhi)/256),  // 128 +-32
             int8_t((Line1->BurstPhi-Line3->BurstPhi)/256),  // 128 +-32
             int8_t((Line0->BurstPhi-Line1->BurstPhi)/256),  //   0 +-32
             int8_t((Line2->BurstPhi-Line3->BurstPhi)/256)); //   0 +-32 
    }

    if(iLine-22>=0 && iLine-22<288 && 1==2)
    {
      // Phase
      static int Hist[256];
      static int Max = 1;
      uint8_t dp = (Line2->BurstPhi-Line0->BurstPhi)/256;
      dp = (128+(rand()%32)-(rand()%32)); // Sollwert
      if(_TotalLine>2*15625) Hist[dp]++;
      static int x;
      HDC PnDC = Blit->GetDC();
      BitBlt(PnDC, x, 0, 1, 256, NULL, 0, 0, WHITENESS);
      MoveToEx(PnDC, x, 256, NULL);
      if(Hist[x]>Max) Max=Hist[x];
      LineTo(PnDC, x, 256-256*Hist[x]/Max);
      x = (x+1)%256;
    }

    for(int iSample=0; iSample<_nSample; iSample++)
    {
      int xdxColor = _ImageOfs0+_ImageOfs+iSample*_nSub;
      uint16_t Phi0 = uint16_t(xdxColor/1e6/_fADCMHz*fPAL*(1+_dPPM_PAL*1e-6)*65536);
      Phi0 += uint16_t(65536*_dphiColor_degree/360);
      #ifdef VC20
      {
        Phi0 += uint16_t(65536*22/360); // VC20
      }
      #endif

      // 1 Halbild
      // 2 Vollbild 
      // 8 x+1 und Phasengleich
      if(iLine>50 && iLine<280 && _TotalLine>256 && iSample>5 && iSample<45 && 1==2)
      {
        // Amplitude
        static int Hist[256];
        static int Max = 1;
        int p = ImgArr[iFrame].Img[iLine].ADC1[iSample]&0xff;
        Hist[ImgArr[iFrame].Img[iLine].ADC1[iSample]] += 100;
        int x = _TotalLine%256;
        HDC PnDC = Blit->GetDC();
        BitBlt(PnDC, x, 0, 1, 256, NULL, 0, 0, WHITENESS);
        MoveToEx(PnDC, x, 256, NULL);
        Hist[x] -= Hist[x]/10;
        if(Hist[x]>Max) Max=Hist[x];
        LineTo(PnDC, x, 256-256*Hist[x]/Max);
        break;
      }

      // Chroma
      double U = 0;
      double V = 0;
      LineToUV(Line0, Line1, Line2, Line3, Phi0, iSample, &U, &V);

      // Luma
      double Y = 0;
      LineToY(Line0, Line2, Phi0, iSample, U, V, &Y);

      int xx = (iSample*_nSub+Line0->xSub)/1;
      int yy = Line0->y;

      // Mittel über zwei Frames
      if(1==2)
      {
        static double* PrevFrame = NULL;
        static const int Size_nx = _nSample*_nSub;
        static const int Size_ny = 288*2;
        if(PrevFrame==NULL)
        {
          PrevFrame = (double*)malloc(Size_nx*Size_ny*3*sizeof(*PrevFrame));
          ZeroMemory(PrevFrame, Size_nx*Size_ny*3*sizeof(*PrevFrame));
        }
        if(yy>=0 && yy<Size_ny)
        {
          if(xx>=0 && xx<Size_nx)
          {
            int p = (Size_nx*yy+xx)*3;
            double pY = PrevFrame[p+0];
            double pU = PrevFrame[p+1];
            double pV = PrevFrame[p+2];
            PrevFrame[p+0] = Y;
            PrevFrame[p+1] = U;
            PrevFrame[p+2] = V;
            Y = (pY+Y)/2;
            U = (pU+U)/2;
            V = (pV+V)/2;
            // Mittel über drei Pixel
            if(1==2)
            {
              Y = (PrevFrame[p+0]+PrevFrame[p+3]+PrevFrame[p+6])/3;
              U = (PrevFrame[p+1]+PrevFrame[p+4]+PrevFrame[p+7])/3;
              V = (PrevFrame[p+2]+PrevFrame[p+5]+PrevFrame[p+8])/3;
              // xx /= 2;
            }
          }
        }
      }

      DWORD RGB = YUV_to_RGB(Y-_State.RefBlank, U, V);

      Blit->SetPixel(xx, yy, RGB);
    }
  }
  if(iLine==0)
  {
    Blit->DoBlit();
    // Blit->SaveImg();
  }
}
