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 * -# Keyboard/Mouse Dual Class Host
* -# Multiple-Report HID device * -# Multiple-Report HID device
* -# Device/Host bridge * -# Device/Host bridge
* -# PDI Programming Support in the AVRISP Project
* - Ports * - Ports
* -# AVR32 UC3B series microcontrollers * -# AVR32 UC3B series microcontrollers
* -# Atmel ARM7 series microcontrollers * -# Atmel ARM7 series microcontrollers

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

@ -2,6 +2,8 @@
soft_uart soft_uart
v0.2
Copyright John Steggall 2009 Copyright John Steggall 2009
*/ */
@ -30,17 +32,31 @@
*/ */
/* /*
Specifically designed for the xplain board, other uses could be made by furkling through the code Specifically designed for the xplain board, other uses could be made by adjusting uart_soft_conf.h
and replacing the port and pin assignments. Also relies on and external interupt to detect the low 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. 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) 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 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. 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 #ifndef UART_SOFT_H
#define UART_SOFT_H #define UART_SOFT_H
/* status */
extern uint8_t status;
/* initialises software uart and enables transmit */ /* initialises software uart and enables transmit */
extern void SoftUART_Init(void); 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