Class: CW::Tx

Inherits:
Tester show all
Includes:
FileDetails, ToneHelpers
Defined in:
lib/cw/tx.rb

Constant Summary

Constants included from FileDetails

FileDetails::ABBREVIATIONS, FileDetails::AUDIO_DIR, FileDetails::BOOKMARK_FILE, FileDetails::CALLS, FileDetails::CALLS_FILENAME, FileDetails::CODE, FileDetails::CODE_FILENAME, FileDetails::CONFIG_FILENAME, FileDetails::CONFIG_PATH, FileDetails::DASH_FILENAME, FileDetails::DATA, FileDetails::DEF_AUDIO_FILENAME, FileDetails::DICT_DIR, FileDetails::DICT_FILENAME, FileDetails::DOT_AUDIO_DIR, FileDetails::DOT_CW_DIR, FileDetails::DOT_FILENAME, FileDetails::E_SPACE_FILENAME, FileDetails::HERE, FileDetails::Q_CODES, FileDetails::ROOT, FileDetails::SPACE_FILENAME, FileDetails::TEXT, FileDetails::USER_CONFIG_PATH, FileDetails::WORK_DIR

Constants included from ToneHelpers

CW::ToneHelpers::TWO_PI

Instance Method Summary collapse

Methods included from FileDetails

#audio_dir, #audio_filename, #dash_path, #default_audio_dir, #dot_audio_dir, #dot_cw_dir, #dot_path, #e_space_path, #init_filenames, #process_audio_dir, #process_dot_audio, #process_dot_cw, #progress_file, #space_path, #user_audio_dir

Methods included from ToneHelpers

#convert_words, #generate_space, #last_element?, #space_sample?

Methods inherited from Tester

#audio_stop, #complete_word?, #current_word, #do_events, #exit!, #exit?, #failed!, #failed?, #finish?, #get_key_input, #get_word_last_char, #init_char_timer, #is_relevant_char?, #key_chr, #key_input, #kill_threads, #monitor_keys_thread, #move_word_to_process, #play, #play_words_thread, #print, #print_failed_exit_words, #print_letters?, #print_words, #print_words_exit, #print_words_thread, #print_words_until_quit, #process_letters, #process_space_maybe, #process_word_maybe, #process_words, #push_letter_to_current_word, #quit, #quit?, #quit_key_input?, #reset_stdin, #run, #sleep_char_delay, #stream, #sync_with_audio_player, #sync_with_play, #sync_with_print, #timing, #wait_for_no_word_process, #wait_for_start_sync, #word_proc_timeout

Constructor Details

#initializeTx

Returns a new instance of Tx.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/cw/tx.rb', line 9

def initialize
  @max_amplitude = (Cfg.config["volume"].to_f > 1.0 ?
                      1.0 : Cfg.config["volume"].to_f)
  @wpm = Cfg.config["wpm"].to_f
  @frequency = Cfg.config["frequency"].to_i
  @effective_wpm = Cfg.config["effective_wpm"] ?
                     Cfg.config["effective_wpm"].to_f : @wpm
  @sample_rate = 2400
  @print = Print.new
  @words = []
  @recording = []
  print.rx "\n"
  print.tx "\n"
  print.menu "\n"
end

Instance Method Details

#acknowledgeObject



214
215
216
217
218
# File 'lib/cw/tx.rb', line 214

def acknowledge
  their_callsign
  morsify ' de '
  my_callsign
end

#add_space(words) ⇒ Object



29
30
31
32
33
# File 'lib/cw/tx.rb', line 29

def add_space words
  str = ''
  words.to_array.collect { |word| str << word + ' '}
  str
end

#audio_threadObject



402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# File 'lib/cw/tx.rb', line 402

def audio_thread
  temp = @word_parts.collect {|part| word_composite(part) }
  @word_parts = nil
  wpm = 1.5
  temp.each do |letr|
    letr.each do |ele|
      if (:space == ele[:name]) || (:e_space == ele[:name])
        core_audio.generate_silence(tone.data[
                                     ele[:name]][:spb] * 20)
      else
        core_audio.generate_tone( tone.data[
                                  ele[:name]][:spb] * 20)
      end
    end
  end
end

#captureObject



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/cw/tx.rb', line 103

