Loading...
 

AVR DDS

; AVR DDS Code
;  Copyright (C) 2000 Jesper Hansen <jesperh@telia.com>. 
; 
;  This program is free software; you can redistribute it and/or 
;  modify it under the terms of the GNU General Public License 
;  as published by the Free Software Foundation; either version 2 
;  of the License, or (at your option) any later version. 
; 
;  This program is distributed in the hope that it will be useful, 
;  but WITHOUT ANY WARRANTY; without even the implied warranty of 
;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
;  GNU General Public License for more details. 
; 
;  You should have received a copy of the GNU General Public License 
;  along with this program; if not, write to the Free Software Foundation,  
;  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
; 
; 
;******************************************************************* 
;******************************************************************* 
; 
;Description 
; 
; Poor-mans DDS Synthesizer 
;  
; Author = Jesper Hansen 
; Target = AT90S2313 
; Date   = 2001-02-15 
; 
; Code is written for use with AVR-GCC in assembler mode  
; flag:  -x assembler-with-cpp  
; 
; 
; PB0..7 = D/A Data out 
; 
; PD0		RXD 
; PD1		TXD 
; PD2..6	not used 
; 
 
;******************************************************************* 
;******************************************************************* 
; 
; 
; 
; Output frequency (using 24 bit accumulator) : 
; 
;	f = deltaPhase * fClock/2^24 
; 
;   fClock is in this case the CPU clock divided by the 
;	number of cycles to output the data ( 9 cycles ) 
; 
;	f = r24/r25/r26 * (11059200/9)/16777216 
; 
;	f = r24/r25/r26 * 0.073242188 
; 
;	fMax (theoretical) = 0.5 * fClock 
; 
 
 
;****************************************************************************** 
; start of code 
;****************************************************************************** 
 
 
#include <io2313.h> 
 
 
	.section 	.text 
 
	.org 0 
		rjmp	RESET 
 
	.org 14 
		rjmp	RX_COMPLETE_INT 
 
 
;****************************************************************************** 
; data tables 
;****************************************************************************** 
 
	; force table to begin at 256 byte boundary 
 
	.org 0x100 
 
sine:		; 256 step sinewave table 
	.byte	0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae 
	.byte	0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8 
	.byte	0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5 
	.byte	0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff 
	.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7 
	.byte	0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc 
	.byte	0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3 
	.byte	0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83 
	.byte	0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51 
	.byte	0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27 
	.byte	0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a 
	.byte	0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00 
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08 
	.byte	0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23 
	.byte	0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c 
	.byte	0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c 
 
sawtooth:	; 256 step sawtoothwave table 
	.byte	0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f 
	.byte	0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f 
	.byte	0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f 
	.byte	0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f 
	.byte	0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f 
	.byte	0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f 
	.byte	0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f 
	.byte	0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f 
	.byte	0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f 
	.byte	0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f 
	.byte	0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf 
	.byte	0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf 
	.byte	0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf 
	.byte	0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf 
	.byte	0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef 
	.byte	0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff 
 
triangle:	; 256 step trianglewave table 
	.byte	0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e 
	.byte	0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e 
	.byte	0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e 
	.byte	0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e 
	.byte	0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e 
	.byte	0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe 
	.byte	0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde 
	.byte	0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee,0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe 
	.byte	0xff,0xfd,0xfb,0xf9,0xf7,0xf5,0xf3,0xf1,0xef,0xef,0xeb,0xe9,0xe7,0xe5,0xe3,0xe1 
	.byte	0xdf,0xdd,0xdb,0xd9,0xd7,0xd5,0xd3,0xd1,0xcf,0xcf,0xcb,0xc9,0xc7,0xc5,0xc3,0xc1 
	.byte	0xbf,0xbd,0xbb,0xb9,0xb7,0xb5,0xb3,0xb1,0xaf,0xaf,0xab,0xa9,0xa7,0xa5,0xa3,0xa1 
	.byte	0x9f,0x9d,0x9b,0x99,0x97,0x95,0x93,0x91,0x8f,0x8f,0x8b,0x89,0x87,0x85,0x83,0x81 
	.byte	0x7f,0x7d,0x7b,0x79,0x77,0x75,0x73,0x71,0x6f,0x6f,0x6b,0x69,0x67,0x65,0x63,0x61 
	.byte	0x5f,0x5d,0x5b,0x59,0x57,0x55,0x53,0x51,0x4f,0x4f,0x4b,0x49,0x47,0x45,0x43,0x41 
	.byte	0x3f,0x3d,0x3b,0x39,0x37,0x35,0x33,0x31,0x2f,0x2f,0x2b,0x29,0x27,0x25,0x23,0x21 
	.byte	0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x11,0x0f,0x0f,0x0b,0x09,0x07,0x05,0x03,0x01 
 
 
 
