//**********************************************************************// program pro rizeni TRXu//**********************************************************************// (c) OK1XGL 2005// verze 1.0.0 - uvodni verze// verze 1.0.1 - prechod 16F877 a usazeni sibnalu na porty// verze 1.0.2 = odladeni zakladnich funkci - muzeme delat tistak// verze 1.0.3 - definitivni usazeni signalu - hotovy DPS// verze 1.0.4 - prvni pouzitelna verze// verze 1.1.0 - SIGNAL ATN1 PRESUNUT NA RE0 A SIGNAL ATN2 PRESUNUT NA RC0 !!!!!// verze 1.2.0 - doprobramovan jednopakovy klic// verze 1.3.0 - elbug zmenen na dvoupakovy a cely presunut do preruseni// verze 1.4.0 - po zapnuti se RX naladi na QRP kmitocet na danem pasmu// - PSV se povazuje za platne jen kdyz je skutecne zaklicovano// verze 1.5.0 - upraven zpusob cteni dat z AD prevodniku// - pwm rozsirena na 157 kroku// - doplneno ALC pro vykon a nastaveni vykonu v 0.5W jednotkach// verze 1.6.0 - provedena kalibrace S-metru// Poznamky:// zobrazeni kmitoctu na LCD trva 30ms !!!// pri rychlosti klicovani 200zn/s je sirka impulzu (tecka) cca 30ms// timer2 vyhrazen na generovani tonu a ma nastaven kmitocet 800Hz, ton se generuje PWM, rizeni vykonu tez PWM 800Hz je baze// timer 1 vyhrazen pro elbug//DODELAT: - pri BK provozu je treba, aby se pri prepnuti na prjem mezi elementy znacky nezobrazoval S-metr, protoze// se to tak rychle nestiha zobrazovat a je lepsi,aby se zobrazovalo stale psv a vykon. Nyni je toho dosazeno tak,// ze pokud je aktivni elbug, tak se zobrazeni nedela ovsem toto reseni nebude fungovat pri externim elbugu// spravne reseni je timerem, ktery bude vykryvat cas mezi znackami// - projit kod a nektere veci ucesat#include "vfo.h"#include <lcd.c>//#define ADC_LCD // misto obvyklych udaju zobrazuje hodnoty AD prevodniku//#define NO_FILTER_CONTROL // vyrazuje prubeznou kontrolu pritomnosti filtru pro prislusne pasmo/////////// FUNKCE PRO ZOBRAZOVANI NA LCD /////////// podpora zobrazeni RIT// POZOR: pred pouzitim je nutno vynulovat promennou lcd_pos !!!void rit_lcd_putc(int8 c){lcd_pos++;if(lcd_pos==2) lcd_putc('.'); // prida tecku za KHZlcd_putc(c);} // rit_lcd_putc// podpora zobrazeni kmitoctu VFO// POZOR: pred pouzitim je nutno vynulovat promennou lcd_pos !!!void vfo_lcd_putc(int8 c){lcd_pos++;// za MHz dopln pismenko VFOif(lcd_pos==3)if(vfo_index)if(bit_test(_SPLIT)) lcd_putc('\21'); // vyplnene belse lcd_putc('b');else if(bit_test(_SPLIT)) lcd_putc('\22'); // vyplnene aelse lcd_putc('a');// za KHz dopln teckuif(lcd_pos==6)if(step_index) lcd_putc(':'); // hrube ladenielse lcd_putc('.'); // jemne ladenilcd_putc(c);} //vfo_lcd_putc// podpora zobrazeni vykonu a psv// POZOR: pred pouzitim je nutno vynulovat promennou lcd_pos !!!void pwr_lcd_putc(int8 c){lcd_pos++;if(lcd_pos==2) lcd_putc('.');lcd_putc(c);} // pwr_lcd_putc// podpora zobrazeni napeti baterie// POZOR: pred pouzitim je nutno vynulovat promennou lcd_pos !!!void batt_lcd_putc(int8 c){lcd_pos++;if(lcd_pos==3) lcd_putc('.');lcd_putc(c);} // batt_lcd_putc/////////// FUNKCE PRO PRACI S DDS /////////// odesle 16 bitovy zaznam do DDS//void dds_send(int16 record){int8 i;#use fast_io(A)#use fast_io(B)#use fast_io(C)#use fast_io(D)output_low(DDS_FSYNC); // zacatek komunikace s DDSi=16;do{if(bit_test(record,15)) output_high(DDS_SDATA); // vystav datovy bit, zaciname MSBelse output_low(DDS_SDATA);output_low(DDS_SCK); // hodinovy impulzoutput_high(DDS_SCK);record=record<<1; // na dalsi bit} while(--i);output_high(DDS_FSYNC); // konec komunikace s DDS#use standard_io(A)#use standard_io(B)#use standard_io(C)#use standard_io(D)} // dds_send// naplni registr0 pro kmitocet v DDS (28 bitu)//void dds_freq0(int32 freq){int16 record;// posli ridici slovodds_send(CTRL_FREQ0);// zapis pozadovane frekvence// zapis LSBrecord=(int16)freq;bit_set(record,14); // zapis do frekvencniho registru 0bit_clear(record,15);dds_send(record);// zapis MSBrecord=(int16)((freq<<2)>>16); // divny zapis, ale >> 14 dava hrozny vysledekbit_set(record,14); // zapis do frekvencniho registru 0bit_clear(record,15);dds_send(record);} // dds_freq0/////////// FUNKCE PRO RIZENI PRIPOSLECHU /////////// vypne generovani tonu priposlechu//#inlinevoid tone_off(){int8 a;a=input(TONE);} // tone_off()// zapne generovani tonu priposlechu//#inlinevoid tone_on(){output_low(TONE);} // tone_on/////////////////////////////////// Prerusovaci rutiny/////////////////////////////////// rezie preruseni je cca 30+30 cyklu// preruseni od zmeny polohy kroutitka#int_EXTvoid Encoder_handler(){#use fast_io(a)#use fast_io(b)#use fast_io(c)#use fast_io(d)int1 dir;dir=input(ENCODER_DIR); // zapamatuj si smer kroucenibit_set(_ENC_CHNG); // oznam zmenu polohy kroutitkaif(dir) enc_delta++; // pridejelse enc_delta--; // uber#use standard_io(a)#use standard_io(b)#use standard_io(c)#use standard_io(d)} // Encoder_handler// periodicke tiky, granularita TICK_TIME// citace/ casovace se granularitou TICK_TIME#INT_TIMER0void Tick_handler(){#use fast_io(a)#use fast_io(b)#use fast_io(c)#use fast_io(d)set_timer0(TICK_TIME); // znovu natahni timer// mereni napeti z prevodnikuif(bit_test(_ADC_START)){read_adc(ADC_START_ONLY); // spust prevodbit_clear(_ADC_START); // priste budeme cist vysledek} else{adc_val=read_adc(ADC_READ_ONLY); // vyzvedni vysledekif(bit_test(_KEYING)) // hodnoty vykonu aktualizuj jen pokud je zaklicovano{if(adc_ch==1) fwd_val=adc_val;if(adc_ch==0) rev_val=adc_val;}if(adc_ch==2) batt_val=adc_val;else if(adc_ch==3) smtr_val=adc_val;else if(adc_ch==4) bnd_val=adc_val;if(adc_ch>=4) adc_ch=0; // mame 5 kanaluelse adc_ch++;set_adc_channel(adc_ch); // priste nasledujici kanalbit_set(_ADC_START); // priste budeme spoustet prevod}// klicovaniif(bit_test(_TXDELAY)) // jen pokud tx_delay vyprsel{if(!bit_test(_ELBUG_ON))keyer=(~input_b()) & 0b10000000; // pokud neni zapnut elbug, zavzorkuj stav kliceif((keyer!=0 && !bit_test(_ELBUG_ON)) || // pri vypnutem elbugu rizeno stavem pak(bit_test(_ELBUG_OUT) && bit_test(_ELBUG_ON))) // pri zapnutem elbugu rizeno stavem _ELBUG_ON{// zaklicujoutput_high(KEYING);tone_on();bit_clear(_RUN_VOX);bit_set(_KEYING);adc_ch=0; // zacneme merit dopredny vykonset_adc_channel(adc_ch);bit_set(_ADC_START); // priste spustime prevod ADC} else{// prestan klicovatoutput_low(KEYING);vox_timer=vox_time; // natahni vox_timerbit_set(_RUN_VOX);tone_off();bit_clear(_KEYING);}bit_clear(_TXDELAY);}// periodicky timer na aktualizaci kde cehoif(update_timer==0xFF) update_timer=UPDATE_TIME;else update_timer--;// vox timerif(bit_test(_RUN_VOX))if(vox_timer!=0) vox_timer--;else{// vox vyprselbit_clear(_RUN_VOX);output_low(RXTX); // prepni zpet na prijembit_clear(_TRANSMIT);bit_set(_DDS_UPDATE);}// timer pro zjisteni dlouheho stisku tlacitekif(key_timer!=0) key_timer--;// periodicke cteni tlacitek#use fast_io(C)keys_work=(~input_c()) & KEY_MASK; // precti stav tlacitek#use standard_io(C)if(keys_work!=keys_old) keys_old=keys_work; // neshoda zapamatuj si novy stavelse{// shodaif(keys_work!=0){// tlacitko je STISKNUTOif(keys==0){// akceptujeme jen pokud bylo zpracovano vse predchozikeys=keys_work; // zapamatuj si nove tlacitkokey_timer=KEY_LONG; // natahni casovac pro zjisteni dlouheho stisku} else{// neco je jeste ke zpracovaniif(key_timer==0 && !bit_test(_KEYS_RELEASE)){// jde o dlouhy stisk tlacitkabit_set(_KEYS_LONG);bit_set(_KEYS_VALID);}}} else{// tlacitko je UVOLNENOif(key_timer!=0){// jde o kratky stisk tlacitkabit_set(_KEYS_VALID);key_timer=0;} else if(bit_test(_KEYS_RELEASE)){keys_flags=0; // jde o klidovy stav - tlacitka zpracovanakeys=0;}}}#use standard_io(a)#use standard_io(b)#use standard_io(c)#use standard_io(d)} // Tick_handler// periodicke tiky kazdych 5ms// vyuzito pro rizeli LCD_LED//#INT_TIMER2void led_handler(){#use fast_io(a)#use fast_io(b)#use fast_io(c)#use fast_io(d)flash_timer++;// rizeni LED// pri prijmu bez attenuatoru sviti zelena// pri prijmu s attenuatorem sviti zluta// pri vysilani sviti cervena// pri vybite baterii pri prijmu led blikaif(bit_test(_TRANSMIT)){// vysilani - rozsvid cervenou LEDif(bit_test(_LED_UPDATE)) output_high(LCD_LED1);else output_low(LCD_LED1);output_low(LCD_LED2);} else{if(bit_test(_BATT_LOW) && bit_test(flash_timer,7)){// zhasni ledoutput_low(LCD_LED1);output_low(LCD_LED2);} else{// prijem - rozsvid zelenou nebo zlutou ledif(bit_test(_LED_UPDATE)){output_high(LCD_LED2);output_low(LCD_LED1);} else{output_low(LCD_LED2);if(bit_test(_ATTN)) output_high(LCD_LED1);else output_low(LCD_LED1);}}}if(bit_test(_LED_UPDATE)) bit_clear(_LED_UPDATE);else bit_set(_LED_UPDATE);#use standard_io(a)#use standard_io(b)#use standard_io(c)#use standard_io(d)} // led_handler// cteni pak, klice#INT_RBvoid paddle_handler(){#use fast_io(a)#use fast_io(b)#use fast_io(c)#use fast_io(d)keyerb=(~input_b()); // precti stav pakif(bit_test(_ELBUG_ON)) keyerb=keyerb & 0b11000000; // platne jsou obe pakyelse keyerb=keyerb & 0b10000000; // platna je paka tecekif(!bit_test(_TXDELAY)) // reagujeme jen kdyz nebezi TXDELAY{if(!bit_test(_ELBUG_ON)){// RUCNI KLICOVANIset_timer0(TICK_TIME); // txdelay je dano jednim zakladnim tikem, natahni tik_T0IF=0;bit_set(_TXDELAY); // spustime TXDELAY} else{// ELBUG// nastav priznaky pakif(bit_test(_ELBUG_REV)){if(bit_test(keyerb,6)) bit_set(_ELBUG_DOT);if(bit_test(keyerb,7)) bit_set(_ELBUG_DASH);} else{if(bit_test(keyerb,7)) bit_set(_ELBUG_DOT);if(bit_test(keyerb,6)) bit_set(_ELBUG_DASH);}if(!bit_test(_ELBUG_BSY)){// spusteni elbugusetup_timer_1(T1_INTERNAL | T1_DIV_BY_8); // spust casovac_TMR1IF=1;}}if(!bit_test(_TRANSMIT) && keyerb!=0) // pri stisku pak prejdeme na vysilani pokud tomu jiz tak neni{bit_set(_TRANSMIT); // priznak stavu vysilanioutput_high(RXTX); // prepni TRX na vysilanibit_set(_DDS_UPDATE); // nastav vysilaci kmitocet}}#use standard_io(a)#use standard_io(b)#use standard_io(c)#use standard_io(d)} // paddle_handler// elbug//#int_timer1void elbug_handler(){#use fast_io(a)#use fast_io(b)#use fast_io(c)#use fast_io(d)if(bit_test(_ELBUG_SP)){// odvysilali jsem tecku nebo carku - musime dovysilat mezerubit_clear(_ELBUG_SP); // priste budeme vysilat podle stavu pakbit_clear(_ELBUG_OUT);set_timer1(elbug_dot_sp); // natahni casovac na mezeruset_timer0(TICK_TIME); // txdelay je dano jednim zakladnim tikem, natahni tik_T0IF=0;bit_set(_TXDELAY); // spustime TXDELAYreturn;}if(bit_test(_ELBUG_BSY)){// odvysilali jsme posloupnost tecka-mezera nebo carka-mezera// nuluj priznak prave dovysilaneho elementuif(bit_test(_ELBUG_LAST)) bit_clear(_ELBUG_DASH);else bit_clear(_ELBUG_DOT);// dale se rozhodujeme podle stavu pakkeyer=(~input_b()) & 0b11000000; // precti stav pak// nastav priznak pak podle stisknute pakyif(bit_test(_ELBUG_REV)){if(bit_test(keyer,6)) bit_set(_ELBUG_DOT);if(bit_test(keyer,7)) bit_set(_ELBUG_DASH);} else{if(bit_test(keyer,7)) bit_set(_ELBUG_DOT);if(bit_test(keyer,6)) bit_set(_ELBUG_DASH);}if(bit_test(_ELBUG_REAL) && keyer==0) // nestisknuto nic{// pri realnem klicovani po uvolneni pak se uz dal nic nevysilabit_clear(_ELBUG_DOT);bit_clear(_ELBUG_DASH);}}// prepnuti na vysilani pokud tomu uz tak neniif(!bit_test(_TRANSMIT) &&(bit_test(_ELBUG_DOT) || bit_test(_ELBUG_DASH))){bit_set(_TRANSMIT); // priznak stavu vysilanioutput_high(RXTX); // prepni TRX na vysilanibit_set(_DDS_UPDATE); // nastav vysilaci kmitocet}// nastav hodnotu casovace podle stisknute pakyif(bit_test(_ELBUG_DOT)){if(bit_test(_ELBUG_DASH)){// stisknuty obe paky - vysilej opak priznaku LASTif(bit_test(_ELBUG_LAST)){bit_clear(_ELBUG_LAST);set_timer1(elbug_dot_sp); // natahni casovac na tecku} else{bit_set(_ELBUG_LAST);set_timer1(elbug_dash); // natahni casovac na carku}} else{bit_clear(_ELBUG_LAST);set_timer1(elbug_dot_sp); // natahni casovac na tecku}} else if(bit_test(_ELBUG_DASH)){bit_set(_ELBUG_LAST);set_timer1(elbug_dash); // natahni casovac na carku} else{// NENI CO VYSILAT -KONCIMEbit_clear(_ELBUG_BSY);setup_timer_1(T1_DISABLED); // zastav casovacreturn;}bit_set(_ELBUG_BSY); // elbug bezibit_set(_ELBUG_SP); // priste musime vysilat mezerubit_set(_ELBUG_OUT);set_timer0(TICK_TIME); // txdelay je dano jednim zakladnim tikem, natahni tik_T0IF=0;bit_set(_TXDELAY); // spustime TXDELAY#use standard_io(a)#use standard_io(b)#use standard_io(c)#use standard_io(d)} // elbug_handler/////////// FUNKCE PRO OVLADANI UTLUMU /////////// natavi utlum//void Attn_0dB(){output_low(ATN1);output_low(ATN2);output_high(ATNC);delay_ms(RELE_PULSE);input(ATNC); // prepni ANTC zpet do tretiho stavu (vstup)delay_ms(RELE_PULSE);input(ATN1);input(ATN2);}// natavi utlum//void Attn_6dB(){output_high(ATN1);output_low(ATNC);delay_ms(RELE_PULSE);input(ATNC); // prepni ANTC zpet do tretiho stavu (vstup)output_low(ATN2);output_high(ATNC);delay_ms(RELE_PULSE);input(ATNC); // prepni ANTC zpet do tretiho stavu (vstup)delay_ms(RELE_PULSE);input(ATN1);input(ATN2);}// natavi utlum//void Attn_12dB(){output_low(ATN1);output_high(ATNC);delay_ms(RELE_PULSE);input(ATNC); // prepni ANTC zpet do tretiho stavu (vstup)output_high(ATN2);output_low(ATNC);delay_ms(RELE_PULSE);input(ATNC); // prepni ANTC zpet do tretiho stavu (vstup)delay_ms(RELE_PULSE);input(ATN1);input(ATN2);}// natavi utlum//void Attn_18dB(){output_high(ATN1);output_high(ATN2);output_low(ATNC);delay_ms(RELE_PULSE);input(ATNC); // prepni ANTC zpet do tretiho stavu (vstup)delay_ms(RELE_PULSE);input(ATN1);input(ATN2);}/*// precte z prevodnihu hornich 8 bitu//int8 adc(){return(read_adc()>>8) ;} // adc*//////////// FUNKCE PRO PRACI S EEPROM /////////// aktualizuje kontrolni soucet//void update_eeprom(){int8 i;int8 crc;crc=0;for(i=0;i<EE_ADR_CRC;i++) crc+=read_eeprom(i);crc=0-crc;write_eeprom(EE_ADR_CRC,crc);} // update_eeprom// zkontroluje obsah pameti eeprom a pokud je poskozen, nAstavi defaultni parametry//void check_eeprom(){int8 i;int8 crc;crc=0;for(i=0;i<=EE_ADR_CRC;i++) crc=crc+read_eeprom(i);if(crc!=0){i=EE_ADR_POWER;while(i<BAND_NUM) write_eeprom(i++,PAR_LIMIT[PAR_POWER][0]); // minimalni vykon na vsech pasmechwrite_eeprom(EE_ADR_KEYER,20); // nastaveno 20 WPMwrite_eeprom(EE_ADR_VOX,6); // vox 300mswrite_eeprom(EE_ADR_BATT,0); // konstantni hodntota,dale se nemeniwrite_eeprom(EE_ADR_KEYER_REV,0); // nereverzuj pakywrite_eeprom(EE_ADR_KEYER_MODE,0); // doplnkove klicovaniwrite_eeprom(EE_ADR_ATTN,PAR_LIMIT[PAR_VOX][0]); // utlum vypnutupdate_eeprom(); // aktualizuj kontorlni soucet}} // check_eeprom/////////////////////////////////////// VYKONNE FUNKCE HLAVNI SMYCKY/////////////////////////////////////// zpracovani zmeny polohy kroutitka// trva max 600cyklu (600us)//// CHELO BY TO UCESAT POMOCI KONSTRUKCE IF - RETURN#inlinevoid enc_chng(){int32 freq_dds;signed int32 delta_freq;signed int16 delta_rit;if(bit_test(_MNU) || bit_test(_MNU2)){// NASTAVUJEME PARAMETRYif(enc_delta<ENC_HISTEREZE && enc_delta>-ENC_HISTEREZE) return; // zmeny pod minimum si nevsimejif(enc_delta>0){// nastala zmena +1if(bit_test(_MNU2)){if(par_index<PAR_NUM-3){par_index++; // zmena typu parametru pokud projde kontrola horni mezebit_set(_LCD2_UPDATE);}} else if(par[par_index]<PAR_LIMIT[par_index][1]) // zmena hodnoty parametru pokud projde kontrola horni meze{par[par_index]++;bit_set(_PAR_UPDATE); // pozadavek aktualizace parametru}} else{// nastala zmena -1if(bit_test(_MNU2)){if(par_index>0){par_index--; // zmena typu parametru pokud projde kontrola dolni mezebit_set(_LCD2_UPDATE);}} else if(par[par_index]>PAR_LIMIT[par_index][0]) // zmena hodnoty parametru pokud projde kontrola dolni meze{par[par_index]--;bit_set(_PAR_UPDATE); // pozadavek aktualizace parametru}}enc_delta=0; // zmena provedena} else{// LADIME KMITOCETif(bit_test(_RIT)){// ladime RITdelta_rit=enc_delta*RIT_STEP;enc_delta=0;if(freq_rit+delta_rit <=RIT_LIMIT[1] &&freq_rit+delta_rit >=RIT_LIMIT[0]) freq_rit+=delta_rit;} else{// ladime VFOdelta_freq=enc_delta*FREQ_STEP[step_index];enc_delta=0;freq_dds=freq_vfo[vfo_index]+delta_freq;if(freq_dds <=BAND_LIMIT[band_index][1] &&freq_dds >=BAND_LIMIT[band_index][0]) freq_vfo[vfo_index]+=delta_freq;}bit_set(_DDS_UPDATE); // pozadujeme zmenu kmitoctu v DDS}bit_clear(_ENC_CHNG); // zmena polohy kroutitka zpracovana} // enc_chng// aktualizuje parametry//#inlinevoid par_update(){// int16 power;bit_clear(_PAR_UPDATE);switch(par_index){case PAR_ATTN:bit_set(_ATTN); // pri utlumu bude misto zelene led svitit zlutaswitch(par[PAR_ATTN]){case 1: Attn_6dB();break;case 2: Attn_12dB();break;case 3: Attn_18dB();break;default:Attn_0dB();bit_clear(_ATTN); // zadny utlum, zpet zelena ledbreak;}break;case PAR_POWER:// set_pwm2_duty(par[PAR_POWER]);// power=par[PAR_POWER];// set_pwm2_duty(power<<1);//!!!!!power=par[PAR_POWER]*5; // vykon je v nasobcich 0.5Wbreak;case PAR_KEYER:if(par[PAR_KEYER]<=PAR_LIMIT[PAR_KEYER][0]) bit_clear(_ELBUG_ON); ///elbug_flags=0; // vypni elbugelse{// zapni elbug a nastav rychlostbit_set(_ELBUG_ON);elbug_dot_sp=~(ELBUG_CONST/par[PAR_KEYER]); // preved na hodnotu citace TMR1elbug_dot_sp++;elbug_dash=(elbug_dot_sp<<1)+elbug_dot_sp; // *3, ale rychleji}break;case PAR_VOX:vox_time=par[PAR_VOX];if(vox_time!=0) vox_time=vox_time*10; // cas je ve 50ms jednotkachelse vox_time=1; // minimalni vox je 5msbreak;case PAR_KEYER_REV:if(par[PAR_KEYER_REV]) bit_set(_ELBUG_REV); //else bit_clear(_ELBUG_REV);break;case PAR_KEYER_MODE:// if(par[PAR_KEYER_MODE]) bit_set(_ELBUG_REAL); //// else bit_clear(_ELBUG_REAL);break;}bit_set(_LCD2_UPDATE); // pozadujeme update 2. radku dispeje} // par_update()// aktualizuje kmitocet v dds// trva max. cca 2500cyklu (2.5ms)//#inlinevoid dds_update(){int32 freq_dds;signed int32 delta_freq;signed int32 freq_rit2;if(!bit_test(_TRANSMIT)){// PRIJEMif(band_index>=SUB_IF_INDEX) freq_dds=freq_vfo[vfo_index]-FREQ_IF; // pri prijmu na 14MHz se odecita kmitocet mezifrekvenceelse freq_dds=freq_vfo[vfo_index]+FREQ_IF; // pri prijmu pod 14MHz se pricita kmitocet mezifrekvenceif(bit_test(_RIT)){freq_rit2=freq_rit; // prevod na signed int32, chyba v C, neumi int32 + signed int16freq_dds=freq_dds+freq_rit2; // je-li zapnut RIT, udelej korekci kmitoctu}bit_set(_LCD1_UPDATE); // pozadujeme zmenit kmitocet na lcd} else{// VYSILANIif(bit_test(_SPLIT)) // pri split se pouzije opacne vfofreq_dds=freq_vfo[(~vfo_index)];else freq_dds=freq_vfo[vfo_index];}dds_freq0((int32)((float)freq_dds*CONVERT_CONST)); // odesli jej do DDS trva to cca 2050 cylklu (2.05ms)bit_clear(_DDS_UPDATE); // kmitocet v dds zmenen// bit_set(_LCD1_UPDATE); // pozadujeme zmenit kmitocet na lcd} // dds_update// aktualizuje zobrazeni na lcd - 1.radek// trva max. 3000cyklu (30ms) !!!!!!////#inline#separateint8 lcd1_update(){int16 rit_val;lcd_gotoxy(1,1);bit_clear(_LCD1_UPDATE);if(bit_test(_MNU2)) printf(lcd_putc,"PARAM: "); // zobraz ze vybirame typ parametruelse if(bit_test(_MNU)){// zobraz nazev parametruswitch(par_index){case PAR_ATTN: printf(lcd_putc,"ATTN: ");break;case PAR_POWER: printf(lcd_putc,"POWER: ");break;case PAR_KEYER: printf(lcd_putc,"KEYER: ");break;case PAR_VOX: printf(lcd_putc,"DELAY: ");break;case INF_BATT: printf(lcd_putc,"BATTERY:");break;case PAR_KEYER_MODE: printf(lcd_putc,"MODE: ");break;case PAR_KEYER_REV: printf(lcd_putc,"REVERSE:");break;}} else if(bit_test(_RIT)){// POZN: fce printf spatne zachazi se znaminkovimi cisly, proto je znamenko// zobrazeno samostatne a rit je preveden na neznamenkove cisloprintf(lcd_putc,"RIT:");if(freq_rit<0) lcd_putc('+');else lcd_putc('-');rit_val=abs(freq_rit);lcd_pos=0;printf(rit_lcd_putc,"%04LU",rit_val); // zobraz RIT na LCD} else{lcd_pos=0;printf(vfo_lcd_putc,"%8LD",freq_vfo[vfo_index]); // zobraz kmitocet na LCD}} // lcd1_update// pomocna funkce pro zobrazeni vykonu a psv na lcd//#separatevoid lcd_pwr_psv(){#ifdef ADC_LCDprintf(lcd_putc,"F%2X R%2X",pwr_val,psv_val);#else// vysilani - zobrazujeme vykon a psvif(pwr_val>99) printf(lcd_putc,">10");else{lcd_pos=0;printf(pwr_lcd_putc,"%02U",pwr_val);}printf(lcd_putc,"W ");if(psv_val>99) printf(lcd_putc,">10");else{lcd_pos=0;printf(pwr_lcd_putc,"%02U",psv_val);}#endif} // lcd_pwr_psv// aktualizuje zobrazeni na lcd - 2.radek// trva max 2000 cyklu (2ms)////#inline#separatevoid lcd2_update(){int8 i;int16 vox;int16 batt;bit_clear(_LCD2_UPDATE);lcd_gotoxy(1,2);if(bit_test(_MNU2)){// zobraz vybrany parametrswitch(par_index){case PAR_POWER: printf(lcd_putc,"POWER ");break;case PAR_VOX: printf(lcd_putc,"DELAY ");break;case INF_BATT: printf(lcd_putc,"BATTERY ");break;case PAR_KEYER_MODE: printf(lcd_putc,"MODE ");break;case PAR_KEYER_REV: printf(lcd_putc,"REVERSE ");break;}} else if(bit_test(_MNU)){// zobraz hodnotu parametruswitch(par_index){case PAR_ATTN: printf(lcd_putc,"-%2U dB ",par[PAR_ATTN]*6); // krok je po 6dBbreak;case PAR_POWER: if(!bit_test(_TRANSMIT)){lcd_pos=0;printf(pwr_lcd_putc,"%02UW PTT",power); // prijem - zobraz pozadovany vykon a vyzvu k vysilani} else lcd_pwr_psv(); // vysilani - zobraz vykon a psvbreak;case PAR_KEYER: if( par[PAR_KEYER]<=PAR_LIMIT[PAR_KEYER][0]) printf(lcd_putc,"OFF ");else printf(lcd_putc,"%2U ",par[PAR_KEYER]);break;case PAR_VOX:vox=par[PAR_VOX];vox=vox*50; // ve 50ms jednotkachprintf(lcd_putc,"%4LU ms ",vox);break;case INF_BATT:#ifdef ADC_LCDprintf(lcd_putc,"%3X V ",batt_val);#else// zobraz napeti baterie na desetiny voltubatt=batt_val;batt=(batt*10)/16;lcd_pos=0;printf(batt_lcd_putc,"%03UV ",(int8)batt);#endifbreak;case PAR_KEYER_MODE:if(par[PAR_KEYER_MODE]) printf(lcd_putc,"B ");else printf(lcd_putc,"A ");break;case PAR_KEYER_REV:if(par[PAR_KEYER_REV]) printf(lcd_putc,"YES ");else printf(lcd_putc,"NO ");break;}} else if(bit_test(_TRANSMIT)) lcd_pwr_psv(); // vysilani - zobraz vykon a psvelse if(!bit_test(_ELBUG_BSY)) // v mezerach mezi znackami elbugu S-metr nezobrazuj{// prijem - zobrazujeme S-metr#ifdef ADC_LCDprintf(lcd_putc,"SMTR:%2X ",smtr_val);#elseif(smtr_val<=S_METER[0]) lcd_putc('2');else lcd_putc(' ');if(smtr_val<=S_METER[1]) lcd_putc('3');else lcd_putc(' ');if(smtr_val<=S_METER[2]) lcd_putc('4');else lcd_putc(' ');if(smtr_val<=S_METER[3]) lcd_putc('5');else lcd_putc(' ');if(smtr_val<=S_METER[4]) lcd_putc('6');else lcd_putc(' ');if(smtr_val<=S_METER[5]) lcd_putc('7');else lcd_putc(' ');if(smtr_val<=S_METER[6]) lcd_putc('8');else lcd_putc(' ');if(smtr_val<=S_METER[8]) lcd_putc('\23');else if(smtr_val<=S_METER[7]) lcd_putc('9');else lcd_putc(' ');#endif}} // lcd2_update()// nastavi pasmo podle pripojeneho filtru////#inlinevoid set_band(){// int8 adc_band;set_adc_channel (BND_CH); // prepni ADC na vstup signalu BANDdelay_ms(20);// opakuj dokud neni pripojen vhodny filtrfor(;;){bnd_val=read_adc() & BAND_ADC_MASK;// prohlidni tabulku moznych filtruband_index=BAND_NUM;while(band_index--){if(bnd_val==BAND_ADC[band_index]) return; // platny filtr pritomen}printf(lcd_putc,"\rCONNECT\n");printf(lcd_putc," FILTER");delay_ms(500);}} // set_band// mereni analogovych vstupu//// doba trvani max 3000 cyklu (3ms)#separatevoid analog_inputs(){static int8 count;int16 k;int32 pom32,pom32_2; // pro vypocet dopredneho vykonuint16 pom16,pom16_2; // pro vypocet PSVsigned int8 delta;#ifndef NO_FILTER_CONTROL // vyrazuje prubeznou kontrolu pritomnosti filtru pro prislusne pasmoif((bnd_val & BAND_ADC_MASK)!=BAND_ADC[band_index]) reset_cpu(); // fittr byl odpojen#endif// mereni napeti baterieif(batt_val+5<=BATT_MIN) bit_set(_BATT_LOW); // baterie je vybita// vypocti aktualni vykon a psv a reguluj vykonif(bit_test(_TRANSMIT)){#ifdef ADC_LCD // vypina zpracovani - zobrazuje prime hodnoty z prevodnikupwr_val=fwd_val;psv_val=rev_val;#else// vypocti vykon na desetiny watupom32=fwd_val;pom32=pom32*pom32; // vykon je umerny kvadratu napeti// vynasobime *10 - vykon bude 100mW jednotkach// realizuje *10, je vyrazne casove kratsi ( o cca 500cyklu)pom32_2=pom32<<3;pom32_2=pom32_2+pom32;pom32_2=pom32_2+pom32;pwr_val=pom32_2/PWR_FWD_CONST; // vydelime kalibracni konstantou pro dopredny vykon// vypocti PSV na desetinuif(fwd_val>=0 && rev_val==0) psv_val=10; // psv je 1.0 pokud je odrazeny vykon nulovyelse{pom16=fwd_val;pom16=pom16<<4; // vynasobime *16 pro vetsi presnostk=pom16/rev_val; // pomer odpovidajici ciniteli odrazuif(k<=16) psv_val=250; // PSV se blizi nekonecnuelse if(k>337) psv_val=10; // psv je lepsi jak 1.1 tedy ho povazujeme za 1.0else{// toto realizuje vyraz (k+16)*10pom16=k+16;pom16_2=pom16<<3;pom16_2=pom16_2+pom16;pom16_2=pom16_2+pom16;// vypocet psvpsv_val=pom16_2/(k-16);}}// rizeni vykonu (ALC)if(psv_val>BAD_PSV) delta=PWR_LIM-pwr_val; // pri spatnem PSV omez vykonelse delta=power-pwr_val;if(delta<-PWR_HIST_HI && pwm_val>PWM_MIN){if(delta<-10) pwm_val=pwm_val-4;else pwm_val--;pom16=pwm_val;set_pwm2_duty(pom16<<1);} else if(delta>PWR_HIST_LO && pwm_val<PWM_MAX){if(delta>10) pwm_val=pwm_val+4;else pwm_val++;pom16=pwm_val;set_pwm2_duty(pom16<<1);}#endif}// zobrazeni na LCD delame mene castoif(count>4){bit_set(_LCD2_UPDATE);count=0;} else count++;}// analog_inputs/*void pwr_control(){int16 aaa;signed int8 delta;if(bit_test(_TRANSMIT)){delta=power-pwr_val;if(delta<-1 && pwm_val>27){if(delta<-10) pwm_val=pwm_val-4;elsepwm_val--;aaa=pwm_val;set_pwm2_duty(aaa<<1);} else if(delta>2 && pwm_val<157){if(delta>10) pwm_val=pwm_val+4;elsepwm_val++;aaa=pwm_val;set_pwm2_duty(aaa<<1);}}} // pwr_control*/////////////////////////////////////// HLAVNI FUNKCE //////////////////////////////////////void main(){int8 ee_adr;int8 a;int8 b;signed int8 c;// inicializace LCDlcd_init();// definice specialnich znakulcd_define_char(2,LCD_CHAR_a_FILL);lcd_define_char(1,LCD_CHAR_b_FILL);lcd_define_char(3,LCD_CHAR_9_FILL);// nastaveni smeru signalu a jejich klidovych stavuport_b_pullups(TRUE);output_high(DDS_FSYNC); // zapis_so DDS neaktivnioutput_low(DDS_SDATA); // data do 0output_high(DDS_SCK); // hodiny do neaktivniho stavuoutput_low(RXTX); // prepni na prijemoutput_low(KEYING); // neklicujoutput_low(LCD_LED2); // zhasni ledoutput_low(LCD_LED1); // zhasni ledinput(TONE); // vypni priposlechoutput_low(PWR_CTRL); // nulovy vykonoutput_low(ATN1);output_low(ATN2);output_low(ATNC);// inicializace DDSdds_send(CTRL_RESET); // pozadujeme resetdds_send(CLR_PHASE0);dds_send(CLR_PHASE1);// zakladni nastaveni ridicich promennych programuupdate_timer=UPDATE_TIME; // natahni periodicky timer pro LCDflags=0; // nuluj priznaky ridici programelbug_flags=0; // nuluj priznaky pro elbugkeys_flags=0;adc_flags=0;adc_ch=0;pwm_val=PWM_MIN;enc_delta=0; // zadna zmena od kroutitkakeys=0; // zadna tlacitka nejsou stisknutafreq_rit=0; // nuluj RIT// uvodni hlaseni programulcd_gotoxy(1,1);printf(lcd_putc,NAME);lcd_gotoxy(1,2);printf(lcd_putc,VERSION);delay_ms(1000);// nastaveni AD prevodnikusetup_adc(ADC_CLOCK_DIV_8);setup_adc_ports(AN0_AN1_AN2_AN3_AN4); // povoleny porty AN0-AN4set_band(); // nastav pasmo podle pripojeneho filtru nebo cekej na jeho pripojenicheck_eeprom(); // kontrola platnosti obsahu eeprom, pri poruse nastav defaultni parametry// obnoveni a nastaveni parametru programupar[PAR_POWER]=read_eeprom(EE_ADR_POWER+band_index); // vyzvedni nastaveny vykon pro dane pasmopower=par[PAR_POWER]*5;par[PAR_KEYER]=read_eeprom(EE_ADR_KEYER); // vyzvedni rychlost kliceif(par[PAR_KEYER]<=PAR_LIMIT[PAR_KEYER][0]) elbug_flags=0; // vypni elbugelse{// zapni elbug a nastav rychlostbit_set(_ELBUG_ON);elbug_dot_sp=~(ELBUG_CONST/par[PAR_KEYER]); // preved na hodnotu citace TMR1elbug_dot_sp++;elbug_dash=(elbug_dot_sp<<1)+elbug_dot_sp; // *3, ale rychleji}par[PAR_VOX]=read_eeprom(EE_ADR_VOX); // vyzvedni voxvox_time=par[PAR_VOX];if(vox_time!=0) vox_time=vox_time*20; // cas je ve 100ms jednotkachelse vox_time=2;par[PAR_KEYER_REV]=read_eeprom(EE_ADR_KEYER_REV); // vyzvedni chapani pakif(par[PAR_KEYER_REV]) bit_set(_ELBUG_REV); //else bit_clear(_ELBUG_REV);par[PAR_KEYER_REV]=read_eeprom(EE_ADR_KEYER_REV); // vyzvedni mod elbugu// if(par[PAR_KEYER_REV]) bit_set(_ELBUG_REAL); //// else bit_clear(_ELBUG_REAL);bit_clear(_ELBUG_REAL); // mod elbugu je zatim vzdy doplnkovypar[PAR_ATTN]=PAR_LIMIT[PAR_ATTN][0]; // attenuator vzdy vypnutAttn_0dB();freq_vfo[0]=START_FREQ[band_index]; // QRP volaci kmitocet BAND_LIMIT[band_index][0] ; // po zapnuti ma VFO nejmensi kmitocet pasmafreq_vfo[1]=START_FREQ[band_index]; // QRP volaci kmitocet BAND_LIMIT[band_index][0] ; // po zapnuti ma VFO nejmensi kmitocet pasmabit_set(_DDS_UPDATE); // pozadujeme nastavit kmitocet v ddsstep_index=0; // defaultne jemny krok ladenivfo_index=0; // defaultne vfoA// nastaveni zakladniho tikusetup_timer_0(RTCC_INTERNAL|RTCC_DIV_128);set_timer0(TICK_TIME);// nastaveni pro generovani priposlechu, rizeni LCD_LED a PWM pro rizeni vykonusetup_timer_2(T2_DIV_BY_16,TONE_SET,4); // zajisti pro PWM rozliseni 8.28 bitusetup_ccp1(CCP_PWM); // pro generovani tonuset_pwm1_duty((TONE_SET+1)/2); // strida cca 1:1tone_off(); // priposlech vypnutsetup_ccp2(CCP_PWM); // pro rizeni vykonuset_pwm2_duty((int16)27); //setup_timer_1(T1_DISABLED); // elbug je v klidu#use fast_io(b)keyer=(~input_b()) & 0b11000000; // precti stav pak#use standard_io(b)if(bit_test(keyer,6)) bit_clear(_ELBUG_ON); // pokud je ori zapnuti stisknuta paka carek, je pripojen rucni klic// povoleni prerusenienable_interrupts(INT_EXT); // preruseni od zmeny polohy kroutitkaenable_interrupts(INT_TIMER0); // zakadni tikenable_interrupts(INT_TIMER2); // preruseni pro rizeni vykonu, LED a generovani priposlechuenable_interrupts(INT_TIMER1); // preruseni pro elbugenable_interrupts(INT_RB); // preruseni od stavu pak kliceenable_interrupts(GLOBAL);//#define TEST#ifdef TESTbit_set(_TRANSMIT);//bit_set(_MNU);fwd_val=150;rev_val=10;smtr_val=150;bnd_val=0x20;a=50;b=5;// testovaci smycka pro zjistovani doby behu testovane funkcesetup_timer_1(T1_INTERNAL|RTCC_DIV_1);set_timer1(0);//Analog_inputs();c=b-a;setup_timer_1(T1_DISABLED);lcd_gotoxy(1,1);printf(lcd_putc,"T:%LU",get_timer1());lcd_gotoxy(1,2);printf(lcd_putc,"%D",c);for(;;);#else// HLAVNI SMYCKAfor(;;){/////////////////// pozadavek na zmenu kmitoctu (max. 2,5ms)if(bit_test(_DDS_UPDATE)) dds_update();////////////////// nastala zmena polohy kroutitkaif(bit_test(_ENC_CHNG)) enc_chng();/////////////////// zmena parametruif(bit_test(_PAR_UPDATE)) par_update();/////////////////// pozadavek zmeny kmitoctu na lcd - 1.radek (zabere 30ms !!!!!)// PODMINKU NUTNO UPRAVITif(bit_test(_LCD1_UPDATE) && update_timer==0 && !bit_test(_ELBUG_BSY)) lcd1_update();/////////////////// pozadavek na zmenu informaci na lcd - 2.radek (max 2ms)if(bit_test(_LCD2_UPDATE) && update_timer==0){lcd2_update();update_timer=0xFF; // ukonci okno,kdy je timer vyprseny}/////////////////// periodicka mereni (max 3ms)if(update_timer==0){analog_inputs();update_timer=0xFF; // ukonci okno,kdy je timer vyprseny}/////////////////// stisknuta tlacitkaif(bit_test(_KEYS_VALID)) // stisknuto nejake tlacitko{// kratky stisk libovolneho tlacitka ukonci nastavovaniif(bit_test(_MNU) && !bit_test(_KEYS_LONG)){bit_clear(_MNU); // vypni nastavovanienc_delta=0; // zahod nacitane zbyle impulzy korutitkaif(bit_test(_ELBUG_ON_TMP)) bit_set(_ELBUG_ON); // obnov zapnuti elbugu pokud byl zapnutif(par_index!=PAR_ATTN) // stav attenuatoru se neuklada do eeprom{ee_adr=EE_ADDR[par_index];if(par_index==PAR_POWER) ee_adr=ee_adr+band_index; // pro parametr vykonu urci adresu eeprom pro dane pasmoif(read_eeprom(ee_adr)!=par[par_index]) // pokud doslo ke zmene parametru, aktualizuj ho v eeprom{write_eeprom(ee_adr,par[par_index]);update_eeprom();}}bit_set(_LCD1_UPDATE);bit_set(_LCD2_UPDATE);} else{// ktere tlacitko je stisknuto?if(keys==KEY_SPLIT) // SPLIT/MNU{if(bit_test(_KEYS_LONG)){// dlouhy stisk - vstup do MENUbit_set(_MNU2); // prvni stisk - vyber parametrpar_index=PAR_POWER;bit_set(_LCD1_UPDATE);bit_set(_LCD2_UPDATE);} else{// kratky stisk - pokracovani v MENUif(bit_test(_MNU2)){if(par_index==PAR_POWER){// zapamatuj si , zda je elbug zapnut nebo vypnutif(bit_test(_ELBUG_ON)) bit_set(_ELBUG_ON_TMP);else bit_clear(_ELBUG_ON_TMP);bit_clear(_ELBUG_ON); // pri nastavovani vykonu je elbug vypnut}bit_clear(_MNU2); // druhy stisk - prejdi do vybraneho parametrubit_set(_MNU);} else{// kratky stisk - funkce SPLITif(bit_test(_SPLIT)) bit_clear(_SPLIT);else bit_set(_SPLIT);}bit_set(_LCD1_UPDATE);}} // KEY_SPLIT// ostani tlacitka jsou aktivni jen kdyz nejsme ve vyberu parametruif(!bit_test(_MNU2)){if(keys==KEY_RIT) // RIT/STEP{if(bit_test(_KEYS_LONG)){// dlouhy stisk - funkce STEPif(step_index) step_index=0;else step_index=1;bit_set(_LCD1_UPDATE);} else{// kratky stisk - funkce RITif(bit_test(_RIT)){bit_clear(_RIT);freq_rit=0; // pri vypnuti RIT vynuluj} else bit_set(_RIT);bit_set(_DDS_UPDATE);}} // KEY_RITif(keys==KEY_CHNGVFO) // prepni VFO/srovnej VFO{if(bit_test(_KEYS_LONG)){// dlouhy stisk - funkce srovnej VFOif(vfo_index) freq_vfo[0]=freq_vfo[1];else freq_vfo[1]=freq_vfo[0];} else{// kratky stisk - funkce prepni VFOif(vfo_index) vfo_index=0;else vfo_index=1;bit_set(_DDS_UPDATE);}} // KEY_CHNGVFOif(keys==KEY_ATTN) // ATTN/ELBUG{if(bit_test(_KEYS_LONG)){// dlouhy stisk - funkce ELBUGpar_index=PAR_KEYER;bit_set(_MNU);bit_set(_LCD1_UPDATE);bit_set(_LCD2_UPDATE);} else{// kratky stisk - funkce ATTN - mozne jen pokud se nevysilapar_index=PAR_ATTN;bit_set(_MNU);bit_set(_LCD1_UPDATE);bit_set(_LCD2_UPDATE);}} // KEY_ATTN}}bit_clear(_KEYS_VALID); // tlacitko zpracovanobit_set(_KEYS_RELEASE); // budeme cekat na uvolneni tlacitek}} // hlavni smycka#endif}// End of File