(http://xv4y NULL.radioclub NULL.asia/wp-content/uploads/2012/12/100_3339 NULL.jpg)Dans un commentaire Sylvain F6GGX m’a demandé après ce bout de code. Il était disponible gratuitement dans la boutique mais comme j’ai désactivé cette dernière il a disparu du site…
Voici donc le code source d’un VFO très simpliste à base de AD9850/AD9851 qui utilise les librairies que j’ai écrites ou adaptées (http://xv4y NULL.radioclub NULL.asia/docs/). Honnêtement je pense pas que ce code soit très utile, rien de particulièrement compliqué et l’ergonomie à 4 boutons n’est pas super. C’est utile en dépannage avec le kit balise WSPR que je produisais mais c’est tout. Le code est écrit pour Energia sur MSP430, le porter sur Arduino (ATMega328) ne devrait poser aucun problème.
/* Simple VFO with DDS for MSP430G2553
* Code for Energia 009
* By Yannick DEVOS - XV4Y - March 2013
http://xv4y.radioclub.asia/
Copyright 2012-2013 Yannick DEVOS under GPL 3.0 license
Any commercial use or inclusion in a kit is subject to author approval
====
* Agile Frequency generation using AD9850/9851 DDS
* Output to Nokia 5110 compatible LCD
* Check if P2_2 has changed state and switch VFO (like when PTT is pressed to operate split)
Usage for short press of buttons :
- Up / Down increase or decrease the frequency following the choosen digit
- Left / Right increase or decrease the digit
- OK validate the frequency and send it to the DDS
Long press of buttons :
- Left Set the current VFO to the next band bottom frequency
- Right VFO A = VFO B
- OK Switch between VFO A and VFO B
====
Revision history :
v1.00 2013-03-18
First release
====
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You can download a copy of the GNU General Public License at <http://www.gnu.org/licenses/>
*/
// Here modify to your taste or needs
#define PTT_key P2_2
#define ANALOG_BUTTONS A5
#define AUTO_VALID // Uncomment if you want the DDS frequency to be udapted automatically after each value change
#define DEFAULT_FREQ 8 // Value 8 in Frequencies array is 14000000
// Here under don't touch anything unless you know what you do
#include <legacymsp430.h>
#include <AD9850.h> // Library for AD9850 control by MSP430
#include <LCD_5110.h>
// Frequencies (1 Hz precision) you can select
const unsigned long int frequencies[] = {
137000, 471000, 501000, 1830000, 3500000, 5200000, 7000000, 10100000,
14000000, 18068000, 21000000, 24890000, 28000000, 50000000, 70000000};
const byte Analog_Noise = 5; // Margins for reading analog buttons
boolean vfo=0, saved_PTT; // VFO A or B and PTT input state
char multiplier, aff_multiplier, freq_select=DEFAULT_FREQ;
unsigned long int frequency_A=frequencies[DEFAULT_FREQ], frequency_B=frequencies[DEFAULT_FREQ], debounce;
char chaine_txt[6] = {' ', ' ', ' ', ' ', ' ', 0x00};
AD9850 myDDS (P1_0, P1_1, P1_2, P1_4); // Call the AD9850 Library, AD9850 pins for CLOCK, LOAD, DATA and RESET
//AD9850 myDDS (P1_1, P1_2, P1_0, P1_4); // Call the AD9850 Library, AD9851 pins for CLOCK, LOAD, DATA and RESET
LCD_5110 myScreen(P2_3, // Chip Select *
P1_6, // Serial Clock *
P2_5, // Serial Data *
P2_4, // Data/Command *
NULL, // Reset *
P1_7, // Backlight
NULL); // Push Button 0
//******************************************************************
// Defining pins mode and initializing hardware
void setup() {
pinMode(PTT_key, INPUT_PULLUP);
myDDS.begin();
pinMode(ANALOG_BUTTONS, INPUT);
myScreen.begin();
myScreen.setBacklight(1);
myScreen.setFont(1);
myScreen.text(0, 0, "sVFO");
myScreen.text(0, 2, "AD9850");
myScreen.setFont(0);
myScreen.text(0, 4, "v1.00 - XV4Y");
myScreen.text(0, 5, "Init...");
delay(1000);
myDDS.reset();
myDDS.SetFrequency( frequency_A, 0, false );
digitalWrite( PTT_key, LOW );
};
//******************************************************************
// Here starts the actual sequence sending
void loop() {
myScreen.clear();
myScreen.setBacklight(1);
myScreen.setFont(1);
if (vfo == 0) {
myScreen.text(0, 0, "VFO A");
myDDS.SetFrequency( frequency_A, 0, false );
} else {
myScreen.text(0, 0, "VFO B");
myDDS.SetFrequency( frequency_B, 0, false );
};
myScreen.setFont(0);
display_freq (frequency_A, 3);
display_freq (frequency_B, 5);
while (read_buttons()==5 || read_buttons()==4 || read_buttons()==2) delay(10); // Debounce except for UP/DWN
while (1) {
// Update the frequencies display
if (multiplier > 5) {
aff_multiplier = multiplier + 2;
} else if (multiplier > 2) {
aff_multiplier = multiplier + 1;
} else {
aff_multiplier = multiplier;
};
myScreen.text(0, 4, " ");
if (vfo == 0) {
myScreen.text(9-aff_multiplier, 4, "^");
} else {
myScreen.text(9-aff_multiplier, 4, "v");
}
display_freq (frequency_A, 3);
display_freq (frequency_B, 5);
// Read the analog buttons input
if(read_buttons()==1) { // Up we increase frequency
delay(200); // Debounce
if (vfo == 0) {
frequency_A = frequency_A + powf(10,(float)multiplier);
} else {
frequency_B = frequency_B + powf(10,(float)multiplier);
};
#if defined AUTO_VALID
break;
#endif
} else if (read_buttons()==3) { // Down we decrease frequency
delay(200); // Debounce
if (vfo == 0) {
frequency_A = frequency_A - powf(10,(float)multiplier);
} else {
frequency_B = frequency_B - powf(10,(float)multiplier);
};
#if defined AUTO_VALID
break;
#endif
} else if (read_buttons()==2) { // Left we increase multiplier
debounce = millis();
while (read_buttons()==2) { //Debounce
if ((millis()-debounce)>1000) { // Long press we do "Band UP"
freq_select++;
if (freq_select > 14) freq_select = 0;
if (vfo == 1) frequency_B = frequencies[freq_select]; else frequency_A=frequencies[freq_select];
multiplier--;
break;
};
};
multiplier++;
if (multiplier > 7) multiplier = 7;
} else if (read_buttons()==4) { // Right we decrease multiplier
debounce = millis();
while (read_buttons()==4) { //Debounce
if ((millis()-debounce)>1000) { // Long press we do VFO A=B
if (vfo == 1) frequency_A = frequency_B; else frequency_B=frequency_A;
multiplier++;
break;
};
};
multiplier--;
if (multiplier < 0) multiplier = 0;
} else if (read_buttons()==5) { // OK we go out
debounce = millis();
while (read_buttons()==5) { //Debounce
if ((millis()-debounce)>1000) { // Long press we switch VFO A/B
if (vfo == 1) vfo=0; else vfo=1;
break;
};
};
break; // Short press we just leave the loop so the frequency is transmitted to the AD9850
}
// Check if we are transmitting split (momentaneous VFO A->B switch)
if (saved_PTT != digitalRead(PTT_key)) {
saved_PTT = digitalRead(PTT_key);
if (vfo == 1) vfo=0; else vfo=1;
break;
};
}
};
//******************************************************************
// Display the frequency
void display_freq (unsigned long freq, char ligne) {
myScreen.text(10, ligne, " Hz ");
chaine_txt[5] = 0x00;
chaine_txt[4] = 0x30 + (((freq)/1)%10);
chaine_txt[3] = 0x30 + (((freq)/10)%10);
chaine_txt[2] = 0x30 + (((freq)/100)%10);
chaine_txt[1] = '.';
chaine_txt[0] = 0x30 + (((freq)/1000)%10);
myScreen.text(5, ligne, chaine_txt);
chaine_txt[5] = 0x00;
chaine_txt[4] = 0x30 + (((freq)/10000)%10);
chaine_txt[3] = 0x30 + (((freq)/100000)%10);
chaine_txt[2] = '.';
chaine_txt[1] = 0x30 + (((freq)/1000000)%10);
chaine_txt[0] = 0x30 + (((freq)/10000000)%10);
myScreen.text(0, ligne, chaine_txt);
}
//******************************************************************
// Display a 2 digits number
void display_number (byte number, char column, char ligne) {
chaine_txt[2] = 0x00;
chaine_txt[1] = 0x30 + (number%10);
chaine_txt[0] = 0x30 + ((number/10)%10);
myScreen.text(column, ligne, chaine_txt);
}
//******************************************************************
// Return a button value depending on the analog reading
byte read_buttons () {
int value = analogRead(ANALOG_BUTTONS);
if ( value<(1+Analog_Noise) ) {
return 1;
} else if ( value<(78+Analog_Noise) ) {
return 2;
} else if ( value<(146+Analog_Noise) ) {
return 3;
} else if ( value<(205+Analog_Noise) ) {
return 4;
} else if ( value<(255+Analog_Noise) ) {
return 5;
} else {
return 0;
}
}