summaryrefslogblamecommitdiffstats
path: root/tools/cpu/sh/sci.c
blob: 2b0cbd758f7d5d2e1524d07dc23bf7f64986f21a (plain) (tree)























































                                                              
               











                                                         
   
                        


                    


























































                                                                                
                                                       



                


                                     














                                                   
                                                          







                                            
/*
 * Copyright (c) 1998 Ralf Corsepius (corsepiu@faw.uni-ulm.de)
 *
 * See the file COPYING for copyright notice.
 */

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

#include "sci.h"

/*
   n .. baudrate generator source 0,1,2,3
   
   N .. BRR setting (0..255)
   
   Phi .. processor baud rate
   
   B .. bitrate
 */

typedef struct sci_tab {
  unsigned int  B ;
  unsigned int  n ;
  int 		N ;
  double        err ;
  } sci_tab_t ;

static unsigned int bitrate [] = {
  50,
  75,
  110,
  134,
  150,
  200,
  300,
  600,
  1200,
  1800,
  2400,
  4800,
  9600,
  19200,
  38400,
  57600,
  115200,
  230400,
  460800
};

static sci_tab_t test_array[4] ;

static void Compute( 
  unsigned int n, 
  unsigned int B, 
  double   Phi,
  struct sci_tab *entry )
{
  int    a = ( 32 << ( 2 * n ) ) * B ;
  
  entry->n = n ;
  entry->B = B ;
  entry->N = rint( ( Phi / a ) - 1.0 ) ;

  if ( ( entry->N > 0 ) && ( entry->N < 256 ) ) 
    entry->err = 
      ( ( Phi / ( (entry->N + 1) * a ) - 1.0 ) * 100.0 );
  else
  {
    entry->err = 100.0 ;
    entry->n = 255 ;
    entry->N = 0 ;
  }
}

static sci_tab_t *SelectN( 
  unsigned int 	B,
  double 	Phi )
{
  unsigned int i ;
  struct sci_tab* best = NULL ;
    
  for ( i = 0 ; i < 4 ; i++ )
  { 
    double err ;
    
    Compute( i, B, Phi, &test_array[i] );
    err = fabs( test_array[i].err );

    if ( best )
    {
      if ( err < fabs( best->err ) )
        best = &test_array[i] ;
    }
    else
      best = &test_array[i] ;
  }

  return best ; 
}

int shgen_gensci(
  FILE		*file,
  double	Phi ) /* Processor frequency [Hz] */
{
  unsigned int i ;

  fprintf( file, 
    "/*\n * Bitrate table for the serial devices (sci) of the SH at %.3f MHz\n"
    " */\n\n", Phi / 1000000.0 );
  fprintf( file,
    "/*\n"
    " * n     .. SMR bits 0,1 : baud rate generator clock source\n"
    " * N     .. BRR bits 0..7: setting for baud rate generator\n"
    " * error .. percentual error to nominal bitrate\n"
    " *   Hitachi's HW manual recommends bitrates with an error less than 1%%\n"
    " *   We experienced values less than 2%% to be stable\n"
    " */\n\n" );
  fprintf( file, "#include <termios.h>\n\n" );
  fprintf( file, 
    "static struct sci_bitrate_t {\n"
    "  unsigned char n ;\n"
    "  unsigned char N ;\n"
    "} _sci_bitrates[] = {\n"
    "/*  n    N      error */\n" );
  
  for ( i = 0 ; i < sizeof(bitrate)/sizeof(int) ; i++ )
  {
    struct sci_tab* best = SelectN( bitrate[i], Phi );

    if ( i > 0 )
      fprintf( file, ",\n" );
    fprintf( file, "  { %1d, %3d } /* %+7.2f%% ; B%d ",
      best->n,
      best->N,
      best->err,
      best->B );
    if ( best->n > 3 )
      fprintf( file, "(unusable) " );
    fprintf( file, "*/" );
  }

  fprintf( file, "\n};\n\n" );

  fprintf( file, 
    "int _sci_get_brparms( \n"
    "  tcflag_t      cflag,\n"
    "  unsigned char *smr,\n"
    "  unsigned char *brr )\n"
    "{\n"
    "  unsigned int offset ;\n\n"
    "  offset = ( cflag & ( CBAUD & ~CBAUDEX ) )\n"
    "    + ( ( cflag & CBAUDEX ) ? B38400 : 0 );\n"
    "  if ( offset == 0 ) return -1 ;\n"
    "  offset-- ;\n\n"
    "  if ( _sci_bitrates[offset].n > 3 )  return -1;\n\n"
    "  *smr &= ~0x03;\n"
    "  *smr |= _sci_bitrates[offset].n;\n"
    "  *brr =  _sci_bitrates[offset].N;\n\n"
    "  return 0;\n"
    "}\n" );
    
  return 0 ;
}