(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; } }