-- ------------------------------------------------------ -- Title: TRX control firmware of PFR-3A analog -- -- Author: Alexis Klyuev, RA1CAC, Copyright (c) 2014, all rights reserved. -- -- Adapted-by: -- -- Compiler: 2.4l -- -- Description: -- Программа управления трансивером - аналогом PFR-3A -- для Microchip PIC16f648a. -- -- Sources: -- -- Notes: -- - File creation date/time: 10 May 2014 17:18:00 MSK. -- -- ------------------------------------------------------ -- include 16f648a -- target PICmicro -- -- This program assumes a 20 MHz resonator or crystal -- is connected to pins OSC1 and OSC2. pragma target clock 4_000_000 -- oscillator frequency -- configuration memory settings (fuses) pragma target OSC INTOSC_NOCLKOUT -- internal clock pragma target WDT disabled -- no watchdog pragma target PWRTE disabled pragma target LVP disabled -- no Low Voltage Programming --pragma target MCLR internal -- reset internally pragma target MCLR external -- reset externally pragma target BROWNOUT disabled pragma target CPD disabled pragma target CP disabled ; Bands central QRP frequencies pragma eedata ; HEX value address in eeprom 0xE0,0x03,0x1C,0x00, -- 1_836_000 - 0 0x40,0x52,0x36,0x00, -- 3_560_000 - 4 0xF0,0x44,0x6B,0x00, -- 7_030_000 - 8 0xA0,0x5B,0x9A,0x00, -- 10_116_000 - 12 0xE0,0x89,0xD6,0x00, -- 14_060_000 - 16 0x70,0xF8,0x13,0x01, -- 18_086_000 - 20 0xA0,0x59,0x41,0x01, -- 21_060_000 - 24 0x10,0x09,0x7C,0x01, -- 24_906_000 - 28 0x60,0x29,0xAC,0x01, -- 28_060_000 - 32 0x02, -- Current band 0..9 - 36 0x83,0x80, -- saved trx_state - 37 0x01,0x00 -- saved tune_step - 39 ---------------------------------------------------- var volatile byte digital_pos var volatile byte freq_str[12] var volatile byte portb_state var volatile byte keyer_state var volatile byte keyer_state_old var volatile byte valcoder_state var volatile byte valcoder_state_old var volatile byte valcoder_state_old_old var volatile byte comparator_state var volatile byte comparator_state_old var volatile byte uref_state var volatile byte uref_band_state var volatile byte uref_btns_state var volatile byte current_band var volatile sword rx_delta var volatile word trx_state var volatile word tune_step var volatile word tune_step_old var volatile word autosave_cnt var volatile dword main_frequency var volatile dword rx_frequency ;var volatile word ctrl ;var volatile bit*2 keyer_state at ctrl : 0 ;var volatile bit*2 keyer_state_old at ctrl : 2 ;var volatile bit*2 valcoder_state at ctrl : 4 ;var volatile bit*2 valcoder_state_old at ctrl : 6 ;var volatile bit*2 valcoder_state_old_old at ctrl : 8 ;var volatile bit*2 comparator_state at ctrl : 10 ;var volatile bit*2 comparator_state_old at ctrl : 12 ;var volatile word uref ;var volatile bit*4 uref_state at uref : 0 ;var volatile bit*4 uref_band_state at uref : 4 ;var volatile bit*4 uref_btns_state at uref : 8 ;var volatile bit*4 current_band at uref : 12 ---------------------------------------------------- var volatile bit cw_dot_global at trx_state : 0 var volatile bit cw_dash_global at trx_state : 1 var volatile bit is_dot_start at trx_state : 2 var volatile bit is_dash_start at trx_state : 3 var volatile bit is_dot_dash_start at trx_state : 4 var volatile bit is_freq_changed at trx_state : 5 var volatile bit is_rit_on at trx_state : 6 var volatile bit valcoder_key_state at trx_state : 7 var volatile bit is_band_switch at trx_state : 8 var volatile bit is_band_changed at trx_state : 9 var volatile bit is_btn_switch at trx_state : 10 --... var volatile bit is_state_save at trx_state : 14 var volatile bit is_state_saved at trx_state : 15 ; ---- Default trx_state values = 0x8083 ----------- ; cw_dot_global = high ; cw_dash_global = high ; is_dot_start = false ; is_dash_start = false ; is_dot_dash_start = false ; is_freq_changed = false ; is_rit_on = false ; valkoder_key_state = high ; is_band_switch = false ; is_band_changed = false ; is_btn_switch = false ; 0 ; 0 ; 0 ; is_state_save = false ; is_state_saved = true ---------------------------------------------------- const bit MAIN_FREQ_UP = 1 const bit MAIN_FREQ_DN = 0 const byte CURR_BAND_INDEX = 36 const byte TRX_STATE_INDEX = 37 const byte TUNE_STEP_INDEX = 39 const byte AUTOSAVE_PER = 2000 const word cw_tone = 700 const dword if_frequency = 5_000_000 -------------------------------------------------------------------------------- -- You may want to change the selected pin: -- LCD KTM-S1601 alias LCD_SCK is pin_B0 pin_B0_direction = output alias LCD_SI is pin_B1 pin_B1_direction = output alias LCD_CS is pin_B2 pin_B2_direction = output alias LCD_CD is pin_B3 pin_B3_direction = output -- CW keyer alias CW_DOT is pin_B4 pin_B4_direction = input alias CW_DASH is pin_B5 pin_B5_direction = input -- Testing leds-------- ;alias LED_B4 is pin_B4 ;pin_B4_direction = output ;alias LED_B5 is pin_B5 ;pin_B5_direction = output -- Valcoder alias VAL_DN is pin_B6 pin_B6_direction = input alias VAL_UP is pin_B7 pin_B7_direction = input --DDS AD9834 alias DDS_SDATA is pin_A2 pin_A2_direction = output alias DDS_SCLK is pin_A3 pin_A3_direction = output alias DDS_FSYNC is pin_A4 pin_A4_direction = output alias DDS_FSELECT is pin_A6 pin_A6_direction = output -- Tranceiver Control alias CTRL_RXTX is pin_A7 pin_A7_direction = output -------------------------------------------------------------------------------- include dds_ad9834 include lcd_ktms1201 include pic_data_eeprom -------------------------------------------------------------------------------- ------------------------------------------- procedure set_digital_pos(word in step) is case tune_step of 1000: digital_pos = 9 100 : digital_pos = 10 10 : digital_pos = 11 1 : digital_pos = 12 end case end procedure ------------------------------------------- procedure tune_step_increment(word in step) is tune_step_old = step case step of 1 : tune_step = 10 10 : tune_step = 100 100: tune_step = 1000 end case set_digital_pos(step) end procedure ------------------------------------------- procedure tune_step_decrement(word in step) is tune_step_old = step case step of 1000: tune_step = 100 100 : tune_step = 10 10 : tune_step = 1 end case set_digital_pos(step) end procedure ------------------------------------------- procedure main_frequency_change(bit in is_increment) is var dword corr_freq if tune_step_old != tune_step then corr_freq = dword(main_frequency / tune_step) main_frequency = dword(corr_freq * tune_step) if !is_increment then main_frequency = main_frequency + tune_step end if tune_step_old = tune_step end if if is_increment then main_frequency = main_frequency + tune_step else main_frequency = main_frequency - tune_step end if end procedure ------------------------------------------- procedure calculate_rx_frequency() is if main_frequency >= c10_000_000 then rx_frequency = main_frequency - if_frequency - cw_tone else rx_frequency = main_frequency + if_frequency + cw_tone end if rx_frequency = rx_frequency + rx_delta end procedure ------------------------------------------- procedure calculate_and_output_freqs() is -- Output a frequence to dds: calculate_rx_frequency() dds_frequency(main_frequency, 0) -- TX register 0 dds_frequency(rx_frequency, 1) -- RX register 1 -- Output frequency string to lcd display lcd_dword_to_str(main_frequency, rx_delta, freq_str, is_rit_on) lcd_puts(freq_str, 0) lcd_insert_decimal(digital_pos) if (is_rit_on & (current_band >= 3)) then lcd_insert_decimal(4) end if end procedure ------------------------------------------- procedure hardware_interrupts() is pragma interrupt INTCON_PEIE = false -- if it was a interrupt on change --------- -- Timer 2 out --------------------------- if PIR1_TMR2IF == true then PIR1_TMR2IF = false PIE1_TMR2IE = false T2CON_TMR2ON = false autosave_cnt = autosave_cnt + 1 if (!is_state_saved & (autosave_cnt >= AUTOSAVE_PER)) then autosave_cnt = 0x0005 is_state_saved = true is_state_save = true ; LED_B4 = low ; _usec_delay(200_000) ; LED_B4 = high ; _usec_delay(200_000) end if PIE1_TMR2IE = true T2CON_TMR2ON = true end if -- Comparators ---------------------------- if PIR1_CMIF == true then comparator_state = (CMCON & 0xC0) >> 6 PIR1_CMIF = false -- clear interrupt on change comparators bit PIE1_CMIE = false is_btn_switch = false is_band_switch = false if comparator_state_old == 0x00 then case comparator_state of 0x01 : block is_btn_switch = true is_band_switch = false end block 0x02 : block is_btn_switch = false is_band_switch = true end block 0x03 : block is_btn_switch = true is_band_switch = true end block end case elsif comparator_state_old == 0x01 then case comparator_state of 0x03 : block is_btn_switch = false is_band_switch = true end block end case elsif comparator_state_old == 0x02 then case comparator_state of 0x03 : block is_btn_switch = true is_band_switch = false end block end case elsif comparator_state_old == 0x03 then case comparator_state of 0x03 : block is_btn_switch = false is_band_switch = false end block end case end if comparator_state_old = comparator_state if is_band_switch then if uref_state != uref_band_state then uref_band_state = uref_state is_band_changed = true is_band_switch = false end if end if if is_btn_switch then if uref_state != uref_btns_state then uref_btns_state = uref_state case uref_btns_state of 1 : block autosave_cnt = 0x0000 valcoder_key_state = false end block 7 : block valcoder_key_state = true if ((autosave_cnt >= 2) & (autosave_cnt <= 4)) then is_rit_on = !is_rit_on is_freq_changed = true end if end block end case is_btn_switch = false end if end if PIE1_CMIE = true -- comparators interrupt on change enable bit end if -- Port B pins ---------------------------- if INTCON_RBIF == TRUE then portb_state = PORTB INTCON_RBIF = FALSE -- clear interrupt on change pin bit INTCON_RBIE = false -- port b interrupt on change disable bit keyer_state = (portb_state >> 4) & 0x03 valcoder_state = (portb_state >> 6) & 0x03 if keyer_state != keyer_state_old then autosave_cnt = 0x0005 is_state_saved = false case keyer_state of 0x00: is_dot_dash_start = true 0x01: is_dash_start = true 0x02: is_dot_start = true 0x03: block is_dot_start = false is_dash_start = false is_dot_dash_start = false end block end case keyer_state_old = keyer_state end if if valcoder_state_old != valcoder_state then autosave_cnt = 0x0005 is_state_saved = false if ((valcoder_state_old == 0x03) & (valcoder_state != valcoder_state_old_old)) then case valcoder_state of 0x01: block if valcoder_key_state then if is_rit_on then rx_delta = rx_delta + 1 if rx_delta > 999 then rx_delta = 999 end if else main_frequency_change(MAIN_FREQ_UP) end if else tune_step_decrement(tune_step) end if end block 0x02: block if valcoder_key_state then if is_rit_on then rx_delta = rx_delta - 1 if rx_delta < -999 then rx_delta = -999 end if else main_frequency_change(MAIN_FREQ_DN) end if else tune_step_increment(tune_step) end if end block end case elsif ((valcoder_state_old == 0x00) & (valcoder_state != valcoder_state_old_old)) then case valcoder_state of 0x02: block if valcoder_key_state then if !is_rit_on then main_frequency_change(MAIN_FREQ_UP) end if end if end block 0x01: block if valcoder_key_state then if !is_rit_on then main_frequency_change(MAIN_FREQ_DN) end if end if end block end case end if valcoder_state_old_old = valcoder_state_old valcoder_state_old = valcoder_state is_freq_changed = true end if INTCON_RBIE = TRUE -- port b interrupt on change enable bit end if INTCON_PEIE = true end procedure ------------------------------------------- ; wait 1 second a few us for /RESET to exit high impedance state _usec_delay(1_000_000) -- ; enable_digital_io() -- disable analog I/O (if any) -- OPTION_REG_NRBPU = 0 -- Включаем подтяжку порта B к +5в. CTRL_RXTX = high -- Set RX mode (high - RX, low - TX) DDS_FSELECT = high -- First register on (0 - TX, 1 - RX) of DDS DDS_FSYNC = high ;cw_keyer_type = CW_KEYER_PADDLE -- Default keyer -- LCD init lcd_init() -- Reset DDS. dds_reset() -- Set sine in DDS out. dds_sine() -- Default setup of variables rx_delta = 0 keyer_state_old = 0x03 valcoder_state_old = 0x00 valcoder_state_old_old = 0x00 autosave_cnt = 0x0005 comparator_state = 0x00 comparator_state_old = 0x00 valcoder_key_state = true -- data_eeprom_write_dword(0, main_frequency) current_band = data_eeprom(CURR_BAND_INDEX) uref_band_state = current_band + 3 trx_state = data_eeprom_word(TRX_STATE_INDEX) tune_step = data_eeprom_word(TUNE_STEP_INDEX) tune_step_old = tune_step set_digital_pos(tune_step) main_frequency = data_eeprom_dword(current_band * 4) ;---------------------------------- ; is_rit_on = true ;---------------------------------- --calculate_and_output_freqs() is_freq_changed = true VRCON = 0b_1000_0000 -- enable internal Uref CMCON = 0b_0000_0010 -- set use comparators with internal Uref uref_state = 0x00 VRCON_VR = (uref_state & 0x0F) -- set level 0..16 of Uref T2CON = 0b_0111_1110 -- Enable T2 timer with prescaler 1:16 and postscaler 1:16 -- enable global interrupts INTCON_GIE = true -- Enables all unmasked interrupts INTCON_PEIE = true -- Enables all unmasked peripheral interrupts INTCON_RBIE = true -- port b interrupt on change enable bit INTCON_RBIF = false -- clear interrupt on change pin bit PIE1_CMIE = true -- comparators interrupt on change enable bit PIR1_CMIF = false -- clear interrupt on change comparators bit PIE1_TMR2IE = true -- timer 2 interrupt on change enable bit PIR1_TMR2IF = false -- clear interrupt on change timer 2 out ------------------------------------------- ;******************************************************************************* forever loop -- Band changed ---------------------------- if is_band_changed then current_band = uref_band_state - 3 main_frequency = data_eeprom_dword(current_band * 4) is_freq_changed = true is_band_changed = false end if -- Valcoder changed ---------------------- -- Frequency changed --------------------- if is_freq_changed then calculate_and_output_freqs() is_freq_changed = false end if -- Keyer pressed -------------------------- ; if cw_keyer_type == CW_KEYER_PADDLE then if is_dot_start then CTRL_RXTX = low _usec_delay(200) DDS_FSELECT = low else DDS_FSELECT = high _usec_delay(200) CTRL_RXTX = high end if ; else -- if cw_keyer_type ; DDS_FSELECT = CW_DASH ; end if if is_state_save then is_rit_on = false is_state_save = false data_eeprom_write(CURR_BAND_INDEX, current_band) data_eeprom_write_word(TRX_STATE_INDEX, trx_state) data_eeprom_write_word(TUNE_STEP_INDEX, tune_step) data_eeprom_write_dword(current_band * 4, main_frequency) is_freq_changed = true _usec_delay(200) end if -- Uref values scan -------------------------- if PIE1_CMIE then VRCON_VR = (uref_state & 0x0F) uref_state = uref_state + 1 if uref_state >= 0x0F then uref_state = 0x00 comparator_state_old = 0x00 end if _usec_delay(200) end if end loop --