/****************************************************************************
 * WEAVE.C                                                                  *
 *                                                                          *
 * Purpose: Demonstrates frame capturing with the Rage 128 and the ATI TV   *
 *          Tuner card (Brooktree 8x9 decoder)                              *
 *                                                                          *
 * Copyright (C) 1999 ATI Technologies Inc.  All rights reserved.           *
 ****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <ctype.h>
#include "..\util\main.h"
#include "..\util\defines.h"
#include "..\util\regdef.h"

DWORD SRCWIDTH = 640;
DWORD SRCHEIGHT = 240; // we're only capturing one field at a time.
DWORD OVWIDTH = 640;
DWORD OVHEIGHT = 480;
BYTE FORMAT = 0; // 0 = 640x480, 1 = 720x480, 2 = 320x240
WORD CHANNEL = 24;
BYTE INPUT = DEC_SRC_TUNER; // 1 = COMPOSITE, 2 = TUNER, 3 = SVIDEO

void SetOverlayDetailedSurface (CAPTURE_DESCRIPTOR *cap);

/****************************************************************************
 * Main Program to demonstrate 'weaving' video capture                      *
 *  Function: Enables capture with the Bt8x9 chip, using the selected       *
 *            video input.                                                  *
 *    Inputs: Arguments for mode spatial and colour resolution              *
 *   Outputs: NONE                                                          *
 ****************************************************************************/
void main (int argc, char *argv[])
{
    DWORD x, y, offset, temp, phase;
    char input;
    char buffer[80];
    CAPTURE_DESCRIPTOR cap;

    R128_StartUp (argc, argv);
    R128_ClearScreen (BLACK);
    R128_LoadText ();

    // Initialize and enable the R128 capture 0 unit
    R128_InitCaptureDescriptor (&cap);
    // set up the capture buffers and other fields we want to use
    cap.buf0_offset = 0;
    cap.buf0_even_offset = SRCWIDTH * 2;
    cap.input_mode = CAP_MODE_CONTINUOUS;
    cap.buf_mode = CAP_BUF_MODE_SINGLE;
    cap.buf_type = CAP_BUF_TYPE_FRAME;
    cap.video_in_format = CAP_VIDEO_IN_FORMAT_VYUY422;
    cap.stream_format = CAP_STREAM_FORMAT_BT;
    cap.buf_pitch = SRCWIDTH*4;
    cap.width = SRCWIDTH;
    cap.height = SRCHEIGHT;

    R128_InitCapture (&cap);
    R128_EnableCapture ();

    // set up the I2C engine
    R128_GetPLLInfo ();
    R128_SetI2CInfo (10000);  // use a 10 kHz clock

    // enable I2C hardware
    I2C_Enable ();

    R128_GetI2CAddressInfo ();
    GetCaptureCardType ();

/*    if (AddressInfo.BoardID == 0)
    {
        // shut down.  No ATI TV Tuner card detected.
        R128_DisableCapture ();
        I2C_Stop ();
        I2C_Disable ();
        R128_ShutDown ();
        printf ("\nCould not detect ATI TV Tuner.\nShutting down.");
        exit (1);
    }
  */
    // Set up the overlay.  The overlay buffer will be at offset
    // 0, at the start of the frame buffer.
    offset = 0;
    R128_InitOverlayDescriptor (&OverlayDescriptor);
    R128_GetBandwidthInfo (&OverlayDescriptor);
    R128_SetOverlayDefaults (0xB, SRCWIDTH, SRCHEIGHT*2, 1.0, 1.0, &OverlayDescriptor);
    R128_SetupOverlay (&OverlayDescriptor, &OverlayRegFields);
    SetOverlayDetailedSurface (&cap);
//    R128_SetOverlayColourKey (LIGHTMAGENTA, WHITE, 5, 0, 0);

    // Enable the decoder for default operation: 640x480 NTSC capture,
    // composite input.
    R128_SetDecoderDefaults (FORMAT, INPUT);

    // at this point, you should be seeing the captured video on the screen.
    // The actual captured data (in YUV format) will be in the top left,
    // while the overlay, with the converted data is in the bottom right.
    // The overlay it being displayed at 640x480.
    x = R128_AdapterInfo.xres-OVWIDTH;
    y = R128_AdapterInfo.yres-OVHEIGHT;

    INPUT = DEC_SRC_TUNER;
    R128_SetDecoderSource (INPUT);
    R128_SetTunerChannel (CHANNEL);
    EnableDecoder();
    R128_ClearScreen (BLACK);
    // Draw the keying rectangle.
    R128_DrawRectangle (x, y, OVWIDTH, OVHEIGHT, LIGHTMAGENTA);
    if (INPUT == DEC_SRC_TUNER)
    {
        sprintf (buffer, "Channel: %d", CHANNEL);
        R128_PrintText (buffer, x+5, y+5, LIGHTGREEN, WHITE, 1);
    }
    R128_SetOverlay (x, y, OVWIDTH, OVHEIGHT);

    phase = 0;

    while ((input = getch ())!=27)
    {
        switch (toupper(input))
        {
            case 'C':   cap.input_mode = CAP_MODE_CONTINUOUS;
                        R128_SetCaptureConfig (&cap);
                        break;
            case 'T':   cap.input_mode = CAP_MODE_ONE_SHOT;
                        R128_SetCaptureConfig (&cap);
                        // set the trigger to capture a frame
                        R128_WaitForFifo (2);
                        temp = regr (CAP0_TRIG_CNTL) | 0x1;
                        regw (CAP0_TRIG_CNTL, temp);
                        break;
            case '1':   // set for composite input to be used.
                        INPUT = DEC_SRC_COMPOSITE;
                        R128_SetDecoderSource (INPUT);
                        break;
            case '2':   // set for tuner input.
                        // make sure we are in continuous capture mode first.
                        cap.input_mode = CAP_MODE_CONTINUOUS;
                        R128_SetCaptureConfig (&cap);

                        INPUT = DEC_SRC_TUNER;
                        R128_SetDecoderSource (INPUT);
                        R128_SetTunerChannel (CHANNEL);
                        break;
            case '3':   // set for S-video input
                        INPUT = DEC_SRC_SVIDEO;
                        R128_SetDecoderSource (INPUT);
                        break;
            case '+':   if (INPUT == DEC_SRC_TUNER)
                        {
                            CHANNEL++;
                            if (CHANNEL >= 125) CHANNEL = 1;
                            R128_SetTunerChannel (CHANNEL);
                        }
                        break;
            case '-':   if (INPUT == DEC_SRC_TUNER)
                        {
                            CHANNEL--;
                            if (CHANNEL == 0) CHANNEL = 125;
                            R128_SetTunerChannel (CHANNEL);
                        }
                        break;
            default:    break;
        }

        // Draw the keying rectangle.
        R128_DrawRectangle (x, y, OVWIDTH, OVHEIGHT, LIGHTMAGENTA);
        if (INPUT == DEC_SRC_TUNER)
        {
            sprintf (buffer, "Channel: %d", CHANNEL);
            R128_PrintText (buffer, x+5, y+5, LIGHTGREEN, WHITE, 1);
        }
        R128_SetOverlay (x, y, OVWIDTH, OVHEIGHT);

    }

    R128_DisableCapture ();

    I2C_Stop ();
    I2C_Disable ();

    R128_DisableOverlay ();
    R128_Delay (5);
    R128_ShutDown ();

    exit (0);
} // main ()...

