// filename *************** SCIutil.C ********

// Serial port I/O routines, utilities



// This example accompanies the book

//    "Embedded Microcomputer Systems: Real Time Interfacing", Brooks-Cole, copyright (c) 2000,

//    Jonathan W. Valvano  12/21/02



// Copyright 2003 by Jonathan W. Valvano, valvano@uts.cc.utexas.edu 

//    You may use, edit, run or distribute this file 

//    as long as the above copyright notice remains 



// Modified from University of Texas students Charlie Gough && Matt Hawk





//-------------------------SCI_OutString------------------------

// Output String (NULL termination)

void SCI_OutString(char *pt){ char letter;

  while(letter=*pt++){

    SCI_OutChar(letter);

  }

}



//--------------------SCI_UpCase-------------------------------

// converts lowercase to uppercase

// char by subtracting	$20 from lowercase ASCII to	make uppercase ASCII

char SCI_UpCase(char character){	

  return ((character>='a') && (character<='z'))?character-0x20:character;}



//----------------------SCI_InUDec-------------------------------

// InUDec accepts ASCII input in unsigned decimal format

//     and converts to a 16 bit unsigned number

//     with a maximum value of 65535

// If you enter a number above 65535, it will truncate without reporting the error

// Backspace will remove last digit typed

unsigned short SCI_InUDec(void){	

unsigned short number=0, length=0;

unsigned char character;	

  while((character=SCI_InChar())!=CR){ // accepts until carriage return input

// The next line checks that the input is a digit, 0-9.

// If the character is not 0-9, it is ignored and not echoed

    if((character>='0') && (character<='9')) {

      number = 10*number+(character-'0');   // this line overflows if above 65535

      length++;

      SCI_OutChar(character);

    } 

// If the input is a backspace, then the return number is

// changed and a backspace is outputted to the screen

    else if((character==BS) && length){

      number /= 10;

      length--;

      SCI_OutChar(character);

    }

  }

  return number;

}



//----------------------------SCI_InSDec-----------------------------

// InSDec accepts ASCII input in signed decimal format

//    and converts to a signed 16 bit number 

//    with an absolute value up to 32767

// If you enter a number above 32767 or below -32767, 

//    it will truncate without reporting the error

// Backspace will remove last digit typed

short SCI_InSDec(void){	

short number=0, sign=1;	// sign flag 1=positive 0=negative

unsigned int length=0;

unsigned char character;

  while ((character=SCI_InChar())!=CR){ // Check for carriage return

    if(!length) {			        // + or - only valid as first char			

      if(character=='-'){

        sign = -1;

        length++;

        SCI_OutChar('-');	// if - inputted, sign is negative

      }

      else if(character=='+'){

        length++;

        SCI_OutChar('+');	//if + inputted, sign is positive

      }

    }

// The next line checks that the input is a digit, 0-9

// If the character is not 0-9, it is ignored and not echoed

    if((character>='0') && (character<='9')){

      number = number*10+character-'0';   // this line overflows if above 32767

      length++;

      SCI_OutChar(character);

    }

// If the input is a backspace, then the return number is changed and a backspace

// is outputted to the screen.  If the backspace erases a minus, then sign is 

// reset to positive

    else if((character==BS) && length){

      number /=10;

      length--;

      if(!length){

        sign = 1;

      }

      SCI_OutChar(BS);

    }

  }

  return sign*number;

}



//-----------------------SCI_OutUDec-----------------------

// Output a 16 bit number in unsigned decimal format

// Variable format 1-5 digits with no space before or after

// This function uses recursion to convert decimal number

//   of unspecified length as an ASCII string 

void SCI_OutUDec(unsigned short n){

  if(n >= 10){

    SCI_OutUDec(n/10);

    n=n%10;

  }

  SCI_OutChar(n+'0'); /* n is between 0 and 9 */

}



//----------------------SCI_OutSDec---------------------------------------

// Output a 16 bit number in signed decimal format

// Variable format (optional sign)1 to 5 digits with no space before or after

// This function checks if the input parameter is negative,  

// If the number is negative, then 

//    1) it outputs a "-", 

//    2) negates the number and 

//    3) outputs it with OutUDec.

// Otherwise, it just calls OutUDec (i.e., no "+" sign)

void SCI_OutSDec(short number){

  if(number<0){	

    number = -number;

    SCI_OutChar('-');

  }

  SCI_OutUDec(number);

}



//---------------------SCI_InUHex----------------------------------------

// InUHex accepts ASCII input in unsigned hexadecimal (base 16) format

// No '$' or '0x' need be entered, just the 1 to 4 hex digits

// It will convert lower case a-f to uppercase A-F

//     and converts to a 16 bit unsigned number

//     with a maximum value of FFFF

// If you enter a number above FFFF, it will truncate without reporting the error

// Backspace will remove last digit typed

unsigned short SCI_InUHex(void){	

unsigned short number=0, digit, length=0;

unsigned char character;

  while((character=SCI_UpCase(SCI_InChar()))!=CR){	

    digit = 0x10; // assume bad

    if((character>='0') && (character<='9')){

      digit = character-'0';

    }

    else if((character>='A') && (character<='F')){ 

      digit = (character-'A')+0xA;

    }

// If the character is not 0-9 or A-F, it is ignored and not echoed

    if(digit<=0xF ){	

      number = number*0x10+digit;

      length++;

      SCI_OutChar(character);

    }

// Backspace outputted and return value changed if a backspace is inputted

    else if(character==BS && length){

      number /=0x10;

      length--;

      SCI_OutChar(character);

    }

  }

  return number;

}



//--------------------------SCI_OutUHex----------------------------

// Output a 16 bit number in unsigned hexadecimal format

// Variable format 1 to 4 digits with no space before or after

// This function uses recursion to convert the number of 

//   unspecified length as an ASCII string

void SCI_OutUHex(unsigned short number){

  if(number>=0x10)	{

    SCI_OutUHex(number/0x10);

    SCI_OutUHex(number%0x10);

  }

  else if(number<0xA){

    SCI_OutChar(number+'0');

  }

  else{

    SCI_OutChar((number-0x0A)+'A');

  }

}



//------------------------SCI_InString------------------------

// This function accepts ASCII characters from the serial port

//    and adds them to a string until a carriage return is inputted 

//    or until max length of the string is reached.  

// It echoes each character as it is inputted.  

// If a backspace is inputted, the string is modified 

//    and the backspace is echoed

// InString terminates the string with a null character

// -- Modified by Agustinus Darmawan + Mingjie Qiu --

void SCI_InString(char *string, unsigned int max) {	

unsigned int length=0;

unsigned char character;

  while((character=SCI_InChar())!=CR){

    if(character==BS){

      if(length){

        string--;

        length--;

        SCI_OutChar(BS);

      }

    }

    else if(length<max){

      *string++=character;

      length++; 

      SCI_OutChar(character);

    }

  }

  *string = 0;

}



//------------------------SCI_upCaseString------------------------

// converts a NULL terminated string to uppercase

void SCI_upCaseString(char *inString){

  char *pt = inString;

// 'a' = 0x61 and 'A' = 0x41, so their difference is 0x20 

  while(*pt){  //  NULL => done 

    if((*pt >= 'a') && (*pt <= 'z'))

      *pt -= 0x20;

    pt++;

  }

}

