Updated John Steggall's software USART in the XPLAINBridge project.

pull/1469/head
Dean Camera 15 years ago
parent ab602a8b48
commit f37d21bbe9

File diff suppressed because one or more lines are too long

@ -31,6 +31,7 @@
* -# Keyboard/Mouse Dual Class Host
* -# Multiple-Report HID device
* -# Device/Host bridge
* -# PDI Programming Support in the AVRISP Project
* - Ports
* -# AVR32 UC3B series microcontrollers
* -# Atmel ARM7 series microcontrollers

@ -2,6 +2,8 @@
uart_soft
v0.2
copyright John Steggall 2009
*/
@ -30,10 +32,8 @@
*/
#include <avr/io.h>
#include "SoftUARTConf.h"
/* BITLENGTH is the time for a bit cycle worked out at F_CPU / BAUD. Gives a rough but usable figure. Wouldn't like to try
* anything faster than 9600! */
#define BITLENGTH 833
#define SFT_TX_EN 7
@ -52,43 +52,59 @@ rxShifter:
.byte 0
rxBitcount:
.byte 0
.global status
status:
.byte 0
.section .text
.global RX_PIN_INT
/*********************************************
* External interrupt
*
* RX pin has gone low.
*/
.global INT0_vect
INT0_vect:
RX_PIN_INT:
push r16
lds r16,SREG
push r16
lds r16,PIND
#if (RXPORT>=32)
lds r16,RXPORT
sbrc r16,0 // anti glitch
#else
sbic RXPORT,0
#endif
rjmp ignore
nop
nop
nop
nop
lds r16,PIND
sbrc r16,0 // just make sure
#if (RXPORT>=32)
lds r16,RXPORT
sbrc r16,0 // anti glitch
#else
sbic RXPORT,0
#endif
rjmp ignore
push r17
// grab timer value
lds r16,TCNT3L
lds r17,TCNT3H
lds r16,TC_COUNTL
lds r17,TC_COUNTH
// set trigger for RX timer (will need to add a little more though)
sts OCR3CH,r17
sts OCR3CL,r16
sts TC_RX_COMPH,r17
sts TC_RX_COMPL,r16
pop r17
@ -98,13 +114,15 @@ INT0_vect:
// turn off interrupt, will get annoying.
cbi 0x1D,0
cbi EXTI_MASK_REG,EXTI_MASK_BIT
// turn on interrupt on compare match
sbi 0x18,OCF3C
lds r16,TIMSK3
ori r16,(1<<OCIE3C)
sts TIMSK3,r16
sbi TC_INTFLAG_REG,TC_RX_IF_BIT //------------------------
lds r16,TC_INT_MASK_REG
ori r16,(1<<TC_RX_COMPEN)
sts TC_INT_MASK_REG,r16
ignore:
pop r16
@ -136,17 +154,23 @@ TIMER3_COMPB_vect:
lds r16,txShifter
lds r17, PORTD
#if (TXPORT>=32)
lds r17, TXPORT
sbrs r16,0
andi r17,0xFD
andi r17,~(1<<TXPIN)
sbrc r16,0
ori r17,0x02
ori r17,(1<<TXPIN)
sts TXPORT,r17
sts PORTD,r17
#else
sbrs r16,0
cbi TXPORT,TXPIN
sbrc r16,0
sbi TXPORT,TXPIN
lsr r16
ori r16,0x80
#endif
sec
ror r16
txout:
sts txShifter,r16
@ -164,9 +188,9 @@ lastBitTX:
ori r17,SF_UART_TX // set TXC/DRE flag
sts status,r17
lds r16,TIMSK3
andi r16,~(1<<OCIE3B)
sts TIMSK3,r16
lds r16,TC_INT_MASK_REG
andi r16,~(1<<TC_TX_COMPEN)
sts TC_INT_MASK_REG,r16
rjmp lastBitOut // over and out
@ -199,11 +223,27 @@ TIMER3_COMPC_vect:
ldi r18,3 // set counter to 3
ldi r17,0
// cbi 0x0B,1 // marker
#ifdef DEBUG
#if RXPORT>64
lds r16,RXPORT
andi r16,~(1<<TXPIN)
sts TXPORT,r16
#else
cbi TXPORT,TXPIN // marker
#endif
#endif
loopGetBit:
lds r16,PIND
sbrc r16,0
#if (RXPORT>=32)
lds r16,RXPORT
sbrs r16,RXPIN
#else
sbic RXPORT,RXPIN
#endif
inc r17
dec r18
nop
@ -212,7 +252,19 @@ loopGetBit:
nop
brne loopGetBit
// sbi 0x0B,1 // marker
#ifdef DEBUG
#if RXPORT>64
lds r16,RXPORT
ori r16,1<<TXPIN
sts r16
#else
sbi TXPORT,TXPIN // marker
#endif
#endif
lds r16,rxShifter
lsr r16
@ -226,8 +278,16 @@ skipBitSet:
lastBitRX:
lds r17,status // store status
lds r16,PIND // get status of stop bit
sbrc r16,0
#if (RXPORT>=32)
lds r16,RXPORT
sbrc r16,RXPIN
#else
sbic RXPORT,RXPIN
#endif
ori r17,0x02 // set flag if stop bit was high
sts status,r17
@ -237,19 +297,19 @@ lastBitRX:
// switch interrupt back on to get another go
sbi 0x1C,0 // clear interrupt flag
sbi 0x1D,0 // enable external interrupt 0 (RX)
sbi EXTI_FLAG_REG,EXTI_MASK_BIT // clear interrupt flag
sbi EXTI_MASK_REG,EXTI_MASK_BIT // enable external interrupt 0 (RX)
// switch off rx bit timer
lds r16,TIMSK3
andi r16,~(1<<OCIE3C)
sts TIMSK3,r16
lds r16,TC_INT_MASK_REG
andi r16,~(1<<TC_RX_COMPEN)
sts TC_INT_MASK_REG,r16
rjmp lastBitOut // loud and clear
rx1stbit:
lds r16,TCNT3L
lds r17,TCNT3H
lds r16,TC_COUNTL
lds r17,TC_COUNTH
subi r16,lo8(BITLENGTH / 2)
sbci r17,hi8(BITLENGTH / 2)
@ -259,8 +319,8 @@ rx1stbit:
sbci r17,hi8(0xFFFF - BITLENGTH)
skipOverflow:
sts OCR3CH,r17
sts OCR3CL,r17
sts TC_RX_COMPH,r17
sts TC_RX_COMPL,r17
rjmp lastBitOut
@ -273,12 +333,20 @@ skipOverflow:
SoftUART_Init:
lds r18,PORTD
#if (TXPORT>=32)
lds r18,TXPORT
ori r18,0x02
sts PORTD,r18
lds r18,DDRD
sts TXPORT,r18
lds r18,TXDIR_REG
ori r18,0x02
sts DDRD,r18
sts TXDIR_REG,r18
#else
sbi TXPORT,TXPIN
sbi TXDIR_REG,TXPIN
#endif
ldi r18,(1<<SFT_TX_EN)|SF_UART_TX
sts status,r18
@ -290,17 +358,17 @@ SoftUART_Init:
// Start timer 3
ldi r18,0b00001001 // ctc count mode, clock div 1
sts TCCR3B,r18
sts TC_CTRLB,r18
// Interrupt on low level INT0
sbi 0x1C,0
sbi 0x1D,0
// Interrupt on pin change INT0
sbi EXTI_FLAG_REG,EXTI_MASK_BIT
sbi EXTI_MASK_REG,EXTI_MASK_BIT
ret
/*********************************************
* char SoftUART_TxByte(char)
* char SoftUART_RxByte(char)
*
* starts a byte send and returns the byte to be sent
*/
@ -309,7 +377,7 @@ SoftUART_Init:
SoftUART_TxByte:
lds r18,status
sbrs r18,SFT_TX_EN
rjmp uart_putchar_end
rjmp SoftUART_TxByte_end
andi r18,0xFE // clear tx empty flag
sts status,r18
@ -320,28 +388,35 @@ SoftUART_TxByte:
sts txBitcount,r18
// grab timer value
lds r18,TCNT3L
lds r19,TCNT3H
cli // Atomic section start
lds r18,TC_COUNTL
lds r19,TC_COUNTH
// drop down tx line for start bit
lds r20, PORTD
andi r20,0xFD
sts PORTD,r20
#if (TXPORT>=32)
lds r20, TXPORT
andi r20,~(1<<TXPIN)
sts TXPORT,r20
#else
cbi TXPORT,TXPIN
#endif
// set trigger for tx timer
cli
sts OCR3BH,r19
sts OCR3BL,r18
sei
sts TC_TX_COMPH,r19
sts TC_TX_COMPL,r18
sei // Atomic section end
// clear interrupt flag and enable tx interrupt
sbi 0x18,OCF3B
lds r18,TIMSK3
ori r18,(1<<OCIE3B)
sts TIMSK3,r18
uart_putchar_end:
sbi TC_INTFLAG_REG,TC_TX_IF_BIT
lds r18,TC_INT_MASK_REG
ori r18,(1<<TC_TX_COMPEN)
sts TC_INT_MASK_REG,r18
SoftUART_TxByte_end:
ret