def capture
  puts "\n\r"
  puts "\r Menu: [C]allsign,    [N]ame, "
  puts "\r       [L]ocation,    [R]st,  "
  puts "\r       [T]emperature, [S]tore,"
  puts "\r       [I]nfo,        [W]PM,  "
  puts "\r       [Q]uit capture!"
  puts "\r"
  puts "\r        Use CAPITAL to capture"

  loop do
    char = key_input.read
#        print.menu char
    upcase = /[[:upper:]]/.match(char)
    case char.downcase
    when 'c'
      return capture_attribute :callsign, upcase
    when 'n'
      return capture_attribute :name, upcase
    when 'l'
      return capture_attribute :qth, upcase
    when 'r'
      return capture_attribute :rst, upcase
    when 't'
      return capture_attribute :temperature, upcase
    when 'i'
      return info
    when 's'
      return store
    when 'q'
      puts "\rCancelled!"
      return
    else
      puts "\nInvalid letter(#{char}) - try again!"
    end
    sleep 0.001
  end
end

#capture_attribute(attr_type, use_recording = false) ⇒ Object



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/cw/tx.rb', line 154

def capture_attribute(attr_type, use_recording = false)
  puts "\n\r"
  puts "Enter their #{attr_type.to_s} followed by SPACE" unless use_recording
  temp = use_recording ? @recording : []
  print.menu temp.join('').delete(' ') if(@recording && ! use_recording)
  @recording = []
  if use_recording
    write_attribute temp, attr_type
    return
  end
  loop do
    char = key_input.read
    if key_input.is_relevant_char?(char)
      temp << char
      print.menu char unless use_recording
      if ' ' == char
        temp << char
        write_attribute temp, attr_type
        return
      end
    elsif char == 'Q'
      puts "\n\n\rCancelled!\n\n\r"
      return
    end
  end
end

#char_spaceObject



384
385
386
# File 'lib/cw/tx.rb', line 384

def char_space
  @effective_wpm == @wpm ? [space,space] : [e_space,e_space]
end

#char_to_tx(char) ⇒ Object



350
351
352
353
# File 'lib/cw/tx.rb', line 350

def char_to_tx char
  @words << char
#      print.tx char
end

#check_clear(char) ⇒ Object



50
51
52
53
54
# File 'lib/cw/tx.rb', line 50

def check_clear char
  if char == "\e"
    @words = []
  end
end

#core_audioObject



25
26
27
# File 'lib/cw/tx.rb', line 25

def core_audio
  @core_audio ||= Coreaudio.new
end

#create_element_method(ele) ⇒ Object



439
440
441
# File 'lib/cw/tx.rb', line 439

def create_element_method ele
  define_singleton_method(ele) {tone.data[ele]}
end

#create_element_methodsObject



443
444
445
446
447
# File 'lib/cw/tx.rb', line 443

def create_element_methods
  elements.each do |ele|
    create_element_method ele
  end
end

#cw_encodingObject



376
377
378
# File 'lib/cw/tx.rb', line 376

def cw_encoding
  @encoding ||= Encoding.new
end

#cw_threadsObject



457
458
459
# File 'lib/cw/tx.rb', line 457

def cw_threads
  @cw_threads ||= Threads.new(self, thread_processes)
end

#dit_ditObject



261
262
263
# File 'lib/cw/tx.rb', line 261

def dit_dit
  morsify 'e e '
end

#elementsObject



449
450
451
# File 'lib/cw/tx.rb', line 449

def elements
  [:dot, :dash, :space, :e_space]
end

#generate(wrds) ⇒ Object



419
420
421
422
423
424
425
426
427
428
429
430
# File 'lib/cw/tx.rb', line 419

def generate wrds
  word_parts(wrds)
  create_element_methods
  core_audio.start
  cw_threads.add self, :audio_thread
  #      th = Thread.start do
  cw_threads.join :audio_thread
  sleep 0.001
  core_audio.stop
  cw_threads.kill_thread_x :audio_thread
  #      puts 'end thread'
end

#infoObject



265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/cw/tx.rb', line 265

def info
  now = Time.now.utc
  time = now.strftime("%H:%M:%S Z")
  date = now.strftime("%d/%m/%y")
  puts "\r----------------------------\r"
  puts "Time:       #{time}\r"
  puts "Date:       #{date}\r"
  puts "Temp:       #{@temperature}°C\r"
  puts "\r"
  callsign = @their_callsign.nil? ? '' : @their_callsign.upcase
  puts "Their Call: #{callsign}\r"
  puts "Their Name: #{@their_name}\r"
  puts "Their RST:  #{@their_rst}\r"
  puts "Their qth:  #{@their_qth}\r"
  puts "\r----------------------------\r"
  puts "\n\r"
