#include #include #include "lcd.h" #pragma config FOSC = IRC #pragma config WDTEN = OFF #pragma config FCMEN = OFF #pragma config PWRTEN = ON #pragma config BOREN = ON #pragma config BORV = 30 #pragma config LVP = OFF #pragma config MCLRE = OFF #pragma config HFOFST = ON #pragma config PLLEN = OFF //#pragma config CPUDIV = NOCLKDIV #define DEBUG #define _XTAL_FREQ 16000000 #define DDS_FSYNC LATAbits.LATA5 // AD9834 sync #define DDS_SCLK LATAbits.LATA4 // AD9834 clock #define DDS_SDATA LATCbits.LATC5 // AD9834 data #define MAX_FREQ 4300000 // max frequency #define MIN_FREQ 4000000 // min frequency #define DEF_FREQ 4248000 // default frequency #define FIX_FREQ 8000000 // IF frequency #define EEPROM 0x0000 // EEPROM address unsigned long freq; // VFO frequency unsigned long step; // frequency up down step unsigned char renc_now, renc_old; // value of rotary encoder unsigned char cflag; // frequency change flag unsigned char diff; void delay_ms(unsigned int t) { for(; t > 0; t--) // 16MHz clock __delay_ms(1); // 1ms: 0.001 / ((1 / (16000000 / 4)) * 1000) = 12 } 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)); } } long eeprom_read_long(unsigned int adr) { long d; d = (unsigned long)eeprom_read(EEPROM + adr * 4); d |= (unsigned long)eeprom_read(EEPROM + adr * 4 + 1) << 8; d |= (unsigned long)eeprom_read(EEPROM + adr * 4 + 2) << 16; d |= (unsigned long)eeprom_read(EEPROM + adr * 4 + 3) << 24; return d; } /*************************************************************** serial data send (MSB first) ***************************************************************/ void dds_dataset(unsigned long data, unsigned int bt) { unsigned int i; DDS_FSYNC = 0; for(i = bt; i > 0 ; i--) { DDS_SDATA = (data >> (i - 1)) & 0x00000001; DDS_SCLK = 0; DDS_SCLK = 1; } DDS_FSYNC = 1; } /*************************************************************** AD9833 DDS control (frequency to serial code) ***************************************************************/ void freq2serial(unsigned long f) { unsigned long msb, lsb; unsigned long data; char buf[10]; data = (double)(f / 0.093132257); msb = (data >> 14) + 0x4000; lsb = (data & 0x00003fff) + 0x4000; dds_dataset(0x2000, 16); dds_dataset(lsb, 16); dds_dataset(msb, 16); } /*************************************************************** pin change interrupt for rotary encoder ***************************************************************/ void interrupt isr(void) { if(INTCONbits.RABIF) { if(PORTBbits.RB6 == 1) { if(PORTBbits.RB7 == 0) renc_now = 0; else renc_now = 1; } else { if(PORTBbits.RB7 == 1) 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; INTCONbits.RABIF = 0; } cflag = 1; } /*************************************************************** lcd write routine ***************************************************************/ void lcd_update() { char buf[10]; lcd_gotopos(0, 0); sprintf(buf, "%6ld00", freq / 10); lcd_puts(buf); lcd_gotopos(0, 1); sprintf(buf, "step%4d", step * 10); lcd_puts(buf); } /*************************************************************** main ***************************************************************/ void main(void) { unsigned char sw0_state, sw1_state; unsigned int tim0, tim1; unsigned long ftmp; OSCCON = 0b11110111; // 16MHz internal clock TRISA = 0b00000000; // RA4,5 AD9834 serial control TRISB = 0b11110000; // RB6,7 rotary encoder input and RB4,5 input TRISC = 0b00000000; // LCD and RC5 AD9834 serial control ADCON0bits.ADON = 0; // ad converter off ANSEL = 0; ANSELH = 0; INTCONbits.RABIE = 1; // PortA,B pin change interrupt enable INTCON2bits.RABPU = 0; // PortA,B pull-up enable INTCON2bits.RABIP = 0; // PortA,B interruput priority low WPUB = 0b11100000; // RB5,6,7 pull-up IOCBbits.IOCB6 = 1; // RB6 pin change interrupt enable IOCBbits.IOCB7 = 1; // RB7 pin change interrupt enable sw0_state = sw1_state = 0; freq = DEF_FREQ; mode = 0; step = 10; diff = 0; tim0 = tim1 = 0; lcd_init(); lcd_update(); INTCONbits.GIE = 1; // general interrupt enable cflag = 0; delay_ms(500); freq2serial(freq); while(1) { // step down or press for long time to EEPROM memory write if(PORTBbits.RB5 == 0) { sw0_state = 1; delay_ms(10); tim0++; } if(sw0_state && PORTBbits.RB5 == 1) { sw0_state = 0; tim0 = 0; if(mode == 0) { PORTCbits.RC2 = 1; mode = 1; step = 1000; lcd_update(); } else { PORTCbits.RC2 = 0; mode = 0; step = 10; lcd_update(); } } // frequency and offset write to EEPROM if(tim0 > 100) { sw0_state = 0; tim0 = 0; // write eeprom delay_ms(1000); lcd_update(); } // frequency changed if(cflag) { if(diff) { if((freq + step) <= MAX_FREQ) freq += step; } else { if((freq - step) >= MIN_FREQ) freq -= step; } freq2serial(freq); lcd_update(); cflag = 0; } } }