Hi. First, I want to thank everyone for helping me getting my DDS Controller working. Although it is not working yet, it is very close. I have the synchronous mode working perfectly, transmitting the bytes in the proper data order and giving us the exact number of bits to clock in the 40 data bits of frequency ivisor and control word. Now I have a new problem.
After the data is clocked into the DDS, I have to send a Frequency Load pulse. I have that working but it is occuring too soon. I need to know if when the last byte of data to send has been completely sent. Can I read the TXREG and see if it is empty? If so, I could use this to know it's time to generate the pulse. Alternatively, how about polling the TRMT bit?
Reminder I am using the PIC16F690.
Thanks again for the help,
Harley
N5BFB
Last edit: Harley Burton 2017-11-16
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I wanted to let y'all know that I have my HF-APRS tracker working. I am able to transmit packets, but still testing. I don't have enough transmit power but I'm working that too.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Harley,
To check that the Tx buffer is empty is checking the SSPBF bit.
1 = Transmit in progress, SSPBUF is full
0 = Transmit complete, SSPBUF is empty
WaitWhileSSPBUF=On
then do the load pulse
You could use this ame statement between loading each of the 5 bytes too.
(For more intense jobs you would enable the interrupts SSPIE and check the SSPIF bit.)
Alert!
I am hoping you understand that SSP sends MSB first and the AD9850 is expecting LSB first. The bits need to be swapped before you send them to the SSP txbuf. I mentioned this before but you have acknowledged doing it and i haven't seen your code.
GL
Mike w9ys
Last edit: mmotte 2017-11-16
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sorry Mike, I turn the data around byte and bitwise before I do anything with it. I have only two frequencies to send to the DDS so this can be canned in thed code. I want to write a routine to do it regardless of what I want to send but I haven't taken time to figure out what how to reverse the bit order of a byte or word of data. That's tomorrows job. For now, I'll just do it by hand.
Bye the way, I don't think I told you, I am building an HF APRS. The goal is to do it as an under $100 kit buying modules off of ebay. If this goes well, I should have it testing in a couple weeeks. It's going well thanks to you and the others on this forum.
Thanks again,
Harley
N5BFB
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm making great headway with my DDS Controller. However, I am having difficulty with the Synchronous port. As I read the PIC16F690 manual, when I load a series of 5 bytes into the TXREG, the device should send out the 5 bytes but it should also provide 40 clocks. When I looked on at the signals with a logic analyzer, I see that I get 42 pulses instead of 40 clock pulses. For some reason, the PIC adds two pulses to the front of the transmission and first one is a very short one followed by a long one neither on of which belong there.
Additionally, I used a bit on PORTC to provide my load pulse. Unfortunately, it also has a high going glitchy load pulse that is an exact copy of the two extraneous pulse at the beginning of the synchronous pulse stream.
Finally, if you notice, the first 24 valid synchronous pulses are twice as long as the last 16. The 16 pulses are the correct length, 0.1 msec, but the 24 pulses are twice that length, almost exactly. There are no operations between the loading 5 bytes. Here's the code that sends the bytes:
Sub SendMark 'Send the bytes that set the FSK frequency to a Mark
TCounter = 0
Do
'Check TRMT bit to see if a new value can be loaded into Transmit
'Shift Register (TSR)
If TRMT then
'Transmit byte synchronously
HSerSend MarkOut(TCounter)
TCounter = TCounter + 1
End If
Loop until TCounter = 5
'Wait till the last byte has been shifted out
Wait 1000 us
'Pulse the Frequency Load Bit (FQ_UD)
PulseOut PORTC.5, 50 us
End sub
Some short explainations. I use TCounter to send exactly 5 bytes, 4 of frequency and 1 of control. I added your code suggestion "Wait While SSPBUF = On" to move my load pulse out to the end of the synchronous transmission where it should be. Unfortunately, it only move it out 8 bits, not the 16 I needed. At that time I decided to just put a timer to hold off until the message was completely shifted out. That actually worked and it pulses a millisecond or so after the final bit is shifted out and the last clock has completed. For some reason, during that time is when the shift clock is pulsing at the correct timing. Prior to that 1000 us time, the pulses are twice as long as they should be. After one transmission, five bytes, it all stops until I command it to transmit again.
It also appears I don't have my load constants worked out correctly but right now I only want to load any frequency, then work out the right numbers.
I have not figured out how to reverse the bit order of a byte or long. Until I do, I won't have a generic module for controlling a DDS but I'll do it if I have to rotate the byte and then shift it one bit at a time and test the "C" bit. Lousy way to do it but if that's what it takes, I may do it in assembler.
In response to your suggestion, I definitely will upload the code or some symplified version if I can make one when I get it all working.
Quick update. I changed the code so that it repeated sending the 5 bytes once a second. Interestingly enough, it only glitched on the very first time. I could probably just hold the DDS in reset, send the 5 bytes the first time to initialize it then release reset and continue to use it normally. It isn't a true fix but it will probably make it work. I'll keep working on the glitches. I think they are related to initializing the port and port bit.
I also searched the forum for something to reverse the bit order. Someone wrote a small function called "Reorder". It works great. I don't know how much code it generates, nor how fast it executes, but I'll try to find out. I'll post it if I can figure it out.
'' ByteReversal.gcb'#chip 16f690,4dim TestByte as byteTestByte = 0b01101010 dir PortC Out PortC = TestByte wait 1 s PortC = RevByte(TestByte)EndFunction RevByte(InByte) Dim OutByte, Index as Byte for Index = 0 to 7RotateInByteLeft' Shift Left MSB into CarryRotateOutByteRight' Shift Carry Right into MSB Next RevByte = OutByteEnd Function
Cheers
Chris
Last edit: Chris Roper 2017-11-18
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Subsequent to posting the above I refined it to use less space and to be able to reverse Byte, Word or Long Values so that it can handle 8,16 or 32 Bit chunks.
Hi. First, I want to thank everyone for helping me getting my DDS Controller working. Although it is not working yet, it is very close. I have the synchronous mode working perfectly, transmitting the bytes in the proper data order and giving us the exact number of bits to clock in the 40 data bits of frequency ivisor and control word. Now I have a new problem.
After the data is clocked into the DDS, I have to send a Frequency Load pulse. I have that working but it is occuring too soon. I need to know if when the last byte of data to send has been completely sent. Can I read the TXREG and see if it is empty? If so, I could use this to know it's time to generate the pulse. Alternatively, how about polling the TRMT bit?
Reminder I am using the PIC16F690.
Thanks again for the help,
Harley
N5BFB
Last edit: Harley Burton 2017-11-16
I wanted to let y'all know that I have my HF-APRS tracker working. I am able to transmit packets, but still testing. I don't have enough transmit power but I'm working that too.
Harley,
To check that the Tx buffer is empty is checking the SSPBF bit.
1 = Transmit in progress, SSPBUF is full
0 = Transmit complete, SSPBUF is empty
then do the load pulse
You could use this ame statement between loading each of the 5 bytes too.
(For more intense jobs you would enable the interrupts SSPIE and check the SSPIF bit.)
Alert!
I am hoping you understand that SSP sends MSB first and the AD9850 is expecting LSB first. The bits need to be swapped before you send them to the SSP txbuf. I mentioned this before but you have acknowledged doing it and i haven't seen your code.
GL
Mike w9ys
Last edit: mmotte 2017-11-16
Thank you Mike, I will try that tomorrow. I have a little work to do tonight. You guys are all great help.
Thanks again.
Harley
N5BFB
Sorry Mike, I turn the data around byte and bitwise before I do anything with it. I have only two frequencies to send to the DDS so this can be canned in thed code. I want to write a routine to do it regardless of what I want to send but I haven't taken time to figure out what how to reverse the bit order of a byte or word of data. That's tomorrows job. For now, I'll just do it by hand.
Bye the way, I don't think I told you, I am building an HF APRS. The goal is to do it as an under $100 kit buying modules off of ebay. If this goes well, I should have it testing in a couple weeeks. It's going well thanks to you and the others on this forum.
Thanks again,
Harley
N5BFB
Harley,
Thatis in the tradition of ham radio, building equipment and now programming it! I like it. I am a biulder, some work, some don't.
GCB has a section in demos on radios but there isn't much in there right now. Maybe you can share some working code for the AD9850.
GL
Mike w9ys
Mike,
I'm making great headway with my DDS Controller. However, I am having difficulty with the Synchronous port. As I read the PIC16F690 manual, when I load a series of 5 bytes into the TXREG, the device should send out the 5 bytes but it should also provide 40 clocks. When I looked on at the signals with a logic analyzer, I see that I get 42 pulses instead of 40 clock pulses. For some reason, the PIC adds two pulses to the front of the transmission and first one is a very short one followed by a long one neither on of which belong there.
Additionally, I used a bit on PORTC to provide my load pulse. Unfortunately, it also has a high going glitchy load pulse that is an exact copy of the two extraneous pulse at the beginning of the synchronous pulse stream.
Finally, if you notice, the first 24 valid synchronous pulses are twice as long as the last 16. The 16 pulses are the correct length, 0.1 msec, but the 24 pulses are twice that length, almost exactly. There are no operations between the loading 5 bytes. Here's the code that sends the bytes:
Sub SendMark 'Send the bytes that set the FSK frequency to a Mark
TCounter = 0
Do
'Check TRMT bit to see if a new value can be loaded into Transmit
'Shift Register (TSR)
If TRMT then
'Transmit byte synchronously
HSerSend MarkOut(TCounter)
TCounter = TCounter + 1
End If
Loop until TCounter = 5
'Wait till the last byte has been shifted out
Wait 1000 us
'Pulse the Frequency Load Bit (FQ_UD)
PulseOut PORTC.5, 50 us
End sub
Some short explainations. I use TCounter to send exactly 5 bytes, 4 of frequency and 1 of control. I added your code suggestion "Wait While SSPBUF = On" to move my load pulse out to the end of the synchronous transmission where it should be. Unfortunately, it only move it out 8 bits, not the 16 I needed. At that time I decided to just put a timer to hold off until the message was completely shifted out. That actually worked and it pulses a millisecond or so after the final bit is shifted out and the last clock has completed. For some reason, during that time is when the shift clock is pulsing at the correct timing. Prior to that 1000 us time, the pulses are twice as long as they should be. After one transmission, five bytes, it all stops until I command it to transmit again.
It also appears I don't have my load constants worked out correctly but right now I only want to load any frequency, then work out the right numbers.
I have not figured out how to reverse the bit order of a byte or long. Until I do, I won't have a generic module for controlling a DDS but I'll do it if I have to rotate the byte and then shift it one bit at a time and test the "C" bit. Lousy way to do it but if that's what it takes, I may do it in assembler.
In response to your suggestion, I definitely will upload the code or some symplified version if I can make one when I get it all working.
Thanks again,
Harley
N5BFB
Quick update. I changed the code so that it repeated sending the 5 bytes once a second. Interestingly enough, it only glitched on the very first time. I could probably just hold the DDS in reset, send the 5 bytes the first time to initialize it then release reset and continue to use it normally. It isn't a true fix but it will probably make it work. I'll keep working on the glitches. I think they are related to initializing the port and port bit.
I also searched the forum for something to reverse the bit order. Someone wrote a small function called "Reorder". It works great. I don't know how much code it generates, nor how fast it executes, but I'll try to find out. I'll post it if I can figure it out.
Harley,
N5BFB
Last edit: Harley Burton 2017-11-18
This should do it:
Cheers
Chris
Last edit: Chris Roper 2017-11-18
Subsequent to posting the above I refined it to use less space and to be able to reverse Byte, Word or Long Values so that it can handle 8,16 or 32 Bit chunks.
You can find the latest version here:
https://sourceforge.net/p/gcbasic/discussion/629990/thread/188543c6/
Cheers
Chris