You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					157 lines
				
				3.9 KiB
			
		
		
			
		
	
	
					157 lines
				
				3.9 KiB
			|   
											14 years ago
										 | ;---------------------------------------------------------------------------;
 | ||
|  | ; Software implemented UART module                                          ;
 | ||
|  | ; (C)ChaN, 2005 (http://elm-chan.org/)                                      ;
 | ||
|  | ;---------------------------------------------------------------------------;
 | ||
|  | ; Bit rate settings:
 | ||
|  | ;
 | ||
|  | ;            1MHz  2MHz  4MHz  6MHz  8MHz  10MHz  12MHz  16MHz  20MHz
 | ||
|  | ;   2.4kbps   138     -     -     -     -      -      -      -      -
 | ||
|  | ;   4.8kbps    68   138     -     -     -      -      -      -      -
 | ||
|  | ;   9.6kbps    33    68   138   208     -      -      -      -      -
 | ||
|  | ;  19.2kbps     -    33    68   102   138    173    208      -      -
 | ||
|  | ;  38.4kbps     -     -    33    50    68     85    102    138    172
 | ||
|  | ;  57.6kbps     -     -    21    33    44     56     68     91    114
 | ||
|  | ; 115.2kbps     -     -     -     -    21     27     33     44     56
 | ||
|  | 
 | ||
|  | .nolist | ||
|  | #include <avr/io.h> | ||
|  | .list | ||
|  | 
 | ||
|  | #define	BPS	102 	/* Bit delay. (see above table) */ | ||
|  | #define	BIDIR	0	/* 0:Separated Tx/Rx, 1:Shared Tx/Rx */ | ||
|  | 
 | ||
|  | #define	OUT_1		sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT	/* Output 1 */ | ||
|  | #define	OUT_0		cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT	/* Output 0 */ | ||
|  | #define	SKIP_IN_1	sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT	/* Skip if 1 */ | ||
|  | #define	SKIP_IN_0	sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT	/* Skip if 0 */ | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | #ifdef SPM_PAGESIZE | ||
|  | .macro	_LPMI	reg | ||
|  | 	lpm	\reg, Z+ | ||
|  | .endm | ||
|  | .macro	_MOVW	dh,dl, sh,sl | ||
|  | 	movw	\dl, \sl | ||
|  | .endm | ||
|  | #else | ||
|  | .macro	_LPMI	reg | ||
|  | 	lpm | ||
|  | 	mov	\reg, r0 | ||
|  | 	adiw	ZL, 1 | ||
|  | .endm | ||
|  | .macro	_MOVW	dh,dl, sh,sl | ||
|  | 	mov	\dl, \sl | ||
|  | 	mov	\dh, \sh | ||
|  | .endm | ||
|  | #endif | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | ;---------------------------------------------------------------------------;
 | ||
|  | ; Transmit a byte in serial format of N81
 | ||
|  | ;
 | ||
|  | ;Prototype: void xmit (uint8_t data);
 | ||
|  | ;Size: 16 words
 | ||
|  | 
 | ||
|  | .global xmit
 | ||
|  | .func xmit
 | ||
|  | xmit: | ||
|  | #if BIDIR | ||
|  | 	ldi	r23, BPS-1	;Pre-idle time for bidirectional data line
 | ||
|  | 5:	dec	r23     	;
 | ||
|  | 	brne	5b		;/
 | ||
|  | #endif | ||
|  | 	in	r0, _SFR_IO_ADDR(SREG)	;Save flags
 | ||
|  | 
 | ||
|  | 	com	r24		;C = start bit
 | ||
|  | 	ldi	r25, 10		;Bit counter
 | ||
|  | 	cli			;Start critical section
 | ||
|  | 
 | ||
|  | 1:	ldi	r23, BPS-1	;----- Bit transferring loop 
 | ||
|  | 2:	dec	r23     	;Wait for a bit time
 | ||
|  | 	brne	2b		;/
 | ||
|  | 	brcs	3f		;MISO = bit to be sent
 | ||
|  | 	OUT_1			;
 | ||
|  | 3:	brcc	4f		;
 | ||
|  | 	OUT_0			;/
 | ||
|  | 4:	lsr	r24     	;Get next bit into C
 | ||
|  | 	dec	r25     	;All bits sent?
 | ||
|  | 	brne	1b	     	;  no, coutinue
 | ||
|  | 
 | ||
|  | 	out	_SFR_IO_ADDR(SREG), r0	;End of critical section
 | ||
|  | 	ret | ||
|  | .endfunc | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | ;---------------------------------------------------------------------------;
 | ||
|  | ; Receive a byte
 | ||
|  | ;
 | ||
|  | ;Prototype: uint8_t rcvr (void);
 | ||
|  | ;Size: 19 words
 | ||
|  | 
 | ||
|  | .global rcvr
 | ||
|  | .func rcvr
 | ||
|  | rcvr: | ||
|  | 	in	r0, _SFR_IO_ADDR(SREG)	;Save flags
 | ||
|  | 
 | ||
|  | 	ldi	r24, 0x80	;Receiving shift reg
 | ||
|  | 	cli			;Start critical section
 | ||
|  | 
 | ||
|  | 1:	SKIP_IN_1		;Wait for idle
 | ||
|  | 	rjmp	1b | ||
|  | 2:	SKIP_IN_0		;Wait for start bit
 | ||
|  | 	rjmp	2b | ||
|  | 	ldi	r25, BPS/2	;Wait for half bit time
 | ||
|  | 3:	dec	r25 | ||
|  | 	brne	3b | ||
|  | 
 | ||
|  | 4:	ldi	r25, BPS	;----- Bit receiving loop
 | ||
|  | 5:	dec	r25     	;Wait for a bit time
 | ||
|  | 	brne	5b		;/
 | ||
|  | 	lsr	r24     	;Next bit
 | ||
|  | 	SKIP_IN_0		;Get a data bit into r24.7
 | ||
|  | 	ori	r24, 0x80 | ||
|  | 	brcc	4b	     	;All bits received?  no, continue
 | ||
|  | 
 | ||
|  | 	out	_SFR_IO_ADDR(SREG), r0	;End of critical section
 | ||
|  | 	ret | ||
|  | .endfunc | ||
|  | 
 | ||
|  | 
 | ||
|  | ; Not wait for start bit. This should be called after detecting start bit.
 | ||
|  | .global recv
 | ||
|  | .func recv
 | ||
|  | recv: | ||
|  | 	in	r0, _SFR_IO_ADDR(SREG)	;Save flags
 | ||
|  | 
 | ||
|  | 	ldi	r24, 0x80	;Receiving shift reg
 | ||
|  | 	cli			;Start critical section
 | ||
|  | 
 | ||
|  | ;1:	SKIP_IN_1		;Wait for idle
 | ||
|  | ;	rjmp	1b
 | ||
|  | ;2:	SKIP_IN_0		;Wait for start bit
 | ||
|  | ;	rjmp	2b
 | ||
|  | 	ldi	r25, BPS/2	;Wait for half bit time
 | ||
|  | 3:	dec	r25 | ||
|  | 	brne	3b | ||
|  | 
 | ||
|  | 4:	ldi	r25, BPS	;----- Bit receiving loop
 | ||
|  | 5:	dec	r25     	;Wait for a bit time
 | ||
|  | 	brne	5b		;/
 | ||
|  | 	lsr	r24     	;Next bit
 | ||
|  | 	SKIP_IN_0		;Get a data bit into r24.7
 | ||
|  | 	ori	r24, 0x80 | ||
|  | 	brcc	4b	     	;All bits received?  no, continue
 | ||
|  | 
 | ||
|  | 	ldi	r25, BPS/2	;Wait for half bit time
 | ||
|  | 6:	dec	r25 | ||
|  | 	brne	6b | ||
|  | 7:	SKIP_IN_1		;Wait for stop bit
 | ||
|  | 	rjmp	7b | ||
|  | 
 | ||
|  | 	out	_SFR_IO_ADDR(SREG), r0	;End of critical section
 | ||
|  | 	ret | ||
|  | .endfunc |