




/**********************************************************************************************
 *                                                                                            *
 * Ex1.      :   Using Command Read ASCII Distance (RA and Ra)                                *
 *               By Use Interupt Recive ASCII Distance                                        *
 *                                                                                            *
 *                                                                                            *
 **********************************************************************************************
 *                                                                                            *
 *                                                                                            *
 * Target MCU     : ATMEL AVR-MEGA128 (ET-BASE AVR ATMEGA128 r3 Board)                        *
 *                : X-TAL : 16 MHz                                                            *
 *                                                                                            *
 * Editor         : AVR Studio 4.15 Build 623                                                 *
 * Compiler       : WinAVR-20081205                                                           *
 * Create By      : Mr. Sittiphol Yooyod (WWW.ETT.CO.TH)                                      *
 * Last Update    : 06/October/2014                                                           *
 *                                                                                            *
 * Port Interface :  --- MCU-AVR Mega 128 ---           --- Module REMOTE DISTANCE ---        *
 *                                                                                            *
 *       Uart0    :  PE0 = RXDO (LineDrive)     Connect      Tx(RS232 Port)                   *    
 *                   PE1 = TXD0 (LineDrive)     Connect      Rx(RS232 Port)                   * 
 *                                                                                            *
 *                                                         Set JP-TTL/RS232 to RS232          *
 *       Baud Rate = 57600 at Clock 16 Mhz                 Set JP-BR (57600)                  *
 *                                                         Disable Filter                     *
 *                                                                                            *
 *       LCD     :   Connect 4bit data ;LCD 16x2 by                                           *
 *                                                                                            *  
 *                   PG4(output)         Connect         RS                                   *
 *                   PD7(output)         connect         E                                    *
 *                   PG0-PG3(output)     connect         Data 4 bit Low                       *
 *                                                                                            *
 *                                                                                            *
 *       5V                                                                                   *
 *      --+--                                                                                 *
 *        |                                                                                   *
 *        +-----------------+                                                                 *
 *        |                 |                                                                 *
 *       ---                |                                                                 *
 *       |\|                |                                                                 *
 *    VR |/|<---------------|--+                                                              *
 *   10K ---                |  |  PG4    PD7            PG0   PG1    PG2    PG3               *
 *        |                 |  |   ^      ^              ^     ^      ^      ^                *
 *        |                 |  |   |      |              |     |      |      |                *
 *        +--------------+--|--|---|---+--|--+--+--+--+  |     |      |      |                *
 *      __|__            |  |  |   |   |  |  |  |  |  |  |     |      |      |                *
 *       ---             |  |  |   |   |  |  |  |  |  |  |     |      |      |                *
 *        -             1| 2| 3|  4|  5| 6| 7| 8| 9|10|11|   12|    13|    14|                *
 *                     __|__|__|___|___|__|__|__|__|__|__|___ _|___ __|___ __|_               *
 *                    |  G Vcc Vo RS  R/W E D0 D1 D2 D3 D4    D5      D6    D7 |              *
 *                    |      _____________________________________________     |              *
 *                    |     |                                             |    |              *
 *                    |     |                 Module                      |    |              *
 *                    |     |           LCD 2x16 Charecter                |    |              *  
 *                    |     |_____________________________________________|    |              *
 *                    |                                                        |              *
 *                    |________________________________________________________|              *
 *                                                                                            *                                                                                           
 *                                                                                            *
 *                                                                                            * 
 *                                                                                            * 
 *   Operation    : Read Distance (RA-Cmm) Value Integer Display to LCD on Line 1 and         *
 *                  Read Distance (Ra-Cmm) Value Integer+Point Display to LCD on Line 2       *                                                                           
 *                                                                                            *
 **********************************************************************************************/
 

#include <stdio.h>
#include <avr/io.h>                  //define port
#include <compat/deprecated.h>       //call function sbi(port,bit),cbi(port,bit) = Set,Clear bit
#include <avr/pgmspace.h>            //for progrm data to Area Flash
#include <avr/interrupt.h>           //Interrupt Service routine

#define F_CPU 16000000UL             //CPU Clock Frequency (Hz)
#include<util/delay.h>               //util_delay


volatile unsigned char distance[10],num=0 ;  //,fag_rx=0  ;

//------------------LCD Function ------------------
void init_lcd(void)                   ;                // Function Initial LCD
void write_ins(unsigned char cmm)     ;                // Function write Command LCD
void write_data(unsigned char dat)    ;                // Function write data LCD
void gotolcd(unsigned char p)         ;                // Function Write position Curser
void EN_LCD(void)                     ;                // Function Enable Clock

