/*------------------------------------------------------------------------------ SIO.C: Serial Communication Routines. Copyright 1995-2002 KEIL Software, Inc. ------------------------------------------------------------------------------*/ #include #include #include "hwconfig.h" #include "sio.h" /*------------------------------------------------------------------------------ Notes: The length of the receive and transmit buffers must be a power of 2. Each buffer has a next_in and a next_out index. If next_in = next_out, the buffer is empty. (next_in - next_out) % buffer_size = the number of characters in the buffer. ------------------------------------------------------------------------------*/ #define TBUF_SIZE 2 /*** Must be one of these powers of 2 (2,4,8,16,32,64,128) ***/ #define RBUF_SIZE 8 /*** Must be one of these powers of 2 (2,4,8,16,32,64,128) ***/ #define TBUF_SPACE idata /*** Memory space where the transmit buffer resides ***/ #define RBUF_SPACE idata /*** Memory space where the receive buffer resides ***/ #define CTRL_SPACE data /*** Memory space for the buffer indexes ***/ /*------------------------------------------------------------------------------ ------------------------------------------------------------------------------*/ #if TBUF_SIZE < 2 #error TBUF_SIZE is too small. It must be larger than 1. #elif TBUF_SIZE > 128 #error TBUF_SIZE is too large. It must be smaller than 129. #elif ((TBUF_SIZE & (TBUF_SIZE-1)) != 0) #error TBUF_SIZE must be a power of 2. #endif #if RBUF_SIZE < 2 #error RBUF_SIZE is too small. It must be larger than 1. #elif RBUF_SIZE > 128 #error RBUF_SIZE is too large. It must be smaller than 129. #elif ((RBUF_SIZE & (RBUF_SIZE-1)) != 0) #error RBUF_SIZE must be a power of 2. #endif /*------------------------------------------------------------------------------ ------------------------------------------------------------------------------*/ static TBUF_SPACE unsigned char tbuf [TBUF_SIZE]; static RBUF_SPACE unsigned char rbuf [RBUF_SIZE]; static CTRL_SPACE unsigned char t_in = 0; static CTRL_SPACE unsigned char t_out = 0; static CTRL_SPACE unsigned char r_in = 0; static CTRL_SPACE unsigned char r_out = 0; static bit ti_restart = 0; /* NZ if TI=1 is required */ /*------------------------------------------------------------------------------ ------------------------------------------------------------------------------*/ static void com_isr (void) interrupt 4 { /*------------------------------------------------ Received data interrupt. ------------------------------------------------*/ if (RI != 0) { RI = 0; if (((r_in - r_out) & ~(RBUF_SIZE-1)) == 0) { rbuf [r_in & (RBUF_SIZE-1)] = SBUF; r_in++; } } /*------------------------------------------------ Transmitted data interrupt. ------------------------------------------------*/ if (TI != 0) { TI = 0; if (t_in != t_out) { SBUF = tbuf [t_out & (TBUF_SIZE-1)]; t_out++; ti_restart = 0; } else { ti_restart = 1; } } } /*------------------------------------------------------------------------------ ------------------------------------------------------------------------------*/ #pragma disable void com_initialize (void) { /*------------------------------------------------ Setup TIMER1 to generate the proper baud rate. ------------------------------------------------*/ PT0 = 1; /* set timer 0 to high priority */ PT1 = 1; /* set timer 1 to high priority */ com_baudrate (9600); /*------------------------------------------------ Clear com buffer indexes. ------------------------------------------------*/ t_in = 0; t_out = 0; r_in = 0; r_out = 0; /*------------------------------------------------ Setup serial port registers. ------------------------------------------------*/ SM0 = 0; SM1 = 1; /* serial port MODE 1 */ SM2 = 0; REN = 1; /* enable serial receiver */ RI = 0; /* clear receiver interrupt */ TI = 0; /* clear transmit interrupt */ ti_restart = 1; ES = 1; /* enable serial interrupts */ PS = 0; /* set serial interrupts to low priority */ } /*------------------------------------------------------------------------------ ------------------------------------------------------------------------------*/ #pragma disable void com_baudrate (unsigned int baudrate) { /*------------------------------------------------ Clear transmit interrupt and buffer. ------------------------------------------------*/ TI = 0; /* clear transmit interrupt */ t_in = 0; /* empty transmit buffer */ t_out = 0; /*------------------------------------------------ Set internal Baudrate generator ------------------------------------------------*/ /* disable baudrate generator while we initalize it */ /*select internal baudrate generator */ BRGCON = 0x2; /* CCLK/((BRGR1,BRGR0)+16) == baudrate */ /* (BRGR1,BRGR0) == (Baudrate*CCLK)-16 */ BRGR0 = 0xf0; //(unsigned char) (baudrate*CCLK-16); BRGR1 = 0x02; //(unsigned char) (baudrate*CCLK-16) << 8; BRGCON = 0x3; /* re-enable the now initalized baudrate genrator */ } /*------------------------------------------------------------------------------ ------------------------------------------------------------------------------*/ #pragma disable char com_putchar ( unsigned char c) { /*------------------------------------------------ If the buffer is full, return an error value. ------------------------------------------------*/ if (com_tbuflen () >= TBUF_SIZE) return (-1); /*------------------------------------------------ Add the data to the transmit buffer. If the transmit interrupt is disabled, then enable it. ------------------------------------------------*/ tbuf [t_in & (TBUF_SIZE - 1)] = c; t_in++; if (ti_restart) { ti_restart = 0; TI = 1; /* generate transmit interrupt */ } return (0); } /*------------------------------------------------------------------------------ ------------------------------------------------------------------------------*/ #pragma disable int com_getchar (void) { if (com_rbuflen () == 0) return (-1); return (rbuf [(r_out++) & (RBUF_SIZE - 1)]); } /*------------------------------------------------------------------------------ ------------------------------------------------------------------------------*/ #pragma disable unsigned char com_rbuflen (void) { return (r_in - r_out); } /*------------------------------------------------------------------------------ ------------------------------------------------------------------------------*/ #pragma disable unsigned char com_tbuflen (void) { return (t_in - t_out); } /*------------------------------------------------------------------------------ ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ _getkey waits until a character is received from the serial port. This may not be the exact desired operation (for example if the buffer is empty, this function hangs waiting for a character to be received). ------------------------------------------------------------------------------*/ char _getkey (void) { int k; do { k = com_getchar (); } while (k == -1); return ((unsigned char) k); } /*------------------------------------------------------------------------------ ------------------------------------------------------------------------------*/ char putchar (char c) { volatile unsigned int i; while (com_putchar (c) != 0) { for (i=0; i<1000; i++) { /*** DO NOTHING ***/ } } return (c); }