/****************************************************************************
 * SetOverlayDetailedSurface (CAPTURE_DESCRIPTOR *cap)                      *
 *  Function: sets the buffer addresses for multiple overlay buffers.       *
 *    Inputs: CAPTURE_DESCRIPTOR *cap - pointer to capture structure        *
 *   Outputs: NONE                                                          *
 ****************************************************************************/
void SetOverlayDetailedSurface (CAPTURE_DESCRIPTOR *cap)
{
    DWORD offset, offset2, offset3, offset4;

    offset = cap->buf0_offset;
    offset2 = cap->buf0_even_offset;
    offset3 = offset4 = offset2;

    OverlayDescriptor.USE_DETAILED_SURFACE_DESCRIPTION = 1;
    OverlayDescriptor.AutoFlipVideoProvider = 0; // use cap port 0

    OverlayDescriptor.BaseOffsetOfSurface[0] = offset;
    OverlayDescriptor.BaseOffsetOfSurface[1] = offset2;
    OverlayDescriptor.BaseOffsetOfSurface[2] = offset3;
    OverlayDescriptor.BaseOffsetOfSurface[3] = offset4;
    OverlayDescriptor.PitchSelectOfSurface[0] = 0;
    OverlayDescriptor.PitchSelectOfSurface[1] = 0;
    OverlayDescriptor.TiledFlagOfSurface[0] = 0;
    OverlayDescriptor.TiledFlagOfSurface[1] = 0;
    OverlayDescriptor.SurfacePitch[0] = SRCWIDTH*2;
    OverlayDescriptor.SurfacePitch[1] = SRCWIDTH*2;
    R128_SetupOverlay (&OverlayDescriptor, &OverlayRegFields);

    OverlayRegFields.val_OV0_VID_PORT_SELECT = 0;
    OverlayRegFields.val_OV0_DEINT_PAT = 0xAAAAA;
    R128_WriteOverlayFields (&OverlayRegFields);

} // SetOverlayDetailedSurface ()...


