/* * si5351a RF twotone generator * File: rf_twotone_generator.c * Author: www.henteko.org * * Created on 2022/03/05, 18:33 */ #include #include #include "pic16f_i2c.h" #include "i2c_lcd.h" #include "si5351a.h" #pragma config FEXTOSC = OFF // external clock off #pragma config RSTOSC = HFINT32 // internal clock 16mhz X 2 (pll) #pragma config MCLRE = ON // RA3 disable #pragma config FCMEN = OFF #pragma config PWRTE = OFF #pragma config WDTE = OFF // #pragma config BOREN = ON // #pragma config LVP = OFF // LVP=off MCLRE=off RA3 input enable #define _XTAL_FREQ 32000000 #define MAX_FREQ 149999000 // max frequency #define MIN_FREQ 1000000 // min frequency #define DEF_FREQ 7000000 // default frequency #define DIF_FREQ -10000 // diff frequency #define EEPROM 0x0000 // EEPROM address #define MAX_DIFF 1000000 // max difference frequency #define MIN_DIFF -1000000 // min difference frequency long freq; // frequency long step; // frequency up down step long dfreq; // difference frequency unsigned char renc_now, renc_old; // value of rotary encoder unsigned char cflag; // frequency change flag unsigned char diff; // frequency up down flag unsigned char buf[19]; // oled output buffer unsigned char mode; // mode flag unsigned int pos; // cursor position // millisecond delay void delay_ms(unsigned int t) { for(; t > 0; t--) __delay_ms(1); } // eeprom write routine void eeprom_write_long(unsigned int adr, long data) { unsigned char i; for(i = 0; i < 4; i++) { eeprom_write(EEPROM + adr * 4 + i, (unsigned char)((data >> (i * 8)) & 0x000000ff)); } } // eeprom read routine long eeprom_read_long(unsigned int adr) { long d; d = (long)eeprom_read(EEPROM + adr * 4); d |= (long)eeprom_read(EEPROM + adr * 4 + 1) << 8; d |= (long)eeprom_read(EEPROM + adr * 4 + 2) << 16; d |= (long)eeprom_read(EEPROM + adr * 4 + 3) << 24; return d; } // pin change interrupt for rortary encoder void interrupt isr(void) { if(IOCIF) { if(RC1) { if(RC2 == 0) { renc_now = 1; } else { renc_now = 0; } } else { if(RC2) { renc_now = 2; } else { renc_now = 3; } } if((renc_now + 3 + 1) % 3 == renc_old) diff = 0; if((renc_now + 3 - 1) % 3 == renc_old) diff = 1; IOCCFbits.IOCCF1 = 0; IOCCFbits.IOCCF2 = 0; renc_old = renc_now; cflag = 1; } } // write value to eeprom void setvalue_write(void) { eeprom_write_long(0, dfreq); delay_ms(100); eeprom_write_long(1, freq); delay_ms(100); } // read value from eeprom void setvalue_read(void) { dfreq = eeprom_read_long(0); if(dfreq >= MAX_DIFF || dfreq < MIN_DIFF) dfreq = DIF_FREQ; freq = eeprom_read_long(1); if((freq + dfreq)> MAX_FREQ || (freq + dfreq) < MIN_FREQ) freq = DEF_FREQ; } // lcd output routine void lcd_output(long f) { unsigned char buf[16]; unsigned int i; if(mode == 0) { sprintf(buf, "Fr %9ldHz", f); i2c_lcd_goto(0, 0); } else { sprintf(buf, "Df %9ldHz", f); i2c_lcd_goto(1, 0); } for(i = 0; i < 16; i++) { i2c_lcd_putch(buf[i]); if(i == 5) { if(f >= 1000000 || f <= -1000000) i2c_lcd_putch('.'); else i2c_lcd_putch(' '); } if(i == 8) { if(f >= 1000 || f <= -1000) i2c_lcd_putch('.'); else i2c_lcd_putch(' '); } } if(mode == 0) i2c_lcd_goto(0, pos); else i2c_lcd_goto(1, pos); } // change lpf routine void setFilter(void) { LATCbits.LATC3 = 0; LATCbits.LATC4 = 0; LATCbits.LATC5 = 0; LATCbits.LATC6 = 0; LATCbits.LATC7 = 0; LATBbits.LATB7 = 0; if(freq < 4000000) { LATCbits.LATC5 = 1; } else if(freq < 8000000) { LATCbits.LATC4 = 1; } else if(freq < 15000000) { LATCbits.LATC3 = 1; } else if(freq < 30000000) { LATCbits.LATC6 = 1; } else if(freq < 55000000) { LATCbits.LATC7 = 1; } else { LATBbits.LATB7 = 1; } } void main(void) { unsigned char sw0_state; unsigned int tim0; ANSELB = 0x00; // Port B all digital TRISBbits.TRISB4 = 1; // RB4 i2c sda TRISBbits.TRISB6 = 1; // RB6 i2c scl ODCONBbits.ODCB4 = 1; // RB4 Open-Drain set ODCONBbits.ODCB6 = 1; // RB6 Open-Drain set TRISBbits.TRISB7 = 0; // RB7 filter control SSP1DATPPS = 0x0C; // RB4 i2c sda RB4PPS = 25; // RB4 i2c sda SSP1CLKPPS = 0x0E; // RB6 i2c scl RB6PPS = 24; // RB6 i2c scl ANSELC = 0x00; // Port C all digital TRISCbits.TRISC3 = 0; // PC3 - PC7 filter control TRISCbits.TRISC4 = 0; TRISCbits.TRISC5 = 0; TRISCbits.TRISC6 = 0; TRISCbits.TRISC7 = 0; TRISCbits.TRISC0 = 1; // RC0 sw input for step and memory TRISCbits.TRISC1 = 1; // RC1 rotaly encoder TRISCbits.TRISC2 = 1; // RC2 rotaly encoder WPUCbits.WPUC0 = 1; // RC0 weak pull-up enable WPUCbits.WPUC1 = 1; // RC1 weak pull-up enable WPUCbits.WPUC2 = 1; // RC2 weak pull-up enable IOCCNbits.IOCCN1 = 1; // RC1 interrupt-on-change negative edge IOCCNbits.IOCCN2 = 1; // RC2 interrupt-on-change negative edge InitI2C(); delay_ms(10); i2c_lcd_init(26); si5351_init(); setvalue_read(); step = 1000000; pos = 5; diff = 0; cflag = 0; sw0_state = 0; tim0 = 0; mode = 0; lcd_output(freq); mode = 1; lcd_output(dfreq); mode = 0; i2c_lcd_goto(0, pos); i2c_lcd_cursor(2); si5351_setfreq(0, freq); si5351_setfreq(1, freq + dfreq); setFilter(); IOCIE = 1; // intertupt-on-change interrupt enable GIE = 1; // general interrupt enable while(1) { if(cflag) { if(mode == 0) { if(diff) { if((freq + step ) <= MAX_FREQ) freq += step; } else { if((freq - step) >= MIN_FREQ) freq -= step; } si5351_setfreq(0, freq); si5351_setfreq(1, freq + dfreq); setFilter(); lcd_output(freq); } else { if(diff) { if((dfreq + step ) <= MAX_DIFF) dfreq += step; } else { if((dfreq - step) >= MIN_DIFF) dfreq -= step; } lcd_output(dfreq); } cflag = 0; } if(PORTCbits.RC0 == 0) { sw0_state = 1; delay_ms(20); tim0++; } if(sw0_state && PORTCbits.RC0 == 1) { sw0_state = 0; tim0 = 0; if(step == 1) { step = 10; pos = 12; } else if(step == 10) { step = 100; pos = 11; } else if(step == 100) { step = 1000; pos = 9; } else if(step == 1000) { step = 10000; pos = 8; } else if(step == 10000) { step = 100000; pos = 7; } else if (step == 100000) { step = 1000000; pos = 5; } else if(step == 1000000) { step = 1; pos = 13; } if(mode == 0) i2c_lcd_goto(0, pos); else i2c_lcd_goto(1, pos); } // difference frequency setup routine and write memory if(tim0 > 60) { sw0_state = 0; tim0 = 0; if(mode == 0) { i2c_lcd_goto(0, 0); i2c_lcd_puts("Difference Setup"); delay_ms(2000); mode = 1; step = 1000; pos = 9; lcd_output(dfreq); } else { mode = 0; GIE = 0; i2c_lcd_goto(0, 0); i2c_lcd_puts("==Write Memory=="); delay_ms(2000); setvalue_write(); si5351_setfreq(1, freq + dfreq); lcd_output(freq); GIE = 1; } } } }