square:		; 256 step squarewave table 
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 
	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 
	.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff 
	.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff 
	.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff 
	.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff 
	.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff 
	.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff 
	.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff 
	.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff 
 
 
 
;****************************************************************************** 
; code 
;****************************************************************************** 
 
 
RESET: 
		ldi		r16, RAMEND 
		out		SPL, r16		; setup stack pointer 
 
		ldi		r16,0x05		; set uart speed to 115.2 kbps 
		out		UBRR,r16 
 
		ldi		r16,0x98		; enable RXint and enable tx/rx 
		out		UCR,r16 
 
		sei						; global enable interrupts 
 
		ser		r16				;  
		out		DDRB,r16		; set all PORTB bits as output 
	 
 
		; set sinewave output as default 
		 
		ldi		r31,hi8(sine)	; setup Z pointer hi 
		ldi		r30,lo8(sine)	; setup Z pointer lo 
 
		; clear accumulator  
 
		ldi 	r29,0x00		; clear accumulator  
		ldi 	r28,0x00		; clear accumulator  
 
		; setup adder registers		 
		 
		ldi 	r24,0x55		; setup adder value 
		ldi 	r25,0x35		; to 1 kHz 
		ldi 	r26,0x00		;  
 
 
 
; main loop 
; 
;	r28,r29,r30 is the phase accumulator 
;  	r24,r25,r26 is the adder value determining frequency 
; 
; 	add value to accumulator 
;	load byte from current table in ROM 
;	output byte to port 
;	repeat  
; 
LOOP1: 
		add		r28,r24			; 1 
		adc		r29,r25			; 1 
		adc		r30,r26			; 1 
		lpm						; 3 
		out		PORTB,r0		; 1 
		rjmp	LOOP1			; 2 => 9 cycles 
 
 
;********************************************************************** 
; communication functionality 
;********************************************************************** 
 
; 
; get char in r16 
; 
get_char: 
		in 		r16,USR			; wait for a byte to be ready 
		sbrs	r16,7			; ready ? 
		rjmp	get_char		; no, wait some more 
		in		r16,UDR			; get the byte 
		ret						; and return 
		 
; 
; send char in r16 
; 
send_char: 
		push	r16				; save r16 
send_c2: 
		in 		r16,USR			; wait for the transmitter to be ready 
		sbrs	r16,5			; ready ?  
		rjmp	send_c2			; no, wait some more 
		pop		r16				; restore r16 
		out		UDR,r16			; send char 
		ret						; ans return 
 
; 
; send the current frequency to the PC 
; as a 5 byte sequence : 
; 'F' folowed by a 32 bit phase accumulator value 
; 
; 
send_data: 
		push	r16				; save r16 
		ldi		r16,'F'			; flag 
		rcall	send_char 
 
		clr		r16				; zero byte for 32-bit compatibility 
		rcall	send_char		; MSB 
 
		mov		r16,r26 
		rcall	send_char		; high add 
 
		mov		r16,r25 
		rcall	send_char		; mid add 
 
		mov		r16,r24 
		rcall	send_char		; low add 
 
		ldi		r16,0x0a 
		rcall	send_char		; terminator 
		pop		r16 
		ret 
 
 