//-------------- Function Delay_ms ------------------

void delay_ms(unsigned int i)
 {
   for(;i>0;i--)
      _delay_ms(1);
 }




/***************************************************************
 **                 Function use For Printf(UART0)            **
 ***************************************************************/


//--------------------- Prototype function ---------------------

static int uart_putchar(char c,FILE *stream) ;
static FILE uart_str = FDEV_SETUP_STREAM(uart_putchar,NULL,_FDEV_SETUP_WRITE);
void Init_Serial(unsigned int baudrate);




//----------------------- UART0 Putchar -------------------------

static int uart_putchar(char c,FILE *stream)
 {
   if(c=='\a')
     {
     fputs("*ring*\n",stderr) ;
     return 0 ;
     }
   
   if(c=='\n')
     uart_putchar('\r',stream) ;

   loop_until_bit_is_set(UCSR0A,UDRE);
   UDR0 = c ;

   return 0 ;
 }



//------------------- Initial UART0 -----------------------

 static void UART0_Init(void)
 {

   UCSR0B = 0x00      ;     //disable while setting baud rate
   UBRR0H = 0         ;
   UBRR0L = 16        ;     //Set Baud Rate 57600(16) : BURR= [Fosc/[16x(9600)]]-1
  
   UCSR0C = 0x06      ;     //Set Frame format : 8data,NoneParity,1stop bit
   UCSR0B = 0x98      ;     //Uart0 Control Enable Reciver and transmitter,enable Rx INT.
   
   sei()              ;     //Set Global Interrupt enable 
   
   stdout = &uart_str ;     //Set address uart_str to stdout/stdin

   
 }


/**********************************************************
 **                                                      **
 **      Interrupt Service Receive DATA UART0 (RX0)      **
 **                                                      **
 **********************************************************/
   
ISR (USART0_RX_vect) 
   {

      char ch ;

  
      ch = UDR0                     ;  //Recive Data 
      distance[num] = ch            ;  //Keep data to Buffer Distance
                
      num++                         ;  //Increment Array Pointer      
         
      if(ch == 0x0D)                   //Check end Command
		 num=0                      ;  //Clear Pointer buffer
              
   }   


/********************************************************
 **                                                    **
 **                        MAIN                        **   
 **                                                    **
 ********************************************************/


 int main (void) 
  {
     unsigned char enter = 0x0D,k ;
    
     char mes1[] = {"DistanRA:     Cm"} ;
     char mes2[] = {"DistanRa:   . Cm"} ;


    //---------------Initial Port I/O ----------------

     DDRD  = 0x80      ;        //Set PD7 = Output for LCD Pin EN      
     DDRG  = 0xFF      ;        //Set PG0..PG7 = Output for Control LCD+Data
   
     PORTD = 0         ;        //Set Default data 0  PortD       
     PORTG = 0         ;        //Set Default data 0  PortG
  
     init_lcd()        ;        //Initial LCD 

//----------- Print Start Message to LCD -----------

     gotolcd(0x00)                         ;  //Start Position data on LCD Line1
     for(k=0;k<16;k++)
        write_data(mes1[k])                ;  //Sent data to LCD

     gotolcd(0x40)                         ;  //Start Position data on LCD Line2
     for(k=0;k<16;k++)                           
        write_data(mes2[k])                ;  //Sent data to LCD
  
    delay_ms(200)                          ;  //Wait Module ET-Remote Distance Ready when Power On
       

    UART0_Init()                           ;  //Initial Uart0 and Enable Golbal Interrupt


//----------------- Start Sent Command Read Distance --------------

    while(1) 
    {   
      //################---- Sent Command RA ----#################

	  //---For CMM RA Recive Data to Buffer Distance[] by Byte0 keep '#' ,Byte1-3 Keep Distance or 'Err' ,Byte4 Keep  0x0D(Enter)
	  
	  
	  printf("*RA=%c",enter)           ;       // Sent Command Read Distance ASCII Integer  
	   
	   
      while((distance[0]!='#')||(distance[4]!=0x0D)){;} //Wait Recive data Check data Byte0 and Byte4
	  
      
	  if(distance[1]=='E')                    //Check data byte1 if is 'E'(error)  :Distance is not between 3-210 cm
       {
         gotolcd(0x09)                 ;      //Start Position data on LCD Line1
         for(k=1;k<4;k++)                          
            write_data(distance[k])    ;      //Sent Message "Err" to LCD  

	   }
      else    //Distance is between 3-210 cm.
	   {
          gotolcd(0x09)                ;      //Start Position data on LCD Line1
          for(k=1;k<4;k++)                          
             write_data(distance[k])   ;      //Sent Ascii Distance "xxx" to LCD
        }          


       distance[0]=0;         //Clear Buffer keep Distance Byte Start and Byte end
       distance[4]=0;

    
	
	
	  //#########---- Sent Command Ra ----############

	  //---For CMM Ra Recive Data to Buffer Distance[] by Byte0 Keep '#' ,Byte1-3 Keep Distance integer or 'Err' 
	  //                                                 ,Byte4 Keep '.' or'o' ,Byte5 Keep Distance Point or 'r' 
	  //                                                  Byte6 Keep 0x0D(Enter)
	  
	  
	  printf("*Ra=%c",enter)           ;       // Sent Command Read Distance ASCII Integer+Point  
	   
	   
      while((distance[0]!='#')||(distance[6]!=0x0D)){;} //Wait Recive data Check data Byte0 and Byte6
	  
      
	  if(distance[1]=='E')                    //Check data byte1 if is 'E'(error)  :Distance is not between 3-210 cm
       {
         gotolcd(0x49)                 ;      //Start Position data on LCD Line2
         for(k=1;k<6;k++)                          
            write_data(distance[k])    ;      //Sent Message "Error" to LCD  

	   }
      else    //Distance is between 3-210 cm.
	   {
          gotolcd(0x49)                ;      //Start Position data on LCD Line2
          for(k=1;k<6;k++)                          
             write_data(distance[k])   ;      //Sent Ascii Distance "xxx.x" to LCD
        }          


       distance[0]=0;         //Clear Buffer keep Distance Byte Start and Byte end
       distance[6]=0;

	
	}

  }



 /**********************************************************
  **                                                      **  
  **                       Sub-Program                    ** 
  **                                                      **
  **********************************************************/