@ -2,6 +2,8 @@
soft_uart
v0.2
Copyright John Steggall 2009
*/
@ -30,17 +32,31 @@
*/
/*
Specifically designed for the xplain board, other uses could be made by furkling through the code
and replacing the port and pin assignments. Also relies on and external interupt to detect the low
Specifically designed for the xplain board, other uses could be made by adjusting uart_soft_conf.h
replacing the port, pin and timer assignments. Also relies on and external interupt to detect the low
level of the start bit, in this case INT0.
Always configured to 9600baud. Can be changed by setting the BITLENGTH define to F_CPU/(desired baud)
code may need optimising when getting any faster to sample the bit in the correct place. No
compensation has been made for the response time of the int routine.
Note: Configured to use 16bit timers.
*/
/* Changes
*
* v0.2
* - Added configuration file to ease pain of setup for different hardware configuration
* - Changed bit access for ports that can be accessed directly
* - Fixed atomic section in uart_init to encompass counter read
*/
#ifndef UART_SOFT_H
#define UART_SOFT_H
/* status */
extern uint8_t status;
/* initialises software uart and enables transmit */
extern void SoftUART_Init(void);

@ -0,0 +1,75 @@
/*
soft_uart
v0.2
Copyright John Steggall 2009
*/
/*
Copyright 2009 John Steggall (steggall.j@gmail.com)
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
#ifndef UART_SOFT_CONF
#define UART_SOFT_CONF
#define BITLENGTH 833 // Length of data bit, worked out by F_CPU/desired baud
#define TXPIN 1 // Port pin TX is connected to
#define RXPIN 0 // Port pin RX is connected to
/* PORT setup */
#define RXPORT 0x09 // RX port selection
#define TXPORT 0x0B // TX port selection
#define TXDIR_REG 0x0A // Data direction port for TX pin
/* RX pin setup */
#define EXTI_FLAG_REG 0x1C
#define EXTI_MASK_REG 0x1D
#define EXTI_MASK_BIT 0
#define RX_PIN_INT INT0_vect // external interrupt vector for RX pin
#define RX_INT_vect TIMER3_COMPC_vect // interrupt vector for OCRnC
#define TX_INT_vect TIMER3_COMPB_vect // interrupt vector for OCRnB
#define TC_INT_MASK_REG TIMSK3 // interrupt timer mask register for timer(n)
#define TC_COUNTL TCNT3L // count high register for timer(n)
#define TC_COUNTH TCNT3H // count low register for timer(n)
/* Reciever setup */
#define TC_RX_COMPEN OCIE3C // interrupt enable for OCRnC (RX bit timer)
#define TC_RX_COMPH OCR3CH // OCRnC compare match high register
#define TC_RX_COMPL OCR3CL // OCRnC compare match high register
/* Transmitter setup */
#define TC_TX_COMPEN OCIE3B // interrupt enable for OCRnB (TX bit timer)
#define TC_TX_COMPH OCR3BH // OCRnB compare match high register
#define TC_TX_COMPL OCR3BL // OCRnB compare match low register
#define TC_CTRLB TCCR3B // timer(n) control register B
#define TC_INTFLAG_REG 0x18 // timer(n) interupt flag register
#define TC_TX_IF_BIT OCIE3B // timer(n) interrupt flag bit for OCRnB
#define TC_RX_IF_BIT OCIE3C // timer(n) interrupt flag bit for OCRnC
#endif
Loading…
Cancel
Save