#include <graphics.h>
#include <stdio.h>
#include <math.h>


#include "dibujos.h"

#define _FREC_F_H
 #include "FREC_F.h"
#undef  _FREC_F_H

#include "FREC.h"

int SaltosMatrixX = 10,             // Saltos en la Matrix X
    SaltosMatrixY = 10;             // Saltos en la Matrix Y

int  IncrementoMarca = 2;           // Incrementos en el despl. de marcas

long MRK_begin=20, MRK_end=50,      // Marcas de comienzo y final originales
     oldMRK_begin = MRK_begin,      // >>>>>>>>>>>>>>>>>>>>>>>>>>>
     oldMRK_end   = MRK_end;        // >>> marcas de arrastre  >>>

char GenOsc = GENERADOR,            // determina para quien son los controles
     GenOscf[2] = { OFF, OFF };     // quien est  funcionando ahora

int  Desplazamiento = 0,            // Desplazamiento virtual de la onda
     mAnchoMarco = 125;             // Ancho a mostrar ( reducido )

long oDesde =   0,                  // Inicio de la onda a mostrar
     oHasta = (mAnchoMarco*5);        // Fin de la onda a mostrar

int  oAncho = oAnchoVentana,        // Ancho de la ventana de visualizaci¢n
     oAlto  = oAltoVentana;         // Alto de la ventana de vizualizaci¢n
                                    // Cero de la onda Generada

int  ceroOGenerada = ( oAltoVentana / 2 ) + 2;

char Tonda = -1;                    // Tipo de onda a tratar
int  Dispersion = 1;                // Dispercion entre puntos


/***************************************************************************\
|*                                                                         *|
|* SeleccionaControles                                                     *|
|*                                                                         *|
|* Descripci¢n:                                                            *|
|*              Selecciona para quien trabajaran casi todos los controles  *|
|*              para el generador o el osciloscopio.                       *|
|*                                                                         *|
|* Entradas: (ninguna)                                                     *|
|* Salidas:  (ninguna)                                                     *|
|*                                                                         *|
\***************************************************************************/
void SeleccionaControles(void)
{
               // Borramos la zona de funcion
               setfillstyle( SOLID_FILL, EGA_LIGHTGRAY );
               bar( 318,   3, 337, 21 );
               if ( GenOsc == GENERADOR )
               {
                GenOsc = OSCILOSCOPIO;
                ponicono( 319,   3, flecha, 1 ); // Flecha dentro
                // Led Off / On
                if ( GenOscf[OSCILOSCOPIO] == OFF )
                                     ponicono( 245,   7, led_off, 1 );
                else
                                     ponicono( 245,   7, led_on, 1 );
               } else {
                GenOsc = GENERADOR;
                ponicono( 319,   3, flecha, 3 ); // Flecha fuera
                // Led Off / On
                if ( GenOscf[GENERADOR] == OFF )
                                     ponicono( 245,   7, led_off, 1 );
                else
                                     ponicono( 245,   7, led_on, 1 );
               }
}

/***************************************************************************\
|*                                                                         *|
|* EnviaRecibe                                                             *|
|*                                                                         *|
|* Descripci¢n:                                                            *|
|*              Activa/Desactiva la funci¢n de enviar/recibir onda.        *|
|*              ( seg£n este seleccionado osciloscopio/generador )         *|
|*                                                                         *|
|* Entradas: (ninguna)                                                     *|
|* Salidas:  (ninguna)                                                     *|
|*                                                                         *|
\***************************************************************************/
void EnviaRecibe(void)
{
               // Enviar/Recibir onda SI / NO
               GenOscf[ GenOsc ] = !GenOscf[ GenOsc ];
               if ( GenOscf[ GenOsc ] == OFF )
                                     ponicono( 245,   7, led_off, 1 );
                else
                                     ponicono( 245,   7, led_on, 1 );
}

