View previous topic :: View next topic |
Author |
Message |
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Mon Mar 27, 2006 9:34 am Post subject: |
|
|
Sorry for that, comes from writing code "on the fly"
the statements
lds zl,{low wWavetable}
lds zh,{high wWavetable}
should be
lds zl,{wWavetable}
lds zh,{wWavetable+1}
to get z pointed at the value loaded into the word wWavetable in ram.
It is really easy to get confused about the various forms of syntax for pointers in rom and in ram, and whether you want the value of a variable, or its address. _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
davidapex
Joined: 12 Mar 2006 Posts: 42 Location: Auckland
|
Posted: Mon Mar 27, 2006 11:45 am Post subject: |
|
|
Hello Luciano,
Many thanks for the comprehensive answer to my post. I believe I can follow your code but could never had originated it - still many months away from this level.
That's a busy interrupt routine - more than I would have comtemplated. I look forward to trying it.
BTW - back in the '70s when function generators were high tech there was a great myth about dovetail waveform generators. Imagine a square wave with a rise time that goes back in time (T anticipation) and a fall time that also goes back in time (T hesitation) While I never saw a dovetail waveform generator I know a few who made raster scans on their 'scopes that looked like they had "cracked" it.
Thanks again.
Cheers,
David |
|
Back to top |
|
|
davidapex
Joined: 12 Mar 2006 Posts: 42 Location: Auckland
|
Posted: Mon Mar 27, 2006 12:00 pm Post subject: |
|
|
Hello Adrian,
Thanks for the update.
I will go back and revisit this. Luciano has kindly posted all I need to get underway but I also need to understand the process involved rather than just have code handed to me so I will go back and play a bit more to help my understanding.
I agree - even without syntax it's very confusing trying to learn about variable contents and variable addresses. Will keep chipping away.....
Cheers,
David |
|
Back to top |
|
|
Luciano
Joined: 29 Nov 2004 Posts: 3149 Location: Italy
|
Posted: Mon Mar 27, 2006 12:18 pm Post subject: |
|
|
Hi,
Just one quick note to avoid confusion:
The code sample I have posted yesterday and the code sample I have posted last
week have the table(s) in ROM only. (The table is not copied from ROM to RAM).
As far I understand, for now, David is working on code with the tables in
ROM only. It makes sense to load the table in RAM, but if we jump back and
forth between the two solutions this thread will be difficult to follow.
Please specify clearly in your post if the table is copied first from
ROM to RAM and then its values read from RAM.
* * *
David,
You are welcome!
I have edited the sample code posted yesterday.
(Eliminated 3 lines of redundant code, "Set Eifr.6" moved down, comments improved).
About the interrupt routine:
Yes, it looks strange but it will work. If you add a 4x4 keypad
and an LCD, the keypad will be read in polling mode from within
the interrupt routine. (The keypad will also trigger the interrupt).
Best regards,
Luciano |
|
Back to top |
|
|
davidapex
Joined: 12 Mar 2006 Posts: 42 Location: Auckland
|
Posted: Mon Mar 27, 2006 10:58 pm Post subject: |
|
|
Hello Luciano,
Yes I am still using the wave tables in the code space and not in SRAM. May try that later. Will also try the keypad - I had this on my Pic version and it was really nice to tap in the numbers.
I don't have a need for a signal generator as I have good audio generator but DDS has always fascinated me and it also allows you to write your own waveform (dovetails) as well as having programmable precision.
I think it should be possible to make an FSK sender from the DDS by converting the input data to binary and switching between two set frequencies. As mentioned before, it should also be possible to run two (smaller ) accumulators and generate two waveforms, sort of analog DTMF
Thanks again for your input. I will take little steps so I don't break anything.
Cheers,
David |
|
Back to top |
|
|
jenalcom
Joined: 10 Apr 2004 Posts: 365 Location: Perth, Western Australia
|
Posted: Fri Mar 31, 2006 5:34 am Post subject: |
|
|
Bascom already does that to produce DTMF!
And it will also work with a standard 3.579545MHz crystal so you can run a decoder of the same clock.
Alan |
|
Back to top |
|
|
Luciano
Joined: 29 Nov 2004 Posts: 3149 Location: Italy
|
Posted: Fri Mar 31, 2006 8:40 am Post subject: |
|
|
David was talking about FSK, not DTMF.
(Read "sort of analog DTMF").
Luciano
(Click to enlarge the picture)
Last edited by Luciano on Mon Dec 04, 2006 5:57 pm; edited 1 time in total |
|
Back to top |
|
|
jenalcom
Joined: 10 Apr 2004 Posts: 365 Location: Perth, Western Australia
|
Posted: Fri Mar 31, 2006 12:18 pm Post subject: |
|
|
He actually did mention DTMF
<quote>
As mentioned before, it should also be possible to run two (smaller ) accumulators and generate two waveforms, sort of analog DTMF
</quote>
Using the same (similar) code it should also be able to generate FSK.
Personally I always use square waves for FSK, especially as most FSK (I use) is sent over severely limited bandwidth links (eg radio with 2.4KHz b/w). I normally use a timer in auto reload mode to generate the square wave. I have thought about using DDS for this but never got that far with the idea.
Of course if you wanted to get really clever you would be able to do Phase Shift Keying as well or perhaps even QAM and other modulation schemes. Unfortunately I think the loop size would probably get too large too quickly. May be worth investigating if you have a high enough cloak frequency.
Alan |
|
Back to top |
|
|
davidapex
Joined: 12 Mar 2006 Posts: 42 Location: Auckland
|
Posted: Sun Apr 02, 2006 12:00 am Post subject: |
|
|
Hi,
I did indeed mention FSK and DTMF, not for any specific task but more to highlight the flexibility of the DDS.
Phase shift keying should be straight forward as would quadrature waveforms (or any phase)
It should be possible to generate 3 phase sinewave using three output ports but a single accumulator and three table reads. These would be the calculated table value, table value plus 60 degree offset, table value plus 120 degree offset. Not sure if it would have any applications but the theory is nice.
Cheers,
David |
|
Back to top |
|
|
AdrianJ
Joined: 16 Jan 2006 Posts: 2483 Location: Queensland
|
Posted: Tue Apr 04, 2006 2:20 am Post subject: |
|
|
Yes, I do more things with this DDS than just a single tone. In fact I have twin outputs from the same wavetable, but I can adjust both independently for both amplitude and relative phase. So I can synthesise a "stereo" effect by both delaying one wave with respect to the other, and reducing its amplitude, to give the effect of turning the head. Only works with phones on, but its fairly effective. The amplitude effect seems to be the most obvious, the phase effect is difficult to pick by itself. _________________ Adrian Jansen
Computer language is a framework for creativity |
|
Back to top |
|
|
davidapex
Joined: 12 Mar 2006 Posts: 42 Location: Auckland
|
Posted: Fri May 12, 2006 6:52 am Post subject: DDS |
|
|
Hi,
Over the last month I have had stolen just enough time to make a real pigs ear of the code that Luciano posted and have got myself in to trouble.
I have learned how to add the keypad and LCD to this Mega168 DIP but was not impressed with the chip pin layout or the peripheral feature placement.
Why did they put the xtal on one of the full 8 bit ports and the UART on the other full port, leaving the incomplete 7 bit port alone? Huh? Surely you would trash an incomplete port first?
Anyway, I have removed the xtal and are running off the internal osc for the time being but I have made a mess of the interrupts. I currently have portb.7 as an interrupt but would like to use the keypad eventually. I have used a GOTO instead of return for the ISR just to make something happen but I know it's not correct. The present code starts with the preset frequency values then the interrupt clears it and waits for the keypad input. The value input is then loaded in to the phase register and the new frequency is output. Then nothing else happens - no interrupt. BTW the lookup table offset is not indexed to a boundary either but this is minor compared to the other problems.
Can someone show me how to get my interrupt to be more than a one shot?
Best regards,
David |
|
Back to top |
|
|
Luciano
Joined: 29 Nov 2004 Posts: 3149 Location: Italy
|
Posted: Fri May 12, 2006 9:54 am Post subject: |
|
|
David,
From the Bascom Help file:
ON INTERRUPT
The first RETURN statement that is encountered that is outside a condition will generate a RETI instruction. You may have only one such RETURN statement in your interrupt routine because the compiler restores the registers and generates a RETI instruction when it encounters a RETURN statement in the ISR. All other RETURN statements are converted to a RET instruction.
From the code you have attached:
Code: |
lowerline
lcd add16 ; " " ; add8 ; " " ; add0
return |
This RETURN will make the compiler generate a RETI instruction and the execution
will go back to the main loop. Because of that, "Enable PCInt0" will never be
executed.
Best regards,
Luciano |
|
Back to top |
|
|
davidapex
Joined: 12 Mar 2006 Posts: 42 Location: Auckland
|
Posted: Fri May 12, 2006 11:20 am Post subject: |
|
|
Hello Luciano,
Thanks for that. That return is the return from the regval gosub. I tried restructuring that to in-line code rather than the gosub and although it appears to be working it does not load the correct values in to the phase accumulator anymore.
Will do some more fiddling now you have pointed that out.
Thanks again.
Cheers,
David |
|
Back to top |
|
|
Luciano
Joined: 29 Nov 2004 Posts: 3149 Location: Italy
|
Posted: Fri May 12, 2006 12:07 pm Post subject: |
|
|
Hi David,
The 6 assembly lines below are the main loop. When the
interrupt occurs, the execution will stop somewhere in
these 6 lines of code. When you return from the interrupt,
the execution will resume where it was left when the interrupt
occurred. Again, you don't know where in these 6 lines of code.
Code: |
Main_loop:
add r28,r24 ' 1 cycle
adc r29,r25 ' 1 cycle
adc r30,r26 ' 1 cycle
lpm ' 3 cycles
Out Portb , R0 ' 1 cycle
rjmp Main_loop ' 2 cycles
|
==========================================
Interrupt code:
The last lines of code before you go back to the main loop
must be like that:
Code: | ' Your interrupt code in Basic or assembly
...
...
...
...
...
' The final lines of the interrupt code
If wave_form = 0 Then
'Must be last two lines of code in this IF
!ldi ZH,high (Sine_table * 2) ' setup Z pointer hi
!ldi ZL,low (Sine_table * 2) ' setup Z pointer lo
End If
If wave_form = 1 Then
'Must be last two lines of code in this IF
!ldi ZH,high (Square_table * 2) ' setup Z pointer hi
!ldi ZL,low (Square_table * 2) ' setup Z pointer lo
End If
If wave_form = 2 Then
'Must be last two lines of code in this IF
!ldi ZH,high (Triangle_table * 2) ' setup Z pointer hi
!ldi ZL,low (Triangle_table * 2) ' setup Z pointer lo
End If
If wave_form = 3 Then
'Must be last two lines of code in this IF
!ldi ZH,high (Sawtooth_table * 2) ' setup Z pointer hi
!ldi ZL,low (Sawtooth_table * 2) ' setup Z pointer lo
End If
Set EIFR.6 ' clear Int0 flag set by contacts bouncing.
' See the datasheet of your AVR for the location of the "External Interrupt Flag"
!ldi r29,$00 ' clear accumulator
!ldi r28,$00 ' clear accumulator
Loadadr Adder_bits_0_7 , X 'load the address of the variable into R26 and R27 (X)
!ld r24, X 'load the value of the variable into R24
Loadadr Adder_bits_8_15 , X 'load the address of the variable into R26 and R27 (X)
!ld r25, X 'load the value of the variable into R25
Loadadr Adder_bits_16_23 , X 'load the address of the variable into R26 and R27 (X)
!ld r26, X 'load the value of the variable into R26
Enable Int0
Return
|
======================================
From your code:
This is wrong. R30 and R31 are the Pointer-register Z.
Remove this line.
Best regards,
Luciano
Last edited by Luciano on Fri May 12, 2006 2:03 pm; edited 1 time in total |
|
Back to top |
|
|
davidapex
Joined: 12 Mar 2006 Posts: 42 Location: Auckland
|
Posted: Fri May 12, 2006 1:25 pm Post subject: |
|
|
Hi,
I think I follow that. That also explains why it sort of worked when I used a goto Begin: instead of the Return. I had got confused about where the interrupt was actually happening. I need to have a long hard look at it again - good thing it's the weekend.
Cheers,
David |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|