; ; 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's brilliant ideas ; ...four times better resolution on phase ; ...four times better resolution on frequency ; ...more than double the resolution on voltage ; ...identical sampling rate ; 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 ( 9 cycles ) ; f = r24/r25/r26 * (16000000/9)/67108864 ; ; 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 ; PC4 = SDA TWI ; PC5 = SCL TWI ; PB1 = D/A Data out 8 ; PD0..7 = D/A Data out 0..7 ; ; .include "m8def.inc" ; ; Mode Codes .equ TriangleMode = 0x18;(11000 Bit 4 > table) .equ RectangularMode = 0x11;(10001 Bit 4 SineTable) .equ SineMode = 0x10;(10000 Bit 4 > table) .equ SawtoothMode = 0x04;(00100 Bit 4 no table) .equ NoiseMode = 0x02;(00010 Bit 4 no table) .equ OffMode = 0x00 ; ; ; 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 r16 out DDRD,r16 ; set all PORTD bits as output out DDRB,r16 clr r16 out PORTB,r16 ldi r16,255 ; idle is 255 , 2.5 Volt out PORTD,r16 ; preload DAC ; STACK initialization ldi r16,low(RAMEND) out SPL, r16 ldi r16, high(RAMEND) out SPH,r16 ; TWI initialization ; TWI TWBR ldi temp, 65 out TWBR,temp ; TWI TWCR control-register ldi temp, 1< 40 / 4 = 10 cycles SawtoothLoop: add r28,r24 ; 1 adc r29,r25 ; 1 adc r30,r26 ; 1 adc r31,r27 ; 1 mov r0,r30 ; 1 ror r0 ; 1 divde r30 by two and add MSB ( r31 bit0 * 128 ) out PORTD,r0 ; 1 update bit 0..7 out PORTB,r31 ; 1 update Bit 8 rjmp SawtoothLoop; 2 => 10 cycles NoiseLoop: ; Linear Feedback Register LFR 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 mov r23,r31 ; temp copy rol r23 ; shift bit9 for PortB out PortB,r23 ; have some glitch out PortD,r30 dec r20 ; finished ? brne N1 ; no, go on rjmp N0 UpDateMode:;' ****** not finished here ****** ret ; 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<