/***************************************************************************\
|*                                                                         *|
|* DesplazaMarca                                                           *|
|*                                                                         *|
|* Descripci¢n:                                                            *|
|*              Realiza la funci¢n de dezplazamiento de la marca, con      *|
|*              los cursores, y selecci¢n de toda la onda.                 *|
|*                                                                         *|
|* Entradas:                                                               *|
|*           Incremento en el desplazamiento (puede se negativo)           *|
|*           Marca a desplazar: INICIO, FIN, TODO (marca toda la onda)     *|
|*                                                                         *|
|* Salidas:  (ninguna)                                                     *|
|*                                                                         *|
\***************************************************************************/
void DesplazaMarca( char IncrementoMarca, char InicioFin )
{
 if ( InicioFin == INICIO )
 {
  if ( IncrementoMarca > 0 )
  {
   MRK_begin += IncrementoMarca;
   while ( MRK_begin > MRK_end ) MRK_begin--;
   if ( MRK_begin > (oAnchoVentana * oVentanas) )
                            MRK_begin = (oAnchoVentana * oVentanas);
   Dibuja_OndaSeleccionada( !PINTA );
  } else
  if ( IncrementoMarca < 0 )
  {
   MRK_begin += IncrementoMarca;
   if ( MRK_begin < 0 )
                            MRK_begin = 0;
   Dibuja_OndaSeleccionada( !PINTA );
  }
 } else if ( InicioFin == FIN )
 {
  if ( IncrementoMarca > 0 )
  {
   MRK_end +=IncrementoMarca;
   if ( MRK_end > (oAnchoVentana * oVentanas) )
                            MRK_end = (oAnchoVentana * oVentanas);
   Dibuja_OndaSeleccionada( !PINTA );
  } else
  if ( IncrementoMarca < 0 )
  {
   MRK_end +=IncrementoMarca;
   while ( MRK_end < MRK_begin ) MRK_end ++;
   if ( MRK_end < 0 )
                            MRK_end = 0;
   Dibuja_OndaSeleccionada( !PINTA );
  }
 } else {
   Dibuja_OndaSeleccionada(PINTA);
   MRK_begin = 0;
   MRK_end   = oAnchoVentana * oVentanas;
   Dibuja_OndaSeleccionada(PINTA);
 }


}


/***************************************************************************\
|*                                                                         *|
|* Dibuja_OndaSeleccionada                                                 *|
|*                                                                         *|
|* Descripci¢n:                                                            *|
|*              Dibuja la onda seleccionada.                               *|
|*                                                                         *|
|* Entradas:                                                               *|
|*           PINTA   Redibuja la selecci¢n completa.                       *|
|*          !PINTA   Solo dibuja lo que ha cambiado.                       *|
|*                                                                         *|
|* Salidas:  (ninguna)                                                     *|
|*                                                                         *|
\***************************************************************************/
void Dibuja_OndaSeleccionada( char QueHago )
{
 float xActual;
 int   xReal, yReal;
 float ReduccionX;//, ReduccionYmini;
 static float oldHasta, oldDesde;
 //static long OldDesplazamiento;
 static char PintaBorra = PINTA;

 char tmp, buffer[80];

 if ( QueHago != PINTA )
  {
   tmp = PintaBorra;
   PintaBorra = PINTA;
  }
 // Calculamos el factor de reducci¢n para el ancho de la ventana
 if  ( PintaBorra == PINTA )
      ReduccionX = (float)(oHasta - oDesde) / (float)oAnchoVentana;
 else
      ReduccionX = (float)( oldHasta - oldDesde ) / (float)oAnchoVentana;

//      ReduccionYmini = (float) oAlto / (float)oAltoVentana;

 setwritemode( XOR_PUT );
 setcolor( cfgFREC.oSelect );

 for ( xActual = (PintaBorra == PINTA ? (oDesde + 5 * Desplazamiento ) : oldDesde ), xReal = 0; xReal < oAnchoVentana; xActual += ReduccionX, xReal ++ )
   if ( QueHago == PINTA )
   {
        if ( xActual >= (PintaBorra == PINTA ? MRK_begin : oldMRK_begin ) && xActual <= (PintaBorra == PINTA ? MRK_end : oldMRK_end) )
         line ( xReal + inicioMGx, inicioMGy + SaltosMatrixY, xReal + inicioMGx, inicioMGy+oAltoVentana - SaltosMatrixY );
   } else {
   // Dibuja solo lo necesario de la onda marcada...
        if (
               ( xActual >= oldMRK_begin && xActual < MRK_begin ) ||
               ( xActual <  oldMRK_begin && xActual >= MRK_begin ) ||

               ( xActual > oldMRK_end && xActual <= MRK_end ) ||
               ( xActual <= oldMRK_end && xActual > MRK_end )
           )
         line ( xReal + inicioMGx, inicioMGy + SaltosMatrixY, xReal + inicioMGx, inicioMGy+oAltoVentana - SaltosMatrixY );

   }

 setwritemode( COPY_PUT );

 if ( PintaBorra == PINTA )
 {
                          oldHasta = oHasta + 5*Desplazamiento;
                          oldDesde = oDesde + 5*Desplazamiento;
                          oldMRK_begin = MRK_begin;
                          oldMRK_end   = MRK_end;
                          PintaBorra   = BORRA;
 } else                   PintaBorra   = PINTA;

 if ( QueHago != PINTA )
  {
   PintaBorra = tmp;
   sprintf( buffer, "Selct: %05ld", ( MRK_end-MRK_begin ) );
   Fuente_Amplia( buffer, &Letras );
  }

};

