/* lc -b0 ... .c */
/* genim2 -l ... .s
/* blink with ... .lnk */


#include <exec/types.h>
#include <exec/memory.h>
#include <stdio.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>

#define HACT 10000L
#define ALPHA 70000L
#define MAX_ANUM 20
#define REC_MAX_LEN 50000
#define MAX_LINES 150
#define MAX_SMEM (MAX_LINES*2*32L)

UWORD *vhposr= (UWORD *)0xdff006;

struct lcpl {
  long re;
  long im;
};

extern void fft();
extern void rec();
extern BYTE *rec_adr;
extern long rec_len;
extern struct lcpl f[256];
extern short spec[128];

BYTE  smem[32*MAX_LINES];
short *w=0;              /*  [32L*2*MAXLINES*anum];  */
long  aknot[MAX_ANUM];
char  symbols[30*MAX_ANUM];
char  trf[30*32];
int   trn[32];
int   trf_num=0;
int   tr_cyc;
long  tsteps=0;
long  anum;
short num_256lines;


BYTE get_sqr( short s )
{
int i;
BYTE r=0;

  for( i=1; i<10; i++ )
  {
    if( s<(i*i) )  return( r );
    r++;
  }
  return( r );
}


void do_fft()
{
long x, y, i, l=0;

  y=0;
  while( l<rec_len )
  {
    if( y>=MAX_LINES )  break;

    for( i=0; i<256; i++ ) 
    {
      f[i].re= (long)rec_adr[l+i] << 10;
      f[i].im= 0L;
    }

    fft();

    x=0;
    for( i=1; i<96; i+=3 )
    {
      smem[x+y*32]= get_sqr( (short)(spec[i]+spec[i+1]+spec[i+2]) );
      x++;
    }
    y++;
    l+=256;
  }

  num_256lines= y;
/*
  for( x=0; x<(y*32); x++ )
  {
    if( smem[x]!=0 )  break;
  }
  first= x/32;

  for( x=(y*32-1); x>=0; x-- )
  {
    if( smem[x]!=0 )  break;
  }
  last= x/32;

  for( i=0, x=first*32; i<(last-first+1)*32; i++, x++ )
    smem[i]= smem[x];
  for( ; i<(MAXLINES*32); i++ )  smem[i]=0;
*/

}



void save_nn( char *name )
{
struct FileHandle *fh;

  fh= (struct FileHandle *)Open( (UBYTE *)name, MODE_NEWFILE );
  if( fh==0 )
  { 
    printf( "can't open file\n" );
  }
  else
  {
    Write( fh, (UBYTE *)&anum, 4L );
    Write( fh, (UBYTE *)&tsteps, 4L );
    Write( fh, (UBYTE *)&(symbols[0]), 30L*anum );
    Write( fh, (UBYTE *)&(w[0]), MAX_SMEM*anum );
    Close( fh );
    FreeMem( w, MAX_SMEM*anum );
  }
}


void load_nn( char *name )
{
struct FileHandle *fh;
long sl;
long x;
int i;

  fh= (struct FileHandle *)Open( (UBYTE *)name, MODE_OLDFILE );
  if( fh==0 )
  { 
    printf( "file not found\n" );
    printf( "new net is being generated\n" );
    printf( "number of symbols to be recognized: " );
    scanf("%d", &anum );
    w= (short *)AllocMem( MAX_SMEM*anum, MEMF_PUBLIC );
    if( w==0L )
    {
      printf("no memory for neural net\n");
      exit();
    }

    for( i=0; i<anum; i++ )
    {
      printf("symbol %d: ", i);
      scanf("%s", &symbols[i*30] );
    }

    for( x=0; x<(32L*MAX_LINES*anum); x++ )
    {
      w[x]= 0;
    }
  }
  else
  {
    sl= Read( fh, (UBYTE *)&anum, 4L );
    sl= Read( fh, (UBYTE *)&tsteps, 4L );
    w= (short *)AllocMem( MAX_SMEM*anum, MEMF_PUBLIC );
    if( w==0L )
    {
      printf("no memory for neural net\n");
      Close( fh );
      exit();
    }
    sl= Read( fh, (UBYTE *)&(symbols[0]), 30L*anum );
    sl= Read( fh, (UBYTE *)&(w[0]), MAX_SMEM*anum );
    if( sl!=MAX_SMEM*anum )  printf("ERROR while reading\n");
    Close( fh );
  }
}
  
int get_act()
{
long sum, max_sum=0, ag=0;
long x, i, max_i=0;
short wei;

  for( i=0; i<anum; i++ )
  {
    sum= 0;
    for( x=0; x<(num_256lines*32); x++ )
    {
      wei=  (short)w[x*anum+i];
      ag+=  (long)wei;
      sum+= (long)(wei * (short)smem[x]);
    }
    if( ag!=0 )  sum= sum <<6 /ag;
    aknot[i]= sum;
    printf("  %d) %s=%d\n", i, &symbols[i*30], sum );
    if( sum>max_sum )
    {
      max_sum= sum;
      max_i= i;
    }
  }
  return( max_i );
}


void train_nn( long cor_i )
{
/* long err, si, sj, k;  */
int x;

  tsteps++;

  for( x=0; x<(num_256lines*32); x++ )
  {
    w[x*anum+cor_i]+= (long)smem[x];;  
  }

/*
  for( i=0; i<anum; i++ )
  {
    if( i!=cor_i )
    {
      for( x=0; x<(MAX_LINES*32); x++ )
      {
        sj= (long)smem[x];
        w[x*anum+i]-= sj / 4;  
      }
    }
  }


  for( i=0; i<anum; i++ )
  {
    si= aknot[i];
    if( si==0 )     si=1;  
    if( i==cor_i )  err=  HACT - si;  
    else            err=  0L   - si;

    k= err * si * (HACT-si) / HACT; 

    for( x=0; x<(MAX_LINES*32); x++ )
    {
      sj= (long)smem[x];
      w[x*anum+i]+= k * sj / 10000L;  
    }
  }
*/
}


void main( int argc, char *argv[] )
{
int a, cor_i;

  if( argc!=2 )
  {
    printf( "that's no argument\n" );
    printf( "USAGE: train_nn <net_file>\n" );
    exit();
  }

  load_nn( argv[1] );

  rec_adr= (BYTE *)AllocMem( REC_MAX_LEN, MEMF_PUBLIC );
  if( rec_adr==0L )
  {
    printf("no memory for recording\n");
    FreeMem( w, MAX_SMEM*anum );
    exit();
  }

  for(;;)
  {
    rec();
    do_fft();
    a= get_act();

    printf("------------> \033[32m%s\033[0m <-----------\n", &symbols[a*30] );
    printf("correct answer # (-1 to stop): ");
    scanf("%d", &cor_i );
    if( cor_i<0 || cor_i>=anum )  break;

    train_nn( cor_i );
  }

  FreeMem( rec_adr, REC_MAX_LEN );

  save_nn( argv[1] );
}


