/* * si5351a_28mhz_vfo.c * * Created: 6/26/2022 3:29:55 PM * Author: www.henteko.org */ #include #include #include #include #include #include #include "TinyI2CMaster.h" #include "i2c_lcd.h" #include "si5351a.h" #define MAX_FREQ 289990 // max frequency #define MIN_FREQ 280000 // min frequency #define DEF_FREQ 283000 // default frequency #define DIF_FREQ 122880 // IF frequency #define ADC_ENABLE (_BV(ADEN)|_BV(ADIF)|0b111) // ADC macro #define ADC_START (ADC_ENABLE|_BV(ADSC)) // ADC macro FILE *fp; // file descriptor for LCD unsigned long freq; // frequency unsigned long dfreq; // difference frequency unsigned long tmpfreq; // temp frequency unsigned long step; // frequency step unsigned char pos; // frequency cursor position volatile unsigned char cflag; // rotary-encoder change flag volatile unsigned char diff; // frequency up/down flag volatile unsigned char renc_now, renc_old; // value of rotary encoder static unsigned long fmem[1] __attribute__((section(".eeprom"))); // eeprom // millisecond order delay void delay_ms(unsigned int t) { while(t--) _delay_ms(1); } // adc routine unsigned int get_adc(unsigned char ch) { ADMUX = ch; ADCSRA = ADC_START; loop_until_bit_is_set(ADCSRA, ADIF); return ADCW; } // pin change interrupt for rotaly encoder ISR(PCINT0_vect) { if(bit_is_set(PINB, PB1)) { if(bit_is_clear(PINB, PB4)) renc_now = 0; else renc_now = 1; } else { if(bit_is_set(PINB, PB4)) 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; } renc_old = renc_now; cflag = 1; } // lcd output frequency void lcd_output(unsigned long f) { unsigned char buf[8]; unsigned int i; sprintf(buf, "%6ld", f); i2c_lcd_goto(0, 0); for(i = 0; i < 7; i++) { i2c_lcd_putch(buf[i]); if(i == 1 || i == 4) { i2c_lcd_putch('.'); } } i2c_lcd_goto(0, pos); } // write value to eeprom void setvalue_write(unsigned char ch) { eeprom_busy_wait(); eeprom_write_float(&fmem[ch], freq); delay_ms(100); } // read value from eeprom void setvalue_read(unsigned char ch) { eeprom_busy_wait(); freq = eeprom_read_float(&fmem[ch]); if(freq >= MAX_FREQ || freq < MIN_FREQ) freq = DEF_FREQ; } int main(void) { unsigned char sw0_state, sw1_state; unsigned int tim0, tim1; unsigned int adc; unsigned int send; unsigned char mode; unsigned char tmpstep, tmppos; DDRB = _BV(PB0)|_BV(PB2); // PB0,2 output for i2c PORTB = _BV(PB1)|_BV(PB4); // PB1,4 pull up(PB1,4 rotary encoder) GIMSK = _BV(PCIE); // pin change interrupt enable PCMSK = _BV(PCINT1)|_BV(PCINT4); // PB1,4 pin change interrupt ADCSRA = ADC_ENABLE; // adc enable TinyI2C_Master_init(); si5351_init(); i2c_lcd_init(32); fp = fdevopen(i2c_lcd_putch, NULL); step = 10; pos = 5; send = mode = 0; cflag = diff = 0; sw0_state = sw1_state = tim0 = tim1 = 0; dfreq = DIF_FREQ; setvalue_read(0); si5351_setfreq(0, (freq - dfreq) * 100); lcd_output(freq); i2c_lcd_goto(1, 0); fprintf(fp, " MHz"); i2c_lcd_goto(0, pos); i2c_lcd_cursor(2); sei(); while(1) { send = get_adc(0); if(send < 900) { if(dfreq != 0) { dfreq = 0; si5351_setfreq(0, freq * 100); lcd_output(freq); } } else { if(dfreq == 0) { dfreq = DIF_FREQ; if(mode == 0) { si5351_setfreq(0, (freq - dfreq) * 100); lcd_output(freq); } else { si5351_setfreq(0, (tmpfreq - dfreq) * 100); lcd_output(tmpfreq); } } } 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 - dfreq) * 100); lcd_output(freq); } else { if(diff) { if((tmpfreq + step ) <= MAX_FREQ) tmpfreq += step; } else { if((tmpfreq - step) >= MIN_FREQ) tmpfreq -= step; } si5351_setfreq(0, (tmpfreq - dfreq) * 100); lcd_output(tmpfreq); } cflag = 0; } adc = get_adc(3); // PB3 adc input if(adc < 30) { // sw0 input sw0_state = 1; tim0++; delay_ms(20); } if(adc > 100 && adc < 900) { // sw1 input sw1_state = 1; tim1++; delay_ms(20); } if(sw0_state && adc > 1000) { // frequency step change sw0_state = 0; sw1_state = 0; tim0 = 0; if(mode == 0) { if(step == 1) { step = 10; pos = 5; } else if(step == 10) { step = 100; pos = 4; } else if (step == 100) { step = 1000; pos = 3; } else if (step == 1000) { step = 1; pos = 7; } } i2c_lcd_goto(0, pos); } if(sw1_state && adc > 1000) { // RIT mode sw0_state = 0; sw1_state = 0; tim1 = 0; if(mode == 0) { mode = 1; i2c_lcd_goto(1, 0); fprintf(fp, "RIT"); tmpfreq = freq; tmpstep = step; tmppos = pos; step = 1; pos = 7; } else { mode = 0; i2c_lcd_goto(1, 0); fprintf(fp, " "); step = tmpstep; pos = tmppos; si5351_setfreq(0, (freq - dfreq) * 100); lcd_output(freq); } i2c_lcd_goto(0, pos); } if(tim0 > 60) { // sw0 long push sw0_state = 0; tim0 = 0; i2c_lcd_goto(1, 0); fprintf(fp, "WriteMEM"); delay_ms(2000); setvalue_write(0); i2c_lcd_goto(1, 0); fprintf(fp, " MHz"); lcd_output(freq); } } }