/***************************************************************************\
|*                                                                         *|
|* DesplazaOnda                                                            *|
|*                                                                         *|
|* Descripci¢n:                                                            *|
|*              Mueve la onda en cualquier direcci¢n o la centra vertic.   *|
|*                                                                         *|
|* Entradas:                                                               *|
|*           Lugar a donde ser  movida.   ARRIBA, ABAJO, IZQUIERDA         *|
|*                                        DERECHA, CENTRAR.                *|
|*                                                                         *|
|* Salidas:  (ninguna)                                                     *|
|*                                                                         *|
\***************************************************************************/
void DesplazaOnda( char Lugar )
{
                int oldCero = ceroOGenerada, xM;
                  float xActual;
                  int   xReal;
                  float ReduccionX, ReduccionYmini;

 switch( Lugar )
 {
  case DERECHA:
                 // Limpiamos la zona antigua
                 setwritemode( XOR_PUT );
                 setcolor( cfgFREC.mMarco );
                 rectangle( 8 + Desplazamiento, inicioMmGy, 8 + mAnchoMarco + Desplazamiento, inicioMmGy + mAltoCuadro );
                 Desplazamiento += 5; if ( ( mAnchoMarco + Desplazamiento ) > oAnchoVentana ) Desplazamiento = oAnchoVentana - mAnchoMarco;

                 rectangle( 8 + Desplazamiento, inicioMmGy, 8 + mAnchoMarco + Desplazamiento, inicioMmGy + mAltoCuadro );
                 setwritemode( COPY_PUT );
                 // Tras desplazar redibujamos la onda
                 DibujaOnda(oDesde + 5 * Desplazamiento, oHasta + 5 * Desplazamiento,  oAnchoVentana, oAltoVentana, GRANDEo );
       break;
  case IZQUIERDA:
                 // Limpiamos la zona antigua
                 setwritemode( XOR_PUT );
                 setcolor( cfgFREC.mMarco );
                 rectangle( 8 + Desplazamiento, inicioMmGy, 8 + mAnchoMarco + Desplazamiento, inicioMmGy + mAltoCuadro );
                 Desplazamiento -= 5; if ( Desplazamiento < 0 ) Desplazamiento = 0;

                 rectangle( 8 + Desplazamiento, inicioMmGy, 8 + mAnchoMarco + Desplazamiento, inicioMmGy + mAltoCuadro );
                 setwritemode( COPY_PUT );
                 // Tras desplazar redibujamos la onda
                 DibujaOnda(oDesde + 5 * Desplazamiento, oHasta + 5 * Desplazamiento,  oAnchoVentana, oAltoVentana, GRANDEo );
       break;
  case ARRIBA:
  case ABAJO:
  case CENTRAR:
                  // Tras desplazar redibujamos la onda
                  //       Con una nueva funcion que tenga en cuenta la nueva funci¢n.

                 switch( Lugar )
                  {
                    case ARRIBA:  ceroOGenerada -= 5;                        break;
                    case CENTRAR: ceroOGenerada  = ( oAltoVentana / 2 ) + 2; break;
                    case ABAJO:   ceroOGenerada += 5;                        break;
                  }

                  // Calculamos el factor de reducci¢n para el ancho de la ventana
                  ReduccionX =  (float)( oHasta  - oDesde ) / (float)oAnchoVentana;

                  for ( xActual = oDesde + 5 * Desplazamiento, xReal = 0; xReal < oAnchoVentana; xActual += ReduccionX, xReal ++ )
                  {
                   if (    oOndaGenerada[xReal] >= inicioMGy && oOndaGenerada[xReal] <= inicioMGy + oAltoVentana )
                       // Si vez es cero no restauramos el viejo contenido, ya que no existe
   		       putpixel( xReal + inicioMGx, oOndaGenerada[xReal], cOndaGenerada[xReal] );

                   // Borramos la linea del cero antigua
                   if ( ( inicioMGy+oldCero ) >= inicioMGy && ( inicioMGy + oldCero ) <= ( inicioMGy + oAltoVentana) )
                              if ( oldCero % SaltosMatrixY )
                                             putpixel( xReal + inicioMGx, oldCero + inicioMGy, EGA_BLACK );
                              else
                                             putpixel( inicioMGx +  xReal, inicioMGy + oldCero, ( ( xReal % SaltosMatrixX ) ? EGA_BLACK : cfgFREC.gMatrix ));
                   // Colocamos la nueva
                   if ( ( inicioMGy+ceroOGenerada ) >= inicioMGy && ( inicioMGy + ceroOGenerada ) <= ( inicioMGy + oAltoVentana) )
                              if ( ceroOGenerada % SaltosMatrixY )
                                             putpixel( xReal + inicioMGx, ceroOGenerada + inicioMGy, cfgFREC.gMatrix );
                              else
                                             putpixel( xReal + inicioMGx, ceroOGenerada + inicioMGy, ( ( xReal % SaltosMatrixX ) ? cfgFREC.gMatrix : EGA_BLACK ));

                   oOndaGenerada[xReal] = OndaGenerada[(int)xActual] + ceroOGenerada + inicioMGy;

                   if (    oOndaGenerada[xReal] >= inicioMGy && oOndaGenerada[xReal] <= ( inicioMGy + oAltoVentana ) )
                   {

                        cOndaGenerada[xReal] = (char)getpixel( xReal + inicioMGx, oOndaGenerada[xReal] );
                        putpixel( xReal + inicioMGx, oOndaGenerada[xReal], cfgFREC.gOnda );
                   }
                  } // BUCLE FOR

//                  DibujaOnda(oDesde + 5 * Desplazamiento, oHasta + 5 * Desplazamiento,  oAnchoVentana, oAltoVentana, GRANDEo );
                  Redibuja_MiniOnda();
       break;
 }

}

