;*************************************************************************** ; AT45 microdds square wave generator without table ; linear frequency scale ; ; timer 1 interrupt used to read ADC @ 60.2 ms ; ; Target ATtiny45 GS 2009 ; The timing is adapted for 8 MHz internal Osc (not calibrated) ; frequency range: 1 Hz to abt 18 kHz @ PB3 output ; frequency range: 1 Hz to abt 144 kHz @ PB0 output ; duty cycle is 50% ; ; This program is free software; you can redistribute it and/or ; modify it under the terms of the GNU General Public License. ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; ;*************************************************************************** ; ; ATtiny45 dip ;(PCINT5/RESET/ADC0/dW) PB5 VCC ;(PCINT3/XTAL1/CLKI/OC1B/ADC3) PB3 PB2 (SCK/USCK/SCL/ADC1/T0/INT0/PCINT2) ;(PCINT4/XTAL2/CLKO/OC1B/ADC2) PB4 PB1 (MISO/DO/AIN1/OC0B/OC1A/PCINT1) ; GND PB0 (MOSI/DI/SDA/AIN0/OC0A/OC1A/AREF/PCINT0) ; !!!! PB4 ADC2:ADC Input Channel 2 ok ; ;*************************************************************************** ;Description ; ; very Poor-mans DDS Synthesizer Freq Generator ; ; Target = ATtiny45 ; ; PB4: input ADC2 0-5 Volt (pin3) frequency setting w potentiometer ; PB0: output f*8 ; PB1: output f*4 ; PB2: output f*2 ; PB3: output f ; ;*************************************************************************** ; ; Output frequency (using 16 bit accumulator) : ; ; f = deltaPhase * fClock/2^16 ; ; fClock is the CPU clock divided by the ; number of cycles to output the data ( 7 cycles ) ; ; f = Delta1,Delta2 * (clock/7)/65536 ; ; f = Delta1,Delta2 * 17.44 @ 8Mhz ; fmax = 1023 * 17.44 = 17840 Hz ; ; .DEVICE ATtiny45 ;for gavrasm .equ DDRB_config = 0b00001111 .equ portB_config = 0b00000000 ; set start sequence .equ ADC_poti = 0b00000010 ; frequency set ADC2 pin3 (poti) .def Srin = r15 .def temp = r16 .def temp1 = r17 .def Delta1 = r25 ; Phase increment of DDS .def Delta2 = r26 ; from ADC .def Dds1 = r29 ; 2 byte DDS accumulator .def Dds2 = r30 .cseg .org 0 ; Reset-vector to adress 0000 rjmp Reset ; Reset Handler reti ; IRQ0 Handler reti ; PCINT0 Handler reti ; Timer1 CompareA Handler rjmp TIM1_OVF ; Timer1 Overflow Handler ;*************************************************************************** ; Interrupt-Service-Routine Overflow Handler for counter 1 ;*************************************************************************** TIM1_OVF: in Srin,SREG ; save the content of the flag register ; get ADC value for frequency setting sbi ADCSRA, ADIF ; "1" clears ADIF flag ! sbi ADCSRA, ADSC ; start conversion TIwait2: sbis ADCSRA, ADIF rjmp TIwait2 ; 2 in Delta1, ADCL ; first low byte ; 1 in Delta2, ADCH ; then high byte ; 1 ;sbi PinB, PinB2 ; Flip Pb0 @ 60 ms out SREG,Srin ; restore the initial value of the flag register reti ; Return from interrupt ;****************************************************************************** ; Reset ;****************************************************************************** Reset: ldi temp, low(RAMEND) out SPL, temp ; setup stack pointer ldi temp, high(RAMEND) out SPH, temp ; ; writing the calibration byte to the OSCCAL Register. ;ldi temp,0xf0 ; test ;out OSCCAL,temp ; for the clock nop nop ; Port B ldi temp,portB_config ; set output out PORTB, temp ; 1 = pull-up , 0 = float ldi temp,DDRB_config ; low 4 bits are output, 1 = output , 0 = input out DDRB,temp ; to data direction register ; AD-Converter setup: ; ADMUX: REFS1 REFS0 ADLAR – – MUX2 MUX1 MUX0 ldi temp, ADC_poti ; Ch 2 input=PB4, REFS0,1 =0 Vcc is RefVoltage out ADMUX, temp ldi temp,0b11010110 ; ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0: ADCSRA out ADCSRA, temp ; ADC init single conversion prescale 64: sbi AcsR, Acd ; Disable Comparator sbi DidR0, Adc2d ; Disable Adc2d Digital Input ; timer 1 setup as timer, interrupt used: ldi temp,0b00000000 ;normal mode out TCNT1,temp ;Clear timer1 byte ldi temp,0b00000100 ; out TIFR,temp ;Clear pending timer interrupt out TIMSK,temp ;Enable Timer1 tov interrupt ldi temp,0b00001100 ;Timer/Counter 1 start CK / 2048 out TCCR1,temp ; sei ; global enable interrupts ;********************************************************************** ; main loop ; ; Dds1,Dds2 is the phase accumulator ; Delta1,Delta2 is the adder value determining frequency ; ; add value to accumulator ; swap Dds2 ; output byte (higher nibble of Dds2) to port ; repeat ;********************************************************************** ; LOOP1: ; Dds loop add Dds1,Delta1 ; 1 adc Dds2,Delta2 ; 1 mov temp, Dds2 ; 1 swap temp ; 1 out PORTB, temp ; 1 rjmp LOOP1 ; 2 => 7 cycles ;****************************************************************************** ; end of file ;******************************************************************************