* added FSQCALL(US) compatible modem
  * corrected code-page 1250 Latin-1 extended character keyboard
    entry to UTF-8 strings
    - correctly encodes 1250 characters 080 through 0FF using the
      control + numeric keypad entry for the character
      . British pound sign: control 163
pull/1/head
David Freese 2015-07-11 13:17:55 -05:00
rodzic dfb931831c
commit f61f7d7cc2
57 zmienionych plików z 5893 dodań i 118 usunięć

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 32 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 12 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 15 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 9.7 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 2.9 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 30 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 3.1 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 66 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 224 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 6.9 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 18 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 56 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 206 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 206 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 4.2 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 12 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 3.6 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 43 KiB

Wyświetl plik

@ -43,7 +43,7 @@ INPUT = index.txt \
fldigi_developer.txt \
New-Install.txt thumb_drive.txt colorsandfonts.txt \
configcallsigndb.txt configContestia.txt configCW.txt \
configDomEX.txt configFH.txt ConfigID.txt configIO.txt ConfigMisc.txt \
configDomEX.txt configFH.txt configFSQ.txt ConfigID.txt configIO.txt ConfigMisc.txt \
configModemScan.txt configMT63.txt configOlivia.txt ConfigOperator.txt \
configPSK.txt \
configRTTY.txt configThor.txt ConfigUI-browser.txt \
@ -53,7 +53,7 @@ INPUT = index.txt \
SoundCardSetup.txt Contest-How-To.txt cabrilloreporter.txt \
Logbook.txt LogExports.txt working_logs.txt Macros.txt \
InlineMacroTags.txt atMacroTags.txt advanced_qsy.txt execmacro.txt CW.txt \
DominoEX.txt hell.txt Contestia.txt MFSK.txt MT63.txt \
DominoEX.txt hell.txt Contestia.txt MFSK.txt MT63.txt FSQ.txt \
Navtex.txt psk.txt Olivia.txt RTTYFSK.txt Thor.txt \
throb.txt tune.txt WEFAX.txt WWV-xmt.txt FrequencyAnalysis.txt \
DigiscopeDisplay.txt DigiWWV.txt MousingKeyboardShortcuts.txt \

Wyświetl plik

@ -0,0 +1,688 @@
/**
\page fsq_page FSQ
\tableofcontents
FSQ, Fast Simple QSO, is an Incremental-Frequency-Keyed mode using an offset
differential modulation scheme similar to DominoEX, and Thor. It is a unique
mode for fldigi users in that it is a line by line transmission rather than
character by character. FSQ uses 33 tones spaced by 3 times the 3 baud symbol
rate or 8.8 Hz. The offset rotation of the IFKP sequence offers improved
performance under NVIS conditions, because the rotation significantly reduces
the risk of adjacent symbols causing inter-symbol interference.
fldigi can operate on the following FSQ modes without special setup by the
operator:
<br>
<center>
Mode | Symbol Rate | WPM | Bandwidth
:------:|:-----------:|:---:|:----------:
FSQ 2 | 1.95 baud | ~20 | 290 Hz
FSQ 3* | 2.93 baud | ~30 | 290 Hz
FSQ 4.5 | 3.91 baud | ~40 | 290 Hz
FSQ 6 | 5.86 baud | ~60 | 290 Hz
</center>
* - FSQ-3 is the base rate.
At the time of this release there is only one other amateur modem application
that supports FSQ, FSQCALL, written by Con Wassilieff, ZL2AFP. FSQ is an invention
of Murray Greenman, ZL1BPU. Both Murray and Con were very supportive during
the development and testing of fldigi's FSQ implementation.
fldigi-fsq supports the undirected, directed and image modes of FSQCALL.
This FSQ help content borrows shamelessly from Murray Greenman's (ZL1BPU)
"FSQ Explained" document.
<br>
<center>
\image html fsq-main-dialog.png "fsq main dialog"
\image latex fsq-main-dialog.png "fsq main dialog" width=4.0in
</center>
<br>
The main dialog fsq user interface provides an Rx-text panel, a Tx-text panel,
a "Heard" list, fsq specific control buttons, and a signal to noise indicator.
The Rx-text panel displays all decoded text in the UnDirected Mode. The Tx-text
panel is for entering all transmitted text, including directives. These two panels
can be resized vertically by dragging the dividing bar which separates them.
<center>
<table>
<tr>
<td>
\image html fsq-undirected-mode.png "Undirected Mode"
\image latex fsq-undirected-mode.png "Undirected Mode" width=1.5in
</td>
</tr>
<td>
\image html fsq-directed-mode.png "Directed Mode"
\image latex fsq-directed-mode.png "Directed Mode" width=1.5in
</td>
<tr>
</tr>
</center>
The Rx-text panel displays only recognized text in the Directed Mode. The text
parser must be satisfied that the sending stations callsign/crc8 agree and that
the directed station callsign is your own or "allcall". FSQ is case sensitive,
and your sending case must match the senders case, i.e. w1hkj and W1HKJ are not
the same for the purposes of FSQ Directed Mode.
fldigi-FSQ is active and will respond to directed triggers when the SELCAL button is lit.
Toggling the SELCAL button to "sleep" causes the FSQ parser to only respond to the
&lowast; trigger. When the &lowast; trigger is received the program will return to
the active SELCAL state.
<center>
\image html fsq-heard-list.png "Heard List Panel"
\image latex fsq-heard-list.png "Heard List Panel" width=1.5in
</center>
The "Heard" list displays the callsign, s/n, and time of reception of all correctly
decoded transmissions.
<br>
\section coding_and_modulation Modulation Scheme
FSQ is designed to use 32 tone differences between 33 equally spaced tones; so it is
possible to allocate 29 different individual differences directly to the most
frequently used characters. These characters are all lower case, a-z, plus the
most common punctuation symbols: space, full stop (period), and new line (CR/LF).
The three spare differences are used to define further code tables.
The total alphabet includes upper case and a reasonable range of symbols,
yielding a total alphabet of 104 ASCII characters. The extra characters are
allocated to three additional code tables, which are sent as two sequential
tone differences. These are characterized by an initial difference, describing
the character, and a continuation difference, defining the code table.
When the receiver sees a tone difference in the range 0 – 29, followed by another
in the range 0 – 29, it recognises a single-tone character (lower case etc).
If the tone difference is followed by a difference in the range 30 – 31, it uses
the second difference to decide which code table to select the character from,
and the first difference to choose the character from that table. The encoding
process is the reverse of this.
<center>
\image html fsq-varicode.png "FSQ Varicode Table"
\image latex fsq-varicode.png "FSQ Varicode Table" width=5.0in
</center>
IFK codes the data (the initial and continuation codes) as differences between
two tones, rather than as an absolute tone. This is the MFSK equivalent of
differential BPSK, as used in PSK31, etc. MFSK modes such as Piccolo, Coquelet
and MFSK16 use direct MFSK modulation, assigning the code directly to a tone
number. These modes may suffer from more inter-symbol interference than desirable,
cannot tolerate frequency drift, and can be difficult to tune.
FSQ uses very narrow tone spacing. IFK+ reduces inter-symbol interference by
ensuring that the chance of the same or an adjacent tone being used for
sequential symbols would be very remote.
Since the tones always change due to the differential action and the tone
rotation of IFK+, there is no opportunity for the tones to remain the same for
two consecutive symbols, which allows the sync-less process to operate correctly.
For example, without IFK+, repeated space characters could be seen as a single
character.
Finally, since the coding is differential, any drift and frequency offset is
cancelled out during decoding. IFK+ can handle frequency drift of about a third
of the tone spacing per symbol, or in FSQ about 18 Hz drift per second at 6 baud.
Frequency error tolerance is a matter of decoder design, but ± 50 Hz is tolerated
easily by FSQ.
IFK+, an acronym for Offset Incremental Frequency Keying, was suggested by
Murray Greenman ZL1BPU (2009), and first used in DominoEX. With each symbol
transmitted, as well as adding the difference from the alphabet-coding table
to the previous tone number, an addition rotation offset is added. In the case
of FSQ, this value is ONE.
Only one tone is transmitted at a time.
In order for the first difference (first character) to be correctly decoded, a
dummy tone needs to be transmitted first. This could be the lowest tone, but in
fact any permitted tone will suffice since only the difference to the next tone
is important. The software simply sends a space character to achieve this.
\section transmit_functions Transmit Functions
The user types text into the Tx panel, which can be edited before transmission.
Transmission starts when an ENTER character is pressed. It will also start as a
result of one of the automatic processes, such as Sounding or automated replies.
The characters in the Tx panel are then encoded, and transmitted at
the currently set symbol rate. As they are transmitted, the characters are
transferred to the receive pane as a record of what has been transmitted.
<b>BOT Sequence</b>
At the start of transmission in directed and non-Directed Mode, the BOT sequence,
a SPACE followed by a LINEFEED, is sent. The space serves as a dummy symbol to
allow the next tone difference to be measured. The LF character ensures that
reception starts on a new line.
In Directed Mode, the LF also serves as one delimiter for the callsign search
algorithm. The other delimiter is the colon that follows the callsign. This also
locates the two callsign checksum characters.
<b>EOT Sequence</b>
At the end of transmission in UnDirected Mode, the transmitter is simply turned
off once the last useful character is sent. In Directed Mode, however, a special
character sequence is sent just before the transmission stops, to signal EOT.
The BS (backspace) character is not required in FSQ, so the corresponding character
in the table has been reallocated as an EOT marker.
The purpose of the EOT sequence is to cause the Squelch to close quickly in Directed
Mode. Print will continue through fades without fldigi closing and stopping print
partway through a sentence. If the sentence transmission were to finish without
the EOT, the squelch would close slowly, and junk would print unnecessarily. The
EOT shorts out the Squelch time constant, closing the Squelch instantly.
The transmission consists of 33 tones spaced 8.7890625 Hz, resulting in a spread
of tones of 290.0390625 Hz. Using the ITU-R SM.1138 assessment method, the signal
easily meets 300 Hz useful bandwidth, at all signalling speeds, and its ITU
Emission Designator is therefore 300HF1B.
In Directed mode, a conventional network model CSMA protocol decides when the
station may have access to the radio channel. This protocol defines three classes
of message (chat, responses and soundings), and applies priorities to them.
Priority is provided by means of delays after Squelch has closed. In addition,
to limit clashes between stations wanting access for the same priority message,
random delays are also added.
<center>
Priority | Delay | Message Type
:-------:|:-------:|:-------------------------------:
1 | Short | Chat sentences
2 | Med | Automated responses to commands
3 | Long | Sounding
</center>
<b>Sounding</b>
In Directed Mode, the user may elect to send regular soundings. These are very
short messages with no trigger command and no message body. The message consists
only of the callsign, colon and checksum of the FSQCall preamble.
These sentences do not print at any station, but appear in the Heard List and are
logged in the Heard Log. This allows all stations on the channel to know what other
stations are there with minimum use of channel bandwidth.
Sounding is sent with the lowest message priority. Sounding is essentially
random, although the time between Sounds is selectable at 1, 10 and 30 minute
intervals. The start time is set by user action, and essentially random.
\section fsq_protocol FSQ Protocol
FSQ is designed as a chat mode, not a long-over QSO mode. It is capable of
sending multiple sentences in each transmission, but it is easiest and quickest
when just one sentence is sent.
Each transmission starts with the fldigi station callsign (converted to lowercase).
For example, if the user (say zl1xyz) types:
Hello John – how are you this evening<ENTER>
The software actually transmits:
zl1xyz:Hello John – how are you this evening
Nothing could be simpler. Every station within range will print this message.
<b>Performance</b>
There is no error correction involved, so users rely on the inherent robustness
of the mode, and if there are errors, either due to typos or reception errors,
the users will quickly recognise these. If an error causes confusion, they can
always ask for a repeat.
Operating 20W on the 40m band during the middle of the day, an automated station
300 km away was used to return transmitted sentences. From 250 words transmitted,
at 6 baud, 223 were returned correct (89.2% copy), while at 3 baud, copy was 100%.
For practical purposes, 80% copy is considered adequate for a comfortable QSO.
Tests using an ionospheric simulator bear these measurements out. Reception is
essentially 100% for white-noise tests with the signal above –15dB S/N.
\section directed_mode Directed Mode
FSQ Directed Mode operates as a simple extension of the FSQ protocol. The
preamble is changed a little, a direction (address and command) is applied, and
finally a short EOT signal is added to the end of each message. These differences
are simple to apply, as the user only needs to learn a few simple commands and
remember to add a direction and command to each sentence. The rest is automatic.
Further, directed sentences in FSQ mode can be read easily in undirected FSQ mode,
and undirected text is visible in the monitor panel which can be viewed in
Directed Mode. In Directed Mode, only text directed to your callsign will print
in the Rx panel, and only commands directed to your station will be responded to.
<center>
\image html fsq-mon-dialog.png "FSQ Monitor Panel - a Directed Mode Sentence"
\image latex fsq-mon-dialog.png "FSQ Monitor Panel - a Directed Mode Sentence" width=3.5in
</center>
The Monitor Panel is only shown during Directed Mode operation. It is minimized
when Undirected Mode is in use. All incoming traffic is printed on the Monitor
Panel. This includes both Directed and Undirected traffic. The decoding is
affected by the fldigi squelch setting.
You may see what appears to be a perfectly good Directed data stream on the Monitor
Panel which never appears on the Rx Panel. When this occurs, the data stream has
failed to parse correctly:
<ol>
<li>the BOT is missing or corrupt,
<li>the CRC8 check has failed,
<li>the EOT is missing or corrupt,
<li>or it is not directed to your callsign or allcall.
</ol>
<b>FSQCall Preamble</b>
The FSQCall preamble consists of the sending stations callsign, a colon, and a
two character hexadecimal checksum. For example, the simplest transmission, a
Sounding message, consists of only this. For example:
zl1bpu:b6
The checksum is a standard CCITT CRC8 calculated on the callsign and the colon.
The maximum callsign length is 16 characters, and the CRC is capable of detecting
up to four errors in this distance reliably. Pseudo-callsigns (such as place
names or personal names) can be used, which is very convenient for Public Service
and Emergency applications.
<b>Directions and Triggers</b>
All FSQ Directed Mode messages, apart from the Sounding, carry at least one
direction and a trigger. The direction is the callsign or callsigns of the
recipient station or stations, in other words, where the message is directed.
The trigger is one of a short list of one-letter commands sent to the directed
station, which define what it should do with the message. There may or may not
be a message body following the directions and triggers.
Here are some simple examples:
<center>
\image html fsq-directed-mode-examples.png "Directed Mode Examples"
\image latex fsq-directed-mode-examples.png "Directed Mode Examples" width=3.0in
</center>
In the first example, ZL1BPU is simply chatting to ZL1ABC. He starts typing by
giving the direction, the other stations callsign. The trigger used is a space,
which is understood by the receiving station as an invitation to print the message
that follows.
The second example illustrates how you can send the same sentence to two stations.
There is also an all stations direction (allcall) that can be used to send
messages and some commands to all stations within range.
The third is an example of a simple automated query. It is the FSQ way of asking
for a signal report. The queried station will respond with your s/n report as
measured by the FSQ program that is being used.
<b>Error Checking</b>
FSQ Directed Mode sentences are checked at the receiver in two ways. First, the
senders callsign is checked against the checksum received: if this is incorrect,
the sentence is rejected. If it is correct, the rest of the sentence is checked
to find the recipients callsign. If this is not received correctly, the sentence
is again rejected. If the callsign is received correctly, only the remainder of
the message following the recipients callsign is printed or acted upon.
When (and if) the incoming message is displayed, the preamble is shown without
the checksum, so it looks like the preamble in the UnDirected Mode. However, the
callsign displayed is in this case the callsign verified by the checksum.
Checking the validity of the originators callsign ensures that the message is
correctly attributed, is correctly logged, and most significantly, responses can
be sent to the correct station.
<b>Logging</b>
In Directed Mode, FSQ maintains a log of all stations heard, in chronological
order. With each entry, verified callsign, the date/time, and measured SNR are
recorded in CSV (comma separated value) format. This is suitable for examination
as a spreadsheet. The heard log file is named "fsq_heard_log.txt" and is located
in the fldigi.files/temp folder.
A complete audit log of transactions is also maintained in Directed Mode. This
includes regular time stamps, all raw received text, and all transmitted sentences.
The audit log is named "fsq_audit_log.txt" and is located in the fldigi.files/temp
folder.
<b>Directed Callsigns</b>
<ol>
<li>Each station responds to three callsigns.
<li>The operator callsign (fldigi converts operator call to lowercase).
<li>The callsign allcall, to which the software will act upon certain messages,
including chat, file and image transfer, and alerts. This mechanism is widely
used in nets to send chat to everyone in range.
<li>The callsign cqcqcq is recognised as a legitimate chat callsign.
</ol>
<br>
<b>Use of Lower Case</b>
FSQ is case sensitive, so messages directed (for example) to ZL1EE will not
be recognised by the station with its callsign set to zl1ee. Lower case is not
mandatory for operator callsigns, but is encouraged for these reasons:
<ol>
<li>Lower case is quicker and easier to type.
<li>Lower case is faster to send (most characters are sent in one symbol).
<li>The error rate is half that of upper case characters.
</ol>
<br>
\section fsq_triggers Triggers
All the command triggers (currently) consist of one reserved character. These
are taken from a pool of characters that are not permitted in callsigns. As far
as possible, the characters have a meaning easily associated with the character.
This list shows all the reserved characters, and their current or planned use.
Blank entries are reserved, with no currently planned application.
<center>
CHAR | ASCII | USE
:-----:|:-----:|:-------------------------------------------:
Space | 32 | Directed chat
! | 33 | Repeat command
\" | 34 | --
# | 35 | Message or file transfer
$ | 36 | Request Heard List
% | 37 | Receive image
& | 38 | Report QTC message
| 39 | --
( | 40 | --
) | 41 | --
&lowast; | 42 | Restore FSQ to ACTIVE from SLEEP
+ | 43 | Message retreive
, | 44 | --
- | 45 | Message delete (1)
. | 46 | --
: | 58 | Reserved, not used.
; | 59 | Relay command
< | 60 | Reduce sending speed
= | 61 | Reserved for ECC file transfer
\> | 62 | Increase sending speed
? | 63 | Report reception
@ | 64 | Report QTH (or position) message
[ | 91 | Used in file transfers
\ | 92 | --
] | 93 | Used in file transfers
^ | 94 | Report FSQ program version
_ | 95 | Report the squelch setting in dB (1)
` | 96 | --
{ | 123 | --
\| | 124 | Send Alert
} | 125 | --
~ | 126 | Delayed Repeat command
</center>
(1) not supported
\section fsq_commands Commands
Command sentences consist of a direction followed immediately by a command.
Multiple directions can be used in the same sentence under limited circumstances.
Two directions in the same sentence, which are understood by the same station,
will cause confusion, and only the second will be responded to. For example, one
should not send zl1xyz@ allcall message, as the first part will be ignored by
station zl1xyz.
<b>Command Syntax</b>
The syntax for currently defined commands is listed below.
<ul>
<li><b>callsign</b> <i>text</i> Addressee station starts to print text. No trigger character used except space following callsign. You MUST use a space or the trigger will not be recognised.
<li><b>callsign?</b> <i>text</i> (Is station hearing me?) Addressee station starts to print text. When squelch closes, station responds: origin_callsign snr=xxdB
<li><b>callsign\*</b> Switches station to ACTIVE if FSQSEL is in SLEEP. Addressee station starts to print. When squelch closes, station responds: callsign:<crc> Active
<li><b>callsign!</b> <i>message</i> (Repeat my message) Addressee station starts to print. When squelch closes, station responds: callsign:<crc> message. This is a simple relay mechanism. message may contain further trigger commands.
<li><b>callsign~</b> <i>message</i> (Repeat my message later) Addressee station starts to print. When squelch closes, after a delay of about 15 seconds, station responds: callsign:<crc> message This delayed relay is useful when stations mentioned in message can hear and respond to the original message.
<li><b>callsign;</b> <i> [relay_to]{trigger}{message}</i> Relay my message to the 'relay_to' station. See Relay section for details.
<li><b>callsign!sendto</b><i> message</i> Relay message to the 'sendto' station. Addressee station starts to print. When squelch closes, station relays the message.
<li><b>callsign#[nnn]</b> (Send file to station) Addressee station starts to print. Text following [nnn] will be saved in or appended to text file nnn.txt in the same folder as the log/audit files. When squelch closes, station responds callsign:<crc> Ack if the message stored OK. There is no response if the message was not received. [nnn] can be alpha, numeric or mixed.
<li><b>callsign#[filename.txt]</b> (Send file to station) Addressee station starts to print. File is opened from menu, and filename appended to message before file body text, File will be saved in or appended to text file filename.txt in the same folder as the log/audit files. When squelch closes, station responds callsign:<crc> if the message stored OK. There is no response if the message was not received. [nnn] can be alpha, numeric or mixed.
<li><b>callsign\@</b> (Request station position or location information) Addressee station starts to print. When squelch closes, station responds with pre-recorded sentence, typically containing QTH information. This could be GPS position, locator, or physical address. This is the message stored and retreived by the QTH button.
<li><b>callsign&</b> (Request station message) Addressee station starts to print. When squelch closes, station responds with pre-recorded sentence, typically containing station information or an 'Out to Lunch' message. This is the message stored by the QTC button.
<li><b>callsign^</b> (Request Software Version) Addressee station starts to print. When squelch closes, station responds with current FSQCALL software version.
<li><b>callsign%</b> (Send image) Addressed station receives the command to record
an analog graphic image. The Rx Image Dialog will open and the image painted as it
is being received. Images are in color or grey scale and always
displayed in native size.. Images can be directed to allcall.
<li><b>callsign|</b><i>message</i> (Send alert) Addressee station starts to print. Alert pop-up box containing message is placed on the screen. When the operator closes this dialog, a response transmission is made: origin_callsign Alert ack
<li><b>cqcqcq</b> text (Call for general chat) Following text prints.
<li><b>allcall</b> text (All stations print) Following text prints at all stations.
<li><b>callsign\></b> or <b>callsign\<</b> (Speed change)
\> increases speed, \< decreases speed at target station.
Response is origin_callsign: 4.5 baud (or whatever the new speed is).
If the speed is already at the maximum or minimum speed, the response is the same,
and there is no speed change.
<li><b>allcall#[nnn]</b> (Send file to all stations) All stations within range start to print.
Text following [nnn] will be saved in or appended to text file nnn.txt. When
squelch closes, station responds callsign:<crc> Ack if the message stored OK. There
is no response if the message was not received. allcall#[filename.txt] works the
same as callsign#[filename.txt].
</ul>
<br>
\section relaying_message Relaying messages
This is a relay mechanism which preserves the origin callsign as the message propagates
so that any response can be relayed back to that station. message can contain further
trigger commands.
Originating station: relay_callsign; dest_callsign message
\image html fsq-relay-examples.png "Relay Examples"
\image latex fsq-relay-examples.png "Relay Examples" width=4.5in
\section fsq_keyboard_keys Special keys
Pressing the F1 key will transfer the "last call" selected from the heard list to the
Tx panel. "last call" defaults to allcall on program startup.
Pressing the F2 key will transfer the last command to the Tx panel. The last command
is an empty string on program startup.
\section fsq_heard Heard List
The FSQ heard list is automatically added to, modified, and aged in accordance
with the FSQ user configuration parameters. Each time a valid callsign/crc8 pair
is discovered it is either added to the heard list, or it's entry is updated with
the last GMT and signal-to-noise ratio.
A single click on a heard list entry will make it the "last call" string.
A double click on a heard list entry will also add the call to the Tx panel. If multiple
heard list entries are double clicked each one is added to the Tx panel separated by
a space.
<center>
\image html fsq-heard-list.png "Heard List"
\image latex fsq-heard-list.png "Heard List" width=1.5in
</center>
Heard list entries have an associated pop-up menu, available by right-clicking on
the desired entry:
<center>
<table>
<tr>
<td>
\image html fsq-allcall-popup.png "All Call Menu"
\image latex fsq-allcall-popup.png "All Call Menu" width=2.0in
</td>
<td>
\image html fsq-directed-popup.png "Directed Menu"
\image latex fsq-directed-popup.png "Directed Menu" width=2.0in
</td>
</tr>
</table>
</center>
\section fsq_image_mode Image Mode
fldigi-fsq has the ability to transmit and receive small digital images selected
from those stored on the disk. The image transmission is similar to but not
compatible with the MFSKpic modes. FSQ images are always transmitted in a fixed
width to height ratio. The W x H format is not limited to a single ratio, nor is
it limited to just color, or just gray scale.
The start of the picture is signalled digitally, and the receiver simply captures
data continuously for W lines of H pixels, as requested, resulting in a WxH pixel
image, then reception stops.
The images are approximately in 4:3 or 3:4 aspect ratio. Images must be sent and
received in Directed Mode, and can be sent to just one recipient, to several
recipients, or everyone on the channel, just as with other messages.
Available image aspect ratios / formats include:
<ul>
<li>160x120 color (1)
<li>320x240 color (1)
<li>640x480 grey (1)
<li>640x480 color (1)
<li>240x300 color
<li>240x300 grey
<li>120x150 color
<li>120x150 grey
</ul>
(1) compatible with the program FSQCALL
<b>Narrow-Band Images</b>
FSQ Image Mode was designed for NVIS propagation on the lower HF bands.
Unlike SSTV, the pictures are sent relatively slowly, in a narrow bandwidth
(1/4 of SSTV), and as a result the picture signal to noise ratio is generally
better than SSTV for the same transmission power. As a guideline, FSQ signals
(before the picture is started) need to be about +10dB SNR for noise-free picture
reception.
FSQ pictures also offer significantly better reception than SSTV under NVIS
conditions. Because there is no picture sync, there is no risk of the picture
tearing due to timing changes, or breaking up during selective fades. All that
happens is that the image may noise up momentarily, but will stay correctly
aligned. The mode is also significantly less affected by ghosting.
<b>Image Format</b>
The image mode sampling rate is 12,000 samples/sec, the same as the text mode.
Each pixel consists of 10 samples, and there are P pixels/line. Therefore the
line period is 10 x P/12000 seconds, or the line rate 12000/(10 x P) lines/sec.
In colour, each line is sent three times, in BGR order.
As an example, if there were 320 pixels per line, and 240 lines, the line rate
would be 3.75 lines/sec, and 240 x 3 (for RGB) lines would take 192 seconds, or
3.2 minutes for a colour picture containing 76,800 pixels.
There is no horizontal (line) sync sent with the picture, and no vertical sync
at the start of the picture. As a result, it is possible for reception to start
slightly earlier or later than the standard delay from the time of the command,
depending on the relative speed of the computers used at either end. This has
two effects: first, the picture may be recorded shifted left or right, and the
pixel colour order may be wrong. This is easily fixed after reception using the
Phase control.
If the sound cards in the transmitting and receiving computers differ markedly
in sample rate, the resulting picture can also be skewed. A small timing
difference is enough to cause a noticeable slant in the picture. This is easily
fixed after reception using the Slant control. High quality sound cards should
be better than 5ppm, and result in barely noticeable slant, but some cheaper
computer built-in sound modules may be rather worse. If you plan to send FSQ
images you should calibrate your sound card to WWV.
<b>Receive Image</b>
<center>
\image html fsq-image-rx.png "Image Reception"
\image latex fsq-image-rx.png "Image Reception" width=4.5in
</center>
Reception is completely automatic. Provided the software is in Directed Mode, and
the sending station uses the correct callsign and trigger command, the decoder
will identify the picture start, and record the picture. In doing so, it
automatically opens a separate "FSQ Rx Image" dialog.
Demodulation uses a phase detection algorithm based on quadrature demodulation
using the current and previous samples at 12000 samples/sec. All the samples are
converted to pixels and stored, but only the average over every 10 samples is
displayed.
The raw image is stored in a temporary buffer of expanded size, which allows
fine adjustment of the slant and phase to be made before the image is sampled
and displayed.
If the transmitting station goes off the air or reception is lost during
recording of a picture, the recording will continue until the necessary number
of samples has been made, then reception stops.
\image html fsq-rx-image-raw.png "Received - no correction"
\image latex fsq-rx-image-raw.png "Received - no correction" width = 4.0in
The Rx Image dialog controls from left to right are:
- Reset: clears all rx data
- Phase adjustment: moves image left and right
- Slant adjustment: slews image diagonally
- Save: saves the image to the fldigi image folder with a date-time stamped file name
- Close: closes the image dialog
\image html fsq-rx-image-corrected.png "Received - phase corrected"
\image latex fsq-rx-image-corrected.png "Received - phase corrected" width = 4.0in
Image phase and slant should not be adjusted before the picture reception has
finished, as then only part of the image will be corrected.
<b>Transmit Image</b>
Access to the transmit image functions is only available via the heard list pop-up
menus. Right click on the recipient call sign and select the "Send Image to ..." item
from the pop-up menu.
<center>
\image html fsq-image-xmt.png "Image Transmission"
\image latex fsq-image-xmt.png "Image Transmission" width=4.5in
</center>
A file open dialog is displayed when the "Load" button is pressed on the TX Image
dialog. This allows the user to select any image in a number of different standard
formats. The image is rendered to the selected image size using a resampling process.
fldigi will try to force fit the image to the selected aspect ratio. You should
try to work with images that are in a 4:3 or a 3:4 aspect ratio. The selected
image does not need to be the same size. Fldigi will enlarge or reduce the image
using a resampling technique to fit the selected image size. The example photo
of Star Gazer lilies is a 3.2 MB file, 3008 x 2000 pixels. It was taken in my lily
patch in June 2014.
Once the image has been loaded, the user starts the transmission by pressing the
"Xmt" button on the transmit image dialog. fldigi formats the correct command
sequence and starts the transmission.
The recipient callsign for image transmission can be a single callsign, or allcall.
Sending to a single recipient or to allcall is accomplished as described above. To
send to multiple addresses you must add their callsigns to the Tx panel, separated
by spaces and with a trailing space. Then press the Xmt button on the Tx Image dialog.
fldigi returns to the receive mode at the conclusion of the image transfer.
\section fsq_rsid Disable RxID
You will probably want to disable the RxID detector during FSQ operations. If RxID
is enabled and an RsID signal is detected the program will switch to the mode
specified by the RxID. That will completely alter the user interface.
\ref fsq_page "Return to Top of Page"
<br>
\ref main_page "Return to Main Page"
*/