/***************************************************************************\
|*                                                                         *|
|* ReajusteTierra                                                          *|
|*                                                                         *|
|* Descripci¢n:                                                            *|
|*              Ajusta el nivel de continua                                *|
|*                                                                         *|
|* Entradas:                                                               *|
|*           Ajuste hacia ARRIBA - ABAJO                                   *|
|*                                                                         *|
|* Salidas:  (ninguna)                                                     *|
|*                                                                         *|
\***************************************************************************/
void ReajusteTierra( char aDonde )
{
 int x;

 for (  x = 0; x < (oAnchoVentana * oVentanas); x++ )
     if ( aDonde == ARRIBA)
                OndaGenerada[ x ] --;
     else
     if ( aDonde == ABAJO )
                OndaGenerada[ x ] ++;

 DibujaOnda(oDesde + 5 * Desplazamiento, oHasta + 5 * Desplazamiento,  oAnchoVentana, oAltoVentana, GRANDEo );
 Redibuja_MiniOnda();

};

/***************************************************************************\
|*                                                                         *|
|* DibujaOnda                                                              *|
|*                                                                         *|
|* Descripci¢n:                                                            *|
|*              Dibuja la onda, teniendo encuenta lo que hay detras        *|
|*                                                                         *|
|* Entradas:                                                               *|
|*           Origen de la onda                                             *|
|*           Final de la onda                                              *|
|*           Ancho de la ventana                                           *|
|*           Alto de la ventana                                            *|
|*           Tipo de Onda ( GRANDE / REDUCIDA )                            *|
|*                                                                         *|
|*                                                                         *|
|* Salidas:  (ninguna)                                                     *|
|*                                                                         *|
\***************************************************************************/
void DibujaOnda( int Desde, int Hasta, int Ancho, int Alto, char GrandeMini )
{
 static char vez1 = 0;
 static char vez2 = 0;
 float xActual;
 int xReal, yReal;
 float ReduccionX, ReduccionYmini;

 // Si esta activada la funci¢n de selecci¢n...
 // Borramos la marca
 if ( statusBoton == 17 && GrandeMini == GRANDEo )
                             Dibuja_OndaSeleccionada(PINTA);

 // Calculamos el factor de reducci¢n para el ancho de la ventana
 ReduccionX = (float)( Hasta - Desde ) / (float)oAnchoVentana;


 ReduccionYmini = (float) Alto / (float)oAltoVentana;

 for ( xActual = Desde, xReal = 0; xReal < Ancho; xActual += ReduccionX, xReal ++ )
 {

  if ( GrandeMini == GRANDEo )
  {

        if (    oOndaGenerada[xReal] >= inicioMGy
             && oOndaGenerada[xReal] <= inicioMGy + oAltoVentana
             // Si vez es cero no restauramos el viejo contenido, ya que no existe
             && ( vez1 != 0 ) )
   		  putpixel( xReal + inicioMGx, oOndaGenerada[xReal], cOndaGenerada[xReal] );
        else      vez1 = 1;

        oOndaGenerada[xReal] = OndaGenerada[(int)xActual] + ceroOGenerada + inicioMGy;
        if (    oOndaGenerada[xReal] >= inicioMGy
             && oOndaGenerada[xReal] <= ( inicioMGy + oAltoVentana ) )
        {

                  cOndaGenerada[xReal] = (char)getpixel( xReal + inicioMGx, oOndaGenerada[xReal] );
                  putpixel( xReal + inicioMGx, oOndaGenerada[xReal], cfgFREC.gOnda );
        }
  } else {
        if (    mOndaGenerada[xReal] >= inicioMmGy
             && mOndaGenerada[xReal] <= ( inicioMmGy + mAltoCuadro )
             // Si vez es cero no restauramos el viejo contenido, ya que no existe
             && ( vez2 != 0 ) )
   		  putpixel( xReal + inicioMGx, mOndaGenerada[xReal], cfgFREC.mFondo );
        else      vez2 = 1;

        mOndaGenerada[xReal] = (int)( ( OndaGenerada[(int)xActual] + ceroOGenerada ) * ReduccionYmini + inicioMmGy );
        if (    mOndaGenerada[xReal] >= inicioMmGy
             && mOndaGenerada[xReal] <= ( inicioMmGy + mAltoCuadro ) )
                  putpixel( xReal + inicioMGx, mOndaGenerada[xReal], cfgFREC.mOnda );

  } // SI GrandeMini
 } // BUCLE FOR

 // Redibujamos la marca
 if ( statusBoton == 17 && GrandeMini == GRANDEo )
                             Dibuja_OndaSeleccionada(PINTA);

}

