JS8Call de KN4CRD

2019-06-16 - v1.1.0


JS8Call is an experiment in combining the robustness of FT8 (a weak-signal mode by K1JT) with a messaging and network protocol layer for weak signal communication. The open source software is designed for connecting amateur radio operators who are operating under weak signal conditions and offers both real-time messaging, store-and-forward messaging, and automatic station announcements. JS8Call is heavily inspired by WSJT-X, Fldigi, and FSQCall and would not exist without the hard work and dedication of the many developers in the amateur radio community.

JS8Call stands on the shoulders of giants...the takeoff angle is better up there.


Read more on the original design inspiration here.

For release announcements and discussion, join the JS8Call mailing list here: https://groups.io/g/js8Call


History


Notice

JS8Call is a derivative of the WSJT-X application, restructured and redesigned for message passing using a custom FT8 modulation called JS8. It is not supported by nor endorsed by the WSJT-X development group. While the WSJT-X group maintains copyright over the original work and code, JS8Call is a derivative work licensed under and in accordance with the terms of the GPLv3 license. The source code modifications are public and can be found in js8call branch of this repository: https://bitbucket.org/widefido/js8call/

JS8Call is and will always be open-source and free software (free as in beer and free as in speech, do with it what you like, for the sum of exactly $0).

You might be asking...why is this named JS8Call? Why was it renamed from FT8Call? Why not something else, like BACON or HF Messenger? Good question! It is named this way as an homage to its heritage:

Hence JS8 + Directed Calling = JS8Call. And in case you didn’t get that:

Download & Install

JS8Call currently comes in a variety of builds.

For the most up-to-date download links, first join the groups.io, then check:

Of course, you are always free to take a look at the source code as well!

NOTE: Development versions of JS8Call only carry an approximate 14 day lifespan. After expiration, you will be required to upgrade to the latest version of the application. This helps keep everybody operating with compatible versions while the software is being developed and beta tested. This expiration does not exist in general release versions.

Getting Started

Clock Sync / Timing

In the application you can see the current time reported by your PC in UTC format. An accurate clock is important with JS8Call, as the decoder operates within a 15-second window of transmission (frames). Your clock being off greater than 2 seconds from UTC can cause messages to not decode at your station. It is best to use an Internet, NTP or GPS time source for synchronizing your clock as accurately as possible.

JS8Call includes a manual clock drift tool that you can use to modify your application time to match signals you see / hear (or to an external time source like a Timex watch, a handheld GPS device, WWV, or a rooster crowing). This is intended to be used as a fail-safe for when your synchronized time source is not available (like if you were out portable, away from internet connectivity).

NOTE: You do not actually have to have the exact time synchronized...just synchronized to the start of a 15-second window, +/- 2 seconds. Many operators can manually synchronize their system clock based on signals in the waterfall and the time drift reported for each station.

USB - Upper Sideband Only

Make sure your rig is set to upper sideband (USB) mode for every band. If you are running lower sideband (LSB), you’ll likely see reversed signals you cannot decode.

Duty Cycle

The JS8 modulator is a constant envelope, full-duty modulation that transmits in 12.6 second frames. Because of the dead air between transmission frames, multi-frame messages can be classified as 84% duty on a 15-second window (12.6 / 15 = 0.84).

Please make note of the power restrictions your transceiver manufacturer recommends for full-duty digital transmissions. When in doubt, use only a maximum of 50% of your rig’s power output to “save your finals”.

Audio Levels

Your input and output audio levels control how well you transmit and receive. Too high and the audio becomes distorted. Too low and you have no modulation / demodulation. Calibration is an important step to getting started.

Output & ALC

A rule of thumb is to set your output audio just high enough to drive your transmitter while not engaging your ALC. If you drive your audio too high, your ALC will distort the tones and many stations will not be able to decode your transmissions.

Input & AGC

For best decodes, it’s best to turn off your AGC (or set it to fast) and set your input audio just high enough to read somewhere around 30-40dB on the signal meter in the app. You might have to experiment with the settings that work best for your station and you might also have to engage your attenuator for strong signals.


Your First QSO

Step-by-step walkthrough coming soon.

Operating JS8Call

If you’ve used FSQ, Fldigi or WSJT-X before, you’ll feel right at home with JS8Call. The premise is that JS8Call changes the encoding structure of FT8-style JS8 modulated messages, breaking up long free-text messages into multiple back-to-back 15-second cycles with 12.6 seconds of transmit time between frames.

Here’s what you’ll see when you start up the application:

