WordPress.com



/* Code for Amateur Band transceiver based on Si570 *//* G4BNM October 2017 *//* Based on DDS code of EI9GQ *//* Note on Pinguino PIC32 librariesPinguino I2C_start sends a pure start sequencePinguino I2C_stop sends a pure stop sequencePinguino I2C_writechar sends the address unshifted and includes the ACK clock pulse i.e. 9clock pulses per call */ #include "i2c.c"#include <interrupt.c>#include <stdbool.h>/* I/O pins for LCD RS and ENA lines */#define RS 4#define ENA 5/* rotary encoder pins */#define ENC_A 6 //RD8, external interrupt 1, CON4-D6#define ENC_B 1 //RD3, CON4-D1/* button pins */#define LEFT_BUTT 3 //band button RD5, CON4-D3#define RIGHT_BUTT 7 //step button RD11, CON4-D7/* pins to detect transmitter on and to set TX to low power */#define TXON 12 // +12v tx through potential divider to RG7, CON5-D12#define TXLP 11 // activate relay to route tx to low power socket and blank the PA: RG8, CON5-D11#define RXPRE 9 // activate relay to switch on rx preamp/* Function Prototypes */void lcdinit(void);//Initialise LCD modulevoid line2(void);//Move to start of line 2void home(void);//Move display cursor to home positionvoid clear(void);//Clear LCD displayvoid command(unsigned char lcd_comm);//Send command to LCDvoid display(unsigned char lcd_data);//Send character to displayvoid display_string(char *lcd_message); // Send text string to displayvoid display_frequency(u32 band); // Convert dial frequency to BCD, then to ASCII and send to LCD module.void change_band(void); // changes the band!void set_freq(void); // loads the Si570 registers for a large change in frequencyvoid quickset_freq(void); //loads the Si570 registers for a small change in frequency +/- 3500 ppmvoid read_encoder(void);//called by interrupt routinevoid set_step(void);//frequency tuning stepvoid display_s(void);//display signal strengthvoid display_p(void);//display power void tpwr(u16 pwr);//set transmitter powervoid i2c_write (u8, u8, u8); // write to a registeru8 i2c_read(u8, u8); //read a register unsigned int counter=0;// only used for debug purposes bool twom=FALSE; fourm=FALSE; //interrupt declarations void __attribute__ ((nomips16)) ISR_wrapper_vector_7(void) __attribute__ ((section (".vector_7")));// vector 7 is the external input 1 interrupt vector - see datasheet table 7-1// INT1 is on pin CON4-D6 on Pinguino-Pic32-OTG (RD8) void __attribute__ ((nomips16)) Int1Interrupt(void) __attribute__ ((interrupt)); void __attribute__ ((nomips16)) ISR_wrapper_vector_7(void) { Int1Interrupt(); } /* Variables */int x,count,svalue;char *lcd_message;// Pointer to the address of the String to send to LCDchar buff[32]; // only for debug purposesu16 encoder;// Rotary encoder stateu16 encoder_start; u16 pwr; //transmitter power u16 tp; //temporary power variableu32 rfreq_s, temp_freq;u8 hsdiv_n1, n1_rfreq; u8 reg[6], reg137, stemp;u32 temp;volatile u32 band;volatile u64 rfreq;volatile u32 stepsize; u32 offset_lower, offset_upper, offset_2m, offset_4m;unsigned short int step_count=0, band_step=0; pwr_step=0; rd_pwr;void setup(){/* Basic housekeeping. I/O pin configuration */ /* next 4 statements set up port B for the input filters */ pinMode(14,OUTPUT); //PORTB RB1 CON2-A0 pinMode(15,OUTPUT); //PORTB RB2 CON2-A1 pinMode(16,OUTPUT); //PORTB RB3 CON2-A2 pinMode(17,OUTPUT); //PORTB RB4 CON2-A3 PORTB=0x00; PORTE=0x00; TRISE=0x00;// All PORTE pins are outputs - LCD parallel interfacepinMode(4,OUTPUT); //LCD RS LINE PORTD RD6: board pin D4 pinMode(5,OUTPUT); //LCD ENA LINE PORTD RD7: board pin D5 pinMode(6,INPUT); //Encoder channel A PORTD RD8; board pin CON4-D6 -CLOCK pinMode(1,INPUT); //Encoder channel B PORTD RD3; board pin CON4-D1 - UP/DNpinMode(3,INPUT); // left button (band) PORTD RD5: board pin CON4-D3pinMode(7,INPUT); //right button (step) PORTD RD11: board pin CON4-D7pinMode(12,INPUT); // detects TX ONpinMode(9, OUTPUT); // switches rx preamp relay (relay always inactive while tx)pinMode(11,OUTPUT); // routes TX to low power output socket and blanks PAI2C_init(I2C1, I2C_MASTER_MODE, I2C_SLEW_OFF); //I2C1: board pins UEXT 5(SCL) and 6(SDA) IEC0bits.INT1IE=0; // disable this interrupt INTCONbits.INT1EP=0; // edge polarity for this interrupt ( falling edge ) IPC1bits.INT1IP=1; // interrupt priority IPC1bits.INT1IS=1; // interrupt sub priority IEC0bits.INT1IE=1; // enable this interrupt hsdiv_n1=0xe8; //initialise data for Si570 - start frequency = 1.9 MHz n1_rfreq=0xc2; band=12600000; rfreq=0x2ba8e382e; stepsize=100; svalue=0; tp=200; rd_pwr=21; // set up IF offsets - 2m and 4m will need tweaking according to actual xvrtr LO frequency offset_lower=10698500; offset_upper=10701500; offset_4m=42000000; // 4M offset includes nominal 42 MHz transverter LO offset_2m= 116002222; // 2M offset includes nominal 116 MHz transverter LO lcdinit();// Initialise LCDdisplay_string(" SSB XCVR Firmware v3.10 ");// Startup message delay(3000); clear(); // Sprintf(buff,"%10x",rfreq); debug purposes // display_string(buff); // delay(5000); set_freq(); //load Si570 registers 7-12 with startup frequencydisplay_frequency(band-offset_lower); // display startup frequency minus offset line2();// LCD line 2display_string("Step = 100Hz ");// Show tuning stephome();// Move display to HOME position} //Pinguino main loopvoid loop(){ if (digitalRead(TXON)==LOW) { tpwr(0); set_step(); // poll right button for step change change_band(); // poll left button for band change display_s();} // display S meter else {tpwr(tp); // set tx power according to tp set when changing band (see change_band) display_p();} // display power }/* switch between bands stepwise on left button.Switch input bandpass filters using PORTB. Note we need to shift PORTB data one bit to the left since we are using RB1-RB4 rather than RB0-RB3.Since there 8 input filters (1.9-28.5 MHz excluding 10 MHz), we only need RB1-RB3 to switch using DM74145, so use RB4 to switch sideband filters. Default is LSB, so adding decimal 8 to PORTB will switch to USB. We do this at 14MHz and above */void change_band(void){IEC0bits.INT1IE=0; // disable interrupt when changing band if(digitalRead(LEFT_BUTT)==LOW){delay(50);}if(digitalRead(LEFT_BUTT)==LOW){band_step++;if (band_step > 10) {band_step=0;} switch(band_step){case 1 : hsdiv_n1=0xe7; n1_rfreq=0xc2; rfreq=0x2ca92621a; band=14500000; tp=200; PORTB=1<<1; break; // 3.8MHzcase 2 : hsdiv_n1=0xe6; n1_rfreq=0x42; rfreq=0x2c8b94993; band=17800000; tp=180; PORTB=2<<1; break; // 7.1 MHzcase 3 : hsdiv_n1=0xe4; n1_rfreq=0x42; rfreq=0x2b23d49cc; band=24900000; tp=380; PORTB=3+8<<1; digitalWrite(RXPRE,TRUE); break; // 14.2 MHz switch on rx preampcase 4 : hsdiv_n1=0xe3; n1_rfreq=0xc2; rfreq=0x2c5a4cb5b; band=28800000; tp=350; PORTB=4+8<<1; digitalWrite(RXPRE,TRUE); break; // 18.1 MHzcase 5 : hsdiv_n1=0xe3; n1_rfreq=0x42; rfreq=0x2b1ee7060; band=32000000; tp=550; PORTB=5+8<<1; digitalWrite(RXPRE,TRUE); break; // 21.3 MHzcase 6 : hsdiv_n1=0xa3; n1_rfreq=0xc2; rfreq=0x2cdb53665; band=35600000; tp=750; PORTB=6+8<<1; digitalWrite(RXPRE,TRUE); break; // 24.9 MHzcase 7 : hsdiv_n1=0xe2; n1_rfreq=0xc2; rfreq=0x2d46d8f98; band=39200000; tp=600; PORTB=7+8<<1; digitalWrite(RXPRE,TRUE); break; // 28.5 MHzcase 8 : hsdiv_n1=0xe2; n1_rfreq=0xc2; rfreq=0x2d46d8f98; band=39200000; tp=1024; PORTB=7+8<<1; digitalWrite(TXLP,TRUE); digitalWrite(RXPRE,TRUE); fourm=TRUE; break; // 70 MHz via xvrtr. case 9 : hsdiv_n1=0xe2; n1_rfreq=0xc2; rfreq=0x2d46d8f98; band=39200000; tp=1024; PORTB=7+8<<1; digitalWrite(TXLP,TRUE); fourm=FALSE; digitalWrite(RXPRE,TRUE); twom=TRUE; break; // 144 MHz via xvrtr case 10 : hsdiv_n1=0xe8; n1_rfreq=0xc2; rfreq=0x2ba8e382e; band=12600000; tp=200; PORTB=0<<1; digitalWrite(TXLP,FALSE); digitalWrite(RXPRE,FALSE); twom=FALSE; break; // 1.9 MHz}set_freq(); // load Si570 registers 7-12 with the above band informationhome(); if (band < 20000000) {display_frequency(band-offset_lower);} else if (fourm) {display_frequency(band-offset_upper+offset_4m);} else if (twom) {display_frequency(band-offset_upper+offset_2m);} else {display_frequency(band-offset_upper);} while(digitalRead(LEFT_BUTT)==LOW){}delay(100);}IEC0bits.INT1IE=1; // enable this interrupt} void set_freq(void) // load Si570 registers 7-12 for a large change in frequency - > +/- 3500 ppm{int i;reg[0]=hsdiv_n1; // read reg7 value directly from button reg[1]=n1_rfreq; // read reg8 value directly from buttonrfreq_s=(unsigned long) rfreq;temp_freq=rfreq_s;reg[2]=rfreq_s >> 24; // get reg9 value - msb of rfreq_stemp_freq = temp_freq<<8;reg[3]=temp_freq>>24; // get reg10 - next byte of rfreq_stemp_freq=rfreq_s;temp_freq=temp_freq<<16;reg[4]=temp_freq>>24; // get reg11 - next byte of rfreq_stemp_freq=rfreq_s;temp_freq=temp_freq<<24;reg[5]=temp_freq>>24; // get reg12 - next byte of rfreq_sreg137 = i2c_read(0x55,137); // read register 137i2c_write(0x55,137,reg137 | 0x10); //write new value of register 137 with bit 4 setfor (i=7; i <=12; i++){i2c_write(0x55, i, reg[i-7]); // write registers 7-12}reg137 = i2c_read(0x55,137); // read register 137i2c_write(0x55,137,reg137 & 0xEF); //write register 137 with bit 4=0i2c_write(0x55,135,0x40); //set NewFreq bit to move to new frequency } void quickset_freq(void) // load Si570 registers 9-12 for small frequency change < +/- 3500 ppm {int i;rfreq_s = (unsigned long) rfreq;// get least significant 32 bits of rfreqtemp_freq=rfreq_s;reg[2]=rfreq_s >> 24; // get reg9 value - msb of rfreq_s temp_freq =temp_freq<<8;reg[3]=temp_freq>>24; // get reg10 - next byte of rfreq_s temp_freq=rfreq_s;temp_freq=temp_freq<<16;reg[4]=temp_freq>>24; // get reg11 - next byte of rfreq_stemp_freq=rfreq_s;temp_freq=temp_freq<<24;reg[5]=temp_freq>>24; // get reg12 - next byte of rfreq_sfor (i=9; i <=12; i++){i2c_write(0x55, i, reg[i-7]);}}void read_encoder(void) // called by ISR in response to change in encoder channel A{ if(digitalRead(ENC_B)==HIGH) {//low to high on encoder channel Brfreq = rfreq*(band+stepsize);// Calculate new rfreq rfreq = rfreq/band;band = band+stepsize;} else {rfreq = rfreq*(band-stepsize);// Calculate new rfreq rfreq = rfreq/band;band = band-stepsize;} }void set_step(void){IEC0bits.INT1IE=0; // disable this interrupt while setting the tuning step if(digitalRead(RIGHT_BUTT)==LOW){delay(50);}if(digitalRead(RIGHT_BUTT)==LOW){step_count++;if (step_count > 4) {step_count=0;}switch(step_count){case 1 : stepsize=4; line2(); display_string("Step = 4Hz "); break;case 2 : stepsize=10; line2(); display_string("Step = 10Hz "); break;case 3 : stepsize=100; line2(); display_string("Step = 100Hz "); break;case 4 : stepsize=0; line2(); display_string("Dial lock "); break;}while(digitalRead(RIGHT_BUTT)==LOW){}delay(500);} IEC0bits.INT1IE=0; // enable interrupt} void i2c_write (u8 slave_address, u8 reg_address, u8 data) {I2C_start(I2C1);I2C_writechar(I2C1,slave_address<<1);I2C_writechar(I2C1,reg_address);I2C_writechar(I2C1, data);I2C_stop(I2C1);} u8 i2c_read(u8 slave_address, u8 reg_address) {u8 data;I2C_start(I2C1);I2C_writechar(I2C1,slave_address<<1);I2C_writechar(I2C1,reg_address);I2C_start(I2C1);I2C_writechar(I2C1,slave_address<<1|0x01);data=I2C_readchar(I2C1,0x01);I2C_stop(I2C1);return data;}// Initialise LCD module in 8 bit mode void lcdinit(void){delay(100);// 100ms delay after power-upcommand(0x30);// Function setdelay(1);// Delay more than 39uscommand(0x30);// Function setdelay(1);// Delay more than 39uscommand(0x30);// Function setdelay(1);// Delay more than 39uscommand(0x3C);// 1/16 duty cycle. 5x11 fontdelay(1);// Delay more than 39uscommand(0x0C);// Disp on, Blink off, Cursor offdelay(1);// Delay more than 39uscommand(0x01);// Clear/Homedelay(2);// Delay more than 1.53mscommand(0x06);// Increment rightdelay(2);// Delay more than 1.53ms}/* Move to start of line 2 */void line2(void){command(0xC0);} /* Clear display */void clear(void){command(0x01);}/* Move display cursor to home position */void home(void){command(0x02);}/* Send command to LCD display */voidcommand(unsigned char lcd_comm){digitalWrite(RS,LOW);//RS command modePORTE=lcd_comm;//Command on PORTEdigitalWrite(ENA,HIGH);//Enable line highdelayMicroseconds(1);// Delay digitalWrite(ENA,LOW);//Enable line lowdelayMicroseconds(30);// Delay digitalWrite(RS,HIGH);//RS display data}/* Send single character to LCD display */voiddisplay(unsigned char lcd_data){digitalWrite(RS,HIGH);//RS data (not command)PORTE=lcd_data;//Character on PORTEdigitalWrite(ENA,HIGH);//Enable line highdelayMicroseconds(1);// Delay digitalWrite(ENA,LOW);//Enable line lowdelayMicroseconds(30);// Delay }/* Send text string to LCD display */void display_string(char *lcd_message){for(x=0;x<strlen(lcd_message);x++){ display(lcd_message[x]);// Display string characters one-by-one if(x==15){line2();}// If the message is more than 16 characters, use line 2.}}/* Show frequency on LCD display */void display_frequency(u32 band){home();temp = band/100000000;// Get the first digit for 100s of MHzif(band>99999999) {display((unsigned char)temp+0x30); // Show first digit when f>100MHz }else {display(' ');} temp = band%100000000; // Get the second digit for 10s of Mhz if(band>9999999) { display((unsigned char)(temp/10000000)+0x30); } else {display(' ');}temp=band%10000000;display((unsigned char)(temp/1000000)+0x30);display('.');// Decimal point after MHz digittemp=band%1000000;// Get fractional part of frequencydisplay((unsigned char) (temp/100000)+0x30);// Send 3rd digit to displaytemp=band%100000;display((unsigned char) (temp/10000)+0x30);// Send 4th digit...temp=band%10000;display((unsigned char) (temp/1000)+0x30);// Send 5th digit...display(',');// Comma after kHz digit temp=band%1000;display((unsigned char) (temp/100)+0x30);// Send 6th digit..temp=band%100;display((unsigned char) (temp/10)+0x30);// Send 7th digit...temp=band%10;display((unsigned char) temp+0x30);// Send 8th and last (1hZ) digitdisplay(' ');// Send " MHz" to display display('M');display('H');display('z'); display(' ');}/* Send signal strength to LCD display */void display_s(void){ line2(); svalue=analogRead(20); CDC.printf("%d\n\r",svalue); // log signal strength to USB if (svalue>750) {line2(); display_string("||||||||| S9+ "); } else if (svalue>722 && svalue<=749) {line2(); display_string("||||||||| S9 "); } else if (svalue>686 && svalue<=721) {line2(); display_string("||||||||| S8 "); } else if (svalue>637 && svalue<=685) {line2(); display_string("||||||| S7 "); } else if (svalue>545 && svalue<=636) {line2(); display_string("|||||| S6 "); } else if (svalue>511 && svalue<=544) {line2(); display_string("||||| S5 "); } else if (svalue>493 && svalue<=510) {line2(); display_string("|||| S4 "); } else if (svalue>361 && svalue<=492) {line2(); display_string("||| S3 "); } else if (svalue>201 && svalue<=360) {line2(); display_string("|| S2 "); } else if (svalue>30 && svalue<=200) {line2(); display_string("| S1 "); } else if (svalue<30) {line2(); display_string(" S0 "); }}/* Send power to LCD display */void display_p (void){if(digitalRead(RIGHT_BUTT)==LOW){delay(50);}if(digitalRead(RIGHT_BUTT)==LOW){pwr_step++;if (pwr_step > 2) {pwr_step=0;}switch(pwr_step){case 1 : rd_pwr=20; line2(); display_string(" R"); break;case 2 : rd_pwr=21; line2(); display_string(" F"); break;}while(digitalRead(RIGHT_BUTT)==LOW){}delay(50);} svalue=analogRead(rd_pwr); if (svalue>310) {line2(); display_string("||||||||||10W "); } else if (svalue>294 && svalue<=309) {line2(); display_string("||||||||| 9W "); } else if (svalue>277 && svalue<=293) {line2(); display_string("||||||||| 8W "); } else if (svalue>260 && svalue<=276) {line2(); display_string("||||||| 7W "); } else if (svalue>240 && svalue<=259) {line2(); display_string("|||||| 6W "); } else if (svalue>219 && svalue<=239) {line2(); display_string("||||| 5W "); } else if (svalue>196 && svalue<=218) {line2(); display_string("|||| 4W "); } else if (svalue>170 && svalue<=195) {line2(); display_string("||| 3W "); } else if (svalue>139 && svalue<=169) {line2(); display_string("|| 2W "); } else if (svalue>98 && svalue<=138){line2(); display_string("| 1W "); } else if (svalue<50) {line2(); display_string(" 0W "); }} void tpwr(u16 pwr) { analogWrite(0,1024-pwr); } void __attribute__ ((nomips16)) Int1Interrupt(void) // interrupt treatment{if (IFS0bits.INT1IF) // interrupt flag for INT1{ read_encoder();// on external interrupt 1 read the optical encoder quickset_freq(); if (band < 20000000) {display_frequency(band-offset_lower);} else if (fourm) {display_frequency(band-offset_upper+offset_4m);} else if (twom) {display_frequency(band-offset_upper+offset_2m);} else {display_frequency(band-offset_upper);} IFS0bits.INT1IF=0; // clear the interrupt flag}} ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download