Skip to content

Commit

Permalink
Create UART functions using C macros according to the api.h file
Browse files Browse the repository at this point in the history
  • Loading branch information
Roarin committed Jul 19, 2016
1 parent bc7b0f4 commit da356b1
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 193 deletions.
15 changes: 15 additions & 0 deletions examples/download.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash -e

DEVS=$(lsusb|grep -E '(2a19|16c0|04b4|1d50|fb9a|1443)' |sed 's/:.*//;s/Bus //;s/Device //;s/ /\//')

if [ -z "$1" ]; then
echo "$0: usage: $0 <file>"
exit 1;
fi

for dev in $DEVS;do
echo "Downloading $1 to $dev"
/sbin/fxload -D /dev/bus/usb/$dev -t fx2lp -I $1
done

exit 0
2 changes: 0 additions & 2 deletions examples/uart_main/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,3 @@ SOURCES=uart_main.c
DSCR_AREA=
INT2JT=
include $(FX2LIBDIR)/lib/fx2.mk
fx2_download:
../download.sh build/$(BASENAME).ihx
34 changes: 22 additions & 12 deletions examples/uart_main/uart_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,38 @@
#include <uart/api.h>
#include <uart/soft_uart.h>
#include <fx2macros.h>
#include <fx2types.h>
#include <assert.h>


//We need this declaration
void uart0_tx(char c);

//Initialize UART, call it uart0 and set the tx pin on PA1
CREATE_FAST_UART(uart0,0x82)
CREATE_FAST_UART(uart0, OEB, _PB2,bmBIT2,1,0)
CREATE_FAST_UART(uart1, OEA, _PA3,bmBIT3,1,0)

//Used for setting the baud rate.
enum uart_baud baud;
void main(void)
{
baud = BAUD_115200;
uartX_init(baud);
uartX_set_baud(baud);
SETCPUFREQ(CLK_48M);
while (TRUE)
{
printf("Hello\r\n");
}
baud = BAUD_115200;
SETCPUFREQ(CLK_48M);

while (!uart0_init(baud));

while (!uart1_init(baud));

uart0_set_baud(baud);
baud = BAUD_115200;
uart1_set_baud(baud);

while (TRUE)
{
printf("Hello\r\n");
uart1_tx(0x44);
}
}

void putchar(char c)
{
uart0_tx(c);
uart0_tx(c);
}
4 changes: 2 additions & 2 deletions include/uart/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ BOOL uartX_init(enum uart_baud rate, ...);
* \li 38400
* \li 57600
* \li 115200
* Returns 0 if successful.
* Returns 0 if successful.
**/
BOOL uartX_set_baud(enum uart_baud rate);

Expand All @@ -42,7 +42,7 @@ BOOL uartX_set_baud(enum uart_baud rate);
enum uart_baud uartX_get_baud();

/**
* \brief transmits data through UART
* \brief transmits data through UART
* \param c The character to be sent out
**/

Expand Down
173 changes: 157 additions & 16 deletions include/uart/soft_uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,165 @@
#ifndef SOFT_UART_H
#define SOFT_UART_H

#define load_delay unsigned char
/**
* \brief Automatically generates the function calls to allow multiple
* UARTS to be created. The main parameters for the UART is the pin number
* as well as the speed of the operation. These should be passed as an argument
* to the macro. The load_delay element controls the speed. This is created with the
* uart name .
**/
#define CREATE_FAST_UART(uartname,port,pinname,bitnum,TX_BLOCKING,RX_ENABLED) \
unsigned char uartname##_load_delay; \
enum uart_baud uartname##rate; \
BOOL uartname##_init(enum uart_baud rate,...) \
{ \
uartX_init(rate); \
return TRUE; \
} \
void uartname##_tx(char c) { \
__asm \
.equ _TX_PIN1,pinname \
.equ _load_delay,_##uartname##_load_delay \
__endasm; \
port = bitnum; \
uart_tx(c); \
} \
BOOL uartname##_set_baud(enum uart_baud rate) { \
uartname##rate = rate; \
switch(rate) \
{ \
case BAUD_2400: \
return FALSE; \
case BAUD_4800: \
return FALSE; \
case BAUD_9600: \
return FALSE; \
case BAUD_19200: \
uartname##_load_delay = 0xd0; \
break; \
case BAUD_38400: \
uartname##_load_delay = 0x68; \
break; \
case BAUD_57600: \
uartname##_load_delay = 0x45; \
break; \
case BAUD_115200: \
uartname##_load_delay = 0x20; \
break; \
case BAUD_ANY: \
break; \
case BAUD_FASTEST: \
uartname##_load_delay = 0x20; \
uartname##rate = BAUD_115200; \
break; \
default: \
uartname##_load_delay = 0x20; \
break; \
} \
return TRUE; \
} \
enum uart_baud uartname##_get_baud() \
{ \
return uartname##rate; \
} \
BOOL uartname##_tx_willblock() \
{ \
return TX_BLOCKING; \
} \
char uartname##_rx() \
{ \
assert(FALSE); \
return 0xFF; \
} \
BOOL uartname##_check_rx_blocking() \
{ \
return FALSE; \
} \
BYTE uartname##_check_receive_buffer() \
{ \
return FALSE; \
} \
BOOL uartname##_init(enum uart_baud rate,...); \
void uartname##_tx(char c); \
BOOL uartname##_set_baud(enum uart_baud rate); \
enum uart_baud uartname##_get_baud(); \
BOOL uartname##_tx_willblock(); \
char uartname##_rx(); \
BOOL uartname##_check_rx_blocking(); \
BYTE uartname##_check_receive_buffer();


