| |
//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
|