; add 1 to the phase accumulator		 
up_one: 
		adiw	r24,1	 
		clr		r23 
		adc		r26,r23 
		ret 
 
; add 10 to the phase accumulator		 
up_ten: 
		adiw	r24,10	 
		clr		r23 
		adc		r26,r23 
		ret 
 
; add 100 to the phase accumulator		 
up_hundred: 
		ldi		r23,0x64 
		add		r24,r23 
		clr		r23 
		adc		r25,r23 
		adc		r26,r23 
		ret 
 
; subtract 1 from the phase accumulator		 
down_one: 
		sbiw	r24,1		 
		clr		r23 
		sbc		r26,r23 
		ret 
 
; subtract 10 from the phase accumulator		 
down_ten: 
		sbiw	r24,10		 
		clr		r23 
		sbc		r26,r23 
		ret 
 
; subtract 100 from the phase accumulator		 
down_hundred: 
		clr		r23 
		subi	r24,0x64		 
		sbc		r25,r23 
		sbc		r26,r23 
		ret 
 
;  
; read in 4 characters from the serial link 
; 
read_4: 
		rcall	get_char		; read and ignore bits 32..24 
		rcall	get_char		; read bits 23..16 
		mov		r26,r16 
		rcall	get_char		; read bits 15..8 
		mov		r25,r16 
		rcall	get_char		; read bits 7..0 
		mov		r24,r16 
		ret 
 
; 
; Interrupt routine for incoming bytes on the RS232 link 
; 
	 
RX_COMPLETE_INT: 
		push	r16 
		in 		r16,UDR 
		cpi		r16,'+'				; up one 
		brne	tx_2 
		rcall	up_one 
		rjmp	tx_exit		 
tx_2: 
		cpi		r16,'u'				; up ten 
		brne	tx_3 
		rcall	up_ten 
		rjmp	tx_exit		 
tx_3: 
		cpi		r16,'U'				; up hundred 
		brne	tx_4 
		rcall	up_hundred 
		rjmp	tx_exit		 
tx_4: 
		cpi		r16,'-'				; down one 
		brne	tx_5 
		rcall	down_one 
		rjmp	tx_exit		 
tx_5: 
		cpi		r16,'d'				; down ten 
		brne	tx_6 
		rcall	down_ten 
		rjmp	tx_exit		 
tx_6: 
		cpi		r16,'D'				; down hundred 
		brne	tx_7 
		rcall	down_hundred		 
		rjmp	tx_exit		 
tx_7: 
		cpi		r16,'s'				; frequency setting 
		brne	tx_8 
		rcall	read_4		 
		rjmp	tx_exit		 
tx_8: 
		cpi		r16,'?'				; just force a reply 
		brne	tx_9 
		rjmp	tx_exit		 
tx_9:	 
		cpi		r16,'1'				; request sinewave output 
		brne	tx_10 
		ldi		r31,hi8(sine)		; setup Z pointer hi 
		ldi		r30,lo8(sine)		; setup Z pointer lo 
		rjmp	tx_exit 
tx_10: 
		cpi		r16,'2'				; request sawtooth output 
		brne	tx_11 
		ldi		r31,hi8(sawtooth)	; setup Z pointer hi 
		ldi		r30,lo8(sawtooth)	; setup Z pointer lo 
		rjmp	tx_exit 
tx_11: 
		cpi		r16,'3'				; request triangle output 
		brne	tx_12 
		ldi		r31,hi8(triangle)	; setup Z pointer hi 
		ldi		r30,lo8(triangle)	; setup Z pointer lo 
		rjmp	tx_exit 
tx_12: 
		cpi		r16,'4'				; request squarewave output 
		brne	tx_13 
		ldi		r31,hi8(square)		; setup Z pointer hi 
		ldi		r30,lo8(square)		; setup Z pointer lo 
		rjmp	tx_exit 
 
; unknown command, just ignore it 
tx_13: 
 
 
; always reply with the current frequency 
tx_exit: 
		rcall	send_data 
		pop		r16 
		reti 
 
 
 
 
 
;****************************************************************************** 
; end of file	 
;******************************************************************************