; ; Copyright (C) 2000 Jesper Hansen . ; ; 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 ; Modification = EW6GB ; Target = ATTINY2313 ; Date = 2008-01-10 ; ; ; ; PB0..7 = D/A Data out ; ; PD0 RXD ; PD1 TXD ; PD6 RX/TX control ; ;******************************************************************* ;******************************************************************* ; ; ; ; 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 * (12500000/9)/16777216 ; ; f = r24/r25/r26 * 0.12147427 ; ; fMax (theoretical) = 0.5 * fClock ; ;****************************************************************************** ; start of code ;****************************************************************************** .include .cseg .org 0 rjmp RESET .org URXCaddr rjmp RX_COMPLETE_INT ;****************************************************************************** ; code ;****************************************************************************** RESET: ldi r16, RAMEND out SPL, r16 ; setup stack pointer ldi r16,0x4E ; set uart speed to 9600 kbps for 12.0 crystal out UBRR,r16 ldi r16,0x98 ; enable RXint and enable tx/rx out UCR,r16 sei ; global enable interrupts ldi r16,0x40 ; PD6 out DDRD,r16 ; PD6 bit as output ser r16 ; out DDRB,r16 ; set all PORTB bits as output ; set sine table ldi r31,high(sine*2) ; setup Z pointer hi ldi r30,low(sine*2) ; setup Z pointer lo ; clear accumulator ldi r29,0x00 ; clear accumulator ldi r28,0x00 ; clear accumulator ; setup adder registers ldi r24,0x00 ; setup adder value ldi r25,0x00 ; to 0 (silent start) 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 clr r17 out PORTB,r17 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_12 ldi r31,high(sine) ; setup Z pointer hi ldi r30,low(sine) ; setup Z pointer lo rjmp tx_exit tx_12: cpi r16,'R' ; brne tx_13 clr r17 ; out PORTD,r17 ; PD6=0 rjmp tx_exit tx_13: cpi r16,'T' ; brne tx_14 ser r17 ; out PORTD,r17 ; PD6=1 rjmp tx_exit ; unknown command, just ignore it tx_14: ; always reply with the current frequency tx_exit: rcall send_data pop r16 reti ;****************************************************************************** ; data tables ;****************************************************************************** ; force table to begin at 256 byte boundary .org 0x200 sine: ; 256 step sinewave table .DB 0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae .DB 0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8 .DB 0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5 .DB 0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff .DB 0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7 .DB 0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc .DB 0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3 .DB 0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83 .DB 0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51 .DB 0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27 .DB 0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a .DB 0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00 .DB 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08 .DB 0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23 .DB 0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c .DB 0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c