/**********************************************************
 **                                                      **
 **                        LCD Function                  **
 **                                                      **
 **********************************************************/ 

//---------- Initial LCD -----------

void init_lcd(void)
 {
  
  write_ins(0x33)              ;  //CMM Function Set
  write_ins(0x32)              ;  //CMM Function set
  write_ins(0x28)              ;  //CMM Function Set :DL(0)=4bit LCD ,N(1)=2 Line,F(0)= font 5x7 dot

  write_ins(0x0C)              ;  //CMM Display On/OFF :D=1,Display On
  write_ins(0x06)              ;  //CMM Entry :I/D(1)= DD RAM Address Increment,S(0) Cursor Shift
  write_ins(0x01)              ;  //CMM Clear Display


 }

 //------- Enable LCD -------

 void EN_LCD(void)
  {
    sbi(PORTD,7)        ;  //Set bit PD7 =En = 1
    delay_ms(1)         ;
   
    cbi(PORTD,7)        ;  //Clear bit PD7 =En = 0
    delay_ms(1)         ;
 }


//----------- Write Instruction LCD Command ------------

void write_ins(unsigned char cmm)
 {
     
    cbi(PORTG,4)                ; //Clear bit PG4 = RS  = 0
  
    PORTG  &= 0xF0              ; //Clear 4 bit Low of PORTG
    PORTG  |= ((cmm>>4) & 0x0F) ; //Sent Command 4 Bit High to PORTG
    EN_LCD()                    ; //Enable LCD
    delay_ms(3)                 ;
   

    PORTG &= 0xF0               ; //Clear 4 bit Low of PORTG 
    PORTG |= (cmm  & 0x0F)      ; //Clear Cmm 4 bit High and Sent Command 4 Bit Low   to PORTG
    EN_LCD()                    ;
    delay_ms(3)                 ;


 }

//----------- Write Data LCD Command ------------


 void write_data(unsigned char dat)
  {
          
    sbi(PORTG,4)                  ; //Set Bit PG4   = RS  = 1

    PORTG  &= 0xF0                ; //Clear 4 bit Low of PORTG 
    PORTG  |= ((dat>>4) & 0x0F)   ; //Sent Command 4 Bit High to PORTG
    EN_LCD()                      ; //Enable LCD
    delay_ms(3)                   ;
   

    PORTG  &= 0xF0                ; //Clear 4 bit Low of PORTG
    PORTG  |= (dat & 0x0F)        ; //Clear Cmm 4 bit High and Sent Command 4 Bit Low  to PORTG
    EN_LCD()                      ;
    delay_ms(3)                   ;

  }


//------------ Move Cursor LCD ------------

void gotolcd(unsigned char p)
 {
   p |= 0x80    ;
   write_ins(p) ;
 }
