-
alexis
-
( Пользователь )
-
-
Вне сайта
- Сообщений: 362
-
Репутация: 46
-
|
Спасибо, братцы.
Вот как обещал, полевые испытания:
Позиция (KO48XS):
Антенна - диполь полволны:
CQ CQ CQ .... нет ответа....
Побочный эффект полевых испытаний:
К сожалению, побочный эффект стал основным - ни одного QSO.
Причины - можно много придумать, и времени мало, и время суток не то,
и т.д. и т.п., но главное, думаю - забыл дома согласуйку. Чего там было в антенне - не могу сказать, но эфир слышал.
Отсюда - вывод: Надо крепко подумать в сторону встроенного тюнера - совсем не лишняя деталь, внешний можно ведь и банально забыть дома... Кое-какие мысли есть на эту тему.
|
Последнее редактирование: 21 Сен 2014 14:07 от alexis.
|
-
UV5QR
-
( Пользователь )
-
-
Вне сайта
- Сообщений: 364
-
Репутация: 19
-
|
alexis пишет:
Надо крепко подумать в сторону встроенного тюнера - совсем не лишняя деталь, внешний можно ведь и банально забыть дома... Кое-какие мысли есть на эту тему. Обычная изолента или скотч решит все ваши проблемы! Примотал СУ к трансиверу и не переживай что с памятью нелады!))
А грибочки то знатные!
|
|
-
rk3fw
-
( Пользователь )
-
-
Вне сайта
- Сообщений: 902
-
Репутация: 58
-
|
Не, так не красиво. Надо в одном стиле с ключиком - маленькое СУ, крепится к аппарату болтиками, с боку.
|
|
-
alexis
-
( Пользователь )
-
-
Вне сайта
- Сообщений: 362
-
Репутация: 46
-
|
Исходники прошивки для основной платы - PIC16F648A:
Основной файл проекта Pfr3a_pic16f648a_control.jal -- ------------------------------------------------------
-- 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
--
Библиотека для работы с ЖКИ KTM-S1201 - файл lcd_ktms1201.jal - поместить в JalPack\lib\ -- ------------------------------------------------------
-- Title: Output library to LCD KTM-S1201 lcd_ktms1201.jal
--
-- Author: Alexis Klyuev, RA1CAC, Copyright (c) 2014, all rights reserved.
--
-- Adapted-by:
--
-- Compiler: 2.4l
--
-- Description:
-- Библиотека вывода на дисплей LCD LCD KTM-S1201
-- для Microchip PIC16f6xxa.
--
-- Sources:
--
-- Notes:
-- File creation date/time: 18 May 2014 00:53:00 MSK.
--
-- ------------------------------------------------------
--
--------------------------------------------------------------------------------
-- You may want to change the selected pin:
-- LCD KTM-S1201
-- 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
--------------------------------------------------------------------------------
const byte lcd_CMD = 1
const byte lcd_DATA = 0
const byte lcd_BLINK_OFF = 0x18
const byte lcd_BLINK_ON_SLOW = 0x1a
const byte lcd_BLINK_ON_FAST = 0x1b
const byte lcd_SPACE = 0x0f
const byte lcd_MINUS = 0x0a
const byte lcd_DOT = 0x2e
const dword c10_000_000 = 10_000_000
const dword c1_000_000 = 1_000_000
const dword c100_000 = 100_000
const dword c10_000 = 10_000
const dword c1_000 = 1_000
const dword c100 = 100
const word c10 = 10
const byte ini_buf[6] =
{ 0x40, -- mode set
0x30, -- use unsynchronized transfer
0x18, -- blink off
0x11, -- display on
0x15, -- segment decoder on
0x20 -- clear data memory
}
--var volatile byte freq_str[13] --= {1,2,3,lcd_DOT,4,5,6,7,8,9,lcd_SPACE,1,lcd_MINUS}
var volatile byte decimal[4] = { 0x14, 0xe0, 0xb8, 0x15 }
;-------------------------------------------------------------------
; lcd_write(...)
;
; Note: /CS must be set before calling this function, and
; reset afterwards (because its the release of /CS that makes the
; LCD update its memory).
;-------------------------------------------------------------------
procedure lcd_write(byte in buffer[], byte in cnt, byte in cmd) is
var byte i
var byte c
if(cmd != 0x00) then
LCD_CD = lcd_CMD
else
LCD_CD = lcd_DATA
end if
for cnt using i loop
c = buffer[i]
if (c != ".") then
for 8 loop
LCD_SCK = off
if ((c & 0x80) != 0x00) then
LCD_SI = on
else
LCD_SI = off
end if
LCD_SCK = on
c = c << 1
_usec_delay(20)
end loop
end if
end loop
end procedure
;-------------------------------------------------------------------
; lcd_init()
;
; Initialize the KTM-S1201: segment decoder on, unsynchronized
; transfer mode.
;-------------------------------------------------------------------
procedure lcd_init() is
LCD_CS = low
; wait a few us for /BUSY to exit high impedance state
_usec_delay(2000)
lcd_write(ini_buf, 6, 1)
LCD_CS = high
end procedure
;--------------------------------------------------------------------------------
; lcd_dword_to_str(dword in freq, sword in delta, byte in str[], bit in rit_on)
; freq - source value
; delta - RX delta +-
; str[] - output buffer
; rit_on - rx delta 1 = on, 0 = off
;--------------------------------------------------------------------------------
procedure lcd_dword_to_str(dword in freq, sword in delta, byte in str[], bit in rit_on) is
var byte i,j,d
var word udelta
var dword divider = c10_000_000
for 12 using i loop
str[i] = lcd_SPACE
end loop
j = 7
for 7 loop
d = byte(freq / divider)
if ((d != 0) | (str[j+1] != lcd_SPACE)) then
str[j] = d
end if
freq = freq % divider
divider = divider / 10
j = j - 1
end loop
str[0] = byte(freq)
if rit_on then
if delta < 0 then
str[11] = lcd_MINUS
udelta = word(delta * -1)
else
udelta = word(delta)
end if
str[10] = byte(udelta / c100)
udelta = word(udelta % c100)
str[9] = byte(udelta / c10)
udelta = word(udelta % c10)
str[8] = byte(udelta)
end if
end procedure
--------------------------------------------------------------------------------
;-------------------------------------------------------------------
; lcd_puts(...)
;
; Send a string to the KTM-S1201. Allowed characters are
; 0x00 - 0x09 : numeric digits
; lcd_SPACE : blank
; lcd_DOT : decimal point
; lcd_MINUS : minus sign
;
; position = starting position relative to the left hand side,
; which is 0.
;
; Limitation: only one decimal point is supported in the input
; string. If you need more decimal points, use
; LCD_insert_decimal().
;-------------------------------------------------------------------*/
procedure lcd_puts(byte in buffer[], sbyte in position ) is
var byte ucDecoderOn[1] = {0x15}
var byte ucClear[1] = {0x20}
var byte ucBuffer[2]
var byte i, n, pos, chars=0
LCD_CS = low
; wait a few us for /BUSY to exit high impedance state
_usec_delay(2000)
lcd_write( ucClear, 1, lcd_CMD ) ; clear memory
lcd_write( ucDecoderOn, 1, lcd_CMD ) ; decoder on
n = byte(count(buffer))
for n using i loop
if (buffer[i] != "." ) then
chars = chars + 1
end if
end loop
pos = 12 - ( position + chars )
if (( position + chars ) == 0) then
pos = 11
elsif (( position + chars ) > 12) then
pos = 0
end if
ucBuffer[0] = 0xe0 | (2 * pos)
lcd_write( ucBuffer, 1, lcd_CMD)
lcd_write(buffer, 13, lcd_DATA) ; out data
for 13 using i loop
if ((buffer[i] == lcd_DOT) & (i >= position))then
decimal[1] = 0xE0 + (2 * (i-position))
lcd_write(decimal, 4, lcd_CMD)
end if
end loop
LCD_CS = high
end procedure
;-------------------------------------------------------------------
; LCD_blink(...)
;
; Turn blinking on or off. Use BLINK_ defines for parameter.
;
; Observation: SLOW blinks on and off in approximately 1 second
; FAST blinks twice the speed as slow
; When blinking, some segments stay on all the time!
; why? (looks like crap).
;-------------------------------------------------------------------
procedure lcd_blink (byte in blink) is
var byte ucBuffer[1]
LCD_CS = low
; wait a few us for /BUSY to exit high impedance state
_usec_delay(2000)
ucBuffer[0] = blink
lcd_write( ucBuffer, 1, lcd_CMD);
LCD_CS = high
end procedure
;-------------------------------------------------------------------
; LCD_insert_decimal(...)
;
; Insert a decimal point at the position specified (relative
; to the left hand side).
;-------------------------------------------------------------------
procedure lcd_insert_decimal( byte in position ) is
; static unsigned char ucDecimal[4] = { 0x14, 0xe0, 0xb8, 0x15 };
var byte pos;
if ( position > 12 ) then
position = 12
end if
; if ( position < 0 ) position = 0
LCD_CS = low
; wait a few us for /BUSY to exit high impedance state
_usec_delay(2000)
pos = 12 - position;
if ( pos > 12 ) then
pos = 12
end if
; if ( pos < 0 ) pos = 0;
decimal[1] = 0xe0 | ( 2 * pos );
lcd_write(decimal, 4, lcd_CMD);
LCD_CS = high
end procedure
-------------------------------------------
;procedure lcd_display_number(dword in number, byte in pos) is
; lcd_write(freq_str, 12, 0)
;end procedure
-------------------------------------------
Библиотека для работы с DDS AD9834 - файл dds_ad9834.jal - поместить в JalPack\lib\ -- Title: Analog Devices AD9834 DDS Chip library
--
-- Autor: Alexis Klyuev, RA1CAC 2014 librare is based on:
----------------------------------------------------------------------------------------
-- AD9833 library from autor: Tijs van Roon@RedSam, Copyright (c) 2010, all rights reserved.
--
-- This file is part of jallib (http://jallib.googlecode.com)
-- Released under the ZLIB license (http://www.opensource.org/licenses/zlib-license.html)
----------------------------------------------------------------------------------------
-- Compiler: >=2.4m
-- Revision: $Revision: 2760 $
--
-- Description:
-- Analog Devices AD9834 Direct-Digital-Synthesis (DDS) chip library.
--
-- The library assumes that the AD9834 chip is clocked 25Mhz and 50Mhz (MCLK). If not, read the
-- last section to know how to change the constants to your needs.
-- The library is probably a very good start for other Analog DDS chips as well since
-- all work from the same principal.
-- --
-- Setup:
-- Assure that you are using a 25 Mhz or 50 Mhz oscillator on the dds chip. Otherwise change
-- the constant. See below (in the source) on how to do this.
--
-- First define to which pins the data,clock and fsync pins are connected and
-- make those pins outputs:
-- 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
--
-- Then, include the dds library
-- > include dds_ad9834
--
-- Reset the dds chip. This is mandatory to make it operate!
-- > dds_reset()
--
-- And then output a frequence with:
-- > dds_frequency(<freq in hz>)
--
-- Change the output shape with:
-- > dds_square();
-- > dds_sine();
-- > dds_triangle();
--
-- Or return to sleep mode:
-- > dds_sleep();
--
-- TODO:
-- * Automaticly calculate the constants from a dds_mclk value.
-- * The frequency register calculation might be done more efficient and maybe
-- more correct. The output frequency always seems to be a bit lower than what
-- is given. (I used to add a 'correction' to the FREQ0 reg, of about 2)
--
-- Other MASTERCLOCK, Changing the constants:
-- The DDS chip has 28-bit frequence word. When the clockspeed is known a constant
-- needs to be calculated which defines how many 'steps' per hz are needed to calculate
-- the value of the freq0 register.
--
-- The constant is calculated as follows:
-- <freq. output in hz> = (MCLK / 2^28) * Freg
-- Therefore:
-- Freq0 = (2^28 / MCLK) * <desired frequency output in hz>
--
-- Then 2^28 / MCLK is the constant we need.
-- Since this is fractional number and because at least 6 (preferably more!) digits
-- are needed for the calculation, the freq0 register is calculated in two steps
-- which together serve as a fixed point calculation. First the integral part, second
-- the fractional part. The fractional part is multiplied by 2^24 to gain precision
-- in the calculation and to make the division easier later (>>24).
--
-- Example for 25 Mhz:
-- steps_per_hz = 10.73741824; @ 25Mhz
-- Intergral part:
-- const dword _dds_const_int = 10;
-- Fractional part:
-- = 10.73741824 * 2^24 = 12371824
-- const dword _dds_const_dec = 12_371_824
--
-- CONFIGURE FREQUENCY CONSTANTS HERE!! (If needed..)
--------------------------------------------------------------------------------
-- f = (MCLK / 2^28) * Freg => Freg = (2^28 / MCLK) * f = steps_per_hz * f
-- const MCLK = 25_000_000
-- steps_per_hz = 10.73741824 @ 25Mhz
-- const MCLK = 50_000_000
-- steps_per_hz = 5.36870912 @ 50Mhz
-- const _dds_const_int = (1<<28) / MCLK
-- const _dds_const_dec = ((1<<28 / MCLK) - _dds_const_int) << 24
-- 25 Mhz
--const dword _dds_const_int = 10
--const dword _dds_const_dec = 12_371_825
-- 50 Mhz
const dword _dds_const_int = 5
const dword _dds_const_dec = 6_185_912
-- STOP
-- Info on the Control Word: ---------------------------------------------------
-- bit we use descr
-- 15/14 xx register select: 00 = control, 01 = freq0, 10 = freq1, 11 = phase0&1 (use bit 13
-- 13 1 B28: 0 = select LSB/MSB via bit 12, 1 = write MSB&LSB in consecutive write,
-- B28: 0 = write phase0, 1 = write phase1
-- 12 0 HLB: select LSB/MSB: ignored in 28-bit mode
-- 11 0 FSELECT: 0 = freq0, 1 = freq1
-- 10 0 PSELECT: 0 = phase0, 1 = phase1
-- 9 0 PIN/SW switcher
-- 8 x RESET: 1 = reset state, 0 = no reset. 1 on init, 0 on running
-- 7 0 SLEEP1: 0 = MCLK enabled, 1 = MCLK disabled (device freezes)
-- 6 0 SLEEP12: 0 = DAC on, 1 = DAC disabled
-- 5 x OPBITEN: 0 = DAC (sine/triangle), 1 = MSB (square)
-- 4 0 reserved
-- 3 0 DIV2: 0 = MSB/2, 1 = MSB
-- 2 0 reserved
-- 1 x MODE: 0 = Sine, 1 = triangle
-- 0 0 reserved
-- init: 0b_0010_0001_0000_1000
-- square:0b_0010_0000_0011_1000
-- triang:0b_0010_0000_0000_1010
-- sine: 0b_0010_0000_0000_1000
--
-- write freq0:
-- write 0b_01mm_mmmm_mmmm
-- CONTROL: 0b_0010_000R_SDO0_10M0
const _dds_control_base = 0b_0010_0000_0000_1000 -- MSB+LSB write, MSB:1
const _dds_control_reset = 0b_0000_0001_0000_0000 -- reset
const _dds_control_sleep = 0b_0000_0010_1100_0000 -- Sleep on, DAC off
const _dds_control_square = 0b_0000_0010_0110_0000 -- DAC off, MSB on
const _dds_control_sine = 0b_0000_0010_0011_0000 -- DAC ON, MSB off, Mode=sine
const _dds_control_triangle = 0b_0000_0010_0000_0010 -- DAC ON, MSB off, Mode=triangle
--------------------------------------------------------------------------------
-- PRIVATES --------------------------------------------------------------------
PROCEDURE _dds_send_word(word in msg) IS
-- clock high
DDS_SCLK = high
-- fsync low, we start data
DDS_FSYNC = low
var bit mbit at msg : 15
-- for each bit
for 16 loop
-- set bit on sdata
DDS_SDATA = mbit
-- clock low
DDS_SCLK = low
-- since we're waiting a while, we can shift instead of nop
msg = msg << 1
_usec_delay(20)
-- clock high
DDS_SCLK = high
end loop
-- fsync high
DDS_FSYNC = high
END PROCEDURE
-- PUBLIC ----------------------------------------------------------------------
-- resets the dds chip and prepares it for operation. In will start in 'sleep' mode.
PROCEDURE dds_reset() IS
PRAGMA inline
_dds_send_word(_dds_control_base + _dds_control_reset)
END PROCEDURE
-- instructs the dds chip to sleep: the dac will go off and the device freezes.
-- This reduces power consumption.
-- Calling dds_squeare/dds_sine/dds_triangle will wake the device up again.
PROCEDURE dds_sleep() IS
PRAGMA inline
_dds_send_word(_dds_control_base + _dds_control_sleep)
END PROCEDURE
-- Puts the device into MSB-mode. The device outputs the value of the MSB bit of the
-- phase accumulator. Note that this output is not generated by the DAC and the Vpp is
-- more than the 0.6V of the other modes which do use the DAC.
-- The DAC is put to sleep in this mode.
PROCEDURE dds_square() IS
PRAGMA inline
_dds_send_word(_dds_control_base + _dds_control_square)
END PROCEDURE
-- Puts the device into triangle mode. The device uses the phase accumulator to derive
-- the DAC value.
PROCEDURE dds_triangle() IS
PRAGMA inline
_dds_send_word(_dds_control_base + _dds_control_triangle)
END PROCEDURE
-- Puts the device into sine mode. The device uses the lookup table to output a sine wave.
PROCEDURE dds_sine() IS
PRAGMA inline
_dds_send_word(_dds_control_base + _dds_control_sine)
END PROCEDURE
-- calculates the FREQ0 register word from the input frequency in hz
-- and sends the two control words containing the FREQ0 register to the device.
PROCEDURE dds_frequency(dword in hz, byte in freg) IS
-- integer part
var dword data = hz * _dds_const_int
-- decimal part: data = data + (hz * _dds_const_dec) >> 24,
-- but direct calculation causes overflow (the >>24 is too late)
var dword part;
var byte n = 0
for 4 using n loop
part = hz & 0x00_00_00_FF
part = part * _dds_const_dec
if n == 0 then
part = part >> 24 -- >> 24 << 0
end if
if n == 1 then
part = part >> 16 -- >> 24 << 8
end if
if n == 2 then
part = part >> 8 -- >> 24 << 16
end if
-- n = 3 -> no shift
data = data + part
hz = hz >> 8
end loop
-- send via 2 freq0 or freq1 words
var word freqmsg -- only 2+14 bits at a time
freqmsg = word(data & 0b_00000000_00000000_00111111_11111111) -- 14 lsb
if freg == 0 then
freqmsg = freqmsg | 0b_0100_0000_0000_0000 -- register = FREQ0
else
freqmsg = freqmsg | 0b_1000_0000_0000_0000 -- register = FREQ1
end if
_dds_send_word(freqmsg)
data = data >> 14 -- next 14 bits
freqmsg = word(data & 0b_00000000_00000000_00111111_11111111) -- 14 lsb
if freg == 0 then
freqmsg = freqmsg | 0b_0100_0000_0000_0000 -- register = FREQ0
else
freqmsg = freqmsg | 0b_1000_0000_0000_0000 -- register = FREQ1
end if
_dds_send_word(freqmsg)
-- done
END PROCEDURE
Для компиляции проекта, в среде JalEdit Гл.меню->Tools->Environment Options->Закладка JAL - Надо снять все галочки.
Правила форума не позволяют загрузить файл с "неправильным" расширением. После скачивания уберите расширение .txt
|
Последнее редактирование: 23 Сен 2014 10:02 от alexis.
|
-
alexis
-
( Пользователь )
-
-
Вне сайта
- Сообщений: 362
-
Репутация: 46
-
|
UV5QR пишет:
Обычная изолента или скотч решит все ваши проблемы!... Это да!... Изолента запросто решает многие проблемы... Я даже знаю способ, как через модем грабить банки. Разумеется без изоленты этот способ не работает! Делается это так: Берем модем, к примеру "ZyXEL vmg1312-b30b", большие круглые батарейки штуки 4, припаиваем к ним пук разноцветных проводов, приматываем это хозяйство разноцветной опять же изолентой (или прозрачным скотчем - эстеты меня поправят) к модему. Далее - идем в ближайший банк, заходим внутрь, поднимаем ЭТО над головой и кричим: "Внимание! Всем лежать! У меня ZyXEL vmg1312-b30b!!! Деньги на бочку!", забираем деньги и уходим, если получится... Пардон за оффтоп.
rk3fw пишет:
...Надо в одном стиле с ключиком - маленькое СУ, крепится к аппарату болтиками, с боку. Можно и так.
PS.
С печатной платой прошу немного подождать - такие сопли как у меня сейчас просто стыдно выкладывать - немного подправлю и тогда выложу.
|
Последнее редактирование: 22 Сен 2014 10:10 от alexis.
|
-
UU7JD
-
( Пользователь )
-
-
Вне сайта
- Сообщений: 115
-
Репутация: 6
-
|
rm4hq пишет:
...Поскольку мы начали обсуждать будущий синтезатор на более мощном контроллере ... внесу некоторые предложения применительно к обычной схемотехники трансивера, а не только PFR.
Хотелось бы иметь выходы для включения АТТ, сигнала для настройки тюнера (он же манипулятор CW), включения подсветки, узкополосного фильтра, переключения ДПФ (на бистабильном реле на 2 диапазона)... Зачем все это в простейшем трансивере??? А для более сложных TRX такие синтезаторы уже имеются - можно готовый приобрести, можно самостоятельно спаять.
|
|
-
UT5LP
-
( Модератор )
-
-
Вне сайта
- Сообщений: 1038
-
Репутация: 25
-
|
UU7JD пишет:
Зачем все это в простейшем трансивере???
Понимаете...Хоть в простейшем,хоть в сложнейшем,гетеродин является СЕРДЦЕМ аппарата!!!
Обуславливающим его стабильность и нервное состояние корреспондентов.
Думаю,Вам попадались самодельщики,за которыми нужно "гоняться".
В случае VFO это громоздкая механика( в карман,точно,не влезет)
По этому,синтезатор,это изящное решение вопроса,по массогабаритным показателям.
А главное,это отсутствие громоздкой механики и весьма габаритных высококачественных индукривностей!(речь не идет об аппаратике на одну частоту)
UU7JD пишет:
А для более сложных TRX такие синтезаторы уже имеются - можно готовый приобрести, можно самостоятельно спаять.
Ну конечно же можно! Я грешным делом,давно пасусь у Василия Анатольевича ur5yfv.com.ua/ Но тут всплывает еще один вопрос...Все эти конструкции,сделаны
универсальными,дабы,ублажить все возможные хотелки покупателя...Это переключение
диапазонов,полосовиков,УВЧ,АТТ,всяких фильтров и т.д...А это разъемы...жгуты...МЕСТО в
и без того,маленьком (QRP)аппарате.
По этому ТС и затачивает свой проэкт,под конкретную схему и конкретный набор функций.
Должна получится законченая конструкция!
Конкретная цель(без универсальности) сэкономит ОЧЕНЬ много места на плате!И в кармане
|
Последнее редактирование: 22 Сен 2014 22:09 от UT5LP.
|
-
rm4hq
-
( Пользователь )
-
-
Вне сайта
- Сообщений: 265
-
Репутация: 33
-
|
alexis пишет:
применил м\с LP2985AIM5-3.0 - 3х вольтовый стабилизатор с нормированным уровнем шумов.. Кроме снижения уровня шумов запитка от 3х вольт снижает потребляемый ток? На много?
|
|
-
alexis
-
( Пользователь )
-
-
Вне сайта
- Сообщений: 362
-
Репутация: 46
-
|
rm4hq пишет:
...запитка от 3х вольт снижает потребляемый ток? На много? Питать синтезатор напряжением 3,5в как у автора оригинала я не пробовал, поэтому данных нет. Думаю, что разница несущественная. Можно сравнить потребляемый им ток при 3-х и при 5-ти вольтах.
Из даташита на AD9834 - максимальный потребляемый ток при питании 3в и частоте ЗГ=50мгц - 5,8мА, при питании 5в и той же частоте - 8мА. Разница - 2,2 мА.
Из даташита на PIC16F648a - при питании 3в и тактовой частоте 4мгц потребляемый ток - 0.4мА. При 5в и той же тактовой - 0.75мА. Разница - 0.35 ма.
Итого 2.55 мА.
Кроме того, кварцевый генератор тоже кое-что потребляет, к сожалению сравнительных данных для него привести не могу - в даташите отсутствуют, а сам я не измерял.
Полностью собранный синтезатор потребляет около 11 мА, отсюда 11 - (5.8 + 0.4) = 4.8 мА потребляет генератор при питании 3в. Очень ориентировочно можно предположить, что от 5в синтезатор потреблял бы 15..16 мА.
|
|
-
alexis
-
( Пользователь )
-
-
Вне сайта
- Сообщений: 362
-
Репутация: 46
-
|
UU7JD пишет:
...Зачем все это в простейшем трансивере?.. UT5LP пишет:
...Все эти конструкции,сделаны
универсальными,дабы,ублажить все возможные хотелки покупателя...Это переключение
диапазонов,полосовиков,УВЧ,АТТ,всяких фильтров и т.д...А это разъемы...жгуты...МЕСТО в и без того,маленьком (QRP)аппарате.По этому ТС и затачивает свой проэкт,под конкретную схему и конкретный набор функций.Должна получится законченая конструкция! Конкретная цель(без универсальности) сэкономит ОЧЕНЬ много места на плате!И в кармане
А ведь хороший вопрос. ЗАЧЕМ? - Сколько идей вдребезги разбилось о него!
Чтобы на него ответить, предлагаю использовать системный подход (как в программировании для линукс - не писать ничего лишнего, использовать ресурсы системы).
Для этого разобьем наш будущий аппарат на составные блоки:
1. Приемник
2. Передатчик
3. Синтезатор
4. ДПФ
5. Тюнер
6. Ключ
7. Питание
1,2,3. Совершенно очевидно объединение пп.1..3 в один пункт, называемый "Основная плата трансивера". На вопрос "Зачем...?" - отвечаем: "Патамушта!".
4. Далее ДПФ. В силу существования п.2 на тот же вопрос отвечаем так же. Без ДПФ никуда. Но тут возможна масса конструктивных вариантов:
4.1. 1,2,3 (на выбор) диапазона на основной плате. Заметно увеличит размер основной платы, зато близко к оригиналу.
4.2. Отдельная дорогая многодиапазонная (4..8 диапазонов) плата.
4.3. Сменный диапазонный картридж (идея с дли-инной бородой, если кто помнит "9-ти диапазонный трансивер" Ю. Мединца), очень просто и достаточно дешево, хотя не вполне оперативно. Кроме того, потребуется разработка разъемного соединения, желательно с нулевым усилием. которое можно изготовить из широкодоступных материалов.
4.4. Предлагайте еще...
5. Тюнер. Вполне себе универсальное устройство. Может существовать самостоятельно, как в самодельном, так и в заводском изготовлении. Системный подход предполагает исключение такого устройства из текущей задачи. На вопрос отвечаем - "ХЗ?"
6. Ключ. Аналогично. Все здесь присутствующие - телеграфисты. И каждый знает, что ключ - отдельная тема для творчества. От ключа предлагаю оставить на основной плате только "тон самоконтроля".
7. Питание. Как без ДПФ - никуда. Здесь по-моему однозначно - аккумулятор и варианты:
7.1. Встроенный. Внешняя зарядка. Контроль питания через контроллер основной платы.
7.2. Внешний БП - а надо ли?
7.3. Питание от "прикуривателя" автомобиля - почему нет?
Подытожив вышесказанное, делаем вывод:
Самый простой и дешевый вариант - Основная плата + диапазонный картридж + встроенное питание.
|
|
|