end

#long_cqObject



237
238
239
# File 'lib/cw/tx.rb', line 237

def long_cq
  morsify "cqcq cqcq de m0gzg m0gzg k "
end

#monitor_keysObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/cw/tx.rb', line 35

def monitor_keys
  @char = '#'
  process_letter

  loop do
    @char = key_input.read
    break if quit_key_input?
    break if quit?
    break if exit?
    check_sentence_navigation(@char) if self.class == Book
    check_clear @char
    process_letter
  end
end

#morsify(sentence) ⇒ Object



241
242
243
# File 'lib/cw/tx.rb', line 241

def morsify sentence
  sentence.split('').collect{ |letr| char_to_tx letr }
end

#my_callsignObject



195
196
197
# File 'lib/cw/tx.rb', line 195

def my_callsign
  morsify "m0gzg "
end

#nameObject



249
250
251
# File 'lib/cw/tx.rb', line 249

def name
  morsify "name is m a r t y n  martyn = "
end


56
57
58
59
60
61
62
# File 'lib/cw/tx.rb', line 56

def print_mode(mode)
  msg = "\n\r" + (mode == :rx ?
                    "Receive Mode:" :
                    "Transmit Mode:") + "\n\r"
  print.tx msg if :tx == mode
  print.rx msg if :rx == mode
end

#process_letterObject



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/cw/tx.rb', line 283

def process_letter
  @input_word ||= ''
  case @char
  when '#'
    return_val = receive_mode
    if '>' == return_val
      return_with_k
    else
      @char = ''
    end
  when '.'
    stop
  when 'F'
    @wpm += 1
    @effective_wpm = @wpm
  when 'S'
    @wpm -= 1
    @effective_wpm = @wpm
  when '='
    morsify '= '
  when ','
    morsify ', '
  when '\\'
    info
  when '|'
    capture
  when '?'
    morsify '? '
  when '@'
    long_cq
  when '£'
    my_callsign
  when '$'
    their_callsign
  when '}'
    sign_off
  when '>'
    return_with_k
  when ')'
    return_with_kn
  when '('
    received_ok
  when '^'
    qth
  when '%'
    rst
  when '&'
    name
  when '*'
    weather
  when 'E'
    dit_dit
  when "\n"
    puts "\n"
  when "\r"
    puts "\r"
  when 'Q'
    puts "Quitting..."
    quit!
  else
    if key_input.is_relevant_char?(@char)
      char_to_tx @char
    end
  end
  @char = ''
end

#push_enc(chr) ⇒ Object



367
368
369
370
371
372
373
374
# File 'lib/cw/tx.rb', line 367

def push_enc chr
  arry = []
  chr.each_with_index do |c,idx|
    arry << c
    arry << ((last_element?(idx, chr)) ? (space_or_espace) : space)
  end
  arry += char_space
end

#qthObject



253
254
255
# File 'lib/cw/tx.rb', line 253

def qth
  morsify "qth is o l d  w o o d nr l i n c o l n  lincoln = "
end

#quit!Object



99
100
101
# File 'lib/cw/tx.rb', line 99

def quit!
  Cfg.config.params["exit"] = true
end

#receive_modeObject



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/cw/tx.rb', line 64

def receive_mode
  print_mode :rx
  loop do
    char = key_input.read
    check_clear char
    case char
    when '#'
      print_mode :tx
      return
    when '|'
      capture
    when '\\'
      info
    when '>'
      return '>'
    when "\n"
      puts "\n"
    when "\r"
      puts "\r"
    when 'Q'
      puts "Quitting..."
      quit!
    else
      if(@recording.include? ' ')
        @recording = [char]
      else
        @recording << char
      end
      puts 'here'
      print.rx char
    end
    sleep 0.001
  end
end

#received_okObject



220
221
222
223
# File 'lib/cw/tx.rb', line 220

def received_ok
  acknowledge
  morsify 'en en '
end

#return_with_kObject



203
204
205
206
# File 'lib/cw/tx.rb', line 203

def return_with_k
  acknowledge
  morsify 'k '
end

#return_with_knObject



