; ; DDS generator ; ; SINE and TRIANGLE based on ... ; -------------------------- ; Jesper Hansen's .miniDDS ( 2000 ) ; and a thread at http://www.mikrocontroller.net/topic/244609#new ; many thanks to guest Ulrich ; ; SLOW version * ; ...four times better resolution on phase ; ...four times better resolution on frequency ; ...more than double the resolution on voltage ; ...sampling time only one extra cycle ; compared to Jesper Hansen's design ; Output frequency (using 26 BIT accumulator) : ; ; f = deltaPhase * fClock/2^26 ; ; fClock is LDS this case the CPU clock divided by the ; number of cycles to output the data ( 10 cycles ) ; f = r24/r25/r26 * (16000000/10)/67108864 ; ; FAST version * ; ...double the resolution on phase ; ...double the resolution on frequency ; ...more resolution on voltage , full 8 Bit ; ...sampling time is one cycle less ; compared to Jesper Hansen's design ; Output frequency (using 25 BIT accumulator) : ; ; f = deltaPhase * fClock/2^25 ; ; fClock is LDS this case the CPU clock divided by the ; number of cycles to output the data ( 8 cycles ) ; f = r24/r25/r26 * (16000000/8)/33554432 ; ; SAWTOOTH ; -------- ; calculated on the run, no tables uses 9 and 8 Bit ; SLOW and FAST ; ; NOISE generation based on ... ; ------------------------- ; a PDF from FELJC@LTAM ; (he/she does not mention his/her name) ; ; CONTROL ; ------- ; The Mega8 is connected via TWI. ; Its address is 2 by default. ; Loops are interrupted by TWI activities. ; It waits for TWI START condition, reads number of register ; r24,r25,r26,r27 equals adder register ; r31 stands for mode , not stored directly to r31 ; next reads value for register or mode ; Author = Werner Braun ; Target = ATmega8 ; Date = 2012-02-04 ; ; PC6 = RESET ; PC5 = SCL TWI ; PC4 = SDA TWI ; PC3 = addon capacitor for filter ; PC2 = addon capacitor for filter ; PC1 = addon capacitor for filter ; PC0 = Glitch capacitor on / off (DDR) ; PB1 = D/A Data out 8 ; PD0..7 = D/A Data out 0..7 ; ; .include "m8def.inc" ; ; MODE Codes .equ RectangularMode = 8 .equ TriangleMode_fast = 7 .equ TriangleMode_slow = 6 .equ SineMode_fast = 5 .equ SineMode_slow = 4 .equ SawtoothMode_fast = 3 .equ SawtoothMode_slow = 2 .equ NoiseMode = 1 .equ OffMode = 0 ; ; ; TWI Slave Receiver Codes .equ TW_SR_SLA_ACK = 0x60;(SLA+W received and ACK returned) .equ TW_SR_ARB_LOST_SLA_ACK = 0x68;(Arbitration lost SLA+R/W as MASTER; ; SLA+W received; ACK returned .equ TW_SR_GCALL_ACK = 0x70;(General Call address received;ACK returned .equ TW_SR_ARB_LOST_GCALL_ACK = 0x78;(Arbitration lost SLA+R/W as MASTER; ; General Call address received;ACK returned .equ TW_SR_DATA_ACK = 0x80;(prev. adressed (SLA+W) data received;ACK returned .equ TW_SR_DATA_NACK = 0x88;(prev. adressed (SLA+W) data received;ACK NOT returned .equ TW_SR_GCALL_DATA_ACK = 0x90;(prev. adressed (General Call) data received;ACK returned .equ TW_SR_GCALL_DATA_NACK = 0x98;(prev. adressed (General Call) data received;ACK NOT returned .equ TW_SR_STOP = 0xA0;(STOP received, or repeated START condition) ; TWI Slave Transmitter Codes .equ TW_ST_SLA_ACK = 0xA8;(SLA+R received; ACK returned) .equ TW_ST_ARB_LOST_SLA_ACK = 0xB0;(Arbitration lost SLA+R/W as MASTER, ACK returned) .equ TW_ST_DATA_ACK = 0xB8;(TWDR was tranfered; ACK received .equ TW_ST_DATA_NACK = 0xC0;(TWDR was tranfered; ACK NOT received .equ TW_ST_LAST_DATA = 0xC8;(last data Byte LDS TWDR was tranfered (TWEA = "0");Ack received .equ TW_NO_INFO = 0xF8;(no relevant state; TWINT = "0" no TWDR activity .equ TW_BUS_ERROR = 0x00;(Bus-Error invalid START or STOP condition; no TWDR activity ; TWI SLAVE configuration .equ TWI_SLAVE_ADRESSE = 2 ; own SLAVE adress 1...127 .equ TWI_GENERAL_CALL_enable = 0 ; 1=Generral Call enabled / 0=disabled ; REGISTER .def MODE = r19 .def NUMBER = r18 .def ADRESS = r17 .def TEMP = r16 .def DATA = r15 .def TEMP_SREG = r14 .cseg ; Start of Code-Segment .org 0 rjmp RESET ; Reset Handler .org TWIaddr rjmp TWSI ; Two-wire Serial Interface Handler .org INT_VECTORS_SIZE RESET: ;****************************************************************************** ; code ;****************************************************************************** ; PORT initialization ser TEMP out DDRD,TEMP ; set all PORTD bits as output clr TEMP out DDRB,TEMP ; PORTB is input Bit 9 off out PORTB,TEMP ; internal pullup is off ldi TEMP,0x7F ; idle is 2.5 Volt out PORTD,TEMP ; preload DAC ; TWI initialization ; TWI TWBR ldi TEMP, 65 out TWBR,TEMP ; TWI TWCR control-register ldi TEMP, 1< 32 / 4 = 8 cycles TableLoop: ; 1.6 Mc sampling rate , 360/1024° , 9 Bit ; r28,r29,r30,r31 is the phase accumulator ; r24,r25,r26,r27 is the adder value determining frequency ; ; add value to accumulator ; load Byte from current table in FLASH ; output Byte to port ; repeat in TEMP,DDRB ; Bit 8 is on sbr TEMP,2 out DDRB,TEMP in TEMP,PORTB cbr TEMP,2 out PORTB,TEMP in TEMP,DDRC ; deglitch is needed ori TEMP,1 out DDRC,TEMP in TEMP,PORTC cbr TEMP,1 out PORTC,TEMP TL1: ; cycl. lpm r0,z ; 3 out PORTD,r0 ; 1 update BIT 0..7 out PortB,r31 ; 1 update Bit 8 add r28,r24 ; 1 adc r29,r25 ; 1 adc r30,r26 ; 1 adc r31,r27 ; 1 cbr r31,4 ; 1 limit to 1.5 * table length lpm r0,z ; 3 out PORTD,r0 ; 1 update BIT 0..7 out PortB,r31 ; 1 update Bit 8 add r28,r24 ; 1 adc r29,r25 ; 1 adc r30,r26 ; 1 adc r31,r27 ; 1 lpm r0,z ; 3 add r28,r24 ; 1 out PORTD,r0 ; 1 update BIT 0..7 out PortB,r31 ; 1 update Bit 8 adc r29,r25 ; 1 adc r30,r26 ; 1 adc r31,r27 ; 1 cbr r31,4 ; 1 limit to 1.5 * table length lpm r0,z ; 3 add r28,r24 ; 1 out PORTD,r0 ; 1 update BIT 0..7 out PortB,r31 ; 1 update Bit 8 adc r29,r25 ; 1 adc r30,r26 ; 1 adc r31,r27 ; 1 rjmp TL1 ; 2 => 40 / 4 = 10 cycles SawtoothLoop: ST_slow: ; 2,28 Mc sampling rate , 360/512° , 9 Bit in TEMP,DDRB ; Bit 8 is on sbr TEMP,2 out DDRB,TEMP in TEMP,PORTB cbr TEMP,2 out PORTB,TEMP in TEMP,DDRC ; deglitch is needed ori TEMP,1 out DDRC,TEMP in TEMP,PORTC cbr TEMP,1 out PORTC,TEMP ldi r31,1 add r28,r24 STL1: adc r29,r25 ; 1 adc r30,r26 ; 1 adc r31,r27 ; 1 ori r31,1 ; 1 out PORTD,r30 ; 1 update Bit 0..7 out PORTB,r31 ; 1 update Bit 8 add r28,r24 ; 1 adc r29,r25 ; 1 adc r30,r26 ; 1 adc r31,r27 ; 1 add r28,r24 ; 1 ori r31,1 ; 1 out PORTD,r30 ; 1 update Bit 0..7 out PORTB,r31 ; 1 update Bit 8 rjmp STL1; ; 2 16 / 2 = 8 cycles ST_fast: ; 3,2 Mc sampling rate , 360/256° , 8 Bit in TEMP,DDRB ; Bit 8 is off cbr Temp,2 out DDRB,TEMP in TEMP,PORTB cbr TEMP,2 out PORTB,TEMP in TEMP,DDRC ; deglitch not needed cbr TEMP,1 out DDRC,TEMP in TEMP,PORTC cbr TEMP,1 out PORTC,TEMP add r28,r24 STL2: adc r29,r25 ; 1 adc r30,r26 ; 1 out PORTD,r30 ; 1 update Bit 0..7 add r28,r24 ; 1 adc r29,r25 ; 1 adc r30,r26 ; 1 add r28,r24 ; 1 out PORTD,r30 ; 1 update Bit 0..7 rjmp STL2; ; 2 10 / 2 = 5 cycles NoiseLoop: ; Linear Feedback Register LFR in TEMP,DDRB ori TEMP,2 out DDRB,TEMP ; Bit 8,9 = PORTB0..1 in TEMP,DDRC ; deglitch not needed cbr TEMP,1 out DDRC,TEMP in TEMP,PORTC cbr TEMP,1 out PORTC,TEMP ldi r21,0 ; used for XOR ldi r22,0 ; used for XOR ldi r28,0x5C ; starting value ldi r29,0xD3 ldi r30,0xBC ldi r31,0xB4 N0: ldi R20,32 ; 4*8 = 32 BIT N1: rol r28 ; rotate 3 bytes over carry rol r30 rol r31 bst r31,7 bld r21,0 bst r30,5 bld r22,0 eor r21,r22 bst r28,2 bld r22,0 eor r21,r22 bst r28,0 bld r22,0 eor r21,r22 bst r21,0 bld r28,0 out PortB,r31 ; have some glitch out PortD,r30 dec r20 ; finished ? brne N1 ; no, go on rjmp N0 ; TWI INTERRUPPT-Routine TWSI: in TEMP_SREG,SREG ; save SREG in TEMP, TWSR ; get TWI status andi TEMP, 0xF8 ; mask Bit0...2 (prescaler und reserve-BIT) cpi TEMP, TW_SR_SLA_ACK ; x60 breq TWSI_TW_SR_SLA_ACK cpi TEMP, TW_SR_ARB_LOST_SLA_ACK ; x68 breq TWSI_END cpi TEMP, TW_SR_GCALL_ACK ; x70 breq TWSI_END cpi TEMP, TW_SR_ARB_LOST_GCALL_ACK ; x78 breq TWSI_END cpi TEMP, TW_SR_DATA_ACK ; x80 breq TWSI_TW_SR_DATA_ACK cpi TEMP, TW_SR_DATA_NACK ; x88 breq TWSI_END cpi TEMP, TW_SR_GCALL_DATA_ACK ; x90 breq TWSI_END cpi TEMP, TW_SR_GCALL_DATA_NACK ; x98 breq TWSI_END cpi TEMP, TW_SR_STOP ; xA0 breq TWSI_END ; cpi TEMP, TW_ST_SLA_ACK ; 0xA8 breq TWSI_TW_ST_SLA_ACK cpi TEMP, TW_ST_ARB_LOST_SLA_ACK ; 0xB0 breq TWSI_END cpi TEMP, TW_ST_DATA_ACK ; 0xB8 breq TWSI_TW_ST_DATA_ACK cpi TEMP, TW_ST_DATA_NACK ; 0xC0 breq TWSI_TW_ST_DATA_NACK cpi TEMP, TW_ST_LAST_DATA ; 0xC8 breq TWSI_END cpi TEMP, TW_NO_INFO ; 0xF8 breq TWSI_END rcall TWI_ERROR ; 0x00 TWSI_END: ; clear TWINT-Flag ldi TEMP, 1<