#define CREATE_FAST_UART(uart0,pinname) \
__sbit __at pinname TX_PIN; \
BOOL uart0##_init(enum uart_baud rate,...) \
{__asm \
.equ _TX_PIN , _PA2 \
__endasm; \
return TRUE; \
} \
void uart0##_tx(char c) { \
uart_tx(c); \
}
/*Holds the value of the EA register*/
__bit ea_hold;

/**
* \brief Send data out via UART
**/
void uart_tx(char c);
static inline void uart_tx(char c)
{

#endif
//Done in ASM to improve performance. It takes only 6
//cycles to move the data out, however a delay has been
//introduced in order to get a baud rate of 115200
//The mask which is to be written into the pin
//An efficient UART bitbang routine in assembly
__asm
//Like #define in C. Can easily be used to change the pin
//.equ _TX_PIN, _PA2
//Disable interrupts
//This is used because timing is critical
//If the FX2 jumps into the ISR temporarily , it may cause transmit
//errors. By clearing EA, we can disable interrupts
mov _ea_hold,_EA //Store the EA bit
0002$:
clr _EA //(2 cycles)
//Move the data to be sent into the ACC
//The data which is to be shifted out is held in the dpl register
//We move the data into A for easy access to subsequent instructions
mov a , dpl //(2 cyles)
clr c //(1 cycle )
//We need to send out 8 bits of data
//Load r0 with value 8
mov r0, #0x08 //(2 cycles)
//Create the start bit
clr _TX_PIN1 //(2 cycles)
//Precalculated delay since 1 cycle takes 88ns
//At 12Mhz, it should be about 83.33ns
//But it appears to be about 88ns
//These numbers have been verified using an analyzer
mov r1, _load_delay //(2 cycles)
0003$:
//1 bit is about 8.6us
djnz r1, 0003$ //(3 cycles)
//DJNZ on Rn takes 3 cycles
//NOP takes about 1 cycle
//Add 2 more cycles of delay
//97 cycles
nop //(1 cycle )
nop //(1 cycle )
0004$:
rrc a //(2 cycles)
//The above rotates the accumulator right through the carry
//Move the carry into the port
mov _TX_PIN1, c //(2 cycles)
//Now we need to add delay for the next
mov r1, _load_delay //(2 cycles)
//31*3 , 93 cycles of delay
0005$:
djnz r1, 0005$ //(3 cycles)
nop //(1 cycle )
//3 more cycles of delay
//97 cycles
djnz r0, 0004$ //(3 cycles)
setb _TX_PIN1 //(2 cycles)
//This is for stop bit
//We need to delay the stop bit, otherwise we may get errors.
mov r1, _load_delay //(2 cycles)
0006$:
djnz r1, 0006$ //(3 cycles)
//for DJNZ , Jump for 32*3 , 96 cycles
nop //(1 cycle )
//97 cycles of delay
mov _EA, _ea_hold //Restore the EA register to enable or disable interrupts
__endasm;
}

#endif
2 changes: 1 addition & 1 deletion lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

AS8051?=sdas8051
SOURCES = serial.c i2c.c delay.c setupdat.c gpif.c eputils.c $(wildcard interrupts/*.c) $(wildcard uart/*.c)
SOURCES = serial.c i2c.c delay.c setupdat.c gpif.c eputils.c $(wildcard interrupts/*.c)
FX2_OBJS = $(patsubst %.c,%.rel, $(SOURCES)) usbav.rel
INCLUDES = -I../include
SDCC = sdcc -mmcs51 $(SDCCFLAGS)
Expand Down
2 changes: 2 additions & 0 deletions lib/fx2.mk
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,5 @@ clean:
clean-all: clean
$(MAKE) -C $(FX2LIBDIR)/lib clean

fx2_download:
../download.sh build/$(BASENAME).ihx
Loading

0 comments on commit da356b1

Please sign in to comment.