Band Activity

Band activity is displayed on the left. Call activity (callsigns you've heard) are on the right. Right clicking will show a menu with an option to move your RX/TX offset to that audio frequency (QSY) and send specific messages.

Call Activity

In the Call Activity, when a station responds to you a  indicator will be displayed next to their callsign. This helps you find, at a glance, other operators that are confirmed to be able to hear you.

When a station is calling CQ, a ☎ indicator will be displayed next to their callsign for 5 minutes. This helps you find, at a glance, other operators that are looking to make contact.

If a station has left you a message, a ⚑ indicator will be displayed next to their callsign. You can read that message by right clicking on the station and clicking “Show Message Inbox”.

Station distance and azimuth is computed from the first 6 digits of the maidenhead grid locators. This is enough to present a 2.8 mi / 4.6 km resolution. Closer than this and the distance and azimuth will read 0 distance and 0°.

Waterfall

There is a waterfall at the bottom of the screen to show you the signals in your audio passband. You can click on the waterfall to set your audio frequency offset.

There is also an option to QSY to that frequency by centering your selected audio offset to the rig passband center. This allows you to use narrow filters easily.

Messages

The top yellow text box shows you messages that are either on the frequency offset you're on or who have directed a message to you (they sent a message that included your callsign).

You type into the white box on the bottom to prepare a message for transmission.

Normal FT8 character restrictions do not apply! The extended character set includes all printable uppercase ASCII (A-Z 0-9 Space ./?+-`~!@#$%^&*()_=[]\{}|;’:”,<>). The message structure is variable encoded, so the most common characters take the least amount of space, and special characters take longer to send.

As you type your message you’ll see the send button display the number of frames (15 second transmit cycles) it’ll take to send your complete message. All you have to do is click send (or hit enter) to start transmitting on the next interval. As each frame is transmitted one after the other, the button will update with the number of frames left.

Because of this special variable encoding, messages in JS8Call cannot be decoded by WSJT-X. The same is also true, WSJT-X messages will not be shown in JS8Call.

Messages come in three forms:

  1. standard JS8Call free text messages
  2. undirected JS8Call messages
  3. directed JS8Call messages

Standard Messages

Standard messages are free-text messages that do not start with a callsign or a directed command. These messages will only print at other station locations if they align their receive offset within 10Hz of your transmit offset. This is operation similar to other keyboard-to-keyboard digital modes, like Olivia, RTTY, and PSK.

Undirected Messages

Undirected messages are specially formatted JS8Call transmissions that announce your station via CQ or Heartbeats (HB). They are undirected in that they have no destination.

Directed Messages

Directed messages are special JS8Call transmissions that automatically prefix your message with your callsign, similar to how FSQCall operates. Directed messages are useful for communicating in that you do not have to include your callsign in your message, allowing you to use more of the transmission frame(s) for actual message text, as well as alerting the recipient that a message was sent to them. As long as you are in the same passband, you do not have to be on the same frequency offset to receive a directed message.

To send a directed message, all you need to do is include the callsign of the receiving station as the first word in the message or select a callsign in your heard list to have it automatically prefixed.

You’ll notice a special character at the end of the message, ala  . This is a symbol to indicate the End of Transmission. JS8Call displays this as after the last frame of the message has been transmitted with nothing else to follow. This means you get a visual indicator that the transmission is done and you can begin transmitting a reply. This character can be customized in the Configuration.

Directed messages to you (and to @ALLCALL) are displayed in the top RX window.

When in the middle of receiving a directed message (i.e., after the first directed frame is received), your station will not respond automatically to commands (even with AUTO on) until that message is received or enough time has elapsed to move on (one minute from the last frame decoded).

@ALLCALL Callsign

There is a special “@ALLCALL” group callsign that you can use to send the message to anybody who is able to receive your message. Some examples:

Group Callsigns

Group callsigns are a special form of compound callsigns that begin with an “@” character, and can be up to 8 alpha-numeric (A-Z 0-9) characters in length.. If you modeled that in a regular expression, that would be:

[@][A-Z0-9\/]{0,3}[\/]?[A-Z0-9\/]{0,3}[\/]?[A-Z0-9\/]{0,3}

Group callsign functionality allows you to direct your message to anybody who has “joined” the group. You join the group by adding the group name in the settings.

Say for example, I was part of the GA ARES group and I wanted to send other folks in the group a message, I’d send:

        KN4CRD: @ARESGA QSL?

This is similar to @ALLCALL, in that everybody who is in the @ARESGA would have the message printed on the screen.

There are a number of built-in group callsigns you can use that transmit just as efficiently as standard callsigns:

Directed Commands:

There are special directed messages that you can send to stations to have them automatically reply if they have AUTO enabled. They are comprised in the form of [CALLSIGN][COMMAND].

There are also a number of “short messages” that can be included in a directed message frame, which would be transmitted in one tx cycle with standard (non-compound, non-group) callsigns:

Message Examples:

If we wanted to ask DR4CNK what their station information was, we’d send:

If we wanted to transmit a “relay” message to OH8STN through DR4CNK, we could use the relay command and send:

You can also mix and match standard and free text messages, but most of the time you won’t need to.

Inbox - Message Storage and Retrieval

Directed messaging allows three commands to be used for message storage and retrieval at intermediate stations:

TODO: Let’s add an example here :)

AUTO - Automatic Replies

While AUTO is enabled, the software will automatically respond to directed queries, like “SNR?”, “INFO?”, and “GRID?”. When AUTO is turned off, JS8Call will buffer responses to directed queries in the send message textbox until you are ready to send the replies manually.

If you would like to participate in AUTO, but would not like to be responsible for message relays, you can disable relays while AUTO is enabled in the settings.

LOG - Station Log

There’s a log item in the main menu of the application. You can also press F5 to start a log entry. The software will do its best effort to pre-populate log fields. However, you’ll likely have to fill out some missing information manually since the QSO is free-text and not automated.

The log is stored in JS8Call.log & JS8Call.adif in the log directory (which you can find by clicking “File -> Open log directory” in the main menu).

Currently, the logging function in JS8Call will log each contact, according to the ADIF spec, as MFSK mode and JS8 submode. There is also an option in the Logging settings to log the mode as DATA instead of MFSK & JS8.

Once logged, the selected directed callsign is automatically deselected by default, however this option can be overridden in the configuration.

SPOT - Callsign Spotting

When SPOT is enabled, JS8Call will report callsigns you hear (or your callsign if heard by other stations) to PSKReporter under the “JS8Call” mode.

JS8Call will also spot GRID commands with 6 or more characters to APRS-IS / aprs.fi. Make sure to set your grid locator to 6-12 characters for the most accurate spot. You can drill down with this map to your location if you’re unsure of your grid: http://k7fry.com/grid/. If you have a lat/lon, you can also use the lonlat2maiden script here: http://www.jidanni.org/geo/maidenhead/

HB - Heartbeat Transmission

There is an automated heartbeat mechanism that transmits on an interval once turned on (HB button on the bottom left). This interval can be changed from the control menu or by right clicking the HB button. All heartbeats are transmitted on a random (unused) frequency offset between 500Hz-1000Hz to help prevent QRM. There is an option in the settings to allow heartbeating anywhere...which is especially useful on lower bands like 160m and 630m.

When you have AUTO replies enabled and you’ve selected to Send Heartbeat Acknowledgements, your station will send an ACK reply to signal to the other operator that you can hear them. These are essentially “lightweight heartbeats” from your station and will reset your heartbeat timer.

The intent of heartbeat is not to report on propagation. Instead it is to help populate your call activity (the heard list on the right) so you know who's likely to be reachable to make contact. You can't work them if you can't “hear” them (or if they cannot hear you).

Keep in mind, though, that HBs are not designed to start conversations. When you turn HB on, you’re “joining” the heartbeat network. This network allows for planning of relays and sending messages to be stored at those receiving stations. Think of HBs and ACKs as a way to plot network topology and relays (">") as a way to send messages to be read later (sort of like an SMS text message) through that network.

While heartbeating, if a station has a message to deliver to another station it hears heartbeating, it will announce that in the heartbeat ACK, like so:

KN4CRD: KM4ACK ACK -12 MSG 32 ♢

You can then retreive that message using the “QUERY MSG” directed command:

KM4ACK: KN4CRD QUERY MSG 32

While in QSO (i.e., when you receive a transmission that is displayed in your incoming messages window) the HB timer will be reset to prevent your station from QRMing your QSO.

Keep in mind that unattended transmissions may be against the rules of your jurisdiction. To be most safe, heartbeat should only be automatically sent while you’re at the control point of your station. There’s an idle timer that you can configure in the settings that will disable your heartbeat once you leave your station idle.

CQ - Calling CQ

The default way to call cq is with the “CQCQCQ” message. This is configured by default. What’s notable, though, is that you can configure this message in the settings. These are the messages supported to be sent in one 15-second transmission:

When using one of these message formats, you can also include your 4 digit grid and it will be encoded in one transmission cycle:

You can start your CQ message with one of these formats and it will be sent directed, meaning your callsign will automatically be included. You can also add to the messages without issue:

If you deviate from these formats, you will not be sending a directed message, your grid will not be included, and you must include your callsign in your message.

You can also send CQs on an interval by right clicking the CQ button and selecting a repeat interval. This will cause your station to repeat your CQ transmission until a message is received.

REPLY - Replying to a CQ

The default way to reply to a cq is with “HW CPY?”. This allows the caller to choose who to connect with and send a signal report to. You can customize this message with a reply, but keep in mind that most stations will be replying with something that can be send in one 15-second transmission. Here’s an example exchange:


Configuration

General (Station and Behavior)

TODO

Radio (CAT and PTT control)

There is an advanced feature for rig control called PTT Command. This allows JS8Call to execute an external script for controlling a rig’s PTT:

What this PTT command does is allow you to execute any command line script to toggle your Rig’s PTT line.

In the above example, the toggle-ptt script will be called with the -p 17 and -s parameters on transmit. The %1 in the above command will be replaced with “on” or “off” depending on the state of the PTT. If you do not add a %1 in your command, “on” and “off” will be appended to the end of the command for invocation.

Example:

If you define your PTT command as:   /usr/bin/ptt %1

When JS8Call starts transmitting, it will execute:   /usr/bin/ptt “on”

And when JS8Call has finished transmitting, it will execute:   /usr/bin/ptt “off”

This is particularly helpful for Raspberry Pi / DRAWS when the GPIO ports are used to control your rig PTT. An example script can be found here: https://gist.github.com/jsherer/dd09895ab23bdf571e2117cdd814c198

Audio (Sound Card)

When choosing your sound card, you have the option to set individual devices for input and output. You’ll need to find the device that matches what you’ve integrated with your rig. You can choose Mono or Stereo input/output, so try matching those with the capabilities of your device.

For best decoding, when configuring your audio devices you need to apply the right input/output levels:

  1. Make sure the sound card device you have chosen for input has no microphone amplification enabled Usually you set this at the operating system level. Set the input to 100%.
  2. Move your VFO to a quiet part of the band that has no signals present
  3. Set your rig’s AF Gain to its maximum value
  4. Start adjusting your rig’s RF Gain to the point where the s-meter just starts to read 0
  5. If RF Gain is not enough to bring down the rig’s s-mete, apply your rig’s attenuator. This is usual during noisy band conditions or RFI locally. Most attenuators apply a -10dB to -15dB signal attenuation, so you can usually bring RF Gain up just a touch to match.
  6. If those adjustments are still not enough, you’re likely operating under an extremely noisy condition. You might have luck at this point to start playing with AF Gain to bring the input levels even further down to that sweet spot of 30-60dB as read by the meter in the app.

Audio input it too low!

Audio input is just right!

Audio input is too high!

Reporting (Spotting and API)

TODO

Frequencies (Calling Frequencies and Band Hopping)

Most operators testing the application can be found +/- 4-8kHz from the standard FT8 frequencies. It is essential to avoid the main FT8 frequencies, as that will cause confusion among WSJT-X operators. Here are some suggested frequencies to use:

You might notice a few of these being close to the JT9 frequencies. Don’t grab your pitchforks! JS8Call blocks out transmitting within the lower 500Hz of the passband. This leaves enough room for 25 simultaneous JT9 signals.

 

You might also notice that there are a few bands missing from this list. JS8Call does not make a recommendation for calling frequencies on 2200m, 630m, 60m, or higher than 2m, as many are special case and have unique rules in many jurisdictions. It’s up to the operator to determine the best frequency and operating pattern on these bands.

But also, please keep in mind these are only suggested frequencies. We all have VFOs, so please use them. Just remember to be good operators and prevent from interfering with other signals on our shared bands.

You CAN type in any frequency. JS8Call will not limit which frequencies you can manually transmit on.

You can use the mailing list Sked Chat or the Facebook group to schedule on other frequencies with test operators.

If you want to transmit on a non-standard frequency (recommended) you can either modify the frequencies list in the settings, or you can type directly into the band dropdown box in the top left of the screen.

If you’d like to add custom frequencies for JS8Call, you can do so in the settings:

If you’d like to reset to the suggested frequencies, right click the frequencies box and click Reset.

Saved Messages (Macros)

There are a few quick saved message buttons for transmitting common messages. You can edit these in the settings window. Just be mindful that long messages will take a while to send.

Saved messages have macro-like functionality. These are the macros variables (words that are surrounded by <> characters) that can be used in saved messages which will be replaced when sending the message:

Notifications (Sound Alerts)

TODO

UI (Customize Colors and Font)

TODO

Tips & Tricks

Frequently Asked Questions

 

via https://sourceforge.net/p/wsjt/mailman/message/36224507/

Troubleshooting

If you’re having trouble, head over to the troubleshooting chatroom for help: https://groups.io/g/JS8Call/chat/1423 or email Jordan directly: kn4crd@gmail.com

Common Problems & Solutions

JS8Call will not run on my system
Make sure you are running a supported operating system, that you have disabled any programs that may be using your audio device, or preventing JS8Call from using the audio device...like an aggressive antivirus. If you’re running Windows, and have a Windows Defender running, you’ll need to either whitelist JS8Call or turn off the defender.

I see signals on the waterfall but I cannot decode them
Make sure the signals you are seeing are actually JS8Call signals and not FT8 signals (they are incompatible) by ensuring you’re on one of the JS8Call frequencies. Make sure you are in Upper Sideband (USB) mode. Make sure you have synchronized your clock to within 2 seconds of UTC. Make sure you’re not running WSJT-X at the same time.

I do not see any signals on the waterfall

Check your incoming audio from your rig. Make sure JS8Call audio is configured correctly. Check to make sure you’re on one of the JS8Call frequencies. Keep in mind that JS8Call is still in development and has more than an order of magnitude fewer operators on the air. There may actually be nobody on within your reception range. Check PSKReporter to see if there are others on the band. If you still cannot see any signals, either:

  1. You have an RX problem with your station
  2. None of the operators are operating on the band you are on
  3. Or propagation isn’t being friendly to you

NOTE: Keep in mind that JS8Call isn’t magic...we’re still at the mercy of the ionosphere.

My rig won’t transmit

Check your outgoing audio to your rig. Make sure JS8Call audio is configured correctly. Unplug the rig from the computer and hook up the output to a set of headphones or speakers. Try to transmit, maybe with the TUNE button in the app. Can you hear the tones? If not, then you have an audio problem, if so then you have a transceiver problem. Make sure your PTT is configured correctly for your rig or use VOX. You can test this in the settings. The PTT button will turn green if it can key your transmitter. If you have audio into the rig, but still have no RF out, make sure your rig is configured correctly by checking your digital gain / tx gain / mic levels. After that, make sure your rig works...switch over to FM or CW and send a carrier to make sure the rig can actually transmit at all.

Bug Reports

You can send bug reports to Jordan Sherer (KN4CRD) at kn4crd@gmail.com or submit them to the issue tracker here: https://bitbucket.org/widefido/js8call/issues?status=new&status=open


API Definition

JS8Call uses a JSON API offered over UDP. It is currently highly experimental and subject to drastic change in the future (like, for instance, if we decide to move it to a HTTP or XMLRPC implementation instead).

The API will allow you to:


Technical Implementation

JS8Call is under active development and details about the technical implementation are subject to change. Detail will be added here as the implementation stabilizes. Until then, the code is the source of truth for the implementation.

Modulation

JS8Call uses FT8 modulation as the base transport for data. Being a derivative of WSJT-X, JS8Call heavily leverages the work by the WSJT-X Development Group on the FT8 mode. Very few modifications have been made (see source code for the exhaustive list) to the base FT8 modulation, with the exception of two important items:

  1. Modifying the costas array algorithm to prevent JS8Call from interfering with FT8 signals
  2. And allowing as many of the 75 bits to be utilized for data transport

Protocol

The JS8Call protocol sits at a layer above the base transport. Much of the implementation is inspired by the design document: https://github.com/jsherer/ft8call with a few deviations from the original proposal.

Messages in JS8Call are transmitted in 15-second intervals (frames), with each frame being classified as one of 6 frame types:

  1. Heartbeat
  2. Compound Callsign Partial
  3. Compound Callsign Directed Command
  4. Directed Command
  5. Data Huffman
  6. Data Dictionary

Further, each frame includes a transmission flag identifying it as:

  1. Default Frame (any frame)
  2. First Frame (first frame of the transmission)
  3. Last Frame (last frame of the transmission)
  4. Flag - Reserved (for future use)

And finally, there are special encodings for:

  1. Callsigns
  2. Callsign Prefix/Suffixes
  3. Signal Reports
  4. Grids

Heartbeat

Heartbeat frames are comprised of:

Compound Callsign Partial

Compound callsign partials are used as one-half of a 2-frame compound transmission when one of the stations includes a compound callsign. Compound callsign partials are always the 1st frame in a 2-frame compound transmission, encoding the “from” portion of a directed command with compound callsigns.

The frame includes:

Compound Callsign Directed Command

Compound callsign directed commands are a special case for compound callsign partials where the numeric value encodes a directed command to be used with a compound directed message. It is one-half of a 2-frame compound transmission. Compound callsign directed commands are always the 2nd frame in a 2-frame compound transmission, encoding the “to” portion of a directed command with compound callsigns.

The frame includes:

Directed Command

Standard callsigns can send a directed command in one frame.

The frame includes:

Data

Data frames are the backbone for long-form messages in JS8Call. They are 75-bit frames that use a variable encoding to pack character data into the smallest transmission possible.

Data frames come in two flavors:

Data frames may need to include pad bits because of the variable encoding that character data uses for packing. The variable encoding used is a modified Huffman code that represents the most common characters (based on their frequency of observation in most texts) in fewer bits than less common characters, with the option to shift in alternate alphabets.

The complete modified Huffman code is located in Appendix A. The (s,c)-Dense Code tables include 260K compressible entities. 

Callsigns

Callsigns are encoded in 28-bits as described in: EME 2000 - http://www.ka9q.net/papers/eme-2000.ps.gz

Compound callsigns are a 50-bit encoding of 11 characters following the format:

[@A-Z0-9/][A-Z0-9/][A-Z0-9/][/][A-Z0-9/][A-Z0-9/][A-Z0-9/][/][A-Z0-9/][A-Z0-9/][A-Z0-9/]

Since normal callsigns are 28-bits in length, and compound callsigns are 50-bits in length, and the payload size is only 75 bits, there's no way to transmit both in a single frame. So, when addressing a station with a compound call, the transmission is split into two frames, with any directed command included in the extra space of the second frame.

Callsign Prefix / Suffix

Prefixes and suffixes are 4 character alphanumeric encoded in 21-bits with a 1-bit flag to indicate whether or not it is a prefix or suffix. Alphanumeric digits can each be encoded in 5.25 bits (there are only 1,874,161 combinations of 4 character alphanumeric prefix/suffix, which is less than can be represented in a 21-bit number 221 = 2,097,152)

Grids

Grids are encoded in 15-bits as described in: http://physics.princeton.edu/pulsar/k1jt/wsjtx-doc/wsjtx-main-1.7.0.html#PROTOCOL_OVERVIEW


Future Work

JS8Call is an experiment in combining the robustness of FT8 with a messaging and network protocol layer for weak signal communication. The open source software is designed for connecting amateur radio operators who are operating under weak signal conditions and offers both real-time messaging, store-and-forward messaging, and automatic station announcements.

There are many opportunities to explore reliable messaging in the future with the foundation laid, including:

Appendix A: Code Table

Huffman Code:

Character code weighted by frequency

 " "    "01"

 "E"    "100"

 "T"    "1101"

 "A"    "0011"

 "O"    "11111"

 "I"    "11100"

 "N"    "10111"

 "S"    "10100"

 "H"    "00011"

 "R"    "00000"

 "D"    "111011"

 "L"    "110011"

 "C"    "110001"

 "U"    "101101"

 "M"    "101011"

 "W"    "001011"

 "F"    "001001"

 "G"    "000101"

 "Y"    "000011"

 "P"    "1111011"

 "B"    "1111001"

 "."    "1110100"

 "V"    "1100101"

 "K"    "1100100"

 "-"    "1100001"

 "+"    "1100000"

 "?"    "1011001"

 "!"    "1011000"

"\""    "1010101"

 "X"    "1010100"

 "0"    "0010101"

 "J"    "0010100"

 "1"    "0010001"

 "Q"    "0010000"

 "2"    "0001001"

 "Z"    "0001000"

 "3"    "0000101"

 "5"    "0000100"

 "4"    "11110101"

 "9"    "11110100"

 "8"    "11110001"

 "6"    "11110000"

 "7"    "11101011"

 "/"    "11101010"

(s,c)-Dense Code:

A whitepaper article is being written on this topic. In the meantime, see jsc.h, jsc.cpp, & jsc_map.cpp in the source repository for the complete dense code table.