/* Este firmware se publica con Licencia Creative Commons Atribucion-CompartirIgual 4.0 Internacional . * * Se reconocen los derechos de las licencias de todas las librerias usadas. * https://creativecommons.org/licenses/by-sa/4.0/ * * EA2SA Mayo 2019 * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include // posiciones para constantes de calculo en la EEPROM // X VFO invertido dec 992 HEX 3E0 // C VFO Invertido dec 1000 HEX 3E8 // X VFO DIRECTO dec 1008 HEX 3F0 // C VFO DIRECTO dec 1016 HEX 3f8 //I2C pins declaration LiquidCrystal_I2C lcd(0x3f, 16, 4); // display 2X16 address 0x16 Parece que va tambien con 3F // dispaly 4X20 address 0x3f unsigned long cnt; unsigned long Oldcnt; unsigned long Med1; unsigned long Med2; unsigned long Mdisp ; long OffH ; String Bnd; float X =0.00000; float C= 0.00000; char buf[16]; char buf2[16]; char CnBuf[10]; char Mbuf[16]; // int Stat=0; int caso =0 ; int Rfsc=0; int Mrfsc = 5; int vfoDir = 0 ; // VFODir = 1 VFOInv = 0 int H160 = 6; // Pin digital para seleccionar la banda de 160 mtr. int H80 = 7; // Pin digital para seleccionar la banda de 80 mtr. int H40 = 8; // Pin digital para seleccionar la banda de 40 mtr. int H20 = 9; // Pin digital para seleccionar la banda de 20 mtr. int H15 = 10; // Pin digital para seleccionar la banda de 15 mtr. int H11 = 11; // Pin digital para seleccionar la banda de 11 mtr. int H10A = 12; // Pin digital para seleccionar la banda de 10 mtr. segmento A int H10B = 13; // Pin digital para seleccionar la banda de 10 mtr. segmento B int H10C = 4; // Pin digital para seleccionar la banda de 10 mtr. segmento C int H10D = 3; // Pin digital para seleccionar la banda de 10 mtr. segmento D int HJJY = 2; // Pin digital para seleccionar la banda de JJY, 59 mtrs. SerialCommand sCmd; // The SerialCommand object String verFirm = "Firmware: FT301_V7_045 Eeprom:V745_01.HEX"; /*********************************************************************************************************************** * Inicializa todo el sistema * Global: * Local: * */ void setup() { // Inicializacion de dispositivos, rutinas y variables. Serial.begin(115200); pinMode(H160,INPUT); // Pines para detectar Bnd HAM. pinMode(H80,INPUT); // identificada en metros. pinMode(H40,INPUT); pinMode(H20,INPUT); pinMode(H15,INPUT); pinMode(H11,INPUT); pinMode(H10A,INPUT); pinMode(H10B,INPUT); pinMode(H10C,INPUT); pinMode(H10D,INPUT); pinMode(HJJY,INPUT); // Serial.print("Inicializa "); // Parece que sin esta linea no inicializa bien la variable caso. // Serial.println(caso); // rutinas para comandos serie sCmd.addCommand("VCO", PrConsRS); // Ver constantes por RS232 VCO[CR]. sCmd.addCommand("GDR", GraCXDRS); // Graba las constantes de VFO directo, por RS232 C,X[CR] sCmd.addCommand("GIR", GraCXIRS); // Graba las constantes de VFO invertido por RS232 C,X[CR] sCmd.addCommand("VFD", VFODir); // Usar la medida de frecuencia del VFO directa. VFD[CR] sCmd.addCommand("VFI", VFOInv); // Usar la medida de frecuencia del VFO invertida. VFI[CR] sCmd.addCommand("VFR", VerFrc); // Ver en display la frecuencia de RX/TX. VFR[CR] sCmd.addCommand("VCT", VerCnt); // Ver en display cuentas del frecuencimetro. VCT[CR] sCmd.addCommand("VFV", VerVFO); // Ver en disply frecuencia calculada del VFO. VFV[CR] sCmd.addCommand("VOF", VerOBnd); // Ver en disply frecuencia offset por Bnd. VOB[CR] sCmd.addCommand("STF", Status); // Ver en disply status frecuencimetro. STF[CR] sCmd.addCommand("VER", PVer); // Ver la version del firmware por RS232. VER[CR] sCmd.addCommand("???", Help); // Listar comandos por RS232 ???[CR] sCmd.setDefaultHandler(unrecognized); // Handler unrecognizes comand (contesta "Queee?") InitLCD(); // inicializa display. VFOInv(); // frecuencia del VFO invertida Help() ; // Instrucciones para comandos RS232 FreqCount.begin(500); // inicializa frecuencimetro, t medida. } /*********************************************************************************************************************** * bucle de funcionamiento del programa * Global: * Local: * */ void loop() { // put your main code here, to run repeatedly: if (FreqCount.available()) { Rfsc=Rfsc++ ; if (Rfsc = Mrfsc) { MiraBandaHam(); Rfsc = 0 ; //Serial.println(Rfsc); } cnt = FreqCount.read(); Leefrecuencia(); // ConvierteAFrecuenciaDisplay(); sCmd.readSerial(); } } /*********************************************************************************************************************** * Inicializa el display LCD * Global: * Local: * */ void InitLCD() { lcd.init(); // es importante, y necesario con display I2C, no inicializa sin esta linea lcd.backlight(); //To Power ON the back light lcd.setBacklight(100); // Backlight a 100 //Serial.println(" enciende a 100"); //Serial.println(" "); lcd.print("Frequency meter "); //You can write 16 Characters per line . lcd.setCursor(0,1); // Estos mensajes deben conservarse lcd.print("FT-301 EA2SA "); // segun las condiciones de la licencia delay(2000); //Delay used to give a dynamic effect // } /*********************************************************************************************************************** * rutina para leer la frecuencia del VFO * Local: * */ void Leefrecuencia () { int diferencia; int limit = 2 ; // Serial.println(" Entra >"); if (cnt < 100000) { Med1 = 500000; lcd.clear(); cnt=0; lcd.setCursor(0,1); lcd.print(" NO SIGNAL "); Serial.println(" NO SIGNAL "); goto SalSinConvertir; } diferencia = (Oldcnt-cnt); // Serial.print(" 2 >"); // Serial.println(diferencia); // goto Convierte; if (abs(diferencia) > limit ) { //Serial.print(" print >"); //Serial.println(diferencia ); goto Convierte; } else { // Serial.print(" NO print "); // Serial.println( diferencia ); goto SalSinConvertir; } Convierte:; ConvierteAFrecuenciaDisplay(); SalSinConvertir:; } /*********************************************************************************************************************** * convierte las cuentas a frecuencia y formata la salida al display LCD * Global: * Local: * */ void ConvierteAFrecuenciaDisplay() { Med1 = (((cnt*X)+C)); // VFO en frecuencia ltoa(cnt, CnBuf, 10); // Cuentas frecuencia ltoa(Med1, Mbuf, 10); // Mbuf > VFO calculado // Serial.print(cnt); // Serial.println("< cnt "); ConMedida:; Med2= Med1 + OffH ; ltoa(Med2, buf, 10); // 10 is the base value not the size - look up ltoa for avr if ( Med2 < 10000000 ) { buf2[0] = ' ' ; buf2[1] = ' ' ; buf2[2] =buf[0] ; buf2[3] ='.' ; buf2[4] =buf[1] ; buf2[5] =buf[2] ; buf2[6] =buf[3] ; buf2[7] ='.' ; buf2[8] =buf[4] ; buf2[9] =buf[5] ; buf2[10] =' '; buf2[11] =' '; buf2[12] =' '; buf2[13] =' '; buf2[14] = ' ' ; buf2[15] = ' ' ; buf2[16] = ' ' ; buf2[17] ='\0' ; } else { buf2[0] = ' ' ; buf2[1] = buf[0] ; buf2[2] = buf[1] ; buf2[3] ='.' ; buf2[4] =buf[2] ; buf2[5] =buf[3] ; buf2[6] =buf[4] ; buf2[7] ='.' ; buf2[8] =buf[5] ; buf2[9] =buf[6] ; buf2[10] =' '; buf2[11] =' '; buf2[12] =' '; buf2[13] =' '; buf2[14] = ' ' ; buf2[15] = ' ' ; buf2[16] = ' ' ; buf2[17] ='\0' ; } ImprimeSalida:; PrintInfo(); FinDecode:; } /*********************************************************************************************************************** * selecciona la banda de RF usada en ese momento, para indicarlo en el display y poner el offset en la frecuencia final * Global: * Local: * */ void MiraBandaHam () { if (digitalRead(H160)== 0) { OffH = -3500000 ; Bnd = "160m. 1,5-2 Mhz"; goto FinBandas; } if (digitalRead(H80)== 0) { OffH = -1500000; Bnd = "80m 3,5-4,0 Mhz"; goto FinBandas;} if (digitalRead(H40)== 0) { OffH = 2000000 ; Bnd = "40m 7,0-7,5 Mhz"; goto FinBandas;} if (digitalRead(H20)== 0) { OffH = 9000000; Bnd = "20m 14-14,5 Mhz"; goto FinBandas;} if (digitalRead(H15)== 0) { OffH = 16000000; Bnd = "15m 21-21,5 Mhz"; goto FinBandas;} else if (digitalRead(H11)== 0) { OffH = 22000000; Bnd = "11m 27-27,5 Mhz"; goto FinBandas; } if (digitalRead(H10A)==0) { OffH = 23000000; Bnd = "10A 28-28,5 Mhz"; goto FinBandas;} if (digitalRead(H10B)== 0) { OffH = 23500000; Bnd = "10B 28,5-29 Mhz"; goto FinBandas; } if (digitalRead(H10C)== 0) { OffH = 24000000; Bnd = "10C 29-29,5 Mhz"; goto FinBandas; } if (digitalRead(H10D)== 0) { OffH = 24500000; Bnd = "10D 29,5-30 Mhz"; goto FinBandas; } if (digitalRead(HJJY)== 0) { OffH = 000; Bnd = "JJY mtr 5.0 Mhz"; } FinBandas:; lcd.setCursor(0,0); lcd.print(Bnd); } /*********************************************************************************************************************** * Imprime en el LCD segun configuración. * Global: * Local: * */ void PrintInfo() { //Serial.print("PrintInfo "); //Serial.println(caso); Oldcnt= cnt; switch (caso) {case 0: // presenta frecuencia de salida, normal lcd.setCursor(0,1); lcd.print("F: "); lcd.setCursor(2,1); lcd.print(buf2); lcd.setCursor(13,1); lcd.print("Mhz"); //Serial.println("frecuencia emision/recepcion "); break; case 1: // Presenta cuentas del frecuencimetro lcd.setCursor(0,1); lcd.print(CnBuf); lcd.setCursor(7,1); lcd.print(" cnts. "); break; case 2: // Presenta frecuencia calculada del VFO directa/inversa lcd.setCursor(0,1); lcd.print("Frec.:"); lcd.setCursor(12,1); lcd.print("Hz."); lcd.setCursor(6,1); lcd.print(Mbuf); break; case 3: // Presenta offset por banda lcd.setCursor(0,1); lcd.print("OFFSET:"); lcd.setCursor(11,1); lcd.print(" MHz. "); lcd.setCursor(8,1); lcd.print(OffH/1000000.00 ); default: break; } } /*********************************************************************************************************************** * Imprime por USB la ayuda grabada en la EEPROM * Global: * Local: * */ void Help() // de la eeprom a la salida serie { int address=00 ; char value ; for ( int n = 0; n<927; n++) // /HEX 39F { value = EEPROM.read(address); Serial.print(value); address++; } } /*********************************************************************************************************************** * Imprime las constantes de la ecuacion utilizada en la salida serie/USB * Global: * Local: * */ void PrConsRS () { Serial.print(">Constantes.>C="); Serial.print(C); Serial.print(">X ="); Serial.println(X); } /*********************************************************************************************************************** * Pone en el display LCD las cuentas de la medida de frecuencia * Global: * Local: * */ void VerCnt() { caso= 1; Serial.println(">Ver cnt"); ConvierteAFrecuenciaDisplay();} /*********************************************************************************************************************** * Pone en el display LCD la frecuencia del VFO * Global: * Local: * */ void VerVFO() { caso= 2; Serial.println(">Ver VFO"); ConvierteAFrecuenciaDisplay();} /*********************************************************************************************************************** * Pone en el display LCD la banda utilizada * Global: * Local: * */ void VerOBnd () { caso=3; Serial.println(">Ver BND"); MiraBandaHam (); PrintInfo(); } /*********************************************************************************************************************** * Pone en el display LCD la frecuencia en cada banda * Global: * Local: * */ void VerFrc() { caso = 0; Serial.println(">Ver FRC"); ConvierteAFrecuenciaDisplay(); } /*********************************************************************************************************************** * La frecuencia del VFO se usara medida de manera directa * Si en la EEPROM no hay una variable Float X o C valida usa las variables en el Firmware. * Global: * Local: * */ void VFODir() { // display VFO directo // X =2.0000485725 ; // C= -6.0000114261; // X VFO DIRECTO dec 1008 HEX 3F0 // C VFO DIRECTO dec 1016 HEX 3F8 vfoDir=1 ; Serial.println(">VFO DIR"); int address = 1008; // HEX 3F0 EEPROM.get(address, X); if (isnan( X)) { X= 2.0000485725; } address = 1016944; // HEX 3F8 EEPROM.get(address, C); if ( isnan ( C)) { C= -6.0000114261; } PrConsRS (); ConvierteAFrecuenciaDisplay(); } /*********************************************************************************************************************** * La freecuencia del VFO se usara medida de manera invertida * Si en la EEPROM no hay una variable Float X o C valida usa las variables en el Firmware. * Global: * Local: * */ void VFOInv() { // display VFO invertido // X = -2.0000485725; // C = 10500001.9; // X VFO invertido dec 992 HEX 3E0 // C VFO Invertido dec 1000 HEX 3E8 vfoDir=0 ; Serial.println(">VFO INV"); int address = 992; // HEX 3E0 EEPROM.get(address, X); if(isnan( X )) { X= -2.0000485725; } address = 1000; // HEX 3E8 EEPROM.get(address, C); if (isnan( C)) { C = 10500001.9; } PrConsRS (); ConvierteAFrecuenciaDisplay(); } /*********************************************************************************************************************** * Comando por USB no reconocido * Global: * Local: * */ void unrecognized(const char *command) { Serial.println("Quee?, comando desconocido."); } /*********************************************************************************************************************** * Graba las constantes C y X de conversion de cuentas en frecuencia para VFO directo * Global: * Local: * */ void GraCXDRS() { // dos argumentos Serial.println(); char *arg; String Cstr; int addre =0; arg = sCmd.next(); Cstr = String(arg) ; if (arg != NULL) { C = Cstr.toFloat(); // Converts a char string to an double Serial.print("C:"); Serial.print(C); EEPROM.put(addre, C ); } else { Serial.print("No C!."); } arg = sCmd.next(); Cstr = String(arg) ; if (arg != NULL) {Cstr = String(arg) ; X = Cstr.toFloat(); // Converts a char string to an double Serial.print("X:"); Serial.println(X); addre = 928; EEPROM.put(addre, X ); } else { Serial.println("No X!"); } PrConsRS(); } /*********************************************************************************************************************** * Graba las constantes C y X de conversion de cuentas en frecuencia para VFO Invertido * Global: * Local: * */ void GraCXIRS() { // dos argumentos Serial.println(); char *arg; String Cstr; arg = sCmd.next(); Cstr = String(arg) ; if (arg != NULL) { C = Cstr.toFloat(); // Converts a char string to an double2 Serial.print("C:"); Serial.print(C); int addre = 912; EEPROM.put(addre, C ); } else { Serial.print("No C!"); } arg = sCmd.next(); Cstr = String(arg) ; if (arg != NULL) { Cstr = String(arg) ; X = Cstr.toFloat(); // Converts a char string to an double Serial.print("X:"); Serial.println(X); int addre = 896; EEPROM.put(addre, X ); } else { Serial.println("No X!"); } PrConsRS(); } /*********************************************************************************************************************** * Imprime el estado actual en la salida serie/USB * Global: * Local: * */ void Status ( void) { Serial.print ("Banda:") ; Serial.print (Bnd); Serial.print(" Offset:"); Serial.print(OffH/1000000.00 ); Serial.println ("Mhz") ; Serial.print ("En LCD: "); switch (caso) {case 0: Serial.print("0, frecuencia banda."); break; case 1: // Presenta cuentas del frecuencimetro Serial.print("1, cuentas frecuencia."); break; case 2: // Presenta frecuencia calculada del VFO directa/inversa Serial.print("2, frecuencia del VFO."); break; case 3: // Presenta offset por banda Serial.print("3, offset banda."); default: break; } if (vfoDir==0 ) { Serial.println(" usando VFO invertido."); } else { Serial.println(" usando VFO directo."); } PrConsRS (); } /*********************************************************************************************************************** * Imprime le version del Firmware y EEPROM en la salida serie/USB * Global: * Local: * */ void PVer(void) { Serial.println(); Serial.println(); Serial.print("Version : "); Serial.println( verFirm ); }