serial.h By Zhi-Hern Loh

Home
Design
Results
A 2nd try
Schematics
Code
Files
Links
Contact

//ZHI-HERN LOH
//SERIAL INTERFACE FOR Mega128
//SERIAL.H    
                                
/****USAGE      
Init_Serial() and
sei MUST be called before first use!

to output to USART1 (connected to PD[2..3])
  1.Check that OUT_RDY == 1
  2.Call S_Out(OutStr)
  	where OutStr contains a pointer to a sram string
  or call S_Outf(OutStr)
  	where OutStr contains a pointer to a string in flash
  	
to read USART1        
  1.Check that IN_RDY == 1
  2.Call S_In(InStr[])
  	the input buffer is written to InStr

****/ 
#include <string.h>
#include <lcd.h>
#include "xmodem.h"
#include "sta013.h"

#ifndef begin
#define begin {
#define end }
#endif

#define BUF_SIZE 64
                          
//the following is a state variable for the 
//UART, Nmode-for normal I/O
//      Xmode-for Xmodem transfer  
unsigned char SERIAL_MODE;
#define Nmode 0
#define Xmode 1

unsigned char SERIAL_OUT[BUF_SIZE];//RS232 output
unsigned char SERIAL_IN[BUF_SIZE];//RS232 input
unsigned char SERIAL_OUT_IDX;//index to serial out
unsigned char SERIAL_IN_IDX;//index to serial in

#define OUT_RDY SERIAL_OUT[0]==0 //serial port ready for output
unsigned char IN_RDY;//serial port input ready to read

//the following control the UART ISRs
#define USART1_UDRIEN  UCSR1B=UCSR1B|(1<<5) //Turn on UDR empty ISR
#define USART1_UDRIDIS UCSR1B=UCSR1B&0xdf //Turn off UDR empty ISR

#define USART1_RXCIEN  UCSR1B=UCSR1B|0x80 //Turn on RXC ISR
#define USART1_RXCIDIS UCSR1B=UCSR1B&0x7f //Turn off RXC ISR

//Interrupt flags
#define RXC  UCSR1A&(1<<7)//UCSR1A.7  //rx complete flag
#define UDRE UCSR1A&(1<<5)//UCSR1A.5 //UDR empty flag

//FUNCTION PROTOTYPES
//external prototypes
void Init_Serial(void);
void S_Out(unsigned char OutStr[]);
void S_Outf(unsigned char flash OutStrf[]);
void S_Set_Out_Error(unsigned char Error_Code);
void S_In(unsigned char InStr[]);
void S_Printf(unsigned char flash OutStrf[]); 
void S_Print(unsigned char OutStr[]);
void pause(void);
//internal prototypes
void Serial_Out_Handler(void);//writes to UART


void S_Printf(unsigned char flash OutStrf[])
begin
while(OUT_RDY==0);
S_Outf(OutStrf);
end             

void S_Print(unsigned char OutStr[])
begin
while(OUT_RDY==0);
S_Out(OutStr);
end
void Init_Serial(void)
begin
UBRR1L = 16;//57.6 Kbps
//UBRR1L = 8;//CK16Mhz 115.2Kbps BAUD
//UBRR1L = 103;//CK 16MHz, 9600 BAUD
//UBRR1L = 51;//CK 8MHz 9600 BAUD
UBRR1H = 0;

UCSR1C = 2+4;//set to asyn mode,8 bit data

UCSR1B = 24;//TX,RX enable for UART1   

SERIAL_IN_IDX=0;
SERIAL_OUT_IDX=0;
SERIAL_IN[0]=0;
SERIAL_OUT[0]=0;

SERIAL_MODE = Nmode;//set to normal mode for I/O

IN_RDY = 0;//no <cr> detected yet
USART1_RXCIEN;//turn on RXC ISR
end

void S_Outf(unsigned char flash OutStrf[])
begin                                    
unsigned char OutStr[BUF_SIZE];
strcpyf(OutStr,OutStrf);
S_Out(OutStr);
end