208
209
210
211
212
# File 'lib/cw/tx.rb', line 208

def return_with_kn
  morsify '+ '
  acknowledge
  morsify 'kn '
end

#rstObject



245
246
247
# File 'lib/cw/tx.rb', line 245

def rst
  morsify "rst is 599  5nn = "
end

#send_char(c) ⇒ Object



392
393
394
395
396
397
398
399
400
# File 'lib/cw/tx.rb', line 392

def send_char c
  enc = nil
  if c == ' '
    enc = word_space
  else
    enc = cw_encoding.fetch(c).map { |e| send(e)}
  end
  push_enc enc
end

#sign_offObject



225
226
227
228
229
230
231
# File 'lib/cw/tx.rb', line 225

def sign_off
  morsify "ok om #{@their_name} 73 es tnx fer nice qso = hpe 2cuagn sn + "
  their_callsign
  morsify ' de '
  my_callsign
  morsify ' sk '
end

#space_or_espaceObject



380
381
382
# File 'lib/cw/tx.rb', line 380

def space_or_espace
  (@effective_wpm == @wpm) ? space : e_space
end

#stopObject



233
234
235
# File 'lib/cw/tx.rb', line 233

def stop
  morsify '= '
end

#storeObject



142
143
144
145
146
147
148
149
150
151
152
# File 'lib/cw/tx.rb', line 142

def store
  puts "\n\r"
  puts "\rStoring info:"
  info
  @their_callsign
  @their_name
  @their_location
  @their_rst
  puts "\rCleared info!"
  puts "\r"
end

#their_callsignObject



199
200
201
# File 'lib/cw/tx.rb', line 199

def their_callsign
  morsify @their_callsign unless @their_callsign.nil?
end

#thread_processesObject



355
356
357
358
359
360
361
# File 'lib/cw/tx.rb', line 355

def thread_processes
  [
    :tx_words_thread,
    :monitor_keys_thread,
    #        :print_words_thread
  ]
end

#toneObject



453
454
455
# File 'lib/cw/tx.rb', line 453

def tone
  @tone ||= ToneGenerator.new
end

#tx(string) ⇒ Object



461
462
463
464
465
466
467
468
469
470
471
472
# File 'lib/cw/tx.rb', line 461

def tx string
  @winkey = Winkey.new
  @winkey.on
  @winkey.echo
  @winkey.no_weighting
  @winkey.wpm @wpm
#      @winkey.string "ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890/=+?>(:;"
  @winkey.string ' fb '
  @winkey.wait_while_sending
  cw_threads.run
#      @winkey.close
end

#tx_words_threadObject



474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/cw/tx.rb', line 474

def tx_words_thread
  loop do
    unless @words == []
      temp = @words.shift
      #          generate temp
#          p temp
      @winkey.stringtemp.to_s.upcase
      print.tx temp
    end
    sleep 0.01
  end
end

#weatherObject



257
258
259
# File 'lib/cw/tx.rb', line 257

def weather
  morsify "hr wx is sunny with some clouds = temp #{@temperature}c = "
end

#word_composite(word) ⇒ Object



363
364
365
# File 'lib/cw/tx.rb', line 363

def word_composite word
  send_char word.downcase
end

#word_parts(str = nil) ⇒ Object



432
433
434
435
436
437
# File 'lib/cw/tx.rb', line 432

def word_parts str = nil
  return @word_parts if @word_parts
  @word_parts = []
  str.split('').each { |part| @word_parts << part}
  @word_parts
end

#word_spaceObject



388
389
390
# File 'lib/cw/tx.rb', line 388

def word_space
  @effective_wpm == @wpm ? [space] : [e_space]
end

#write_attribute(attr, type) ⇒ Object



181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/cw/tx.rb', line 181

def write_attribute attr, type
  clip = attr.join('').delete(' ')
  @their_callsign = clip if :callsign == type
  @their_name  = clip    if :name == type
  @their_rst   = clip    if :rst == type
  @their_qth   = clip    if :qth == type
  @temperature = clip    if :temperature == type
  puts "\n\n\r#{type.to_s}: #{@their_callsign.upcase}\n\n\r" if :callsign == type
  unless :callsign == type
    puts "\n\n\rAttr: #{@temperature}°C\n\n\r" if :temperature == type
    puts "\n\n\rTheir #{type.to_s}: #{clip}\n\n\r" unless :temperature == type
  end
end