Wyświetl plik

@ -0,0 +1,103 @@
/**
\page fsq_configuration_page FSQ Configuration
\tableofcontents
\image html config-fsq.png ""
\image latex config-fsq.png "" width=5.0in
<br>
\section fsq_rx_parameters Rx Parameters
The FSQ decoder is essential a set of single frequency filters spaced by the interval
samplerate / symbol_length, 2.93 Hz. The filters are achieved using a Fast Fourier Transform.
Each spectral line (or bin) of the FFT is then filtered using a time domain filter called a
moving average (boxcar) filter. The moving average filter is the optimum filter
for locating a signal transition in the time domain. The moving average filter can
be adjusted to average 1 to 4 samples. A setting of 1 disables the filter. The
default value for the moving average filter is 3.
The filtered spectral lines are then tested for maximum value. The Min Hits adjustment sets
the number of consecutive times a spectral line is the maximum before being designated as
a detected signal. Min Hits can be set over the range 3 to 6. The default value is 3.
Images are detected by first converting the signal to a base band. This is accomplished
by mixing a 1500 Hz sine wave with the rx stream. This is equivalent to an analog receiver
that using direct conversion. The down converted signal can be filtered to reduce the
effect of noise. Your choice is NONE, 300, 400 or 500 Hz for the low pass filter 6 dB
cutoff frequency. Use the narrower filters for noisy conditions, but remember that filtering
will both reduce the image noise and also blur the image.
Callsigns that satisfy the parsing requirements will be added to the FSQ heard list.
You can elect to have the heard list periodically managed so that older entries are removed or aged.
The user can elect no aging, Never; or 1, 5 10, 20 minutes intervals for aging.
\section fsq_tx_parameters Tx Parameters
FSQ transmissions can occur ar 2, 3, 4.5, or 6 baud. The default rate is 4.5. The baud
rate can be selected on the fsq configuration tab, or by left clicking on the left
most entry on the fldigi main dialog status bar.
FSQ "Sounding" is a periodic transmission of your call sign followed by a colon. The
Sounding signal is a way of announcing your presence on the channel with the smallest
possible data stream. Other FSQ stations will add you to their Heard list if they detect
your Sounding signal. You set the Sounding interval to OFF, 1, 10 or 30 minutes.
Your QTC text can be sent using the "QTC" button on the main dialog. It can also be
requested for auto reply by another FSQ station.
All FSQ transmissions are designed to be inhibited so long as the software detects
a received signal (open squelch).
\section fsq_logging Logging
Any of the text in the Rx Panel or the Monitor Panel can be captured for copy, and
saving to a file. Simply right click on the panel for a pop menu.
Fldigi's FSQ also saves a continuous log of all Heard stations, and an Audit log that
includes all received data. These logs are named fsq_heard_log.txt and fsq_audit_log.txt
respectively. The logs are never cleared unless the operator does so using the operating
system file handling facilities. Data is appended to each log as it occurs. These logs
are located in the fldigi temp folder:
<br>
<center>
<table>
<tr>
<td><kbd>XP</kbd></td>
<td><kbd>C:\\Documents and Settings\\<username>\\fldigi.files\\temp</kbd></td>
</tr>
<tr>
<td><kbd>Vista</kbd></td>
<td><kbd>C:\\Users\\<username>\\fldigi.files\\temp</kbd></td>
</tr>
<tr>
<td><kbd>Win7</kbd></td>
<td><kbd>C:\\Users\\<username>\\fldigi.files\\temp</kbd></td>
</tr>
<tr>
<td><kbd>Win8</kbd></td>
<td>C:\\Users\\<username>\\fldigi.files\\temp</kbd></td>
</tr>
<tr>
<td><kbd>Linux</kbd></td>
<td><kbd>/home/\<user\>/.fldigi/temp</kbd></td>
</tr>
<tr>
<td><kbd>OS X</kbd></td>
<td><kbd>/home/\<user\>/.fldigi/temp</kbd></td>
</tr>
<tr>
<td><kbd>Unix</kbd></td>
<td><kbd>/home/\<user\>/.fldigi/temp</kbd></td>
</tr>
</table>
</center>
You can elect to disable the logging functions. You may also rename the log to suit
your particular operations.
<br>
\ref fsq_configuration_page "Return to Top of Page"
<br>
\ref main_page "Return to Main Page"
*/

Wyświetl plik

@ -76,6 +76,7 @@ but the defaults should be satisfactory for most users.
<li> \subpage cw_configuration_page </li>
<li> \subpage domino_ex_configuration_page </li>
<li> \subpage feld_hell_configuration_page </li>
<li> \subpage fsq_configuration_page </li>
<li> \subpage id_configuration_page </li>
<li> \subpage miscellaneous_configuration_page </li>
<li> \subpage mt63_configuration_page </li>

Wyświetl plik

@ -7,6 +7,7 @@
<li> \subpage cw_page </li>
<li> \subpage domino_ex_page </li>
<li> \subpage feld_hell_page </li>
<li> \subpage fsq_page </li>
<li> \subpage mfsk_page </li>
<li> \subpage mt63_page </li>
<li> \subpage navtex_and_sitorb_page </li>

Wyświetl plik

@ -2,7 +2,7 @@ fldigi_configuration.txt fldigi_developer.txt fldigi_logging.txt \
fldigi_macros.txt fldigi_modems.txt fldigi_operating.txt \
New-Install.txt thumb_drive.txt colorsandfonts.txt \
configcallsigndb.txt configContestia.txt configCW.txt \
configDomEX.txt configFH.txt ConfigID.txt ConfigMisc.txt \
configDomEX.txt configFSQ.txt configFH.txt ConfigID.txt ConfigMisc.txt \
configMT63.txt configOlivia.txt ConfigOperator.txt configPSK.txt \
configRTTY.txt configThor.txt ConfigUI-browser.txt \
ConfigUI-contest.txt ConfigUI-general.txt ConfigUI-logging.txt \
@ -10,7 +10,7 @@ ConfigUI-macros.txt ConfigUI-WF-controls.txt ConfigWaterfall.txt \
SoundCardSetup.txt Contest-How-To.txt cabrilloreporter.txt \
Logbook.txt LogExports.txt working_logs.txt Macros.txt \
InlineMacroTags.txt atMacroTags.txt advanced_qsy.txt execmacro.txt CW.txt \
DominoEX.txt hell.txt Contestia.txt MFSK.txt MT63.txt \
DominoEX.txt hell.txt Contestia.txt MFSK.txt MT63.txt FSQ.txt \
Navtex.txt psk.txt Olivia.txt RTTYFSK.txt Thor.txt \
throb.txt tune.txt WEFAX.txt WWV-xmt.txt FrequencyAnalysis.txt \
DigiscopeDisplay.txt DigiWWV.txt map.txt MousingKeyboardShortcuts.txt \

Wyświetl plik

@ -474,6 +474,7 @@ fldigi_SOURCES += \
include/Viewer.h \
include/viterbi.h \
include/waterfall.h \
include/fsq.h \
include/wwv.h \
include/xmlreader.h \
include/adif_def.h \
@ -603,6 +604,8 @@ fldigi_SOURCES += \
widgets/psk_browser.cxx \
widgets/smeter.cxx \
widgets/pwrmeter.cxx \
fsq/fsq.cxx \
fsq/fsq_monitor.cxx \
wwv/analysis.cxx \
wwv/fftscan.cxx \
wwv/wwv.cxx \
@ -633,9 +636,13 @@ EXTRA_fldigi_SOURCES += \
feld/FeldStyl-14.cxx \
feld/FeldVert-14.cxx \
feld/FeldWide-14.cxx \
fsq/fsq_varicode.cxx \
include/crc8.h \
include/Fl_Text_Buffer_mod.H \
include/Fl_Text_Display_mod.H \
include/Fl_Text_Editor_mod.H \
fsq/fsq-pic.cxx \
fsq/bitmaps.cxx \
mfsk/mfsk-pic.cxx \
mt63/alias_1k.dat \
mt63/alias_2k.dat \

Wyświetl plik