void S_Out(unsigned char OutStr[])
begin
SERIAL_OUT_IDX = 0;
while(OutStr[SERIAL_OUT_IDX]!=0)//copy to output buffer
  begin
  SERIAL_OUT[SERIAL_OUT_IDX] = OutStr[SERIAL_OUT_IDX];
  SERIAL_OUT_IDX++;
  if (SERIAL_OUT_IDX>BUF_SIZE) break;
  end              
SERIAL_OUT[SERIAL_OUT_IDX] = 0;//null terminate
if (SERIAL_OUT_IDX == 0) //error, fcn given empty str,output 
  begin
  S_Set_Out_Error(143);//
  end                 
if (SERIAL_OUT_IDX > BUF_SIZE)
  begin//buffer overflow
  S_Set_Out_Error(144);//
  //limit to BUF_SIZE characters
  SERIAL_OUT[BUF_SIZE] = 0;//null terminate
  end               
SERIAL_OUT_IDX = 0;//Start TX from element 0
//Turn on UDR empty ISR
USART1_UDRIEN;                  
end         

void S_Set_Out_Error(unsigned char Error_Code)
begin
SERIAL_OUT[0] = Error_Code;
SERIAL_OUT[1] = 0;
SERIAL_OUT_IDX = 1;
end                 
          

//reading UART, turn RXCIE off
//copy SERIAL_IN to InStr
//turn RXCIE on
void S_In(unsigned char InStr[])
begin          
USART1_RXCIDIS;//turn off RXC ISR
strcpy(InStr, SERIAL_IN);
//Clear IN_RDY flag because message has been read
IN_RDY = 0;
//reset input buffer
SERIAL_IN_IDX=0;
USART1_RXCIEN;//turn on RXC ISR
end

//UART output ISR, reads from SERIAL_OUT[]
interrupt [USART1_DRE] void UART_UDRE_interrupt(void)
begin
//if (SERIAL_MODE == Nmode) Serial_Out_Handler();
//Catch errors
if (SERIAL_OUT[SERIAL_OUT_IDX] == 0)
  begin
  //TX complete turn this ISR off
  USART1_UDRIDIS;
  //Set ready for more input flag
  SERIAL_OUT[0]=0;//OUT_RDY=1
  //DEBUG to see if this runs
  //PORTC = ~(0x01);
  end           
else
  begin
  UDR1 = SERIAL_OUT[SERIAL_OUT_IDX++];
  end
if (SERIAL_OUT[SERIAL_OUT_IDX] == 0)
  begin
  //TX complete turn this ISR off
  USART1_UDRIDIS;
  //PORTC = ~(UCSR1B);//get 10011000, UDRIE off, so correct
  //Set ready for more input flag
  SERIAL_OUT[0]=0;//OUT_RDY=1
  //DEBUG to see if this runs
  //PORTC = ~(0x02);
  end
end

//UART input ISR, writes to SERIAL_IN[]
interrupt [USART1_RXC] void UART_RXC_interrupt(void)
begin          
unsigned char c;
c = UDR1;
if (IN_RDY!=1)//cr not detected yet
  begin       
  //PORTC = PORTC^0x08;
  //write to buffer if it is not full and not a cr
  if (c=='\r')
    begin      
    //PORTC = PORTC^0x01;
    SERIAL_IN[SERIAL_IN_IDX]=0;//null terminate
    //UDR1='*';//DEBUG
    IN_RDY = 1;
    end                                           
  else
    begin              
    //PORTC = PORTC^0x02;
    SERIAL_IN[SERIAL_IN_IDX] = c;
    SERIAL_IN_IDX++;
    UDR1 = c;
    end                            
  end
//else dump the input                            
//haven't checked for input overflow
end                             

void pause(void)
begin
unsigned char tmpstr[32];
while(OUT_RDY==0);
S_Outf("paused");
while(IN_RDY==0);
S_In(tmpstr);
while(OUT_RDY==0);
S_Outf("resumed\n\r");
end   

Home | Design | Results | A 2nd try | Schematics | Code | Files | Links | Contact

For problems or questions regarding this web contact Zhi-Hern Loh.
Last updated: 05/02/02.