/***************************************************************************\
|*                                                                         *|
|* Redibuja_MiniOnda                                                       *|
|*                                                                         *|
|* Descripci¢n:                                                            *|
|*              Dibuja la minionda, teniendo en cuenta no machacar el      *|
|*              cuadro de desplazamiento                                   *|
|*                                                                         *|
|* Entradas: (ninguna)                                                     *|
|*                                                                         *|
|* Salidas:  (ninguna)                                                     *|
|*                                                                         *|
\***************************************************************************/
void Redibuja_MiniOnda(void)
{
   // Cuadro onda visible
   setcolor( cfgFREC.mMarco );   setwritemode( XOR_PUT );
   rectangle( 8 + Desplazamiento, inicioMmGy, 8 + mAnchoMarco + Desplazamiento, inicioMmGy + mAltoCuadro );
   setwritemode( COPY_PUT );

   DibujaOnda(     0, oFinalOnda, oAnchoVentana,   mAltoCuadro, MINIo   );

   // Cuadro onda visible
   setcolor( cfgFREC.mMarco );   setwritemode( XOR_PUT );
   rectangle( 8 + Desplazamiento, inicioMmGy, 8 + mAnchoMarco + Desplazamiento, inicioMmGy + mAltoCuadro );
   setwritemode( COPY_PUT );

}