@ -26,6 +26,7 @@
#include "rx_extract.h"
#include "kmlserver.h"
#include "macroedit.h"
#include "fileselect.h"
extern void WefaxDestDirSet(Fl_File_Chooser *w, void *userdata);
#if USE_HAMLIB
#include "hamlib.h"
@ -57,6 +58,10 @@ static void cbRxFontBrowser(Fl_Widget*, void*) {
ReceiveText->setFont(font);
ReceiveText->setFontSize(size);
ReceiveText->setFontColor(progdefaults.RxFontcolor, FTextBase::RECV);
fsq_rx_text->setFont(font);
fsq_rx_text->setFontSize(size);
fsq_rx_text->setFontColor(progdefaults.RxFontcolor, FTextBase::RECV);
font_browser->hide();
@ -81,6 +86,10 @@ static void cbTxFontBrowser(Fl_Widget*, void*) {
TransmitText->setFontSize(size);
TransmitText->setFontColor(progdefaults.TxFontcolor, FTextBase::RECV);
fsq_tx_text->setFont(font);
fsq_tx_text->setFontSize(size);
fsq_tx_text->setFontColor(progdefaults.RxFontcolor, FTextBase::RECV);
font_browser->hide();
progdefaults.changed = true;
@ -299,6 +308,10 @@ static void cb_noiseDB(Fl_Counter2* o, void*) {
progdefaults.s2n = o->value();
}
Fl_Counter *ctrl_freq_offset=(Fl_Counter *)0;
Fl_Check_Button *btnOffsetOn=(Fl_Check_Button *)0;
Fl_Group *tabUI=(Fl_Group *)0;
Fl_Tabs *tabsUI=(Fl_Tabs *)0;
@ -2767,6 +2780,149 @@ static void cb_btnHellXmtWidth(Fl_Check_Button* o, void*) {
progdefaults.changed = true;
}
Fl_Group *tabFSQ=(Fl_Group *)0;
Fl_Value_Slider *valhits=(Fl_Value_Slider *)0;
static void cb_valhits(Fl_Value_Slider* o, void*) {
progdefaults.fsqhits=(int)o->value();
progdefaults.changed = true;
}
Fl_Choice *sel_fsq_lpf=(Fl_Choice *)0;
static void cb_sel_fsq_lpf(Fl_Choice* o, void*) {
progdefaults.fsq_img_filter=o->value();
progdefaults.changed = true;
}
Fl_Value_Slider *sldrMovAvg=(Fl_Value_Slider *)0;
static void cb_sldrMovAvg(Fl_Value_Slider* o, void*) {
progdefaults.fsq_movavg = o->value();
progdefaults.changed = true;
}
Fl_Choice *sel_fsq_heard_aging=(Fl_Choice *)0;
static void cb_sel_fsq_heard_aging(Fl_Choice* o, void*) {
progdefaults.fsq_heard_aging=o->value();
progdefaults.changed = true;
}
static void cb_btn_fsqbaud(Fl_Round_Button* o, void*) {
if (o->value() == 1) {
progdefaults.fsqbaud = 2;
btn_fsqbaud[1]->value(0);
btn_fsqbaud[2]->value(0);
btn_fsqbaud[3]->value(0);
}
progdefaults.changed = true;
}
static void cb_btn_fsqbaud1(Fl_Round_Button* o, void*) {
if (o->value() == 1) {
progdefaults.fsqbaud = 3;
btn_fsqbaud[0]->value(0);
btn_fsqbaud[2]->value(0);
btn_fsqbaud[3]->value(0);
}
progdefaults.changed = true;
}
static void cb_btn_fsqbaud2(Fl_Round_Button* o, void*) {
if (o->value() == 1) {
progdefaults.fsqbaud = 4.5;
btn_fsqbaud[0]->value(0);
btn_fsqbaud[1]->value(0);
btn_fsqbaud[3]->value(0);
}
progdefaults.changed = true;
}
Fl_Round_Button *btn_fsqbaud[4]={(Fl_Round_Button *)0};
static void cb_btn_fsqbaud3(Fl_Round_Button* o, void*) {
if (o->value() == 1) {
progdefaults.fsqbaud = 6;
btn_fsqbaud[0]->value(0);
btn_fsqbaud[1]->value(0);
btn_fsqbaud[2]->value(0);
}
progdefaults.changed = true;
}
static void cb_QTC(Fl_Input* o, void*) {
progdefaults.fsqQTCtext = o->value();
progdefaults.changed = true;
}
Fl_Choice *sel_fsq_frequency=(Fl_Choice *)0;
static void cb_sel_fsq_frequency(Fl_Choice* o, void*) {
progdefaults.fsq_frequency=o->value();
progdefaults.changed = true;
}
Fl_Choice *sel_fsq_sounder=(Fl_Choice *)0;
static void cb_sel_fsq_sounder(Fl_Choice* o, void*) {
progdefaults.fsq_sounder=o->value();
progdefaults.changed = true;
}
Fl_Check_Button *btn_fsq_lowercase=(Fl_Check_Button *)0;
static void cb_btn_fsq_lowercase(Fl_Check_Button* o, void*) {
progdefaults.fsq_lowercase=o->value();
progdefaults.changed = true;
}
Fl_Output *txtAuditLog=(Fl_Output *)0;
Fl_Light_Button *btn_enable_auditlog=(Fl_Light_Button *)0;
static void cb_btn_enable_auditlog(Fl_Light_Button* o, void*) {
progdefaults.fsq_enable_audit_log = o->value();
progdefaults.changed = true;
}
Fl_Button *btn_select_auditlog=(Fl_Button *)0;
static void cb_btn_select_auditlog(Fl_Button*, void*) {
std::string str = std::string(TempDir);
str.append(progdefaults.fsq_audit_log);
const char *fname = FSEL::saveas("Audit log", "*.txt\t*", str.c_str());
if (fname) {
progdefaults.fsq_audit_log = fl_filename_name(fname);
txtAuditLog->value(progdefaults.fsq_audit_log.c_str());
progdefaults.changed = true;
};
}
Fl_Output *txtHeardLog=(Fl_Output *)0;
Fl_Light_Button *btn_enable_fsq_heard_log=(Fl_Light_Button *)0;
static void cb_btn_enable_fsq_heard_log(Fl_Light_Button* o, void*) {
progdefaults.fsq_enable_heard_log = o->value();
progdefaults.changed = true;
}
Fl_Button *btn_select_fsq_heard_log=(Fl_Button *)0;
static void cb_btn_select_fsq_heard_log(Fl_Button*, void*) {
std::string str = std::string(TempDir);
str.append(progdefaults.fsq_heard_log);
const char *fname = FSEL::saveas("Heard log", "*.txt\t*", str.c_str());
if (fname) {
progdefaults.fsq_heard_log = fl_filename_name(fname);
txtHeardLog->value(progdefaults.fsq_heard_log.c_str());
progdefaults.changed = true;
};
}
Fl_Group *tabMT63=(Fl_Group *)0;
Fl_Check_Button *btnMT63_8bit=(Fl_Check_Button *)0;
@ -5366,6 +5522,7 @@ Fl_Double_Window* ConfigureDialog() {
tabOperator->tooltip(_("Operator information"));
tabOperator->callback((Fl_Callback*)cb_tabOperator);
tabOperator->when(FL_WHEN_CHANGED);
tabOperator->hide();
{ Fl_Group* o = new Fl_Group(55, 35, 490, 170, _("Station"));
o->box(FL_ENGRAVED_FRAME);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
@ -5450,8 +5607,7 @@ Fl_Double_Window* ConfigureDialog() {
btnNoiseOn->callback((Fl_Callback*)cb_btnNoiseOn);
o->value(progdefaults.noise);
} // Fl_Check_Button* btnNoiseOn
{ Fl_Counter2* o = noiseDB = new Fl_Counter2(90, 307, 89, 21, _("dB"));
noiseDB->type(1);
{ Fl_Counter2* o = noiseDB = new Fl_Counter2(312, 264, 130, 21, _("dB"));
noiseDB->box(FL_UP_BOX);
noiseDB->color(FL_BACKGROUND_COLOR);
noiseDB->selection_color(FL_INACTIVE_COLOR);
@ -5461,24 +5617,34 @@ Fl_Double_Window* ConfigureDialog() {
noiseDB->labelcolor(FL_FOREGROUND_COLOR);
noiseDB->minimum(-18);
noiseDB->maximum(60);
noiseDB->step(1);
noiseDB->value(20);
noiseDB->callback((Fl_Callback*)cb_noiseDB);
noiseDB->align(Fl_Align(FL_ALIGN_LEFT));
noiseDB->when(FL_WHEN_CHANGED);
o->value(progdefaults.s2n);
o->lstep(1);
} // Fl_Counter2* noiseDB
{ Fl_Counter* o = ctrl_freq_offset = new Fl_Counter(312, 304, 130, 21, _("freq-offset"));
ctrl_freq_offset->tooltip(_("ONLY FOR TESTING !"));
ctrl_freq_offset->minimum(-250);
ctrl_freq_offset->maximum(250);
ctrl_freq_offset->align(Fl_Align(FL_ALIGN_LEFT));
o->lstep(10);
} // Fl_Counter* ctrl_freq_offset
{ btnOffsetOn = new Fl_Check_Button(93, 307, 70, 15, _("Offset on"));
btnOffsetOn->down_box(FL_DOWN_BOX);
} // Fl_Check_Button* btnOffsetOn
grpNoise->end();
} // Fl_Group* grpNoise
tabOperator->end();
} // Fl_Group* tabOperator
{ tabUI = new Fl_Group(0, 25, 600, 355, _("UI"));
tabUI->tooltip(_("User Interface"));
tabUI->hide();
{ tabsUI = new Fl_Tabs(0, 25, 600, 355);
tabsUI->selection_color(FL_LIGHT1);
{ tabBrowser = new Fl_Group(0, 50, 600, 330, _("Browser"));
tabBrowser->tooltip(_("User Interface - Browser"));
tabBrowser->hide();
{ Fl_Group* o = new Fl_Group(30, 65, 540, 300);
o->box(FL_ENGRAVED_FRAME);
{ Fl_Spinner2* o = cntChannels = new Fl_Spinner2(46, 75, 50, 24, _("Channels, first channel starts at waterfall lower limit"));
@ -6234,7 +6400,6 @@ ab and newline are automatically included."));
} // Fl_Group* tabWF_UI
{ tabColorsFonts = new Fl_Group(0, 50, 600, 330, _("Clrs/Fnts"));
tabColorsFonts->tooltip(_("User Interface - Colors / Fonts"));
tabColorsFonts->hide();
{ tabsColors = new Fl_Tabs(0, 55, 600, 325);
{ Fl_Group* o = new Fl_Group(0, 75, 600, 305, _("Rx/Tx"));
{ Fl_ListBox* o = listbox_charset_status = new Fl_ListBox(96, 85, 165, 24, _("Rx/Tx Character set"));
@ -7055,6 +7220,7 @@ i on a\ntouch screen device such as a tablet."));
tabsModems->selection_color(FL_LIGHT1);
tabsModems->align(Fl_Align(FL_ALIGN_TOP_RIGHT));
{ tabCW = new Fl_Group(0, 50, 600, 330, _("CW"));
tabCW->hide();
{ tabsCW = new Fl_Tabs(0, 50, 600, 330);
tabsCW->selection_color(FL_LIGHT1);
{ Fl_Group* o = new Fl_Group(0, 75, 600, 305, _("General"));
@ -7838,6 +8004,130 @@ i on a\ntouch screen device such as a tablet."));
} // Fl_Group* o
tabFeld->end();
} // Fl_Group* tabFeld
{ tabFSQ = new Fl_Group(0, 50, 600, 330, _("FSQ"));
{ Fl_Group* o = new Fl_Group(5, 60, 585, 80, _("Rx Parameters"));
o->box(FL_ENGRAVED_BOX);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
{ Fl_Value_Slider* o = valhits = new Fl_Value_Slider(140, 72, 125, 21, _("Min Hits"));
valhits->tooltip(_("Minimum # hits in tone detector"));
valhits->type(5);
valhits->minimum(3);
valhits->maximum(6);
valhits->step(1);
valhits->value(3);
valhits->textsize(14);
valhits->callback((Fl_Callback*)cb_valhits);
valhits->align(Fl_Align(FL_ALIGN_RIGHT));
o->value(progdefaults.fsqhits);
} // Fl_Value_Slider* valhits
{ Fl_Choice* o = sel_fsq_lpf = new Fl_Choice(163, 104, 102, 21, _("Image LPF"));
sel_fsq_lpf->tooltip(_("Narrow LPF if image noisy"));
sel_fsq_lpf->down_box(FL_BORDER_BOX);
sel_fsq_lpf->callback((Fl_Callback*)cb_sel_fsq_lpf);
o->add("None"); o->add("300 Hz"); o->add("400 Hz"); o->add("500 Hz");
o->value(progdefaults.fsq_img_filter);
} // Fl_Choice* sel_fsq_lpf
{ Fl_Value_Slider* o = sldrMovAvg = new Fl_Value_Slider(410, 72, 125, 21, _("MovAvg:"));
sldrMovAvg->tooltip(_("Filter FFT output"));
sldrMovAvg->type(1);
sldrMovAvg->minimum(1);
sldrMovAvg->maximum(4);
sldrMovAvg->step(1);
sldrMovAvg->value(4);
sldrMovAvg->textsize(14);
sldrMovAvg->callback((Fl_Callback*)cb_sldrMovAvg);
sldrMovAvg->align(Fl_Align(FL_ALIGN_LEFT));
o->value(progdefaults.fsq_movavg);
} // Fl_Value_Slider* sldrMovAvg
{ Fl_Choice* o = sel_fsq_heard_aging = new Fl_Choice(433, 104, 102, 21, _("Heard aging"));
sel_fsq_heard_aging->tooltip(_("Remove call after ..."));
sel_fsq_heard_aging->down_box(FL_BORDER_BOX);
sel_fsq_heard_aging->callback((Fl_Callback*)cb_sel_fsq_heard_aging);
o->add("Never"); o->add("1 min"); o->add("5 min");o->add("10 min"); o->add("20 min"); o->add("20 min");
o->value(progdefaults.fsq_heard_aging);
} // Fl_Choice* sel_fsq_heard_aging
o->end();
} // Fl_Group* o
{ Fl_Group* o = new Fl_Group(5, 150, 585, 135, _("Tx Parameters"));
o->box(FL_ENGRAVED_BOX);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
{ Fl_Round_Button* o = btn_fsqbaud[0] = new Fl_Round_Button(90, 180, 55, 15, _("2 baud"));
btn_fsqbaud[0]->down_box(FL_ROUND_DOWN_BOX);
btn_fsqbaud[0]->callback((Fl_Callback*)cb_btn_fsqbaud);
o->value(progdefaults.fsqbaud == 2);
} // Fl_Round_Button* btn_fsqbaud[0]
{ Fl_Round_Button* o = btn_fsqbaud[1] = new Fl_Round_Button(198, 180, 55, 15, _("3 baud"));
btn_fsqbaud[1]->down_box(FL_ROUND_DOWN_BOX);
btn_fsqbaud[1]->callback((Fl_Callback*)cb_btn_fsqbaud1);
o->value(progdefaults.fsqbaud == 3);
} // Fl_Round_Button* btn_fsqbaud[1]
{ Fl_Round_Button* o = btn_fsqbaud[2] = new Fl_Round_Button(306, 180, 55, 15, _("4.5 baud"));
btn_fsqbaud[2]->down_box(FL_ROUND_DOWN_BOX);
btn_fsqbaud[2]->callback((Fl_Callback*)cb_btn_fsqbaud2);
o->value(progdefaults.fsqbaud == 4.5);
} // Fl_Round_Button* btn_fsqbaud[2]
{ Fl_Round_Button* o = btn_fsqbaud[3] = new Fl_Round_Button(415, 180, 55, 15, _("6 baud"));
btn_fsqbaud[3]->down_box(FL_ROUND_DOWN_BOX);
btn_fsqbaud[3]->callback((Fl_Callback*)cb_btn_fsqbaud3);
o->value(progdefaults.fsqbaud == 6);
} // Fl_Round_Button* btn_fsqbaud[3]
{ Fl_Input* o = new Fl_Input(90, 253, 456, 23, _("QTC:"));
o->tooltip(_("Enter QTC text"));
o->callback((Fl_Callback*)cb_QTC);
o->value(progdefaults.fsqQTCtext.c_str());
} // Fl_Input* o
{ Fl_Choice* o = sel_fsq_frequency = new Fl_Choice(250, 219, 102, 21, _("Center freq"));
sel_fsq_frequency->down_box(FL_BORDER_BOX);
sel_fsq_frequency->callback((Fl_Callback*)cb_sel_fsq_frequency);
sel_fsq_frequency->align(Fl_Align(FL_ALIGN_TOP));
sel_fsq_frequency->hide();
o->add("1150"); o->add("1500"); o->add("Variable");
o->value(progdefaults.fsq_frequency);
} // Fl_Choice* sel_fsq_frequency
{ Fl_Choice* o = sel_fsq_sounder = new Fl_Choice(90, 214, 102, 21, _("Sounder"));
sel_fsq_sounder->tooltip(_("Send beacon every ..."));
sel_fsq_sounder->down_box(FL_BORDER_BOX);
sel_fsq_sounder->callback((Fl_Callback*)cb_sel_fsq_sounder);
o->add("OFF"); o->add("1 min"); o->add("10 min"); o->add("30 min");
o->value(progdefaults.fsq_sounder);
} // Fl_Choice* sel_fsq_sounder
{ Fl_Check_Button* o = btn_fsq_lowercase = new Fl_Check_Button(306, 217, 70, 15, _("MYCALL always lower case"));
btn_fsq_lowercase->tooltip(_("convert operator callsign to lower case"));
btn_fsq_lowercase->down_box(FL_DOWN_BOX);
btn_fsq_lowercase->callback((Fl_Callback*)cb_btn_fsq_lowercase);
o->value(progdefaults.fsq_lowercase);
} // Fl_Check_Button* btn_fsq_lowercase
o->end();
} // Fl_Group* o
{ Fl_Group* o = new Fl_Group(5, 291, 585, 80, _("Logging"));
o->box(FL_ENGRAVED_BOX);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE));
{ Fl_Output* o = txtAuditLog = new Fl_Output(82, 311, 325, 25, _("Audit log"));
o->value(progdefaults.fsq_audit_log.c_str());
} // Fl_Output* txtAuditLog
{ Fl_Light_Button* o = btn_enable_auditlog = new Fl_Light_Button(421, 313, 74, 20, _("Enable"));
btn_enable_auditlog->selection_color((Fl_Color)2);
btn_enable_auditlog->callback((Fl_Callback*)cb_btn_enable_auditlog);
o->value(progdefaults.fsq_enable_audit_log);
} // Fl_Light_Button* btn_enable_auditlog
{ btn_select_auditlog = new Fl_Button(509, 313, 70, 20, _("Select"));
btn_select_auditlog->callback((Fl_Callback*)cb_btn_select_auditlog);
} // Fl_Button* btn_select_auditlog
{ Fl_Output* o = txtHeardLog = new Fl_Output(80, 340, 325, 25, _("Heard log"));
o->value(progdefaults.fsq_heard_log.c_str());
} // Fl_Output* txtHeardLog
{ Fl_Light_Button* o = btn_enable_fsq_heard_log = new Fl_Light_Button(419, 342, 74, 20, _("Enable"));
btn_enable_fsq_heard_log->selection_color((Fl_Color)2);
btn_enable_fsq_heard_log->callback((Fl_Callback*)cb_btn_enable_fsq_heard_log);
o->value(progdefaults.fsq_enable_heard_log);
} // Fl_Light_Button* btn_enable_fsq_heard_log
{ btn_select_fsq_heard_log = new Fl_Button(507, 342, 70, 20, _("Select"));
btn_select_fsq_heard_log->callback((Fl_Callback*)cb_btn_select_fsq_heard_log);
} // Fl_Button* btn_select_fsq_heard_log
o->end();
} // Fl_Group* o
tabFSQ->end();
} // Fl_Group* tabFSQ
{ tabMT63 = new Fl_Group(0, 50, 600, 330, _("MT-63"));
tabMT63->hide();
{ Fl_Group* o = new Fl_Group(55, 73, 490, 84);
@ -8622,7 +8912,7 @@ le Earth)"));
} // Fl_Group* o
tabTHOR->end();
} // Fl_Group* tabTHOR
{ tabNavtex = new Fl_Group(0, 50, 600, 330, _("Navtex"));
{ tabNavtex = new Fl_Group(0, 50, 600, 330, _("Nav"));
tabNavtex->hide();
{ Fl_Check_Button* o = btnNvtxAdifLog = new Fl_Check_Button(171, 79, 235, 30, _("Log Navtex messages to Adif file"));
btnNvtxAdifLog->down_box(FL_DOWN_BOX);
@ -8637,7 +8927,7 @@ le Earth)"));
} // Fl_Check_Button* btnNvtxKmlLog
tabNavtex->end();
} // Fl_Group* tabNavtex
{ tabWefax = new Fl_Group(0, 50, 600, 330, _("Wefax"));
{ tabWefax = new Fl_Group(0, 50, 600, 330, _("WFax"));
tabWefax->hide();
{ Fl_Group* o = new Fl_Group(2, 63, 598, 300);
{ Fl_Check_Button* o = btnWefaxAdifLog = new Fl_Check_Button(94, 137, 235, 30, _("Log Wefax messages to Adif file"));

Wyświetl plik

@ -101,6 +101,9 @@ decl {\#include "kmlserver.h"} {private local
decl {\#include "macroedit.h"} {private local
}
decl {\#include "fileselect.h"} {private local
}
decl {extern void WefaxDestDirSet(Fl_File_Chooser *w, void *userdata);} {private local
}
@ -115,7 +118,7 @@ decl {Fl_Double_Window *dlgConfig;} {public local
decl {Mode_Browser* mode_browser;} {public local
}
Function {choose_color(Fl_Color & c)} {open private return_type void
Function {choose_color(Fl_Color & c)} {private return_type void
} {
code {unsigned char r, g, b;
Fl::get_color(c, r, g, b);
@ -123,7 +126,7 @@ if (fl_color_chooser("Font color", r, g, b))
c = fl_rgb_color(r, g, b);} {}
}
Function {cbRxFontBrowser(Fl_Widget*, void*)} {private return_type void
Function {cbRxFontBrowser(Fl_Widget*, void*)} {open private return_type void
} {
code {Fl_Font font = font_browser->fontNumber();
int size = font_browser->fontSize();
@ -141,13 +144,18 @@ Function {cbRxFontBrowser(Fl_Widget*, void*)} {private return_type void
ReceiveText->setFont(font);
ReceiveText->setFontSize(size);
ReceiveText->setFontColor(progdefaults.RxFontcolor, FTextBase::RECV);
fsq_rx_text->setFont(font);
fsq_rx_text->setFontSize(size);
fsq_rx_text->setFontColor(progdefaults.RxFontcolor, FTextBase::RECV);
font_browser->hide();
progdefaults.changed = true;} {}
progdefaults.changed = true;} {selected
}
}
Function {cbTxFontBrowser(Fl_Widget*, void*)} {private return_type void
Function {cbTxFontBrowser(Fl_Widget*, void*)} {open private return_type void
} {
code {Fl_Font font = font_browser->fontNumber();
int size = font_browser->fontSize();
@ -166,12 +174,16 @@ Function {cbTxFontBrowser(Fl_Widget*, void*)} {private return_type void
TransmitText->setFontSize(size);
TransmitText->setFontColor(progdefaults.TxFontcolor, FTextBase::RECV);
fsq_tx_text->setFont(font);
fsq_tx_text->setFontSize(size);
fsq_tx_text->setFontColor(progdefaults.RxFontcolor, FTextBase::RECV);
font_browser->hide();
progdefaults.changed = true;} {}
}
Function {cbMacroEditFontBrowser(Fl_Widget*, void*)} {open private return_type void
Function {cbMacroEditFontBrowser(Fl_Widget*, void*)} {private return_type void
} {
code {Fl_Font font = font_browser->fontNumber();
int size = font_browser->fontSize();
@ -340,15 +352,15 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
static const char szProsigns[] = "~|%|&|+|=|{|}|<|>|[|]| ";} {}
Fl_Window {} {
label {Fldigi configuration} open
xywh {666 113 600 415} type Double color 45 selection_color 51 labelsize 18 align 80 non_modal visible
xywh {996 32 600 415} type Double color 45 selection_color 51 labelsize 18 align 80 non_modal visible
} {
Fl_Tabs tabsConfigure {open
xywh {0 0 600 380} color 50 selection_color 50
} {
Fl_Group tabOperator {
label Operator
callback {progdefaults.changed = true;} open selected
tooltip {Operator information} xywh {0 25 600 355} when 1
callback {progdefaults.changed = true;} open
tooltip {Operator information} xywh {0 25 600 355} when 1 hide
} {
Fl_Group {} {
label Station open
@ -420,22 +432,32 @@ progdefaults.changed = true;}
Fl_Counter noiseDB {
label dB
callback {progdefaults.s2n = o->value();}
xywh {90 307 89 21} type Simple align 4 minimum -18 maximum 60 step 1 value 20
xywh {312 264 130 21} align 4 minimum -18 maximum 60 value 20
code0 {o->value(progdefaults.s2n);}
code1 {o->lstep(1);}
class Fl_Counter2
}
Fl_Counter ctrl_freq_offset {
label {freq-offset}
tooltip {ONLY FOR TESTING !} xywh {312 304 130 21} align 4 minimum -250 maximum 250
code0 {o->lstep(10);}
}
Fl_Check_Button btnOffsetOn {
label {Offset on}
xywh {93 307 70 15} down_box DOWN_BOX
}
}
}
Fl_Group tabUI {
label UI open
tooltip {User Interface} xywh {0 25 600 355} hide
tooltip {User Interface} xywh {0 25 600 355}
} {
Fl_Tabs tabsUI {open
xywh {0 25 600 355} selection_color 50
} {
Fl_Group tabBrowser {
label Browser
tooltip {User Interface - Browser} xywh {0 50 600 330}
tooltip {User Interface - Browser} xywh {0 50 600 330} hide
} {
Fl_Group {} {open
xywh {30 65 540 300} box ENGRAVED_FRAME
@ -1325,7 +1347,7 @@ WF_UI();}
}
Fl_Group tabColorsFonts {
label {Clrs/Fnts} open
tooltip {User Interface - Colors / Fonts} xywh {0 50 600 330} hide
tooltip {User Interface - Colors / Fonts} xywh {0 50 600 330}
} {
Fl_Tabs tabsColors {open
xywh {0 55 600 325}
@ -2806,7 +2828,7 @@ behaves inside the waterfall} xywh {65 207 150 22} box DOWN_BOX color 7 align 8
} {
Fl_Group tabCW {
label CW open
xywh {0 50 600 330}
xywh {0 50 600 330} hide
} {
Fl_Tabs tabsCW {open
xywh {0 50 600 330} selection_color 50
@ -3274,7 +3296,7 @@ progdefaults.changed = true;} open
}
}
Fl_Group tabDomEX {
label Dom
label Dom open
xywh {0 50 600 330} hide
} {
Fl_Group {} {open
@ -3411,6 +3433,183 @@ progdefaults.changed = true;}
}
}
}
Fl_Group tabFSQ {
label FSQ open
xywh {0 50 600 330}
} {
Fl_Group {} {
label {Rx Parameters} open
xywh {5 60 585 80} box ENGRAVED_BOX align 21
} {
Fl_Value_Slider valhits {
label {Min Hits}
callback {progdefaults.fsqhits=(int)o->value();
progdefaults.changed = true;}
tooltip {Minimum \# hits in tone detector} xywh {140 72 125 21} type {Horz Knob} align 8 minimum 3 maximum 6 step 1 value 3 textsize 14
code0 {o->value(progdefaults.fsqhits);}
}
Fl_Choice sel_fsq_lpf {
label {Image LPF}
callback {progdefaults.fsq_img_filter=o->value();
progdefaults.changed = true;} open
tooltip {Narrow LPF if image noisy} xywh {163 104 102 21} down_box BORDER_BOX
code0 {o->add("None"); o->add("300 Hz"); o->add("400 Hz"); o->add("500 Hz");}
code1 {o->value(progdefaults.fsq_img_filter);}
} {}
Fl_Value_Slider sldrMovAvg {
label {MovAvg:}
callback {progdefaults.fsq_movavg = o->value();
progdefaults.changed = true;}
tooltip {Filter FFT output} xywh {410 72 125 21} type Horizontal align 4 minimum 1 maximum 4 step 1 value 4 textsize 14
code0 {o->value(progdefaults.fsq_movavg);}
}
Fl_Choice sel_fsq_heard_aging {
label {Heard aging}
callback {progdefaults.fsq_heard_aging=o->value();
progdefaults.changed = true;} open
tooltip {Remove call after ...} xywh {433 104 102 21} down_box BORDER_BOX
code0 {o->add("Never"); o->add("1 min"); o->add("5 min");o->add("10 min"); o->add("20 min"); o->add("20 min");}
code1 {o->value(progdefaults.fsq_heard_aging);}
} {}
}
Fl_Group {} {
label {Tx Parameters} open
xywh {5 150 585 135} box ENGRAVED_BOX align 21
} {
Fl_Round_Button {btn_fsqbaud[0]} {
label {2 baud}
callback {if (o->value() == 1) {
progdefaults.fsqbaud = 2;
btn_fsqbaud[1]->value(0);
btn_fsqbaud[2]->value(0);
btn_fsqbaud[3]->value(0);
}
progdefaults.changed = true;}
xywh {90 180 55 15} down_box ROUND_DOWN_BOX
code0 {o->value(progdefaults.fsqbaud == 2);}
}
Fl_Round_Button {btn_fsqbaud[1]} {
label {3 baud}
callback {if (o->value() == 1) {
progdefaults.fsqbaud = 3;
btn_fsqbaud[0]->value(0);
btn_fsqbaud[2]->value(0);
btn_fsqbaud[3]->value(0);
}
progdefaults.changed = true;}
xywh {198 180 55 15} down_box ROUND_DOWN_BOX
code0 {o->value(progdefaults.fsqbaud == 3);}
}
Fl_Round_Button {btn_fsqbaud[2]} {
label {4.5 baud}
callback {if (o->value() == 1) {
progdefaults.fsqbaud = 4.5;
btn_fsqbaud[0]->value(0);
btn_fsqbaud[1]->value(0);
btn_fsqbaud[3]->value(0);
}
progdefaults.changed = true;}
xywh {306 180 55 15} down_box ROUND_DOWN_BOX
code0 {o->value(progdefaults.fsqbaud == 4.5);}
}
Fl_Round_Button {btn_fsqbaud[3]} {
label {6 baud}
callback {if (o->value() == 1) {
progdefaults.fsqbaud = 6;
btn_fsqbaud[0]->value(0);
btn_fsqbaud[1]->value(0);
btn_fsqbaud[2]->value(0);
}
progdefaults.changed = true;}
xywh {415 180 55 15} down_box ROUND_DOWN_BOX
code0 {o->value(progdefaults.fsqbaud == 6);}
}
Fl_Input {} {
label {QTC:}
callback {progdefaults.fsqQTCtext = o->value();
progdefaults.changed = true;}
tooltip {Enter QTC text} xywh {90 253 456 23}
code0 {o->value(progdefaults.fsqQTCtext.c_str());}
}
Fl_Choice sel_fsq_frequency {
label {Center freq}
callback {progdefaults.fsq_frequency=o->value();
progdefaults.changed = true;} open
xywh {250 219 102 21} down_box BORDER_BOX align 1 hide
code0 {o->add("1150"); o->add("1500"); o->add("Variable");}
code1 {o->value(progdefaults.fsq_frequency);}
} {}
Fl_Choice sel_fsq_sounder {
label Sounder
callback {progdefaults.fsq_sounder=o->value();
progdefaults.changed = true;} open
tooltip {Send beacon every ...} xywh {90 214 102 21} down_box BORDER_BOX
code0 {o->add("OFF"); o->add("1 min"); o->add("10 min"); o->add("30 min");}
code1 {o->value(progdefaults.fsq_sounder);}
} {}
Fl_Check_Button btn_fsq_lowercase {
label {MYCALL always lower case}
callback {progdefaults.fsq_lowercase=o->value();
progdefaults.changed = true;}
tooltip {convert operator callsign to lower case} xywh {306 217 70 15} down_box DOWN_BOX
code0 {o->value(progdefaults.fsq_lowercase);}
}
}
Fl_Group {} {
label Logging open
xywh {5 291 585 80} box ENGRAVED_BOX align 21
} {
Fl_Output txtAuditLog {
label {Audit log}
xywh {82 311 325 25}
code0 {o->value(progdefaults.fsq_audit_log.c_str());}
}
Fl_Light_Button btn_enable_auditlog {
label Enable
callback {progdefaults.fsq_enable_audit_log = o->value();
progdefaults.changed = true;}
xywh {421 313 74 20} selection_color 2
code0 {o->value(progdefaults.fsq_enable_audit_log);}
}
Fl_Button btn_select_auditlog {
label Select
callback {std::string str = std::string(TempDir);
str.append(progdefaults.fsq_audit_log);
const char *fname = FSEL::saveas("Audit log", "*.txt\\t*", str.c_str());
if (fname) {
progdefaults.fsq_audit_log = fl_filename_name(fname);
txtAuditLog->value(progdefaults.fsq_audit_log.c_str());
progdefaults.changed = true;
}}
xywh {509 313 70 20}
}
Fl_Output txtHeardLog {
label {Heard log}
xywh {80 340 325 25}
code0 {o->value(progdefaults.fsq_heard_log.c_str());}
}
Fl_Light_Button btn_enable_fsq_heard_log {
label Enable
callback {progdefaults.fsq_enable_heard_log = o->value();
progdefaults.changed = true;}
xywh {419 342 74 20} selection_color 2
code0 {o->value(progdefaults.fsq_enable_heard_log);}
}
Fl_Button btn_select_fsq_heard_log {
label Select
callback {std::string str = std::string(TempDir);
str.append(progdefaults.fsq_heard_log);
const char *fname = FSEL::saveas("Heard log", "*.txt\\t*", str.c_str());
if (fname) {
progdefaults.fsq_heard_log = fl_filename_name(fname);
txtHeardLog->value(progdefaults.fsq_heard_log.c_str());
progdefaults.changed = true;
}}
xywh {507 342 70 20}
}
}
}
Fl_Group tabMT63 {
label {MT-63} open
xywh {0 50 600 330} hide
@ -4063,7 +4262,7 @@ progdefaults.changed = true;}
}
}
Fl_Group tabNavtex {
label Navtex
label Nav
xywh {0 50 600 330} hide
} {
Fl_Check_Button btnNvtxAdifLog {
@ -4082,7 +4281,7 @@ progdefaults.changed = true;}
}
}
Fl_Group tabWefax {
label Wefax open
label WFax open
xywh {0 50 600 330} hide
} {
Fl_Group {} {open

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,52 @@
// ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flrig.
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include <FL/Fl_Bitmap.H>
static unsigned char s2n_data[] = {
0x02, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
0x01, 0x80, 0x00, 0x40, 0x00, 0x80, 0x00, 0x40, 0x02, 0x80, 0x00, 0x00,
0x01, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40,
0x00, 0x80, 0x00, 0x40, 0x02, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
0x01, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00, 0x80, 0x00, 0x40,
0x02, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
0x01, 0x80, 0x00, 0x40, 0x00, 0x80, 0x00, 0x40, 0x02, 0x80, 0x00, 0x00,
0x01, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40,
0x00, 0x80, 0x00, 0x40, 0x02, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00,
0x01, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00, 0x80, 0x00, 0x40,
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x80,
0x01, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x20,
0x12, 0x00, 0x00, 0x92, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
0x12, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x90,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x40,
0x02, 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x88, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x23, 0x12, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x20,
0x12, 0x00, 0x00, 0x84, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
0x12, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x20, 0x12, 0x00, 0x00, 0x82,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x0c, 0x00, 0x00, 0x80,
0x01, 0x00, 0x00, 0x70, 0x0c, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
Fl_Bitmap image_s2n(s2n_data, 160, 16);

556
src/fsq/fsq-pic.cxx 100644
Wyświetl plik

@ -0,0 +1,556 @@
// ----------------------------------------------------------------------------
// fsqpic.cxx -- fsq image support functions
//
// Copyright (C) 2015
// Dave Freese, W1HKJ
//
// This file is part of fldigi. Adapted from code contained in gfsq source code
// distribution.
//
// Fldigi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Fldigi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include <FL/Fl_Counter.H>
#include <FL/Fl_Choice.H>
#include "gettext.h"
#include "fileselect.h"
Fl_Double_Window *fsqpicRxWin = (Fl_Double_Window *)0;
picture *fsqpicRx = (picture *)0;
Fl_Button *btnfsqRxReset = (Fl_Button *)0;
Fl_Button *btnfsqRxSave = (Fl_Button *)0;
Fl_Button *btnfsqRxClose = (Fl_Button *)0;
Fl_Counter *cnt_phase = (Fl_Counter *)0;
Fl_Counter *cnt_slant = (Fl_Counter *)0;
Fl_Double_Window *fsqpicTxWin = (Fl_Double_Window *)0;
picture *fsqpicTx = (picture *)0;
Fl_Button *btnfsqpicTransmit = (Fl_Button *)0;
Fl_Button *btnfsqpicTxSendAbort = (Fl_Button *)0;
Fl_Button *btnfsqpicTxLoad = (Fl_Button *)0;
Fl_Button *btnfsqpicTxClose = (Fl_Button *)0;
Fl_Choice *selfsqpicSize = (Fl_Choice *)0;
Fl_Shared_Image *fsqTxImg = (Fl_Shared_Image *)0;
unsigned char *fsqxmtimg = (unsigned char *)0;
unsigned char *fsqxmtpicbuff = (unsigned char *)0;
#define RAWSIZE 640*(480 + 8)*3*10
#define RAWSTART 640*4*3*10
unsigned char rawvideo[RAWSIZE + 1];
int numpixels;
int pixelptr;
int rawcol;
int rawrow;
int rawrgb;
char image_type = 'S';
int fsq_txSPP = 8;
char fsq_txclr_tooltip[24];
char fsq_txgry_tooltip[24];
static int translate = 0;
static bool enabled = false;
void correct_video()
{
int W = fsqpicRx->w();
int H = fsqpicRx->h();
int slant = cnt_slant->value();
int vidsize = W * H;
int index, rowptr, colptr;
float ratio = (((float)vidsize - (float)slant)/(float)vidsize);
unsigned char vid[W * H * 3];
for (int row = 0; row < H; row++) {
rowptr = W * 3 * row * 10;
for (int col = 0; col < W; col++) {
colptr = 10*col;
for (int rgb = 0; rgb < 3; rgb++) {
index = ratio*(rowptr + colptr + 10*W*rgb);
index += RAWSTART - 10*pixelptr;
if (index < 2) index = 2;
if (index > RAWSIZE - 2) index = RAWSIZE - 2;
vid[2 - rgb + 3 * (col + row * W)] = rawvideo[index];
}
}
}
fsqpicRx->video(vid, W*H*3);
}
void fsq_updateRxPic(unsigned char data, int pos)
{
if (!fsqpicRxWin->shown()) fsqpicRx->show();
fsqpicRx->pixel(data, pos);
int W = fsqpicRx->w();
if (image_type == 'F' || image_type == 'p' || image_type == 'm') {
int n = RAWSTART + 10*(rawcol + W * (rawrgb + 3 * rawrow));
if (n < RAWSIZE)
for (int i = 0; i < 10; i++) rawvideo[n + i] = data;
rawrgb++;
if (rawrgb == 3) {
rawrgb = 0;
rawcol++;
if (rawcol == W) {
rawcol = 0;
rawrow++;
}
}
} else
for (int i = 0; i < 10; i++) rawvideo[RAWSTART + 10*numpixels + i] = data;
numpixels++;
if (numpixels >= (RAWSIZE - RAWSTART - 10))
numpixels = RAWSIZE - RAWSTART - 10;
}
void cb_btnfsqRxReset(Fl_Widget *, void *)
{
progStatus.fsq_rx_abort = true;
}
void cb_btnfsqRxSave(Fl_Widget *, void *)
{
fsqpicRx->save_png(PicsDir.c_str());
// FILE *raw = fopen("image.raw", "wb");
// std::cout << "wrote " << fwrite(rawvideo, 1, RAWSIZE, raw) << "\n";
// fclose(raw);
}
void cb_btnfsqRxClose(Fl_Widget *, void *)
{
fsqpicRxWin->hide();
progStatus.fsq_rx_abort = true;
// fsqpicRxWin->hide();
// FILE *raw = fopen("image.raw", "rb");
// std::cout << "read " << fread(rawvideo, 1, RAWSIZE, raw) << "\n";
// fclose(raw);
// correct_video();
}
void cb_cnt_phase(Fl_Widget *, void *data)
{
pixelptr = cnt_phase->value();
if (pixelptr >= RAWSTART/10) {
pixelptr = RAWSTART/10 - 1;
cnt_phase->value(pixelptr);
}
if (pixelptr < -RAWSTART/10) {
pixelptr = -RAWSTART/10;
cnt_phase->value(pixelptr);
}
correct_video();
}
void cb_cnt_slant(Fl_Widget *, void *)
{
correct_video();
}
void fsq_disableshift()
{
if (!fsqpicRxWin) return;
cnt_phase->deactivate();
cnt_slant->deactivate();
btnfsqRxSave->deactivate();
fsqpicRxWin->redraw();
}
void fsq_enableshift()
{
if (!fsqpicRxWin) return;
cnt_phase->activate();
cnt_slant->activate();
btnfsqRxSave->activate();
fsqpicRxWin->redraw();
}
void fsq_createRxViewer()
{
fsqpicRxWin = new Fl_Double_Window(324, 274, _("FSQ Rx Image"));
fsqpicRxWin->xclass(PACKAGE_NAME);
fsqpicRxWin->begin();
fsqpicRx = new picture(2, 2, 320, 240);
fsqpicRx->noslant();
Fl_Group *buttons = new Fl_Group(0, fsqpicRxWin->h() - 26, fsqpicRxWin->w(), 26, "");
buttons->box(FL_FLAT_BOX);
btnfsqRxReset = new Fl_Button(2, fsqpicRxWin->h() - 26, 40, 24, "Reset");
btnfsqRxReset->callback(cb_btnfsqRxReset, 0);
cnt_phase = new Fl_Counter(46, fsqpicRxWin->h() - 24, 80, 20, "");
cnt_phase->step(1);
cnt_phase->lstep(10);
cnt_phase->minimum(-RAWSTART + 1);
cnt_phase->maximum(RAWSTART - 1);
cnt_phase->value(0);
cnt_phase->callback(cb_cnt_phase, 0);
cnt_phase->tooltip(_("Phase correction"));
cnt_slant = new Fl_Counter(140, fsqpicRxWin->h() - 24, 80, 20, "");
cnt_slant->step(1);
cnt_slant->lstep(10);
cnt_slant->minimum(-200);
cnt_slant->maximum(200);
cnt_slant->value(0);
cnt_slant->callback(cb_cnt_slant, 0);
cnt_slant->tooltip(_("Slant correction"));
btnfsqRxSave = new Fl_Button(226, fsqpicRxWin->h() - 26, 45, 24, _("Save"));
btnfsqRxSave->callback(cb_btnfsqRxSave, 0);
btnfsqRxClose = new Fl_Button(273, fsqpicRxWin->h() - 26, 45, 24, _("Close"));
btnfsqRxClose->callback(cb_btnfsqRxClose, 0);
buttons->end();
fsqpicRxWin->end();
fsqpicRxWin->resizable(fsqpicRx);
numpixels = 0;
}
void fsq_showRxViewer(int W, int H, char itype)
{
if (!fsqpicRxWin) fsq_createRxViewer();
int winW, winH;
int fsqpicX, fsqpicY;
winW = W < 320 ? 324 : W + 4;
winH = H < 240 ? 274 : H + 34;
fsqpicX = (winW - W) / 2;
fsqpicY = (winH - 30 - H) / 2;
fsqpicRxWin->size(winW, winH);
fsqpicRx->resize(fsqpicX, fsqpicY, W, H);
fsqpicRxWin->init_sizes();
fsqpicRx->clear();
fsqpicRxWin->show();
fsq_disableshift();
memset(rawvideo, 0, RAWSIZE);
numpixels = 0;
pixelptr = 0;
rawrow = rawrgb = rawcol = 0;
image_type = itype;
}
void fsq_clear_rximage()
{
fsqpicRx->clear();
fsq_disableshift();
translate = 0;
enabled = false;
numpixels = 0;
pixelptr = 0;
cnt_phase->value(0);
cnt_slant->value(0);
rawrow = rawrgb = rawcol = 0;
}
//------------------------------------------------------------------------------
// image transmit functions
//------------------------------------------------------------------------------
int fsq_load_image(const char *n, int W, int H) {
int D = 0;
unsigned char *img_data;
switch (selfsqpicSize->value()) {
case 0 : W = 160; H = 120; break;
case 1 : W = 320; H = 240; break;
case 2 : W = 640; H = 480; break;
case 3 : W = 640; H = 480; break;
case 4 : W = 240; H = 300; break;
case 5 : W = 240; H = 300; break;
case 6 : W = 120; H = 150; break;
case 7 : W = 120; H = 150; break;
}
if (fsqTxImg) {
fsqTxImg->release();
fsqTxImg = 0;
}
fsqTxImg = Fl_Shared_Image::get(n, W, H);
if (!fsqTxImg)
return 0;
if (fsqTxImg->count() > 1) {
fsqTxImg->release();
fsqTxImg = 0;
return 0;
}
fsqpicTx->hide();
fsqpicTx->clear();
img_data = (unsigned char *)fsqTxImg->data()[0];
D = fsqTxImg->d();
if (fsqxmtimg) delete [] fsqxmtimg;
fsqxmtimg = new unsigned char [W * H * 3];
if (D == 3)
memcpy(fsqxmtimg, img_data, W*H*3);
else if (D == 4) {
int i, j, k;
for (i = 0; i < W*H; i++) {
j = i*3; k = i*4;
fsqxmtimg[j] = img_data[k];
fsqxmtimg[j+1] = img_data[k+1];
fsqxmtimg[j+2] = img_data[k+2];
}
} else if (D == 1) {
int i, j;
for (i = 0; i < W*H; i++) {
j = i * 3;
fsqxmtimg[j] = fsqxmtimg[j+1] = fsqxmtimg[j+2] = img_data[i];
}
} else
return 0;
// fsq_showTxViewer(W, H);
char* label = strdup(n);
fsqpicTxWin->copy_label(basename(label));
free(label);
// load the fsqpicture widget with the rgb image
fsqpicTx->show();
fsqpicTxWin->redraw();
fsqpicTx->video(fsqxmtimg, W * H * 3);
btnfsqpicTransmit->activate();
return 1;
}
void fsq_updateTxPic(unsigned char data, int pos)
{
if (!fsqpicTxWin->shown()) fsqpicTx->show();
fsqpicTx->pixel(data, pos);
}
void cb_fsqpicTxLoad(Fl_Widget *, void *)
{
const char *fn =
FSEL::select(_("Load image file"), "Image\t*.{png,,gif,jpg,jpeg}\n", PicsDir.c_str());
if (fn)
fsq_load_image(fn);
}
void fsq_clear_tximage()
{
fsqpicTx->clear();
}
void cb_fsqpicTxClose( Fl_Widget *w, void *)
{
fsqpicTxWin->hide();
}
int fsqpic_TxGetPixel(int pos, int color)
{
return fsqxmtimg[3*pos + color]; // color = {RED, GREEN, BLUE}
}
void cb_fsqpicTransmit( Fl_Widget *w, void *)
{
fsq_tx_text->add(fsq_selected_call.c_str());
switch (selfsqpicSize->value()) {
case 0: fsq_tx_text->add("% S"); break;
case 1: fsq_tx_text->add("% L"); break;
case 2: fsq_tx_text->add("% F"); break;
case 3: fsq_tx_text->add("% V"); break;
case 4: fsq_tx_text->add("% P"); break;
case 5: fsq_tx_text->add("% p"); break;
case 6: fsq_tx_text->add("% M"); break;
case 7: fsq_tx_text->add("% m"); break;
}
fsq_tx_text->add("^r");
active_modem->fsq_send_image();
}
void cb_fsqpicTxSendAbort( Fl_Widget *w, void *)
{
}
void cb_selfsqpicSize( Fl_Widget *w, void *)
{
switch (selfsqpicSize->value()) {
case 0 : fsq_showTxViewer('S'); break;
case 1 : fsq_showTxViewer('L'); break;
case 2 : fsq_showTxViewer('F'); break;
case 3 : fsq_showTxViewer('V'); break;
case 4 : fsq_showTxViewer('P'); break;
case 5 : fsq_showTxViewer('p'); break;
case 6 : fsq_showTxViewer('M'); break;
case 7 : fsq_showTxViewer('m'); break;
}
}
void fsq_createTxViewer()
{
fsqpicTxWin = new Fl_Double_Window(324, 270, _("Send image"));
fsqpicTxWin->xclass(PACKAGE_NAME);
fsqpicTxWin->begin();
fsqpicTx = new picture (2, 2, 320, 240);
fsqpicTx->noslant();
fsqpicTx->hide();
selfsqpicSize = new Fl_Choice(5, 244, 110, 24);
selfsqpicSize->add("160x120 clr"); // case 0
selfsqpicSize->add("320x240 clr"); // case 1
selfsqpicSize->add("640x480 gry"); // case 2
selfsqpicSize->add("640x480 clr"); // case 3
selfsqpicSize->add("240x300 clr"); // case 4
selfsqpicSize->add("240x300 gry"); // case 5
selfsqpicSize->add("120x150 clr"); // case 6
selfsqpicSize->add("120x150 gry"); // case 7
selfsqpicSize->value(1);
selfsqpicSize->callback(cb_selfsqpicSize, 0);
btnfsqpicTxLoad = new Fl_Button(120, 244, 60, 24, _("Load"));
btnfsqpicTxLoad->callback(cb_fsqpicTxLoad, 0);
btnfsqpicTransmit = new Fl_Button(fsqpicTxWin->w() - 130, 244, 60, 24, "Xmt");
btnfsqpicTransmit->callback(cb_fsqpicTransmit, 0);
btnfsqpicTxSendAbort = new Fl_Button(fsqpicTxWin->w() - 130, 244, 60, 24, "Abort Xmt");
btnfsqpicTxSendAbort->callback(cb_fsqpicTxSendAbort, 0);
btnfsqpicTxClose = new Fl_Button(fsqpicTxWin->w() - 65, 244, 60, 24, _("Close"));
btnfsqpicTxClose->callback(cb_fsqpicTxClose, 0);
btnfsqpicTxSendAbort->hide();
btnfsqpicTransmit->deactivate();
fsqpicTxWin->end();
}
void fsq_showTxViewer(char c)
{
if (!fsqpicTxWin) fsq_createTxViewer();
int winW = 644, winH = 512, W = 480, H = 320;
int fsqpicX, fsqpicY;
fsqpicTx->clear();
switch (c) {
case 'S' :
case 's' :
W = 160; H = 120; winW = 324; winH = 154;
selfsqpicSize->value(0);
break;
case 'L' :
case 'l' :
W = 320; H = 240; winW = 324; winH = 274;
selfsqpicSize->value(1);
break;
case 'F' :
W = 640; H = 480; winW = 644; winH = 514;
selfsqpicSize->value(2);
break;
case 'V' :
W = 640; H = 480; winW = 644; winH = 514;
selfsqpicSize->value(3);
break;
case 'P' :
W = 240; H = 300; winW = 324; winH = 334;
selfsqpicSize->value(4);
break;
case 'p' :
W = 240; H = 300; winW = 324; winH = 334;
selfsqpicSize->value(5);
break;
case 'M' :
W = 120; H = 150; winW = 324; winH = 184;
selfsqpicSize->value(6);
break;
case 'm' :
W = 120; H = 150; winW = 324; winH = 184;
selfsqpicSize->value(7);
}
fsqpicTxWin->size(winW, winH);
fsqpicX = (winW - W) / 2;
fsqpicY = (winH - 26 - H) / 2;
fsqpicTx->resize(fsqpicX, fsqpicY, W, H);
selfsqpicSize->resize(5, winH - 26, 110, 24);
btnfsqpicTxLoad->resize(120, winH - 26, 60, 24);
btnfsqpicTransmit->resize(winW - 130, winH - 26, 60, 24);
btnfsqpicTxSendAbort->resize(winW - 130, winH - 26, 60, 24);
btnfsqpicTxClose->resize(winW -65, winH - 26, 60, 24);
selfsqpicSize->show();
btnfsqpicTransmit->show();
btnfsqpicTxLoad->show();
btnfsqpicTxClose->show();
btnfsqpicTxSendAbort->hide();
fsqpicTxWin->show();
}
void fsq_deleteTxViewer()
{
fsqpicTxWin->hide();
if (fsqpicTx) delete fsqpicTx;
delete [] fsqxmtimg;
fsqxmtimg = 0;
delete [] fsqxmtpicbuff;
fsqxmtpicbuff = 0;
delete fsqpicTxWin;
fsqpicTxWin = 0;
}
void fsq_deleteRxViewer()
{
fsqpicRxWin->hide();
if (fsqpicRx) {
delete fsqpicRx;
fsqpicRx = 0;
}
delete fsqpicRxWin;
fsqpicRxWin = 0;
}
int fsq_print_time_left(float time_sec, char *str, size_t len,
const char *prefix, const char *suffix)
{
int time_min = (int)(time_sec / 60);
time_sec -= time_min * 60;
if (time_min)
return snprintf(str, len, "%s %02dm %2.1fs%s",
prefix, time_min, time_sec, suffix);
else
return snprintf(str, len, "%s %2.1fs%s", prefix, time_sec, suffix);
}

1630
src/fsq/fsq.cxx 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,169 @@
// ----------------------------------------------------------------------------
//
// Viewer.cxx -- PSK browser
//
// Copyright (C) 2015
// David Freese, W1HKJ
//
// This file is part of fldigi.
//
// Fldigi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Fldigi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#include <FL/Enumerations.H>
#include "config.h"
#include "Viewer.h"
#include "trx.h"
#include "main.h"
#include "configuration.h"
#include "confdialog.h"
#include "status.h"
#include "waterfall.h"
#include "fl_digi.h"
#include "re.h"
#include "gettext.h"
#include "flmisc.h"
#include "spot.h"
#include "icons.h"
#include "qrunner.h"
using namespace std;
//
// External fsq monitor dialog
//
Fl_Double_Window *fsqMonitor = 0;
static Fl_Button *btnCloseMonitor;
FTextRX *fsq_monitor = 0;
static void cb_btnCloseMonitor(Fl_Button*, void*) {
progStatus.fsqMONITORxpos = fsqMonitor->x();
progStatus.fsqMONITORypos = fsqMonitor->y();
progStatus.fsqMONITORwidth = fsqMonitor->w();
progStatus.fsqMONITORheight = fsqMonitor->h();
btn_MONITOR->value(0);
btn_MONITOR->redraw();
fsqMonitor->hide();
}
Fl_Double_Window* create_fsqMonitor(void)
{
Fl_Double_Window* w = new Fl_Double_Window(
progStatus.fsqMONITORxpos, progStatus.fsqMONITORypos,
progStatus.fsqMONITORwidth, progStatus.fsqMONITORheight,
_("FSQ monitor"));
fsq_monitor = new FTextRX(
2, 2,
w->w() - 4, w->h() - 28);
fsq_monitor->color(
fl_rgb_color(
0.98*progdefaults.RxColor.R,
0.98*progdefaults.RxColor.G,
0.98*progdefaults.RxColor.B),
progdefaults.RxTxSelectcolor);
fsq_monitor->setFont(progdefaults.RxFontnbr);
fsq_monitor->setFontSize(progdefaults.RxFontsize);
fsq_monitor->setFontColor(progdefaults.RxFontcolor, FTextBase::RECV);
Fl_Group *g = new Fl_Group(
fsq_monitor->x(), fsq_monitor->y() + fsq_monitor->h() + 2,
fsq_monitor->w(), 22);
Fl_Group *g1 = new Fl_Group(
g->x(), g->y() + 2, g->w() - 80, g->h());
g1->box(FL_FLAT_BOX);
g1->end();
// close button
btnCloseMonitor = new Fl_Button(
g->x() + g->w() - 82, g->y(), 80, g->h(),
icons::make_icon_label(_("Close"), close_icon));
btnCloseMonitor->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
icons::set_icon_label(btnCloseMonitor);
btnCloseMonitor->callback((Fl_Callback*)cb_btnCloseMonitor);
g->resizable(g1);
g->end();
w->end();
w->callback((Fl_Callback*)cb_btnCloseMonitor);
w->resizable(fsq_monitor);
w->size_range( 300, 200 );
w->xclass(PACKAGE_NAME);
w->hide();
return w;
}
void open_fsqMonitor()
{
if (!fsqMonitor)
fsqMonitor = create_fsqMonitor();
fsqMonitor->show();
fsqMonitor->redraw();
}
#if (FSQDEBUG == 1)
Fl_Double_Window *fsqDebug = 0;
FTextRX *fsq_debug = 0;
void close_fsqDebug()
{
if (fsqDebug) fsqDebug->hide();
}
static void cb_CloseDebug(Fl_Button*, void*) {
fsqDebug->hide();
}
Fl_Double_Window* create_fsqDebug(void)
{
Fl_Double_Window* w = new Fl_Double_Window( 50, 50, 500, 300, "FSQ debug");
fsq_debug = new FTextRX(
2, 2,
w->w() - 4, w->h() - 4);
fsq_debug->color( FL_WHITE);
fsq_debug->setFont(progdefaults.RxFontnbr);
fsq_debug->setFontSize(progdefaults.RxFontsize);
fsq_debug->setFontColor(progdefaults.RxFontcolor, FTextBase::RECV);
fsq_debug->setFontColor(progdefaults.XMITcolor, FTextBase::XMIT);
fsq_debug->setFontColor(progdefaults.CTRLcolor, FTextBase::CTRL);
fsq_debug->setFontColor(progdefaults.SKIPcolor, FTextBase::SKIP);
fsq_debug->setFontColor(progdefaults.ALTRcolor, FTextBase::ALTR);
w->end();
w->callback((Fl_Callback*)cb_CloseDebug);
w->resizable(fsq_debug);
w->size_range( 200, 200 );
w->xclass(PACKAGE_NAME);
w->hide();
return w;
}
void open_fsqDebug()
{
if (!fsqDebug)
fsqDebug = create_fsqDebug();
fsqDebug->show();
fsqDebug->redraw();
}
void write_fsqDebug(string s, int style)
{
if (!fsq_debug) return;
REQ(&FTextRX::addstr, fsq_debug, s, style);
}
#endif

Wyświetl plik

@ -0,0 +1,110 @@
int fsq_varicode[][2] = {
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
{27,31}, { 0, 0}, {28, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
{ 0, 0}, {11,30}, {12,30}, {13,30}, {14,30}, {15,30}, {16,30}, {17,30},
{18,30}, {19,30}, {20,30}, {21,30}, {27,29}, {22,30}, {27, 0}, {23,30},
{10,30}, { 1,30}, { 2,30}, { 3,30}, { 4,30}, { 5,30}, { 6,30}, { 7,30},
{ 8,30}, { 9,30}, {24,30}, {25,30}, {26,30}, { 0,31}, {27,30}, {28,29},
{ 0,29}, { 1,29}, { 2,29}, { 3,29}, { 4,29}, { 5,29}, { 6,29}, { 7,29},// ' ' - 7
{ 8,29}, { 9,29}, {10,29}, {11,29}, {12,29}, {13,29}, {14,29}, {15,29},// 8, 9, 0
{16,29}, {17,29}, {18,29}, {19,29}, {20,29}, {21,29}, {22,29}, {23,29}, // ... :
{24,29}, {25,29}, {26,29}, { 1,31}, { 2,31}, { 3,31}, { 4,31}, { 5,31},
{ 9,31}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 0}, { 5, 0}, { 6, 0}, { 7, 0},// @ - g
{ 8, 0}, { 9, 0}, {10, 0}, {11, 0}, {12, 0}, {13, 0}, {14, 0}, {15, 0},// h - o
{16, 0}, {17, 0}, {18, 0}, {19, 0}, {20, 0}, {21, 0}, {22, 0}, {23, 0},// p - w
{24, 0}, {25, 0}, {26, 0}, { 6,31}, { 7,31}, { 8,31}, { 0,30}, {28,31},// x - 127
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//135
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//143
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//151
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//159
{ 0, 0}, { 0, 0}, { 0, 0}, {14,31}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//167
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//175
{12,31}, {10,31}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//183
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//191
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//199
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//207
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {13,31},//215
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//223
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//231
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},//239
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, {11,31},//247
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0} //255
};
/*
* The same in a format more suitable for decoding.
* The index is the varicode symbol, being 1-2 nibbles. The value is the
* ASCII character.
* NB. Do NOT use CR as a line feed, as you will get an extra space and the
* new line will be indented. Use LF = ascii 10 instead.
*/
// decode [ prev * 32 + curr] ; 0 < prev < 29; curr == 29, 30, 31
int wsq_varidecode[] = {
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122, 46, 10, 64,126, 61, // 0 - 31
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 49, 91, // 32 - 63
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 66, 50, 92, // 2
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 67, 51, 93, // 3
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 68, 52, 94, // 4
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 69, 53, 95, // 5
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 70, 54,123, // 6
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 71, 55,124, // 7
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 72, 56,125, // 8
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 73, 57, 96, // 9
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 74, 48,177, // 10
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 75, 33,247, // 11
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 76, 34,176, // 12
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 77, 35,215, // 13
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 78, 36,163, // 14
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 79, 37, -1, // 15
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 80, 38, -1, // 16
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, 39, -1, // 17
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 82, 40, -1, // 18
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 83, 41, -1, // 19
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 84, 42, -1, // 20
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 85, 43, -1, // 21
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 86, 45, -1, // 22
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 87, 47, -1, // 23
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 88, 58, -1, // 24
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 89, 59, -1, // 25
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 90, 60, -1, // 26
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 62, 8, // 27
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 63, 0,127, // 28
};
const char *fsq_ascii[256] = {
"<NUL>", "<SOH>", "<STX>", "<ETX>", "<EOT>", "<ENQ>", "<ACK>", "<BEL>",
"<BS>", "<TAB>", "<LF>", "<VT>", "<FF>", "<CR>", "<SO>", "<SI>",
"<DLE>", "<DC1>", "<DC2>", "<DC3>", "<DC4>", "<NAK>", "<SYN>", "<ETB>",
"<CAN>", "<EM>", "<SUB>", "<ESC>", "<FS>", "<GS>", "<RS>", "<US>",
" ", "!", "\"", "#", "$", "%", "&", "\'",
"(", ")", "*", "+", ",", "-", ".", "/",
"0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", ":", ";", "<", "=", ">", "?",
"@", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W",
"X", "Y", "Z", "[", "\\", "]", "^", "_",
"`", "a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w",
"x", "y", "z", "{", "|", "}", "~", "<DEL>",
"<128>", "<129>", "<130>", "<131>", "<132>", "<133>", "<134>", "<135>",
"<136>", "<137>", "<138>", "<139>", "<140>", "<141>", "<142>", "<143>",
"<144>", "<145>", "<146>", "<147>", "<148>", "<149>", "<150>", "<151>",
"<152>", "<153>", "<154>", "<155>", "<156>", "<157>", "<158>", "<159>",
"<160>", "<161>", "<162>", "£", "<164>", "<165>", "<166>", "<167>",
"<168>", "<169>", "<170>", "<171>", "<172>", "<173>", "<174>", "<175>",
"°", "±", "<178>", "<179>", "<180>", "<181>", "<182>", "<183>",
"<184>", "<185>", "<186>", "<187>", "<188>", "<189>", "<190>", "<191>",
"<192>", "<193>", "<194>", "<195>", "<196>", "<197>", "<198>", "<199>",
"<200>", "<201>", "<202>", "<203>", "<204>", "<205>", "<206>", "<207>",
"<208>", "<209>", "<210>", "<211>", "<212>", "<213>", "<214>", "×",
"<216>", "<217>", "<218>", "<219>", "<220>", "<221>", "<222>", "<223>",
"<224>", "<225>", "<226>", "<227>", "<228>", "<229>", "<230>", "<231>",
"<232>", "<233>", "<234>", "<235>", "<236>", "<237>", "<238>", "<239>",
"<240>", "<241>", "<242>", "<243>", "<244>", "<245>", "<246>", "÷",
"<248>", "<249>", "<250>", "<251>", "<252>", "<253>", "<254>", "<255>"
};

Wyświetl plik

@ -194,7 +194,10 @@ const struct mode_info_t mode_info[NUM_MODES] = {
{ MODE_SSB, &ssb_modem, "SSB", "SSB", "", "SSB", "", DISABLED_IO },
{ MODE_WWV, &wwv_modem, "WWV", "WWV", "", "", "", DISABLED_IO },
{ MODE_ANALYSIS, &anal_modem, "ANALYSIS", "Freq Analysis", "", "", "", DISABLED_IO },
{ MODE_FFTSCAN, &fftscan_modem, "FREQSCAN", "Freq Scan", "", "", "", DISABLED_IO }
{ MODE_FFTSCAN, &fftscan_modem, "FREQSCAN", "Freq Scan", "", "", "", DISABLED_IO },
{ MODE_FSQ, &fsq_modem, "FSQ", "FSQ", "", "", "", DISABLED_IO }
};
std::ostream& operator<<(std::ostream& s, const qrg_mode_t& m)

Wyświetl plik

@ -32,6 +32,9 @@ extern Fl_Group *grpNoise;
#include <FL/Fl_Check_Button.H>
extern Fl_Check_Button *btnNoiseOn;
extern Fl_Counter2 *noiseDB;
#include <FL/Fl_Counter.H>
extern Fl_Counter *ctrl_freq_offset;
extern Fl_Check_Button *btnOffsetOn;
extern Fl_Group *tabUI;
extern Fl_Tabs *tabsUI;
extern Fl_Group *tabBrowser;
@ -106,7 +109,6 @@ extern Fl_Input2 *inpNonword;
extern Fl_Check_Button *btnUSunits;
extern Fl_Group *tabMBars;
extern Fl_Check_Button *btnMacroMouseWheel;
#include <FL/Fl_Counter.H>
extern Fl_Counter *cnt_macro_height;
#include <FL/Fl_Round_Button.H>
extern Fl_Round_Button *btn_scheme_0;
@ -308,6 +310,22 @@ extern Fl_ListBox *listboxHellPulse;
extern Fl_Value_Slider2 *sldrHellBW;
extern Fl_Check_Button *btnFeldHellIdle;
extern Fl_Check_Button *btnHellXmtWidth;
extern Fl_Group *tabFSQ;
#include <FL/Fl_Value_Slider.H>
extern Fl_Value_Slider *valhits;
extern Fl_Choice *sel_fsq_lpf;
extern Fl_Value_Slider *sldrMovAvg;
extern Fl_Choice *sel_fsq_heard_aging;
extern Fl_Round_Button *btn_fsqbaud[4];
extern Fl_Choice *sel_fsq_frequency;
extern Fl_Choice *sel_fsq_sounder;
extern Fl_Check_Button *btn_fsq_lowercase;
extern Fl_Output *txtAuditLog;
extern Fl_Light_Button *btn_enable_auditlog;
extern Fl_Button *btn_select_auditlog;
extern Fl_Output *txtHeardLog;
extern Fl_Light_Button *btn_enable_fsq_heard_log;
extern Fl_Button *btn_select_fsq_heard_log;
extern Fl_Group *tabMT63;
extern Fl_Check_Button *btnMT63_8bit;
extern Fl_Check_Button *btnMT63_rx_integration;
@ -525,7 +543,6 @@ extern Fl_Check_Button *chk_open_flmsg;
extern Fl_Check_Button *chk_open_flmsg_print;
extern Fl_Input2 *txt_flmsg_pathname;
extern Fl_Button *btn_select_flmsg;
#include <FL/Fl_Value_Slider.H>
extern Fl_Value_Slider *sldr_extract_timeout;
extern Fl_Group *tabPskmail;
extern Fl_Counter2 *cntServerCarrier;

Wyświetl plik

@ -621,6 +621,60 @@
ELEM_(bool, mt63_at500, "MT63AT500", \
"Always transmit lowest tone at 500 Hz", \
false) \
/* FSQ */ \
ELEM_(int, fsq_frequency, "FSQFREQUENCY", \
"0 - 1150 Hz, 1 - 1500 Hz, 2 - Variable", \
1) \
ELEM_(int, fsq_movavg, "FSQMOVAVG", \
"size of moving average filter for bin filtering\n" \
"value 2 to 8", \
4) \
ELEM_(double, fsq_img_filter, "FSQIMGFILTER", \
"0 - 300 Hz, 1 - 400 Hz, 2 - 500 Hz (default)", \
2) \
ELEM_(double, fsqbaud, "FSQBAUD", \
"6, 4.5, 3 or 2 baud", \
4.5) \
ELEM_(int, fsqhits, "FSQHITS", \
"3 / 6", \
3) \
ELEM_(bool, fsq_directed, "FSQDIRECTED", \
"FSQCALL directed mode", \
false) \
ELEM_(bool, fsq_show_monitor, "FSQSHOWMONITOR", \
"Show fsq monitor text panel", \
false) \
ELEM_(bool, fsq_fastavg, "FSQFASTAVG", \
"Symbol averaging: true = fast, false = slow", \
true) \
ELEM_(std::string, fsqQTCtext, "FSQQTCTEXT", \
"QTC text string", \
"cq cq cq de nocall") \
ELEM_(int, fsq_heard_aging, "FSQHEARDAGING", \
"0 - NEVER (default)\n" \
"1 - 1 minute, 2 - 5 minutes, 3 - 10 minutes\n" \
"4 - 20 minutes, 5 - 30 minutes", \
0) \
ELEM_(int, fsq_sounder, "FSQSOUNDER", \
"0 - OFF (default)\n" \
"1 - 1 minute, 2 - 10 minutes, 3 - 30 minutes", \
0) \
ELEM_(bool, fsq_lowercase, "FSQLOWERCASE", \
"0 - NO, 1 - YES\n" \
"convert operator MYCALL to lower case for directed call triggers", \
0) \
ELEM_(bool, fsq_enable_heard_log, "FSQ_ENABLE_HEARD_LOG", \
"FSQ enable heard log file", \
1) \
ELEM_(std::string, fsq_heard_log, "FSQ_HEARD_LOG", \
"FSQ heard log pathname", \
"fsq_heard_log.txt") \
ELEM_(bool, fsq_enable_audit_log, "FSQ_ENABLE_AUDIT_LOG", \
"FSQ enable audit log file", \
1) \
ELEM_(std::string, fsq_audit_log, "FSQ_AUDIT_LOG", \
"FSQ audit log pathname", \
"fsq_audit_log.txt") \
/* Waterfall & UI */ \
ELEM_(uchar, red, "", "", 0) \
ELEM_(uchar, green, "", "", 255) \

38
src/include/crc8.h 100644
Wyświetl plik

@ -0,0 +1,38 @@
#ifndef __CRC8_H
#define __CRC8_H
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
class CRC8 {
private:
unsigned char val;
unsigned char table[256];
char ss[3];
public:
CRC8() {
val = 0x00;
unsigned char crc;
for ( int i = 0; i < 256; i++) {
crc = i;
for (int j = 0; j < 8; j++)
crc = (crc << 1) ^ ((crc & 0x80) ? 0x07 : 0);
table[i] = crc & 0xFF;
}
}
~CRC8() {};
std::string sval(std::string s) {
val = 0x00;
for ( size_t i = 0; i < s.length(); i++ ) {
val = table[(val) ^ s[i]];
val &= 0xFF;
}
snprintf(ss, sizeof(ss), "%02x", val);
return ss;
}
};
#endif

Wyświetl plik

@ -120,6 +120,7 @@ public:
double run(double a);
void setLength(int filtlen);
void reset();
double value() { return out / (len > 0 ? len : 1); }
};

Wyświetl plik

@ -44,6 +44,7 @@
#include "re.h"
#include "smeter.h"
#include "pwrmeter.h"
#include "picture.h"
extern fre_t seek_re;
@ -123,6 +124,101 @@ extern Fl_ComboBox *qso_opBW;
extern Fl_Button *qso_opPICK;
extern Fl_Browser *qso_opBrowser;
extern Fl_Group *fsq_group;
extern FTextRX *fsq_rx_text;
extern FTextTX *fsq_tx_text;
extern Fl_Browser *fsq_heard;
extern Fl_Double_Window *fsqMonitor;
extern FTextRX *fsq_monitor;
extern Fl_Double_Window *create_fsqMonitor();
extern void open_fsqMonitor();
extern void close_fsqMonitor();
extern Fl_Double_Window *fsqDebug;
extern Fl_Double_Window *create_fsqDebug();
extern void open_fsqDebug();
extern void close_fsqDebug();
extern void write_fsqDebug(int ch, int style = FTextBase::RECV);
extern void write_fsqDebug(std::string s, int style = FTextBase::RECV);
extern void fsq_disableshift();
extern void fsq_enableshift();
extern void fsq_updateRxPic(unsigned char data, int pos);
extern void fsq_createRxViewer();
extern void fsq_showRxViewer(int W, int H, char c);
extern int fsq_load_image(const char *n, int W = 320, int H = 240);
extern void fsq_updateTxPic(unsigned char data, int pos);
extern void cb_fsqpicTxLoad(Fl_Widget *, void *);
extern void cb_fsqpicTxClose( Fl_Widget *w, void *);
extern int fsqpic_TxGetPixel(int pos, int color);
extern void cb_fsqpicTxSendColor( Fl_Widget *w, void *);
extern void cb_fsqpicTxSendGrey( Fl_Widget *w, void *);
extern void cb_fsqpicTxSendAbort( Fl_Widget *w, void *);
extern void cb_fsqpicTxSPP( Fl_Widget *w, void *);
extern void fsq_createTxViewer();
extern void fsq_TxViewerResize(int W, int H);
extern void fsq_showTxViewer(char c);
extern void fsq_deleteTxViewer();
extern void fsq_deleteRxViewer();
extern int fsq_print_time_left(float time_sec, char *str, size_t len,
const char *prefix, const char *suffix);
extern void fsq_transmit(void *);
extern Fl_Light_Button *btn_FSQCALL;
extern Fl_Light_Button *btn_SELCAL;
extern Fl_Light_Button *btn_MONITOR;
extern Fl_Button *btn_FSQQTH;
extern Fl_Button *btn_FSQQTC;
extern Progress *ind_fsq_speed;
extern Progress *ind_fsq_s2n;
extern Fl_Double_Window *fsqpicRxWin;
extern Fl_Double_Window *fsqpicTxWin;
extern std::string fsq_selected_call;
extern bool in_heard(std::string);
extern void cb_fsq_heard(Fl_Browser*, void*);
extern std::string heard_list();
extern void clear_heard_list();
extern void age_heard_list();
extern void add_to_heard_list(std::string, std::string);
extern void fsq_transmit_string(std::string s);
extern void fsq_repeat_last_heard();
extern void fsq_repeat_last_command();
extern void display_fsq_rx_text(std::string text, int style = FTextBase::SKIP);
extern void display_fsq_mon_text(std::string text, int style = FTextBase::SKIP);
extern void enableSELCAL();
extern void cbFSQQTC(Fl_Widget *w, void *d);
extern void cbFSQQTH(Fl_Widget *w, void *d);
extern void cbMONITOR(Fl_Widget *w, void *d);
extern void cbSELCAL(Fl_Widget *w, void *d);
extern void cbFSQCALL(Fl_Widget *w, void *d);
#include <FL/Fl_Bitmap.H>
extern Fl_Bitmap image_s2n;
//------------------------------------------------------------------------------
// fsq images
//------------------------------------------------------------------------------
extern Fl_Double_Window *picRxWin;
extern picture *picRx;
extern Fl_Button *btnpicRxSave;
extern Fl_Button *btnpicRxAbort;
extern Fl_Button *btnpicRxClose;
extern Fl_Double_Window *picTxWin;
extern picture *picTx;
extern Fl_Button *btnpicTxSPP;
extern Fl_Button *btnpicTxSendColor;
extern Fl_Button *btnpicTxSendGrey;
extern Fl_Button *btnpicTxSendAbort;
extern Fl_Button *btnpicTxLoad;
extern Fl_Button *btnpicTxClose;
//------------------------------------------------------------------------------
extern Fl_Value_Slider2 *mvsquelch;
extern Fl_Light_Button *btnAFC;
extern Fl_Light_Button *btnSQL;
@ -195,6 +291,9 @@ enum status_timeout {
STATUS_DIM,
STATUS_NUM
};
extern const char *zshowtime();
extern void put_status(const char *msg, double timeout = 0.0, status_timeout action = STATUS_CLEAR);
extern void clear_StatusMessages();
extern void put_MODEstatus(const char* fmt, ...) format__(printf, 1, 2);

228
src/include/fsq.h 100644
Wyświetl plik

@ -0,0 +1,228 @@
// ----------------------------------------------------------------------------
// fsq.h -- FSQCALL compatible modem
//
// Copyright (C) 2006
// Dave Freese, W1HKJ
//
// This file is part of fldigi.
//
// Fldigi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Fldigi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------
#ifndef _FSQ_H
#define _FSQ_H
#include <string>
#include <iostream>
#include <fstream>
#include "trx.h"
#include "modem.h"
#include "complex.h"
#include "filters.h"
#include "crc8.h"
#include "picture.h"
#include <FL/Fl_Shared_Image.H>
class fsq : public modem {
#define SR 12000
#define FFTSIZE 4096
#define FSQ_SYMLEN 4096
#define BLOCK_SIZE FFTSIZE // (FFTSIZE / 2)
#define SHIFT_SIZE (FSQ_SYMLEN / 16)
#define NUMBINS 142
//#define FSQBOL " \n"
//#define FSQEOL "\n "
//#define FSQEOT " \b "
enum STATE {TEXT, IMAGE};
friend void timed_xmt(void *);
friend void sounder(void *);
friend void aging(void *);
friend void fsq_add_tx_timeout(void *);
friend void fsq_stop_aging();
friend void fsq_start_sounder(void *);
friend void fsq_stop_sounder();
friend void try_transmit(void *);
friend void fsq_transmit(void *);
public:
static int symlen;
protected:
// Rx
double rx_stream[BLOCK_SIZE + SHIFT_SIZE];
cmplx fft_data[2*FFTSIZE];
double a_blackman[BLOCK_SIZE];
double tones[NUMBINS];
Cmovavg *binfilt[NUMBINS];
int movavg_size;
int bkptr;
g_fft<double> *fft;
Cmovavg *snfilt;
Cmovavg *baudfilt;
double val;
double max;
double noise;
int peak;
int prev_peak;
int last_peak;
int peak_counter;
int peak_hits;
int symbol;
int prev_symbol;
int curr_nibble;
int prev_nibble;
void lf_check(int);
void process_symbol(int);
double s2n;
char szestimate[40];
std::string rx_text;
std::string toprint;
bool valid_callsign(std::string s);
void parse_rx_text();
void parse_space(bool);
void parse_qmark(std::string relay = "");
void parse_star();
void parse_repeat();
void parse_delayed_repeat();
void parse_pound(std::string relay = "");
void parse_dollar(std::string relay = "");
void parse_at(std::string relay = "");
void parse_amp(std::string relay = "");
void parse_carat(std::string relay = "");
void parse_pcnt();
void parse_vline(std::string relay = "");
void parse_greater(std::string relay = "");
void parse_less(std::string relay = "");
void parse_plus(std::string relay = "");
void parse_minus();
void parse_relay();
void parse_relayed();
bool b_bot;
bool b_eol;
bool b_eot;
// Tx
// C_FIR_filter *xmtfilt;
int tone;
int prevtone;
double txphase;
void send_string(std::string);
bool send_bot;
void flush_buffer ();
void send_char (int);
void send_idle ();
void send_symbol(int sym);
void send_tone(int tone);
std::string xmt_string;
double xmtdelay();
void reply(std::string);
void delayed_reply(std::string, int delay);
void send_ack(std::string relay = "");
// Sounder
double sounder_interval;
void start_sounder(int); // 0, 1, 2, 3
void stop_sounder();
// Aging
void start_aging();
void stop_aging();
// RxTx
int fsq_frequency; // 0 / 1
int spacing;
int basetone;
double speed;
double metric;
bool ch_sqlch_open;
CRC8 crc;
std::string station_calling;
std::string mycall;
std::string heard_log_fname;
std::string audit_log_fname;
std::ofstream heard_log;
std::ofstream audit_log;
void show_mode();
void adjust_for_speed();
void process_tones();
void set_freq(double);
bool valid_char(int);
static const char *FSQBOL;
static const char *FSQEOL;
static const char *FSQEOT;
STATE state;
public:
fsq (trx_mode md);
~fsq ();
void init ();
void rx_init ();
void restart ();
void tx_init (SoundBase *sc);
int rx_process (const double *buf, int len);
int tx_process ();
const char *fsq_mycall() { return mycall.c_str(); }
bool fsq_squelch_open();
// support for fsq image transfers
private:
double amplitude;
double pixel;
bool TX_IMAGE;
unsigned char tx_pixel;
int tx_pixelnbr;
int image_mode;
public:
int byte;
double picf;
double picpeak;
C_FIR_filter *picfilter;
double phidiff;
double phase;
cmplx prevz;
cmplx currz;
double image_freq[10];
int image_counter;
int picW;
int picH;
int row;
int col;
int rgb;
int pixelnbr;
int RXspp;
int TXspp;
void recvpic(double smpl);
void send_image();
void fsq_send_image();
};
#endif

Wyświetl plik

@ -226,6 +226,8 @@ enum {
MODE_ANALYSIS,
MODE_FFTSCAN,
MODE_FSQ,
NUM_MODES,
NUM_RXTX_MODES = NUM_MODES - 2
};

Wyświetl plik

@ -150,6 +150,11 @@ public:
virtual void send_color_image(std::string) {}
virtual void send_Grey_image(std::string) {}
virtual void fsq_send_image(){}
virtual const char *fsq_mycall() {return "";}
virtual bool fsq_squelch_open() {return false;}
virtual void fsq_transmit(void *) {}
void set_stopflag(bool b) { stopflag = b;};
bool get_stopflag() const { return stopflag; };
@ -244,6 +249,9 @@ public:
virtual void stop_csv() {}
virtual int is_csv() { return true;}
virtual double track_freq() { return 0;}
// fsq mode
virtual void send_ack(std::string relay) {};
};
extern modem *null_modem;
@ -399,5 +407,6 @@ extern modem *anal_modem;
extern modem *fftscan_modem;
extern modem *ssb_modem;
extern modem *fsq_modem;
#endif

Wyświetl plik

@ -70,16 +70,16 @@ public:
void clear();
void image(Fl_Image *img) {Fl_Widget::image(img);}
void resize(int, int, int, int);
void resize_height(int new_height, bool clear_img);
void shift_horizontal_center(int hShift);
void stretch(double the_ratio);
int save_png(const char * filename, bool monochrome = false, const char * extra_comments = NULL);
void set_zoom(int the_zoom);
void set_binary(bool bin_mode) { binary = bin_mode ;}
int pix_width(void) const {
void resize_height(int new_height, bool clear_img);
void shift_horizontal_center(int hShift);
void stretch(double the_ratio);
int save_png(const char * filename, bool monochrome = false, const char * extra_comments = NULL);
void set_zoom(int the_zoom);
void set_binary(bool bin_mode) { binary = bin_mode ;}
int pix_width(void) const {
return width ;
}
int pix_height(void) const {
int pix_height(void) const {
return height ;
}
const unsigned char * buffer(void) const {
@ -93,6 +93,7 @@ public:
private:
bool restore( int row, int margin );
bool slantcorr;
public:
void dilatation( int row );
void erosion( int row );
@ -102,6 +103,10 @@ public:
unsigned char get_binary_threshold() const {
return binary_threshold ;
}
void slant(int dir);
void rotate();
void shift_center(int dir);
void noslant() {slantcorr = false;}
};
class picbox : public Fl_Box

Wyświetl plik

@ -63,10 +63,15 @@ struct status {
double VIEWER_psksquelch;
double VIEWER_rttysquelch;
bool VIEWERvisible;
unsigned int fsqMONITORxpos;
unsigned int fsqMONITORypos;
unsigned int fsqMONITORwidth;
unsigned int fsqMONITORheight;
int tile_x;
int tile_w;
int tile_y;
int tile_h;
double fsq_ratio;
bool LOGenabled;
double sldrSquelchValue;
double sldrPwrSquelchValue;
@ -163,6 +168,8 @@ struct status {
bool meters;
bool fsq_rx_abort;
bool bLastStateRead;
void initLastState();

Wyświetl plik

@ -455,7 +455,6 @@ void mfsk::recvchar(int c)
if (check_picture_header(c) == true) {
counter = tracepair.delay;
printf("symbolbit = %d, symbits = %d\n", symbolbit, symbits);
switch (mode) {
case MODE_MFSK16:
if (symbolbit == symbits) counter += symlen;

Wyświetl plik

@ -772,12 +772,14 @@ bool Socket_arqRx()
void WriteARQ(unsigned char data)
{
if (active_modem->get_mode() == MODE_FSQ) return;
guard_lock tosend_lock(&tosend_mutex);
tosend += data;
}
void WriteARQ(const char *data)
{
if (active_modem->get_mode() == MODE_FSQ) return;
guard_lock tosend_lock(&tosend_mutex);
tosend.append(data);
}

Wyświetl plik

@ -3493,6 +3493,8 @@ static void *kiss_loop(void *args)
**********************************************************************************/
void WriteKISS(const char data)
{
if (active_modem->get_mode() == MODE_FSQ) return;
if(kiss_reset_flag) return;
{
@ -3511,6 +3513,8 @@ void WriteKISS(const char data)
**********************************************************************************/
void WriteKISS(const char *data)
{
if (active_modem->get_mode() == MODE_FSQ) return;
if(kiss_reset_flag) return;
{
@ -3531,6 +3535,8 @@ void WriteKISS(const char *data)
**********************************************************************************/
void WriteKISS(const char *data, size_t size)
{
if (active_modem->get_mode() == MODE_FSQ) return;
if(kiss_reset_flag) return;
{
@ -3553,6 +3559,8 @@ void WriteKISS(const char *data, size_t size)
**********************************************************************************/
void WriteKISS(std::string data)
{
if (active_modem->get_mode() == MODE_FSQ) return;
if(kiss_reset_flag) return;
{

593
src/misc/locator.c 100644
Wyświetl plik

@ -0,0 +1,593 @@
/**
* \addtogroup utilities
* @{
*/
/**
* \file src/locator.c
* \brief locator and bearing conversion interface
* \author Stephane Fillod and the Hamlib Group
* \date 2000-2006
*
* Hamlib Interface - locator, bearing, and conversion calls
*/
/*
* Hamlib Interface - locator and bearing conversion calls
* Copyright (c) 2001-2006 by Stephane Fillod
* Copyright (c) 2003 by Nate Bargmann
* Copyright (c) 2003 by Dave Hines
*
* $Id$
*
* Code to determine bearing and range was taken from the Great Circle,
* by S. R. Sampson, N5OWK.
* Ref: "Air Navigation", Air Force Manual 51-40, 1 February 1987
* Ref: "ARRL Satellite Experimenters Handbook", August 1990
*
* Code to calculate distance and azimuth between two Maidenhead locators,
* taken from wwl, by IK0ZSN Mirko Caserta.
*
* New bearing code added by N0NB was found at:
* http://williams.best.vwh.net/avform.htm#Crs
*
*
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*! \page hamlib Hamlib general purpose API
*
* Here are grouped some often used functions, like locator conversion
* routines.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "locator.h"
#ifndef DOC_HIDDEN
#define RADIAN (180.0 / M_PI)
/* arc length for 1 degree, 60 Nautical Miles */
#define ARC_IN_KM 111.2
/* The following is contributed by Dave Hines M1CXW
*
* begin dph
*/
/*
* These are the constants used when converting between Maidenhead grid
* locators and longitude/latitude values. MAX_LOCATOR_PAIRS is the maximum
* number of locator character pairs to convert. This number MUST NOT exceed
* the number of pairs of values in loc_char_range[].
* Setting MAX_LOCATOR_PAIRS to 3 will convert the currently defined 6
* character locators. A value of 4 will convert the extended 8 character
* locators described in section 3L of "The IARU region 1 VHF managers
* handbook". Values of 5 and 6 will extent the format even more, to the
* longest definition I have seen for locators, see
* http://www.btinternet.com/~g8yoa/geog/non-ra.html
* Beware that there seems to be no universally accepted standard for 10 & 12
* character locators.
*
* The ranges of characters which will be accepted by locator2longlat, and
* generated by longlat2locator, are specified by the loc_char_range[] array.
* This array may be changed without requiring any other code changes.
*
* For the fifth pair to range from aa to xx use:
* const static int loc_char_range[] = { 18, 10, 24, 10, 24, 10 };
*
* For the fifth pair to range from aa to yy use:
* const static int loc_char_range[] = { 18, 10, 24, 10, 25, 10 };
*
* MAX_LOCATOR_PAIRS now sets the limit locator2longlat() will convert and
* sets the maximum length longlat2locator() will generate. Each function
* properly handles any value from 1 to 6 so MAX_LOCATOR_PAIRS should be
* left at 6. MIN_LOCATOR_PAIRS sets a floor on the shortest locator that
* should be handled. -N0NB
*/
const static int loc_char_range[] = { 18, 10, 24, 10, 24, 10 };
#define MAX_LOCATOR_PAIRS 6
#define MIN_LOCATOR_PAIRS 1
/* end dph */
#endif /* !DOC_HIDDEN */
/**
* \brief Convert DMS to decimal degrees
* \param degrees Degrees, whole degrees
* \param minutes Minutes, whole minutes
* \param seconds Seconds, decimal seconds
* \param sw South or West
*
* Convert degree/minute/second angle to decimal degrees angle.
* \a degrees >360, \a minutes > 60, and \a seconds > 60.0 are allowed,
* but resulting angle won't be normalized.
*
* When the variable sw is passed a value of 1, the returned decimal
* degrees value will be negative (south or west). When passed a
* value of 0 the returned decimal degrees value will be positive
* (north or east).
*
* \return The angle in decimal degrees.
*
* \sa dec2dms()
*/
double HAMLIB_API dms2dec(int degrees, int minutes, double seconds, int sw) {
double st;
if (degrees < 0)
degrees = abs(degrees);
if (minutes < 0)
minutes = abs(minutes);
if (seconds < 0)
seconds = fabs(seconds);
st = (double)degrees + (double)minutes / 60. + seconds / 3600.;
if (sw == 1)
return -st;
else
return st;
}
/**
* \brief Convert D M.MMM notation to decimal degrees
* \param degrees Degrees, whole degrees
* \param minutes Minutes, decimal minutes
* \param sw South or West
*
* Convert a degrees, decimal minutes notation common on
* many GPS units to its decimal degrees value.
*
* \a degrees > 360, \a minutes > 60.0 are allowed, but
* resulting angle won't be normalized.
*
* When the variable sw is passed a value of 1, the returned decimal
* degrees value will be negative (south or west). When passed a
* value of 0 the returned decimal degrees value will be positive
* (north or east).
*
* \return The angle in decimal degrees.
*
* \sa dec2dmmm()
*/
double HAMLIB_API dmmm2dec(int degrees, double minutes, int sw) {
double st;
if (degrees < 0)
degrees = abs(degrees);
if (minutes < 0)
minutes = fabs(minutes);
st = (double)degrees + minutes / 60.;
if (sw == 1)
return -st;
else
return st;
}
/**
* \brief Convert decimal degrees angle into DMS notation
* \param dec Decimal degrees
* \param degrees Pointer for the calculated whole Degrees
* \param minutes Pointer for the calculated whole Minutes
* \param seconds Pointer for the calculated decimal Seconds
* \param sw Pointer for the calculated SW flag
*
* Convert decimal degrees angle into its degree/minute/second
* notation.
*
* When \a dec < -180 or \a dec > 180, the angle will be normalized
* within these limits and the sign set appropriately.
*
* Upon return dec2dms guarantees 0 >= \a degrees <= 180,
* 0 >= \a minutes < 60, and 0.0 >= \a seconds < 60.0.
*
* When \a dec is < 0.0 \a sw will be set to 1. When \a dec is
* >= 0.0 \a sw will be set to 0. This flag allows the application
* to determine whether the DMS angle should be treated as negative
* (south or west).
*
* \retval -RIG_EINVAL if any of the pointers are NULL.
* \retval RIG_OK if conversion went OK.
*
* \sa dms2dec()
*/
int HAMLIB_API dec2dms(double dec, int *degrees, int *minutes, double *seconds, int *sw) {
int deg, min;
double st;
/* bail if NULL pointers passed */
if (!degrees || !minutes || !seconds || !sw)
return -RIG_EINVAL;
/* reverse the sign if dec has a magnitude greater
* than 180 and factor out multiples of 360.
* e.g. when passed 270 st will be set to -90
* and when passed -270 st will be set to 90. If
* passed 361 st will be set to 1, etc. If passed
* a value > -180 || < 180, value will be unchanged.
*/
if (dec >= 0.0)
st = fmod(dec + 180, 360) - 180;
else
st = fmod(dec - 180, 360) + 180;
/* if after all of that st is negative, we want deg
* to be negative as well except for 180 which we want
* to be positive.
*/
if (st < 0.0 && st != -180)
*sw = 1;
else
*sw = 0;
/* work on st as a positive value to remove a
* bug introduced by the effect of floor() when
* passed a negative value. e.g. when passed
* -96.8333 floor() returns -95! Also avoids
* a rounding error introduced on negative values.
*/
st = fabs(st);
deg = (int)floor(st);
st = 60. * (st - (double)deg);
min = (int)floor(st);
st = 60. * (st - (double)min);
*degrees = deg;
*minutes = min;
*seconds = st;
return RIG_OK;
}
/**
* \brief Convert a decimal angle into D M.MMM notation
* \param dec Decimal degrees
* \param degrees Pointer for the calculated whole Degrees
* \param minutes Pointer for the calculated decimal Minutes
* \param sw Pointer for the calculated SW flag
*
* Convert a decimal angle into its degree, decimal minute
* notation common on many GPS units.
*
* When passed a value < -180 or > 180, the value will be normalized
* within these limits and the sign set apropriately.
*
* Upon return dec2dmmm guarantees 0 >= \a degrees <= 180,
* 0.0 >= \a minutes < 60.0.
*
* When \a dec is < 0.0 \a sw will be set to 1. When \a dec is
* >= 0.0 \a sw will be set to 0. This flag allows the application
* to determine whether the D M.MMM angle should be treated as negative
* (south or west).
*
* \retval -RIG_EINVAL if any of the pointers are NULL.
* \retval RIG_OK if conversion went OK.
*
* \sa dmmm2dec()
*/
int HAMLIB_API dec2dmmm(double dec, int *degrees, double *minutes, int *sw) {
int r, min;
double sec;
/* bail if NULL pointers passed */
if (!degrees || !minutes || !sw)
return -RIG_EINVAL;
r = dec2dms(dec, degrees, &min, &sec, sw);
if (r != RIG_OK)
return r;
*minutes = (double)min + sec / 60;
return RIG_OK;
}
/**
* \brief Convert Maidenhead grid locator to Longitude/Latitude
* \param longitude Pointer for the calculated Longitude
* \param latitude Pointer for the calculated Latitude
* \param locator The Maidenhead grid locator--2 through 12 char + nul string
*
* Convert Maidenhead grid locator to Longitude/Latitude (decimal degrees).
* The locator should be in 2 through 12 chars long format.
* \a locator2longlat is case insensitive, however it checks for
* locator validity.
*
* Decimal long/lat is computed to center of grid square, i.e. given
* EM19 will return coordinates equivalent to the southwest corner
* of EM19mm.
*
* \retval -RIG_EINVAL if locator exceeds RR99xx99xx99 or exceeds length
* limit--currently 1 to 6 lon/lat pairs.
* \retval RIG_OK if conversion went OK.
*
* \bug The fifth pair ranges from aa to xx, there is another convention
* that ranges from aa to yy. At some point both conventions should be
* supported.
*
* \sa longlat2locator()
*/
/* begin dph */
int HAMLIB_API locator2longlat(double *longitude, double *latitude, const char *locator) {
int x_or_y, paircount;
int locvalue, pair;
int divisions;
double xy[2], ordinate;
/* bail if NULL pointers passed */
if (!longitude || !latitude)
return -RIG_EINVAL;
paircount = strlen(locator) / 2;
/* verify paircount is within limits */
if (paircount > MAX_LOCATOR_PAIRS)
paircount = MAX_LOCATOR_PAIRS;
else if (paircount < MIN_LOCATOR_PAIRS)
return -RIG_EINVAL;
/* For x(=longitude) and y(=latitude) */
for (x_or_y = 0; x_or_y < 2; ++x_or_y) {
ordinate = -90.0;
divisions = 1;
for (pair = 0; pair < paircount; ++pair) {
locvalue = locator[pair*2 + x_or_y];
/* Value of digit or letter */
locvalue -= (loc_char_range[pair] == 10) ? '0' :
(isupper(locvalue)) ? 'A' : 'a';
/* Check range for non-letter/digit or out of range */
if ((locvalue < 0) || (locvalue >= loc_char_range[pair]))
return -RIG_EINVAL;
divisions *= loc_char_range[pair];
ordinate += locvalue * 180.0 / divisions;
}
/* Center ordinate in the Maidenhead "square" or "subsquare" */
ordinate += 90.0 / divisions;
xy[x_or_y] = ordinate;
}
*longitude = xy[0] * 2.0;
*latitude = xy[1];
return RIG_OK;
}
/* end dph */
/**
* \brief Convert longitude/latitude to Maidenhead grid locator
* \param longitude Longitude, decimal degrees
* \param latitude Latitude, decimal degrees
* \param locator Pointer for the Maidenhead Locator
* \param pair_count Precision expressed as lon/lat pairs in the locator
*
* Convert longitude/latitude (decimal degrees) to Maidenhead grid locator.
* \a locator must point to an array at least \a pair_count * 2 char + '\\0'.
*
* \retval -RIG_EINVAL if \a locator is NULL or \a pair_count exceeds
* length limit. Currently 1 to 6 lon/lat pairs.
* \retval RIG_OK if conversion went OK.
*
* \bug \a locator is not tested for overflow.
* \bug The fifth pair ranges from aa to yy, there is another convention
* that ranges from aa to xx. At some point both conventions should be
* supported.
*
* \sa locator2longlat()
*/
/* begin dph */
int HAMLIB_API longlat2locator(double longitude, double latitude, char *locator, int pair_count) {
int x_or_y, pair, locvalue, divisions;
double square_size, ordinate;
if (!locator)
return -RIG_EINVAL;
if (pair_count < MIN_LOCATOR_PAIRS || pair_count > MAX_LOCATOR_PAIRS)
return -RIG_EINVAL;
for (x_or_y = 0; x_or_y < 2; ++x_or_y) {
ordinate = (x_or_y == 0) ? longitude / 2.0 : latitude;
divisions = 1;
/* The 1e-6 here guards against floating point rounding errors */
ordinate = fmod(ordinate + 270.000001, 180.0);
for (pair = 0; pair < pair_count; ++pair) {
divisions *= loc_char_range[pair];
square_size = 180.0 / divisions;
locvalue = (int) (ordinate / square_size);
ordinate -= square_size * locvalue;
locvalue += (loc_char_range[pair] == 10) ? '0':'A';
locator[pair * 2 + x_or_y] = locvalue;
}
}
locator[pair_count * 2] = '\0';
return RIG_OK;
}
/* end dph */
/**
* \brief Calculate the distance and bearing between two points.
* \param lon1 The local Longitude, decimal degrees
* \param lat1 The local Latitude, decimal degrees
* \param lon2 The remote Longitude, decimal degrees
* \param lat2 The remote Latitude, decimal degrees
* \param distance Pointer for the distance, km
* \param azimuth Pointer for the bearing, decimal degrees
*
* Calculate the QRB between \a lon1, \a lat1 and \a lon2, \a lat2.
*
* This version will calculate the QRB to a precision sufficient
* for 12 character locators. Antipodal points, which are easily
* calculated, are considered equidistant and the bearing is
* simply resolved to be true north (0.0°).
*
* \retval -RIG_EINVAL if NULL pointer passed or lat and lon values
* exceed -90 to 90 or -180 to 180.
* \retval RIG_OK if calculations are successful.
*
* \return The distance in kilometers and azimuth in decimal degrees
* for the short path are stored in \a distance and \a azimuth.
*
* \sa distance_long_path(), azimuth_long_path()
*/
int HAMLIB_API qrb(double lon1, double lat1, double lon2, double lat2, double *distance, double *azimuth) {
double delta_long, tmp, arc, az;
/* bail if NULL pointers passed */
if (!distance || !azimuth)
return -RIG_EINVAL;
if ((lat1 > 90.0 || lat1 < -90.0) || (lat2 > 90.0 || lat2 < -90.0))
return -RIG_EINVAL;
if ((lon1 > 180.0 || lon1 < -180.0) || (lon2 > 180.0 || lon2 < -180.0))
return -RIG_EINVAL;
/* Prevent ACOS() Domain Error */
if (lat1 == 90.0)
lat1 = 89.999999999;
else if (lat1 == -90.0)
lat1 = -89.999999999;
if (lat2 == 90.0)
lat2 = 89.999999999;
else if (lat2 == -90.0)
lat2 = -89.999999999;
/* Convert variables to Radians */
lat1 /= RADIAN;
lon1 /= RADIAN;
lat2 /= RADIAN;
lon2 /= RADIAN;
delta_long = lon2 - lon1;
tmp = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(delta_long);
if (tmp > .999999999999999) {
/* Station points coincide, use an Omni! */
*distance = 0.0;
*azimuth = 0.0;
return RIG_OK;
}
if (tmp < -.999999) {
/*
* points are antipodal, it's straight down.
* Station is equal distance in all Azimuths.
* So take 180 Degrees of arc times 60 nm,
* and you get 10800 nm, or whatever units...
*/
*distance = 180.0 * ARC_IN_KM;
*azimuth = 0.0;
return RIG_OK;
}
arc = acos(tmp);
/*
* One degree of arc is 60 Nautical miles
* at the surface of the earth, 111.2 km, or 69.1 sm
* This method is easier than the one in the handbook
*/
*distance = ARC_IN_KM * RADIAN * arc;
/* Short Path */
/* Change to azimuth computation by Dave Freese, W1HKJ */
az = RADIAN * atan2(sin(lon2 - lon1) * cos(lat2),
(cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon2 - lon1)));
az = fmod(360.0 + az, 360.0);
if (az < 0.0)
az += 360.0;
else if (az >= 360.0)
az -= 360.0;
*azimuth = floor(az + 0.5);
return RIG_OK;
}
/**
* \brief Calculate the long path distance between two points.
* \param distance The shortpath distance
*
* Calculate the long path (respective of the short path)
* of a given distance.
*
* \return the distance in kilometers for the opposite path.
*
* \sa qrb()
*/
double HAMLIB_API distance_long_path(double distance) {
return (ARC_IN_KM * 360.0) - distance;
}
/**
* \brief Calculate the long path bearing between two points.
* \param azimuth The shortpath bearing
*
* Calculate the long path (respective of the short path)
* of a given bearing.
*
* \return the azimuth in decimal degrees for the opposite path.
*
* \sa qrb()
*/
double HAMLIB_API azimuth_long_path(double azimuth) {
return azimuth + (azimuth <= 180.0 ? 180.0 : -180.0);
}
/*! @} */

Wyświetl plik

@ -660,7 +660,6 @@ static void pWPM(std::string &s, size_t &i, size_t endbracket)
if (number > 200) number = 200;
progdefaults.CWspeed = number;
sldrCWxmtWPM->value(number);
printf("wpm %d\n", number);
// second value = Farnsworth WPM
size_t pos;
@ -672,7 +671,6 @@ printf("wpm %d\n", number);
if (number > 200) number = 200;
progdefaults.CWfarnsworth = number;
sldrCWfarnsworth->value(number);
printf("fwpm %d\n", number);
}
}

Wyświetl plik

@ -102,10 +102,15 @@ status progStatus = {
3.0, // double VIEWER_psksquelch
-6.0, // double VIEWER_rttysquelch
false, // bool VIEWERvisible
50, // unsigned int fsqMONITORxpos;
50, // unsigned int fsqMONITORypos;
600, // unsigned int fsqMONITORwidth;
400, // unsigned int fsqMONITORheight;
100, // int tile_x
200, // int tile_w;
90, // int tile_y;
150, // int tile_h;
0.5, // double fsq_ratio;
false, // bool LOGenabled
5.0, // double sldrSquelchValue
5.0, // double sldrPwrSquelchValue
@ -198,6 +203,8 @@ status progStatus = {
false, // meters
false, // fsq_rx_abort
false // bool bLastStateRead;
};
@ -244,6 +251,7 @@ void status::saveLastState()
tile_h = text_panel->h();
if (text_panel->w() != ReceiveText->w())
tile_x = mvgroup->w();
fsq_ratio = 1.0 * fsq_rx_text->h() / fsq_group->h();
}
VIEWERvisible = dlgViewer->visible();
@ -367,10 +375,16 @@ if (!bWF_only) {
spref.set("viewer_rttysq", VIEWER_rttysquelch);
spref.set("viewer_nchars", static_cast<int>(VIEWERnchars));
spref.set("fsq_monitor_x", static_cast<int>(fsqMONITORxpos));
spref.set("fsq_monitor_y", static_cast<int>(fsqMONITORypos));
spref.set("fsq_monitor_w", static_cast<int>(fsqMONITORwidth));
spref.set("fsq_monitor_h", static_cast<int>(fsqMONITORheight));
spref.set("tile_x", tile_x);
spref.set("tile_y", tile_y);
spref.set("tile_w", tile_w);
spref.set("tile_h", tile_h);
spref.set("fsq_ratio", fsq_ratio);
spref.set("scope_visible", scopeVisible);
spref.set("scope_x", scopeX);
@ -562,11 +576,16 @@ void status::loadLastState()
spref.get("viewer_rttysq", VIEWER_rttysquelch, VIEWER_rttysquelch);
spref.get("viewer_nchars", i, VIEWERnchars); VIEWERnchars = i;
spref.get("fsq_monitor_x", i, fsqMONITORxpos); fsqMONITORxpos = i;
spref.get("fsq_monitor_y", i, fsqMONITORypos); fsqMONITORypos = i;
spref.get("fsq_monitor_w", i, fsqMONITORwidth); fsqMONITORwidth = i;
spref.get("fsq_monitor_h", i, fsqMONITORheight); fsqMONITORheight = i;
spref.get("tile_x", tile_x, tile_x);
spref.get("tile_y", tile_y, tile_y);
spref.get("tile_w", tile_w, tile_w);
spref.get("tile_h", tile_h, tile_h);
spref.get("fsq_ratio", fsq_ratio, fsq_ratio);
spref.get("scope_visible", i, scopeVisible); scopeVisible = i;
spref.get("scope_x", scopeX, scopeX);

Wyświetl plik

@ -46,7 +46,7 @@
#include "debug.h"
#include "status.h"
static bool XMLRPC_DEBUG = 1;
static bool XMLRPC_DEBUG = 0;
using namespace XmlRpc;
using namespace std;

Wyświetl plik

@ -173,6 +173,8 @@ modem *thor50x1_modem = 0;
modem *thor50x2_modem = 0;
modem *thor100_modem = 0;
modem *fsq_modem = 0;
modem *dominoex4_modem = 0;
modem *dominoex5_modem = 0;
modem *dominoex8_modem = 0;

Wyświetl plik

@ -22,6 +22,7 @@
#include <math.h>
#include "sound.h"
#include "confdialog.h"
namespace xmttune {
@ -147,6 +148,7 @@ void keyup(double freq, SoundBase *scard)
void tune(double freq, SoundBase *scard)
{
int i;
freq += ctrl_freq_offset->value();
phaseincr = 2.0 * M_PI * freq / active_modem->get_samplerate();
for (i = 0; i < BUFLEN; i++) {

Wyświetl plik

@ -253,6 +253,9 @@ inline void WFdisp::makeMarker_(int width, const RGB* color, int freq, const RGB
if (marker_mode >= MODE_MT63_500S && marker_mode <= MODE_MT63_2000L)
bw_upper = (int)(width * 31 / 32);
if (marker_mode == MODE_FSQ)
bw_upper = (int)(width * 32 / 33);
if (bw_lower + static_cast<int>(freq+0.5) < 0)
bw_lower -= bw_lower + static_cast<int>(freq+0.5);
@ -330,6 +333,7 @@ void WFdisp::makeMarker()
int bw_hi = marker_width;
if (mode >= MODE_MT63_500S && mode <= MODE_MT63_2000L)
bw_hi = bw_hi * 31 / 32;
if (mode == MODE_FSQ) bw_hi = bw_hi * 32 / 33;
for (int y = 0; y < WFMARKER - 2; y++) {
int incr = y * scale_width;
@ -882,6 +886,9 @@ case Step: for (int row = 0; row < image_height; row++) { \
trx_mode mode = active_modem->get_mode();
if (mode >= MODE_MT63_500S && mode <= MODE_MT63_2000L)
bw_hi = bw_hi * 31 / 32;
if (mode == MODE_FSQ) {
bw_hi = bw_lo = 69 * bandwidth / 100;
}
RGBI *pos1 = fft_img + (carrierfreq - offset - bw_lo) / step;
RGBI *pos2 = fft_img + (carrierfreq - offset + bw_hi) / step;
if (unlikely(pos2 == fft_img + disp_width))
@ -948,6 +955,7 @@ void WFdisp::drawcolorWF() {
int bw_hi = bandwidth / 2;
if (mode >= MODE_MT63_500S && mode <= MODE_MT63_2000L)
bw_hi = bw_hi * 31 / 32;
if (mode == MODE_FSQ) bw_hi = bw_hi * 32 / 33;
RGBI *pos0 = (fft_img + cursorpos);
RGBI *pos1 = (fft_img + cursorpos - bw_lo/step);
RGBI *pos2 = (fft_img + cursorpos + bw_hi/step);
@ -1028,6 +1036,7 @@ void WFdisp::drawspectrum() {
int bw_hi = bandwidth / 2;
if (mode >= MODE_MT63_500S && mode <= MODE_MT63_2000L)
bw_hi = bw_hi * 31 / 32;
if (mode == MODE_FSQ) bw_hi = bw_hi * 32 / 33;
uchar *pos0 = pixmap + cursorpos;
uchar *pos1 = (pixmap + cursorpos - bw_lo/step);
uchar *pos2 = (pixmap + cursorpos + bw_hi/step);

Wyświetl plik

@ -66,6 +66,7 @@
#include "status.h"
#include "gettext.h"
#include "arq_io.h"
#include "fl_digi.h"
#include "debug.h"
@ -808,6 +809,12 @@ int FTextTX::handle(int event)
switch (event) {
case FL_KEYBOARD:
if (active_modem->get_mode() == MODE_FSQ) {
if (Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter) {
fsq_transmit(active_modem);
return 1;
}
}
return handle_key(Fl::event_key()) ? 1 : FTextEdit::handle(event);
case FL_PUSH:
if (Fl::event_button() == FL_MIDDLE_MOUSE &&
@ -1061,6 +1068,7 @@ int FTextTX::handle_key(int key)
active_modem->toggleWPM();
return 1;
case FL_Tab:
if (active_modem == fsq_modem) return 1;
// In non-CW modes: Tab and Ctrl-tab both pause until user moves the
// cursor to let some more text through. Another (ctrl-)tab goes back to
// the end of the buffer and resumes sending.
@ -1086,12 +1094,14 @@ int FTextTX::handle_key(int key)
// Move cursor, or search up/down with the Meta/Alt modifiers
case FL_Left:
if (Fl::event_state() & (FL_META | FL_ALT)) {
if (active_modem == fsq_modem) return 1;
active_modem->searchDown();
return 1;
}
return 0;
case FL_Right:
if (Fl::event_state() & (FL_META | FL_ALT)) {
if (active_modem == fsq_modem) return 1;
active_modem->searchUp();
return 1;
}
@ -1113,6 +1123,7 @@ int FTextTX::handle_key(int key)
case '3':
case '4':
if (Fl::event_state() & FL_ALT) {
if (active_modem == fsq_modem) return 1;
static char lbl[2] = "1";
altMacros = key - '1';
if (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX) {
@ -1146,9 +1157,9 @@ int FTextTX::handle_key(int key)
return 1;
// insert a macro
if (key >= FL_F && key <= FL_F_Last)
if (key >= FL_F && key <= FL_F_Last) {
return handle_key_macro(key);
}
// read ctl-ddd, where d is a digit, as ascii characters (in base 10)
// and insert verbatim; e.g. ctl-001 inserts a <soh>
if (Fl::event_state() & FL_CTRL && (key >= FL_KP) && (key <= FL_KP + '9'))
@ -1170,6 +1181,12 @@ int FTextTX::handle_key(int key)
int FTextTX::handle_key_macro(int key)
{
key -= FL_F + 1;
if (active_modem == fsq_modem) {
if (key == 0) fsq_repeat_last_heard();
if (key == 1) fsq_repeat_last_command();
return 1;
}
if (key > 11)
return 0;

Wyświetl plik

@ -745,8 +745,12 @@ int FTextEdit::handle_key_ascii(int key)
key *= 10;
ascii_chr += key;
if (ascii_cnt == 3) {
if (ascii_chr < 0x100) //0x7F)
add(ascii_chr, (iscntrl(ascii_chr) ? CTRL : RECV));
if (ascii_chr < 0x100) {
char buff[fl_utf8bytes(ascii_chr) + 1];
int utf8cnt = fl_utf8encode(ascii_chr, buff);
for ( int i = 0; i < utf8cnt; i++)
add(buff[i], (iscntrl(ascii_chr) ? CTRL : RECV));
}
ascii_cnt = ascii_chr = 0;
}

Wyświetl plik

@ -8,7 +8,7 @@
// Copyright (C) 2010
// Remi Chateauneu, F4ECW
//
// This file is part of fldigi.
// This file is part of fldigi.
//
// fldigi is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -58,7 +58,7 @@
using namespace std;
picture::picture (int X, int Y, int W, int H, int bg_col) :
Fl_Widget (X, Y, W, H)
Fl_Widget (X, Y, W, H)
{
width = W;
height = H;
@ -67,10 +67,11 @@ picture::picture (int X, int Y, int W, int H, int bg_col) :
slantdir = 0;
vidbuf = new unsigned char[bufsize];
background = bg_col ;
memset( vidbuf, background, bufsize );
memset( vidbuf, background, bufsize );
zoom = 0 ;
binary = false ;
binary_threshold = 128 ;
slantcorr = true;
}
picture::~picture()
@ -81,10 +82,8 @@ picture::~picture()
void picture::video(unsigned char const *data, int len )
{
if (len > bufsize) return;
FL_LOCK_D();
memcpy( vidbuf, data, len );
redraw();
FL_UNLOCK_D();
}
unsigned char picture::pixel(int pos)
@ -95,10 +94,8 @@ unsigned char picture::pixel(int pos)
void picture::clear()
{
FL_LOCK_D();
memset(vidbuf, background, bufsize);
redraw();
FL_UNLOCK_D();
}
@ -117,7 +114,6 @@ void picture::resize_zoom(int x, int y, int w, int h)
void picture::resize(int x, int y, int w, int h)
{
FL_LOCK_D();
width = w;
height = h;
delete [] vidbuf;
@ -125,8 +121,6 @@ void picture::resize(int x, int y, int w, int h)
vidbuf = new unsigned char[bufsize];
memset( vidbuf, background, bufsize );
resize_zoom(x,y,w,h);
FL_UNLOCK_D();
}
/// No data destruction. Used when the received image grows more than expected.
@ -201,29 +195,75 @@ void picture::stretch(double the_ratio)
}
/// Change the horizontal center of the image by shifting the pixels.
/// Beware that it is not protected by FL_LOCK_D/FL_UNLOCK_D
// Beware that it is not protected by a mutex
void picture::shift_horizontal_center(int horizontal_shift)
{
/// This is a number of pixels.
horizontal_shift *= depth ;
if( horizontal_shift < -bufsize ) {
horizontal_shift = -bufsize ;
int shift = horizontal_shift * depth;
if( shift < -bufsize ) {
shift = -bufsize ;
}
if( horizontal_shift > 0 ) {
/// Here we lose a couple of pixels at the end of the buffer
/// Here we lose a couple of pixels at the end of the buffer
/// if there is not a line enough. It should not be a lot.
memmove( vidbuf + horizontal_shift, vidbuf, bufsize - horizontal_shift );
memset( vidbuf, background, horizontal_shift );
int tmp, n;
memmove( vidbuf + shift, vidbuf, bufsize - shift );
memcpy(vidbuf, vidbuf + width*depth, shift);
for (int row = 0; row < height; row ++) {
for (int col = 0; col < shift; col++) {
n = (row * width + col) * depth;
tmp = vidbuf[n];
vidbuf[n] = vidbuf[n+2];
vidbuf[n+2] = tmp;
}
}
// memset( vidbuf, background, horizontal_shift );
} else {
/// Here, it is not necessary to reduce the buffer'size.
memmove( vidbuf, vidbuf - horizontal_shift, bufsize + horizontal_shift );
memset( vidbuf + bufsize + horizontal_shift, background, -horizontal_shift );
// shift *= -1;
/// Here, it is not necessary to reduce the buffer's size.
// memmove( vidbuf, vidbuf + shift, bufsize - shift );
// memcpy( vidbuf + bufsize - shift - 1,
// vidbuf + bufsize - width * depth - 1, shift);
// memset( vidbuf + bufsize + horizontal_shift, background, -horizontal_shift );
}
redraw();
}
/// Shift the center by 1 rgb value
// not protected by a mutex
void picture::shift_center(int dir)
{
if( dir > 0 ) {
memmove( vidbuf + 1, vidbuf, bufsize - 1 );
vidbuf[0] = 0;
} else {
memmove( vidbuf, vidbuf + 1, bufsize - 1 );
vidbuf[bufsize-1] = 0;
}
redraw();
}
/// rotate rgb pixel ordering in the image to the right of
/// and including grp pixels from the left
// not protected by a mutex
void picture::rotate()
{
unsigned char tmp;
int n;
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
n = (row * width + col) * depth;
tmp = vidbuf[n];
vidbuf[n] = vidbuf[n+1];
vidbuf[n+1] = vidbuf[n+2];
vidbuf[n+2] = tmp;
}
}
redraw();
}
void picture::set_zoom( int the_zoom )
{
zoom = the_zoom ;
@ -234,8 +274,8 @@ void picture::set_zoom( int the_zoom )
// in data user data passed to function
// in x_screen,y_screen,wid_screen position and width of scan line in image
// out buf buffer for generated image data.
// Must copy wid_screen pixels from scanline y_screen, starting at pixel x_screen to this buffer.
void picture::draw_cb( void *data, int x_screen, int y_screen, int wid_screen, uchar * __restrict__ buf)
// Must copy wid_screen pixels from scanline y_screen, starting at pixel x_screen to this buffer.
void picture::draw_cb( void *data, int x_screen, int y_screen, int wid_screen, uchar * __restrict__ buf)
{
const picture * __restrict__ ptr_pic = ( const picture * ) data ;
const int img_width = ptr_pic->width ;
@ -355,14 +395,14 @@ void picture::slant_undo()
for (row = 0; row < height; row++) {
col = numcol * row / (height - 1);
if (col > 0) {
memmove( temp,
&vidbuf[(row * width + width - col) * depth],
memmove( temp,
&vidbuf[(row * width + width - col) * depth],
(width - col) * depth );
memmove( &vidbuf[(row * width + col)*depth],
&vidbuf[row * width *depth],
memmove( &vidbuf[(row * width + col)*depth],
&vidbuf[row * width *depth],
(width - col) * depth );
memmove( &vidbuf[row * width * depth],
temp,
memmove( &vidbuf[row * width * depth],
temp,
col * depth );
}
}
@ -370,14 +410,14 @@ void picture::slant_undo()
for (row = 0; row < height; row++) {
col = numcol * row / (height - 1);
if (col > 0) {
memmove( temp,
&vidbuf[row * width * depth],
memmove( temp,
&vidbuf[row * width * depth],
col * depth );
memmove( &vidbuf[row * width * depth],
&vidbuf[(row * width + col) * depth],
memmove( &vidbuf[row * width * depth],
&vidbuf[(row * width + col) * depth],
(width - col) * depth );
memmove( &vidbuf[(row * width + width - col) * depth],
temp,
memmove( &vidbuf[(row * width + width - col) * depth],
temp,
col *depth );
}
}
@ -397,14 +437,14 @@ void picture::slant_corr(int x, int y)
for (row = 0; row < height; row++) {
col = numcol * row / (height - 1);
if (col > 0) {
memmove( temp,
&vidbuf[(row * width + width - col) * depth],
memmove( temp,
&vidbuf[(row * width + width - col) * depth],
(width - col) * depth );
memmove( &vidbuf[(row * width + col)*depth],
&vidbuf[row * width *depth],
memmove( &vidbuf[(row * width + col)*depth],
&vidbuf[row * width *depth],
(width - col) * depth );
memmove( &vidbuf[row * width * depth],
temp,
memmove( &vidbuf[row * width * depth],
temp,
col * depth );
}
}
@ -415,14 +455,14 @@ void picture::slant_corr(int x, int y)
for (row = 0; row < height; row++) {
col = numcol * row / (height - 1);
if (col > 0) {
memmove( temp,
&vidbuf[row * width * depth],
memmove( temp,
&vidbuf[row * width * depth],
col * depth );
memmove( &vidbuf[row * width * depth],
&vidbuf[(row * width + col) * depth],
memmove( &vidbuf[row * width * depth],
&vidbuf[(row * width + col) * depth],
(width - col) * depth );
memmove( &vidbuf[(row * width + width - col) * depth],
temp,
memmove( &vidbuf[(row * width + width - col) * depth],
temp,
col *depth );
}
}
@ -431,8 +471,13 @@ void picture::slant_corr(int x, int y)
redraw();
}
void picture::slant(int dir)
{
}
int picture::handle(int event)
{
if (!slantcorr) return 0;
if (Fl::event_inside( this )) {
if (event == FL_RELEASE) {
int xpos = Fl::event_x() - x();
@ -442,6 +487,7 @@ int picture::handle(int event)
slant_corr(xpos, ypos);
else if (evb == 3)
slant_undo();
LOG_WARN("xpos, ypos %d, %d", xpos, ypos);
LOG_DEBUG("#2 %d, %d", xpos, ypos);
return 1;
}
@ -505,11 +551,11 @@ int picture::save_png(const char* filename, bool monochrome, const char *extra_c
fclose(fp);
return -1;
}
/* png_set_compression_level() shall set the compression level to "level".
* The valid values for "level" range from [0,9], corresponding directly
* to compression levels for zlib. The value 0 implies no compression
* and 9 implies maximal compression. Note: Tests have shown that zlib
* compression levels 3-6 usually perform as well as level 9 for PNG images,
/* png_set_compression_level() shall set the compression level to "level".
* The valid values for "level" range from [0,9], corresponding directly
* to compression levels for zlib. The value 0 implies no compression
* and 9 implies maximal compression. Note: Tests have shown that zlib
* compression levels 3-6 usually perform as well as level 9 for PNG images,
* and do considerably fewer calculations. */
png_set_compression_level(png, Z_BEST_COMPRESSION);