libsstvenc
Asynchronous Analogue SSTV encoder
|
Topics | |
CW modulator states | |
Data Structures | |
struct | sstvenc_cw_mod |
struct | sstvenc_cw_pair |
Functions | |
void | sstvenc_cw_init (struct sstvenc_cw_mod *const cw, const char *text, double amplitude, double frequency, double dit_period, double slope_period, uint32_t sample_rate, uint8_t time_unit) |
void | sstvenc_cw_compute (struct sstvenc_cw_mod *const cw) |
size_t | sstvenc_cw_fill_buffer (struct sstvenc_cw_mod *const cw, double *buffer, size_t buffer_sz) |
static const struct sstvenc_cw_pair * | sstvenc_cw_symbol_match (const char *sym, const struct sstvenc_cw_pair *candidate) |
static const struct sstvenc_cw_pair * | sstvenc_cw_symbol_lookup (const char *sym, const struct sstvenc_cw_pair *table, uint8_t len) |
static const struct sstvenc_cw_pair * | sstvenc_cw_get_symbol (const char *sym) |
static void | sstvenc_cw_get_next_sym (struct sstvenc_cw_mod *const cw) |
static void | sstvenc_cw_start_mark (struct sstvenc_cw_mod *const cw) |
static void | sstvenc_cw_end_subsym (struct sstvenc_cw_mod *const cw) |
static void | sstvenc_cw_end_symbol (struct sstvenc_cw_mod *const cw) |
static void | sstvenc_cw_handle_state_mark (struct sstvenc_cw_mod *const cw) |
static void | sstvenc_cw_handle_state_ditspace (struct sstvenc_cw_mod *const cw) |
static void | sstvenc_cw_handle_state_dahspace (struct sstvenc_cw_mod *const cw) |
static void | sstvenc_cw_handle_state_done (struct sstvenc_cw_mod *const cw) |
Variables | |
static struct sstvenc_cw_pair | sstvenc_cw_symbols [] |
static struct sstvenc_cw_pair | sstvenc_cw_mbsymbols [] |
This module implements a morse-code modulator for generating CW IDs as required by some juristictions for computer-generated transmissions.
Operation is pretty simple:
The text is assumed to be UTF-8 format using symbols defined in one of two symbol tables:
Any character not in those tables will be ignored by the state machine.
struct sstvenc_cw_mod |
CW state machine context. This structure bundles an oscillator and pulse shaper to generate a morse code waveform from the plain text given.
This should be initialised by calling sstvenc_cw_init. Then, to obtain samples, call sstvenc_cw_compute. Each output sample is then emitted via sstvenc_cw_mod::output.
The state machine's progress can be tracked by observing sstvenc_cw_mod::state. The modulator is finished transmitting when this changes to SSTVENC_CW_MOD_STATE_DONE.
Data Fields | ||
---|---|---|
uint16_t | dit_period |
Dit period in samples |
struct sstvenc_oscillator | osc |
Oscillator for the modulator. |
double | output |
Output sample. Call @sstvenc_cw_compute to calculate this, then read the result from here. |
uint8_t | pos |
Position within the current symbol being transmitted. |
struct sstvenc_pulseshape | ps |
Pulse shaper for the modulator. |
uint8_t | state |
Current state machine state |
const struct sstvenc_cw_pair * | symbol |
Current symbol being transmitted |
const char * | text_string |
UTF-8 string to be transmitted. Valid symbols for transmission are given in the tables sstvenc_cw_symbols and sstvenc_cw_mbsymbols. The non-English Ch character can be emitted using the pseudo prosign <CH> or the equivalent character Ĥ to avoid it getting confused with the C and H symbols. Anything else will be ignored. During transmission, this pointer will be incremented. |
struct sstvenc_cw_pair |
void sstvenc_cw_compute | ( | struct sstvenc_cw_mod *const | cw | ) |
Compute the next sample in the state machine. The state machine will be advanced to the next state and a sample written to sstvenc_cw_mod::output.
Definition at line 507 of file cw.c.
References sstvenc_cw_get_next_sym(), sstvenc_cw_handle_state_dahspace(), sstvenc_cw_handle_state_ditspace(), sstvenc_cw_handle_state_done(), sstvenc_cw_handle_state_mark(), SSTVENC_CW_MOD_STATE_DAHSPACE, SSTVENC_CW_MOD_STATE_DITSPACE, SSTVENC_CW_MOD_STATE_DONE, SSTVENC_CW_MOD_STATE_INIT, SSTVENC_CW_MOD_STATE_MARK, SSTVENC_CW_MOD_STATE_NEXT_SYM, and sstvenc_cw_mod::state.
Referenced by main(), sstvenc_cw_fill_buffer(), and sstvenc_sequencer_compute().
|
static |
Handle the end of a sub-symbol (dah or dit). This resets the pulse shaper then increments sstvenc_cw_mod::pos. If there's more sub-symbols we go back to state SSTVENC_CW_MOD_STATE_MARK, otherwise we enter state SSTVENC_CW_MOD_STATE_DAHSPACE.
Definition at line 432 of file cw.c.
References sstvenc_cw_mod::pos, sstvenc_cw_mod::ps, sstvenc_cw_handle_state_dahspace(), sstvenc_cw_handle_state_mark(), SSTVENC_CW_MOD_STATE_DAHSPACE, SSTVENC_CW_MOD_STATE_MARK, sstvenc_ps_reset(), SSTVENC_TS_UNIT_SECONDS, sstvenc_cw_mod::state, sstvenc_cw_mod::symbol, and sstvenc_cw_pair::value.
Referenced by sstvenc_cw_handle_state_ditspace(), and sstvenc_cw_handle_state_mark().
|
static |
Called at the end of a morse code symbol. This advances sstvenc_cw_mod::text_string by the length of the sstvenc_cw_pair::key pointed to by sstvenc_cw_mod::symbol.
sstvenc_cw_mod::symbol is then dropped and we move on in state SSTVENC_CW_MOD_STATE_NEXT_SYM.
Definition at line 446 of file cw.c.
References sstvenc_cw_pair::key, sstvenc_cw_mod::ps, sstvenc_cw_get_next_sym(), SSTVENC_CW_MOD_STATE_NEXT_SYM, sstvenc_ps_reset(), SSTVENC_TS_UNIT_SECONDS, sstvenc_cw_mod::state, sstvenc_cw_mod::symbol, and sstvenc_cw_mod::text_string.
Referenced by sstvenc_cw_handle_state_dahspace().
size_t sstvenc_cw_fill_buffer | ( | struct sstvenc_cw_mod *const | cw, |
double * | buffer, | ||
size_t | buffer_sz ) |
Fill the given buffer with audio samples from the CW modulator. Stop if we run out of buffer space or if the CW state machine finishes. Return the number of samples generated.
[in,out] | cw | CW state machine to pull samples from. |
[out] | buffer | Audio buffer to write samples to. |
[in] | buffer_sz | Size of the audio buffer in samples. |
Definition at line 529 of file cw.c.
References sstvenc_cw_mod::output, sstvenc_cw_compute(), SSTVENC_CW_MOD_STATE_DONE, and sstvenc_cw_mod::state.
|
static |
Scan the string given in sstvenc_cw_mod::text_string by repeatedly calling sstvenc_cw_symbol_lookup.
If the text at sstvenc_cw_mod::text_string does not match a known symbol, we increment that and try again (until we run out of characters in sstvenc_cw_mod::text_string).
If we run out of characters, we move the state machine to SSTVENC_CW_MOD_STATE_DONE – we are finished.
Otherwise, we load the symbol into sstvenc_cw_mod::symbol, reset sstvenc_cw_mod::pos and enter SSTVENC_CW_MOD_STATE_MARK.
Definition at line 383 of file cw.c.
References sstvenc_cw_mod::pos, sstvenc_cw_get_symbol(), sstvenc_cw_handle_state_done(), sstvenc_cw_handle_state_mark(), SSTVENC_CW_MOD_STATE_DONE, SSTVENC_CW_MOD_STATE_MARK, sstvenc_cw_mod::state, sstvenc_cw_mod::symbol, and sstvenc_cw_mod::text_string.
Referenced by sstvenc_cw_compute(), and sstvenc_cw_end_symbol().
|
static |
Try to locate the CW symbol that represents the text at the start of the string sym. First, sstvenc_cw_symbols is searched for the most likely case (English letters, digits and punctuation), then if that fails, sstvenc_cw_mbsymbols is scanned (non-English symbols and prosigns).
[in] | sym | The text to be matched to a morse-code symbol. Assumed to be UTF-8 encoding. |
NULL | The character sequence seen at the start of sym does not match any known morse code symbol. |
Definition at line 365 of file cw.c.
References sstvenc_cw_mbsymbols, sstvenc_cw_symbol_lookup(), and sstvenc_cw_symbols.
Referenced by sstvenc_cw_get_next_sym().
|
static |
Handling of the spaces between symbols (morse code symbols). This is the length of one "dah" (3 "dits"), and is measured by sstvenc_pulseshape::sample_idx which is incremented each time sstvenc_ps_compute is called whilst the shaper remains in the SSTVENC_PS_PHASE_DONE state.
As we enter this state after being in the SSTVENC_CW_MOD_STATE_DITSPACE state, one "dit"'s worth of space has already been emitted, so we carry on.
When it passes sstvenc_cw_mod::dit_period * 2, we call sstvenc_cw_end_symbol to move to the next symbol.
Definition at line 493 of file cw.c.
References sstvenc_cw_mod::dit_period, sstvenc_cw_mod::ps, sstvenc_pulseshape::sample_idx, sstvenc_cw_end_symbol(), and sstvenc_ps_compute().
Referenced by sstvenc_cw_compute(), and sstvenc_cw_end_subsym().
|
static |
Handling of the spaces between sub-symbols (individual dahs and dits). This is the length of one "dit", and is measured by sstvenc_pulseshape::sample_idx which is incremented each time sstvenc_ps_compute is called whilst the shaper remains in the SSTVENC_PS_PHASE_DONE state.
When it passes sstvenc_cw_mod::dit_period, we call sstvenc_cw_end_subsym to move to the next sub-symbol.
Definition at line 484 of file cw.c.
References sstvenc_cw_mod::dit_period, sstvenc_cw_mod::ps, sstvenc_pulseshape::sample_idx, sstvenc_cw_end_subsym(), and sstvenc_ps_compute().
Referenced by sstvenc_cw_compute(), and sstvenc_cw_handle_state_mark().
|
static |
Handling of the end of transmission. We reset state variables and the output so it emits zeroes from now on.
Definition at line 501 of file cw.c.
References sstvenc_cw_mod::output, sstvenc_cw_mod::symbol, and sstvenc_cw_mod::text_string.
Referenced by sstvenc_cw_compute(), and sstvenc_cw_get_next_sym().
|
static |
Sub-state machine built around the pulse shaper state machine to handle transmission of a mark. This routine initialises the pulse shaper by calling sstvenc_cw_start_mark then will step the pulse shaper through its state machine by calling sstvenc_ps_compute.
The envelope is modulated by the oscillator by calling sstvenc_osc_compute then multiplying the outputs, storing these in sstvenc_cw_mod::output.
At the end of the envelope, it resets sstvenc_cw_mod::output. If we were actually transmitting a space, we move to the next sub-symbol otherwise we enter SSTVENC_CW_MOD_STATE_DITSPACE to emit the inter-sub-symbol dit space.
Definition at line 454 of file cw.c.
References sstvenc_oscillator::amplitude, sstvenc_cw_mod::osc, sstvenc_cw_mod::output, sstvenc_oscillator::output, sstvenc_pulseshape::output, sstvenc_pulseshape::phase, sstvenc_cw_mod::pos, sstvenc_cw_mod::ps, sstvenc_cw_end_subsym(), sstvenc_cw_handle_state_ditspace(), SSTVENC_CW_MOD_STATE_DITSPACE, sstvenc_cw_start_mark(), sstvenc_osc_compute(), sstvenc_ps_compute(), SSTVENC_PS_PHASE_DONE, SSTVENC_PS_PHASE_FALL, SSTVENC_PS_PHASE_HOLD, SSTVENC_PS_PHASE_INIT, SSTVENC_PS_PHASE_RISE, sstvenc_cw_mod::state, sstvenc_cw_mod::symbol, and sstvenc_cw_pair::value.
Referenced by sstvenc_cw_compute(), sstvenc_cw_end_subsym(), and sstvenc_cw_get_next_sym().
void sstvenc_cw_init | ( | struct sstvenc_cw_mod *const | cw, |
const char * | text, | ||
double | amplitude, | ||
double | frequency, | ||
double | dit_period, | ||
double | slope_period, | ||
uint32_t | sample_rate, | ||
uint8_t | time_unit ) |
Initialise a CW state machine.
[in,out] | cw | CW state machine context being initialised. |
[in] | text | Text to transmit in CW (morse code) |
[in] | amplitude | Peak amplitude of the carrier on the scale 0.0-1.0. |
[in] | frequency | Oscillator frequency in Hz. |
[in] | dit_period | The length of a morse code 'dit'. |
[in] | slope_period | The duration used for rising and falling pulse edges for bandwidth reduction. |
[in] | sample_rate | The sample rate of the output waveform in hertz. |
[in] | time_unit | The time unit used for measuring dit_period and slope_period. |
Definition at line 312 of file cw.c.
References sstvenc_cw_mod::dit_period, sstvenc_cw_mod::osc, sstvenc_cw_mod::pos, sstvenc_cw_mod::ps, SSTVENC_CW_MOD_STATE_INIT, sstvenc_osc_init(), sstvenc_ps_init(), sstvenc_ts_unit_to_samples(), sstvenc_cw_mod::state, sstvenc_cw_mod::symbol, and sstvenc_cw_mod::text_string.
Referenced by main(), and sstvenc_sequencer_begin_cw().
|
static |
Prepare to transmit a "mark" (or a gap between marks).
sstvenc_cw_mod::pos gives the position in the current morse-code symbol being processed. It points to either ‘’ ',
'.'or
'-'`.
For a ‘’ '`: the oscillator amplitude is set to 0.0 and we reset the pulse shaper for the duration of a single dit.
For a ‘’.'`: the oscillator amplitude is set to 1.0 and we reset the pulse shaper for the duration of a single dit.
For a ‘’-'`: the oscillator amplitude is set to 1.0 and we reset the pulse shaper for the duration of three dits.
Definition at line 406 of file cw.c.
References sstvenc_oscillator::amplitude, sstvenc_cw_mod::dit_period, sstvenc_pulseshape::fall_sz, sstvenc_cw_mod::osc, sstvenc_cw_mod::pos, sstvenc_cw_mod::ps, sstvenc_pulseshape::rise_sz, sstvenc_ps_reset_samples(), sstvenc_cw_mod::symbol, and sstvenc_cw_pair::value.
Referenced by sstvenc_cw_handle_state_mark().
|
static |
Look up the symbol at the start of sym in the table table.
[in] | sym | Text symbol being looked up. May be followed by other symbols. Assumed UTF-8 encoding. |
[in] | table | Symbol table to scan for possible matches. The table must be terminated by a sstvenc_cw_pair with both sstvenc_cw_pair::key and sstvenc_cw_pair::value set to NULL. |
[in] | len | The fixed symbol length to check. For sstvenc_cw_symbols, all values are single byte ASCII characters, so in that situation, set this parameter to 1. This optimises the most likely case: plain English characters. If the symbols are a variable length, which is the case for sstvenc_cw_mbsymbols, set this to 0 instead. |
NULL | None of the symbols in table match the character sequence at sym. |
Definition at line 342 of file cw.c.
References sstvenc_cw_pair::key, and sstvenc_cw_symbol_match().
Referenced by sstvenc_cw_get_symbol().
|
static |
Compare the character sequence given to the candidate symbol.
[in] | sym | Text symbol to be compared. May be followed by other symbols. Assumed UTF-8 encoding. |
[in] | candidate | Candidate morse code symbol being compared. The string sym is a match if it starts with the sstvenc_cw_pair::key given by candidate. |
candidate | The candidate is a match. |
NULL | Not a match. |
Definition at line 329 of file cw.c.
References sstvenc_cw_pair::key.
Referenced by sstvenc_cw_symbol_lookup().
|
static |
Multi-byte symbols. These symbols have keys that are more than one byte each. Non-English and CW prosigns.
Definition at line 99 of file cw.c.
Referenced by sstvenc_cw_get_symbol().
|
static |
Symbol table… UTF-8 symbol mapped to the morse code sequence that represents it. This table is for single-byte sequences only.
The values are strings where the characters have the following meanings:
Definition at line 33 of file cw.c.
Referenced by sstvenc_cw_get_symbol().