/***************************************************************************\
|*                                                                         *|
|* ReajustaTipoOnda                                                        *|
|*                                                                         *|
|* Descripci¢n:                                                            *|
|*              Inicia la creaci¢n/tratamiento de un tipo de onda          *|
|*              ya predefinido...                                          *|
|*                                                                         *|
|* Entradas:                                                               *|
|*           PorDonde_ Punto de la onda a retocar, (amplitud-periodo)      *|
|*           (indirectamente recibe tambien el tipo de onda predefinida)   *|
|*                                                                         *|
|* Salidas:  (ninguna)                                                     *|
|*                                                                         *|
\***************************************************************************/
void ReajustaTipoOnda( int PorDonde )
{
  float xReal, xVirtual, xAux;
  float xVirtual2;
  static int count = 0, Tampl = 50;
  static float Tperd = 0.05;

switch( Tonda )
{
 case -1:
    switch( PorDonde )
    {
     case ARRIBA:
     case ABAJO:
                 for ( xReal = MRK_begin; xReal <= MRK_end; xReal++ )
                 {
                  if ( PorDonde == ARRIBA )
                  {
                   OndaGenerada[ xReal ] *= 2;
                   OndaGenerada[ xReal ] ++;
                  } else {
                   OndaGenerada[ xReal ] --;
                   OndaGenerada[ xReal ] /= 2;
                  }
                 }
                 count = 0;
                 break;
     case IZQUIERDA:
                 for ( xReal = xVirtual = MRK_begin; xReal <= MRK_end && xVirtual <= MRK_end; xReal++, xVirtual += IncrementoMarca )
                         OndaGenerada[ xReal ] = OndaGenerada[ xVirtual ];
                 if ( xReal != MRK_end )
                  for ( xReal, xVirtual = MRK_begin; xReal <= MRK_end; xReal++, xVirtual++ )
                         OndaGenerada[ xReal ] = OndaGenerada[ xVirtual ];
                 count = 0;
                 break;
     case DERECHA:
                 for ( xReal = MRK_end; xReal >= MRK_begin; xReal-=(IncrementoMarca+count) )
                  for ( xVirtual = (IncrementoMarca+count); xVirtual > 0 && (xReal-xVirtual+1)>=MRK_begin; xVirtual-- )
                         OndaGenerada[ xReal - xVirtual + 1 ] = OndaGenerada[ xReal ];
                 count = (count++) % 32;
                 break;
    }
    break;
 case 2:
    switch( PorDonde )
    {
     case ARRIBA:
     case ABAJO:
                 Tampl += (PorDonde == ARRIBA) ? 1 : -1;
                 break;
     case IZQUIERDA:
     case DERECHA:
                 Tperd += (PorDonde == IZQUIERDA) ? 0.01 : -0.01;
                 break;
     case CENTRAR:
                 Tampl = 50;
                 Tperd = 0.05;
                 break;

    }
    for ( xReal = MRK_begin; xReal <= MRK_end; xReal++ )
                                   OndaGenerada[ xReal ] = (int)(sin( xReal * Tperd ) * Tampl);
    break;
 case 3:
    switch( PorDonde )
    {
     case ARRIBA:
     case ABAJO:
                 Tampl += (PorDonde == ARRIBA) ? 1 : -1;
                 break;
     case IZQUIERDA:
     case DERECHA:
                 if ( Tperd <= 1 )
                    Tperd += (PorDonde == IZQUIERDA) ? -0.1 : 0.1;
                 else
                     Tperd += (PorDonde == IZQUIERDA) ? -1 : 1;
                 if ( Tperd <= 0.1 ) Tperd = 0.1;
                 break;
     case CENTRAR:
                 Tampl = 50;
                 Tperd = 0.5;
                 break;

    }
    count = 0;
    for ( xReal = MRK_begin; xReal <= MRK_end; )
     {
        count = !count;
       if ( Tperd >= 1 )
        for ( xVirtual= ( !count ? (-1) : 1 ) * ( Tampl / 2 ); xReal <= MRK_end && (xVirtual*( !count ? (1) : (-1) )) < (Tampl/2) ; xVirtual += ( !count ? 1 : (-1) ) * Dispersion )
        for ( xAux = Tperd; xReal <= MRK_end && xAux>=0; xReal++, xAux-- )
                                            OndaGenerada[ xReal ] = (int)xVirtual;
       else
        for ( xVirtual= ( !count ? (-1) : 1 ) * ( Tampl / 2 ); xReal <= MRK_end && (xVirtual*( !count ? (1) : (-1) )) < (Tampl/2) ; xReal+=Tperd, xVirtual += ( !count ? 1 : (-1) ) * Dispersion )
                                            OndaGenerada[ xReal ] = (int)xVirtual;

     }
    break;
 case 1:
 case 4:
    switch( PorDonde )
    {
     case ARRIBA:
     case ABAJO:
                 Tampl += (PorDonde == ARRIBA) ? 1 : -1;
                 break;
     case IZQUIERDA:
     case DERECHA:
                 Tperd += (PorDonde == IZQUIERDA) ? -1 : 1;
                 if ( Tperd <= 0 ) Tperd = 1;
                 break;
     case CENTRAR:
                 Tampl = 50;
                 Tperd = 50;
                 break;

    }
    count = 0;
    for ( xReal = MRK_begin; xReal <= MRK_end; )
     {
        count = !count;

        // Pinto la linea Continua 'Positiva'
        for ( xVirtual = 0; xReal <= MRK_end && xVirtual <= Tperd; xReal++, xVirtual++ )
          OndaGenerada[ xReal ] = ( !count ? (-1) : 1 ) * ( Tampl / 2 );
       if( Tonda == 4 )
        for ( xVirtual= ( !count ? (-1) : 1 ) * ( Tampl / 2 ); xReal <= MRK_end && (xVirtual*( !count ? (1) : (-1) )) < (Tampl/2) ; xReal++, xVirtual += ( !count ? 1 : (-1) ) * Dispersion)
          OndaGenerada[ xReal ] = xVirtual;

     }
    break;
 case  6:
 case  7:
 case  8:
 case  9:

    switch( PorDonde )
    {
     case ARRIBA:
     case ABAJO:
                 Tampl += (PorDonde == ARRIBA) ? 1 : -1;
                 break;
     case IZQUIERDA:
     case DERECHA:
                 Tperd += (PorDonde == IZQUIERDA) ? 0.0005 : -0.0005;
                 if ( Tperd < 0.0005 ) Tperd = 0.0005;
                 break;
     case CENTRAR:
                 Tampl = 50;
                 Tperd = 0.05;
                 break;

    }

    count = Tonda==6 ? 0 : -1;
    for ( xReal = MRK_begin; xReal <= MRK_end; )
     {
        xVirtual = 0;
        while ( xVirtual*Tperd < ( ( (Tonda==6) || (Tonda==8) )?(M_PI):(M_PI+.5*M_PI)) ) xVirtual++;

        for (           ; (xVirtual*Tperd) < (( (Tonda==6) || (Tonda==8) )?(M_PI+0.5*M_PI):(M_PI*2)) && xReal <= MRK_end;  xVirtual++, xReal++ )
                                   OndaGenerada[ xReal ] = (int)( sin(xVirtual*Tperd)*Tampl ) + (Tampl/2);
        if ( Tonda != 8 && Tonda != 9 )
           for ( xVirtual= ( !count ? (-1) : 1 ) * ( Tampl/2 ); xReal <= MRK_end && (xVirtual*( !count ? (1) : (-1) )) < (Tampl/2) ; xReal++, xVirtual += ( !count ? 1 : (-1) ) * Dispersion)
                  OndaGenerada[ xReal ] = xVirtual;
     }
    break;
}

 DibujaOnda(oDesde + 5 * Desplazamiento, oHasta + 5 * Desplazamiento,  oAnchoVentana, oAltoVentana, GRANDEo );

}
/***************************************************************************\
|*                                                                         *|
|* Retoca_Punto                                                            *|
|*                                                                         *|
|* Descripci¢n:                                                            *|
|*              Retoca el punto dado como par metro con el consiguiente    *|
|*              arrastre de puntos adyacentes, hasta que los adyacentes    *|
|*              disten del punto anterior, como m ximo, disperici¢n / 2    *|
|*                                                                         *|
|*                                                                         *|
|* Entradas: Punto del periodo a retocar     Px                            *|
|*           Punto de la amplitud a ''       Ay                            *|
|*                                                                         *|
|* Salidas:  (ninguna)                                                     *|
|*                                                                         *|
\***************************************************************************/
void Retoca_Punto( int Px, int Ay )
{
  int  old_Px;         // Variables guia de la onda
  char inc;            // Infome sobre el incremento de la onda ( ASCENDENTE  / DESCENDENTE )

  old_Px = Px;

  OndaGenerada[Px] = Ay; // Ajustamos el nuevo valor de un punto ( usr des )

  // 1§ Acerco por la derecha del punto a retocar
  while ( abs( OndaGenerada[old_Px+1] - OndaGenerada[old_Px] ) > Dispersion && old_Px < oAnchoVentana*oVentanas )
  {
   if ( OndaGenerada[old_Px+1] > OndaGenerada[old_Px] ) inc = -1; else inc = 1;
   while ( abs( OndaGenerada[old_Px+1] - OndaGenerada[old_Px] ) > Dispersion )
                                                              OndaGenerada[old_Px+1] += inc;
   old_Px ++;
  };

  old_Px = Px;

  // 2§ Acerco por la izquierda del punto a retocar
  while ( abs( OndaGenerada[old_Px] - OndaGenerada[old_Px-1] ) > Dispersion && old_Px > 0  )
  {
   if ( OndaGenerada[old_Px] > OndaGenerada[old_Px-1] ) inc = 1; else inc = -1;
   while ( abs( OndaGenerada[old_Px] - OndaGenerada[old_Px-1] ) > Dispersion )
                                                              OndaGenerada[old_Px-1] += inc;
   old_Px --;
  };

  DibujaOnda(oDesde +  5 * Desplazamiento, oHasta +  5 * Desplazamiento,  oAnchoVentana, oAltoVentana, GRANDEo );

}
